Compare commits

...

806 Commits

Author SHA1 Message Date
Jacob Evans
7bf710f153 Publish
- @0x/contracts-asset-proxy@3.3.0
 - @0x/contracts-broker@1.1.5
 - @0x/contracts-coordinator@3.1.6
 - @0x/contracts-dev-utils@1.3.4
 - @0x/contracts-erc1155@2.1.6
 - @0x/contracts-erc20-bridge-sampler@1.6.0
 - @0x/contracts-erc20@3.2.0
 - @0x/contracts-erc721@3.1.6
 - @0x/contracts-exchange-forwarder@4.2.6
 - @0x/contracts-exchange-libs@4.3.6
 - @0x/contracts-exchange@3.2.6
 - @0x/contracts-extensions@6.2.0
 - @0x/contracts-integrations@2.5.2
 - @0x/contracts-multisig@4.1.6
 - @0x/contracts-staking@2.0.13
 - @0x/contracts-test-utils@5.3.3
 - @0x/contracts-utils@4.5.0
 - @0x/contracts-zero-ex@0.1.1
 - 0x.js@9.1.6
 - @0x/abi-gen@5.3.0
 - @0x/assert@3.0.8
 - @0x/asset-swapper@4.5.0
 - @0x/base-contract@6.2.2
 - @0x/connect@6.0.8
 - @0x/contract-addresses@4.10.0
 - @0x/contract-artifacts@3.7.0
 - @0x/contract-wrappers-test@12.2.15
 - @0x/contract-wrappers@13.7.0
 - @0x/contracts-gen@2.0.9
 - @0x/dev-utils@3.2.2
 - ethereum-types@3.1.1
 - @0x/instant@1.0.52
 - @0x/json-schemas@5.0.8
 - @0x/migrations@6.3.0
 - @0x/monorepo-scripts@1.0.53
 - @0x/order-utils@10.2.5
 - @0x/orderbook@2.2.6
 - @0x/sol-compiler@4.1.0
 - @0x/sol-coverage@4.0.9
 - @0x/sol-doc@3.1.7
 - @0x/sol-profiler@4.0.9
 - @0x/sol-resolver@3.0.4
 - @0x/sol-trace@3.0.9
 - @0x/sol-tracing-utils@7.0.9
 - @0x/sra-spec@3.0.8
 - @0x/subproviders@6.1.0
 - @0x/types@3.1.3
 - @0x/typescript-typings@5.1.0
 - @0x/utils@5.5.0
 - @0x/web3-wrapper@7.1.0
2020-06-24 13:56:20 +10:00
Jacob Evans
e50fd77973 Updated CHANGELOGS & MD docs 2020-06-24 13:55:59 +10:00
Jacob Evans
71cdc8a28f discuss: Continue if protocol fee insufficient 2020-06-23 18:30:22 +10:00
Jacob Evans
549f7bc6ee Initial tests 2020-06-23 18:02:35 +10:00
Jacob Evans
92ec1d6923 Mark as external for try/catch 2020-06-19 18:12:54 +10:00
Jacob Evans
56529180e9 Detect Bridge orders and fill direct 2020-06-19 17:03:06 +10:00
Xianny
f14b6f2ba2 Fix/erc20 sampler/uniswap v2 buys (#2603)
* `@0x/contracts-erc20-bridge-sampler`: Fix `sampleBuysFromUniswapV2()`

* fix uniswapV2 buys

* redeploy ERC20BridgeSampler to fix Uniswap buys

* fix changelog, move artifact to correct dir

Co-authored-by: Lawrence Forman <lawrence@0xproject.com>
2020-06-12 15:54:19 -07:00
Lawrence Forman
4fced276c4 Merge pull request #2591 from 0xProject/feat/asset-swapper/exchange-proxy-support
asset-swapper: Exchange Proxy support
2020-06-12 01:52:07 -04:00
Lawrence Forman
7590471d62 @0x/migrations: Add uniswapV2Bridge entry that was lost in rebase. 2020-06-12 00:40:37 -04:00
Lawrence Forman
0b6bcf6739 @0x/asset-swapper: Fix linter errors. 2020-06-11 23:59:54 -04:00
Lawrence Forman
3a5ce86ed9 @0x/sol-compiler: Fix CompilerOptions schema.
`@0x/contract-addresses`: Add `exchangeProxyGovernor`.
`@0x/contract-addresses`: Add deployed EP addresses.
`@0x/migrations`: Add `exchangeProxyGovernor`.
2020-06-11 23:59:24 -04:00
Lawrence Forman
7b298939e2 @0x/asset-swapper: Guess deployment nonce from transformer address.
`@0x/asset-swapper`: Fix ETH not being passed as the token to `transformERC20()`.
2020-06-11 23:53:18 -04:00
Lawrence Forman
f1f6aa7d80 Switch to using deployment nonce instead of transformer addresses. 2020-06-11 23:53:18 -04:00
Lawrence Forman
7ce7dd7252 @0x/asset-swapper: Address review feedback 2020-06-11 23:53:16 -04:00
Lawrence Forman
01aa556ede @0x/abi-gen: Update python wrappers generation to work with leading underscores in identifiers.' 2020-06-11 23:52:59 -04:00
Lawrence Forman
48ad39c1c7 @0x/asset-swapper: Add ExchangeProxySwapQuoteConsumer. 2020-06-11 23:52:56 -04:00
Lawrence Forman
9cab034448 @0x/migrations: Use new ContractAddresses type. 2020-06-11 23:52:39 -04:00
Lawrence Forman
0d7a22634c @0x/contract-addresses: Add exchange proxy address placeholders. 2020-06-11 23:51:45 -04:00
Lawrence Forman
3e3bc5c06d @0x/contract-artifacts: Add ITransformERC20 artifact.
`@0x/contract-wrappers`: Add `ITransformERC20Contract`.
2020-06-11 23:50:25 -04:00
Lawrence Forman
2a81e468c7 @0x/contracts-zero-ex: Add transformer decoders 2020-06-11 23:49:52 -04:00
Lawrence Forman
0ba67a363e @0x/instant: Pin asset-swapper version. 2020-06-11 23:49:52 -04:00
Lawrence Forman
deae846864 @0x/contracts-broker: Fix broken tests. 2020-06-11 23:49:52 -04:00
Lawrence Forman
3a0d48ad77 Run broker tests on CI 2020-06-11 23:49:52 -04:00
Jacob Evans
81d4803b4d fix: UniswapV2 path order (#2601) 2020-06-12 13:26:56 +10:00
mzhu25
e936c7c507 Merge pull request #2593 from 0xProject/feature/multibridge/asset-swapper
Add MultiBridge support to AssetSwapper
2020-06-11 14:26:32 -07:00
Michael Zhu
cd14a45414 Update sampler artifacts/wrappers 2020-06-11 12:47:54 -07:00
Michael Zhu
44262bf747 MultiBridge support in AssetSwapper 2020-06-11 11:14:48 -07:00
Xianny
0fbbabe208 Add Uniswap V2 support to @0x/asset-swapper (#2599)
* add uniswapV2

* update changelogs

* remove unused import

* add tests for Uniswap V2 ETH

* rename UniswapV2 and UniswapV2Eth

* use correct token address path

* update contract addresses after deploy
2020-06-11 10:23:50 -07:00
Lawrence Forman
b39189fde3 Merge pull request #2594 from 0xProject/feat/contracts-zero-ex/AffiliateFeeTransformer
Exchange Proxy: AffiliateFeeTransformer
2020-06-08 22:24:17 -04:00
Lawrence Forman
18fc1d78f4 @0x/contracts-zero-ex: Rebase 2020-06-08 21:34:09 -04:00
Lawrence Forman
d44a91d10b @0x/contracts-zero-ex: Address review feedback. 2020-06-08 21:33:27 -04:00
Lawrence Forman
5e9829b2d8 @0x/contracts-zero-ex: Add AffiliateFeeTransformer tests. 2020-06-08 21:33:27 -04:00
Lawrence Forman
2176deae36 @0x/contracts-zero-ex: Rebase 2020-06-08 21:33:27 -04:00
Lawrence Forman
7c5035aa39 @0x/contracts-zero-ex: Use array of structs in AffiliateFeeTransformer data. 2020-06-08 21:33:27 -04:00
Lawrence Forman
5707993995 @0x/contracts-zero-ex: Add AffiliateFeeTransformer. 2020-06-08 21:33:26 -04:00
Lawrence Forman
f81697527c Merge pull request #2592 from 0xProject/feat/zero-ex/transformer-deployer
Exchange Proxy: TransformerDeployer
2020-06-08 20:30:09 -04:00
Lawrence Forman
967eff4c58 Merge pull request #2597 from 0xProject/fix/zero-ex/transform-erc20-audit
Exchange Proxy: Address audit feedback (2)
2020-06-08 20:29:27 -04:00
Lawrence Forman
87ed0071c4 @0x/contracts-zero-ex: Make TransformerDeployer boring. 2020-06-08 15:30:56 -04:00
Lawrence Forman
0fed48630c @0x/contracts-zero-ex: Add TransformDeployer contract. 2020-06-08 15:30:56 -04:00
Lawrence Forman
7b3e7c98ac @0x/contracts-zero-ex: Add missing docstrings + fix compilation errors. 2020-06-08 15:28:27 -04:00
Lawrence Forman
09f44b0375 Update changelogs 2020-06-08 15:28:27 -04:00
Lawrence Forman
ebfa62637e @0x/contracts-zero-ex: Address audit feedback. 2020-06-08 15:28:27 -04:00
Lawrence Forman
cb2cc05cac @0x/contracts-erc20: Update LibERC20TokenV06 comments. 2020-06-08 15:28:27 -04:00
Lawrence Forman
f9c9131d81 @0x/contracts-utils: Update V06 contracts to get around 0.6.9 docstring errors 2020-06-08 15:28:27 -04:00
Lawrence Forman
1be9a1cbc7 @0x/utils: Update ZeroExRevertErrors. 2020-06-08 15:28:27 -04:00
F. Eugene Aumson
b7fda8ecf0 Merge pull request #2598 from 0xProject/fix/py-ci-mypy-0.780
Python: pin mypy to <= 0.770
2020-06-08 12:27:30 -04:00
F. Eugene Aumson
db16392821 Python: pin mypy to <= 0.770
See also https://github.com/python/mypy/issues/8953
2020-06-08 11:51:38 -04:00
Xianny
7127f541c3 UniswapV2Bridge (#2590)
* implement UniswapV2 Bridge

* More tests for UniswapV2Bridge

* cleanup and remove ERC20BridgeSampler changes

* enable multihop; address review comments

* solidity 0.6.9 doesnt allow devdoc for public storage vars

* codestyle improvements
2020-06-05 11:56:52 -07:00
Lawrence Forman
32793cc008 Merge pull request #2595 from 0xProject/feat/erc20-bridge-sampler/uniswapv2-tests
Add Uniswap V2 to ERC20BridgeSampler
2020-06-04 12:14:07 -04:00
xianny
fbaf55cb25 update @0x/contract-artifacts and @0x/contract-wrappers 2020-06-03 13:45:35 -07:00
xianny
b8d51fc4e8 rename contract to UniswapV2Router01
https://github.com/Uniswap/uniswap-v2-periphery/blob/master/contracts/UniswapV2Router01.sol
2020-06-03 12:08:08 -07:00
Lawrence Forman
0c6e05d220 Merge pull request #2576 from 0xProject/feat/contracts-zero-ex/0x-api-erc20-transformers
ZeroEx: ERC20 Transformers
2020-06-03 14:09:20 -04:00
Lawrence Forman
4066c17a0f @0x/contracts-erc20-bridge-sampler: Add UniswapV2. 2020-06-03 14:01:09 -04:00
Lawrence Forman
429f2bb8dd @0x/contracts-utils: Add UniswapV2 to DeploymentConstants. 2020-06-03 13:57:59 -04:00
Lawrence Forman
112f4fc4f0 @0x/contracts-zero-ex: Address review comments. 2020-06-02 22:01:22 -04:00
Lawrence Forman
ecfbd6280f @0x/contracts-zero-ex: Address review feedback. 2020-05-28 11:56:59 -04:00
Lawrence Forman
bf84409839 @0x/utils: Update InvalidTransformDataError. 2020-05-28 11:56:59 -04:00
Lawrence Forman
a7ce72cae0 @0x/contracts-zero-ex: Rebase against development 2020-05-28 11:56:59 -04:00
Lawrence Forman
28402ff7d8 @0x/contracts-zero-ex: Add self-destructing to transformers 2020-05-28 11:56:59 -04:00
Lawrence Forman
e1d213d1a3 @0x/utils: Add more transformer revert errors. 2020-05-28 11:56:59 -04:00
Lawrence Forman
c610dd96f5 @0x/contracts-zero-ex: Rebase, returning nonces in transform(). 2020-05-28 11:56:59 -04:00
Lawrence Forman
2ba3818b65 @0x/contracts-zero-ex: Introduce transformer contracts. 2020-05-28 11:56:59 -04:00
Lawrence Forman
0e1a5a375a @0x/contracts-test-utils: Add msg param to assertIntegerRoughlyEquals 2020-05-28 11:56:59 -04:00
Lawrence Forman
cfc3daeb65 @0x/utils: Add ERC20 transformer revert errors. 2020-05-28 11:56:59 -04:00
Lawrence Forman
6359f1950e @0x/contracts-zero-ex: Address review feedback. 2020-05-28 11:56:59 -04:00
Lawrence Forman
d2f581853d @x/utils: Address review feedback. 2020-05-28 11:56:59 -04:00
Lawrence Forman
030cb285da @0x/contracts-zero-ex: Use immutable owner in Puppet instead of Ownable. 2020-05-28 11:56:59 -04:00
Lawrence Forman
af45409959 @0x/contracts-zero-ex: Revamp TransformERC20. 2020-05-28 11:56:59 -04:00
Lawrence Forman
d9a9bc35e3 @0x/zero-ex: Rebase and use "slot" instead of "offset" language in storage buckets. 2020-05-28 11:56:59 -04:00
Lawrence Forman
c911c3352c @0x/contracts-zero-ex: Make TokenSpender's puppet contract a distinct contract type and rename getTokenSpenderPuppet() to getAllowanceTarget() 2020-05-28 11:56:58 -04:00
Lawrence Forman
654abbac25 @0x/contracts-zero-ex: Introduce the TransformERC20 feature. 2020-05-28 11:56:58 -04:00
Lawrence Forman
46d5f42c9d @0x/utils: Add new ZeroExRevertErrors revert types 2020-05-28 11:56:58 -04:00
Lawrence Forman
1509da1215 @0x/contracts-utils: Convert more 0.6 contracts 2020-05-28 11:56:58 -04:00
F. Eugene Aumson
98a99d96aa Merge pull request #2588 from 0xProject/feuGeneA-patch-4
asset-swapper: For RFQ, don't log error status code if there isn't one
2020-05-27 19:31:43 -04:00
F. Eugene Aumson
d62d81af17 Update quote_requestor.ts 2020-05-27 14:19:24 -04:00
Lawrence Forman
dba67eb927 asset-swapper: Increase timeout for tests. (#2587)
* `@0x/asset-swapper`: Increase timeout for tests.

* Update packages/asset-swapper/CHANGELOG.json

Co-authored-by: Kim Persson <kimpers@users.noreply.github.com>

Co-authored-by: Lawrence Forman <me@merklejerk.com>
Co-authored-by: Kim Persson <kimpers@users.noreply.github.com>
2020-05-27 09:51:20 -04:00
Lawrence Forman
548c30d6a0 ZeroEx: Audit Fixes (#2586)
* `@0x/utils`: Remove unused revert error.

* `@0x/contracts-zero-ex`: Address audit feedback.
2020-05-26 20:57:55 -04:00
F. Eugene Aumson
511cd90c44 Merge pull request #2585 from 0xProject/fix/asset-swapper/rfqt-error-status-logging
asset-s/QuoteRequestor: fix statusCode logging
2020-05-21 18:43:04 -04:00
F. Eugene Aumson
8fb2d8da88 asset-s/QuoteRequestor: fix statusCode logging 2020-05-21 16:37:37 -04:00
Lawrence Forman
2fce332ed7 ZeroEx: TransformERC20, TokenSpender (#2545)
* `@0x/contracts-utils`: Convert more 0.6 contracts

* `@0x/contracts-erc20`: Add solidity 0.6 contracts.

* `@0x/utils`: Add new `ZeroExRevertErrors` revert types

* `@0x/contracts-zero-ex`: Introduce the `TransformERC20` feature.

* `@0x/subproviders`: Update ganache-core.
`@0x/web3-wrapper`: Update ganache-core.

* `@0x/contracts-zero-ex`: Make `TokenSpender`'s puppet contract a distinct contract type and rename `getTokenSpenderPuppet()` to `getAllowanceTarget()`

* `@0x/zero-ex`: Rebase and use "slot" instead of "offset" language in storage buckets.

* `@0x/web3-wrapper`: Add `getAccountNonceAsync()` to `Web3Wrapper`

* `@0x/contracts-zero-ex`: Revamp TransformERC20.

* `@0x/contracts-zero-ex`: Remove `payable` from `IERC20Transformer.transform()` and disable hex capitalization linter rule because of prettier conflicts.

* `@0x/contracts-zero-ex`: Use `immutable` owner in `Puppet` instead of `Ownable`.

* `@x/utils`: Address review feedback.

* `@0x/contracts-zero-ex`: Address review feedback.

* `@0x/contracts-utils`: Address review feedback.

* `@0x/contracts-zero-ex`: Return deployment nonce in `transform()`.

* `@0x/contracts-zero-ex`: Finish returning deployment nonce in `transform()`.

* `@0x/contracts-zero-ex`: Fix doc-gen bug.

* `@0x/contracts-zero-ex`: Address review comments.

* `@0x/utils`: Add `NegativeTransformERC20OutputERror`

* `@0x/contracts-zero-ex`: Revert if the taker's output amount decreases.

Co-authored-by: Lawrence Forman <me@merklejerk.com>
2020-05-20 22:47:21 -04:00
Francesco Agosti
b23f1eb145 Merge pull request #2583 from 0xProject/feat/estimated-gas-token-refund
Expose fills object in asset-swapper quote orders
2020-05-20 14:56:49 -07:00
fragosti
f694072b5a Run prettier 2020-05-20 14:20:54 -07:00
fragosti
10de266e0f Remove unused variable SignedOrderWithFillableAmounts 2020-05-20 13:13:01 -07:00
fragosti
71811ed04f Remove unused variable 2020-05-20 12:53:58 -07:00
fragosti
e9638ef95e Add to changelog 2020-05-20 12:52:35 -07:00
fragosti
5226bb5596 Expose fills in asset-swapper quote 2020-05-20 12:50:15 -07:00
F. Eugene Aumson
d9e13d6b99 Merge pull request #2581 from 0xProject/fix/asset-swapper/rfqt-logging
asset-swapper: Improve logging for 0x API consumption
2020-05-11 19:13:07 -04:00
F. Eugene Aumson
dede076835 asset-s/QuoteRequestor: clarify axios error type
Addresses review comment https://github.com/0xProject/0x-monorepo/pull/2581#discussion_r423337773
2020-05-11 18:34:32 -04:00
F. Eugene Aumson
c929782e0d asset-swapper/RFQT: Log params sent to maker
* Include in RFQ-T info log entry the query parameters that were sent to
the maker.

* Re-organize log entry
    * Rename top-level field from rfqtMakerResponse to
    rfqtMakerInteraction.
    * Create separate `request` and `response` sub-objects.

* Rename field `latency` to `latencyMs`.
2020-05-11 18:01:06 -04:00
F. Eugene Aumson
a43c7e36f8 asset-swapper/RFQT: log maker response metadata 2020-05-11 17:40:19 -04:00
F. Eugene Aumson
b95cec9c32 asset-swapper: fix bug: RFQ-T info log was broken 2020-05-11 17:39:30 -04:00
F. Eugene Aumson
9a7d9abe3c asset-swapper: consolidate RFQ-T usage of Axios 2020-05-11 13:52:42 -04:00
F. Eugene Aumson
c77b620453 asset-swapper: Improve RFQ-T logging for 0x API
* Change QuoteRequestor logger parameters to conform to pino logging
library, duplicating (one of) their LogFunction prototype interfaces for
our purposes here.  With this, every log emission now includes BOTH a
human-readable message AND a JSON object.  Also, this pattern has been
applied to both the error logger and the info logger.

* Do better handling of Axios errors when logging them.  Before we were
(a) logging errors in a separate log entry than the message that
explains it, and (b) dumping the whole error object to the log entry,
which was resulting in an object so massive that pino/Kibana was
splitting it into 3 separate entries.  Now, we (a) follow the pattern
described in the previous bullet, which puts the error object and the
human readable message into the same log entry, and (b) we check to see
if an error object is Axios-specific, and if so then we use the
AxiosError.toJSON() method to strip out the irrelevant properties.

* Log a uniform maker response metric, with maker endpoint URL, status
code, and latency, for both successful cases and erroneous ones.
(Before, we were only doing this for successful cases.)
2020-05-11 13:38:37 -04:00
Lawrence Forman
b348084e2a @0x/zero-ex: Always offset storage bucket ID by 1. (#2579)
Co-authored-by: Lawrence Forman <me@merklejerk.com>
2020-05-08 20:13:45 -04:00
F. Eugene Aumson
ff1811ef90 Merge pull request #2574 from 0xProject/rfqt-follow-ups
asset-swapper: RFQ-T follow ups
2020-05-07 17:44:02 -04:00
F. Eugene Aumson
39cf4a7576 Ran prettier...on development code! wtf?
Maybe something weird happened in the merge conflict resolution? Though
I didn't see anything in particular.
2020-05-07 01:39:22 -04:00
F. Eugene Aumson
21b67625a6 Merge branch 'development' into rfqt-follow-ups 2020-05-07 01:07:41 -04:00
Jacob Evans
fb0311e675 feat: ERC20BridgeSampler Unlock Kyber collisions (#2575)
* feat: ERC20BridgeSampler Unlock Kyber collisions

* Updated fallback strategy

* Address comments

* Eth2Dai hop sampler

* Update packages/asset-swapper/src/utils/market_operation_utils/index.ts

Co-authored-by: Lawrence Forman <lawrence@0xproject.com>

* Set DFB expiry to 2hr

Co-authored-by: Lawrence Forman <lawrence@0xproject.com>
2020-05-07 07:56:03 +10:00
F. Eugene Aumson
8a14b4afff asset-swapper: clarify comment
This comment recently got moved from one context to another.  In the old
context, the whole comment made sense, but in the new context it needed
paring down.
2020-05-06 13:24:20 -04:00
F. Eugene Aumson
e42701599a asset-s/RFQT: log each maker resp. time, not agg.
Log each maker's individual response times, rather than logging them in
aggregate.

Addresses review comment https://github.com/0xProject/0x-monorepo/pull/2574#discussion_r419769846
2020-05-06 13:23:35 -04:00
F. Eugene Aumson
352b1b43f2 asset-s: restore type safety to rfqt.skipBuyReq's
Addresses review comment https://github.com/0xProject/0x-monorepo/pull/2574#discussion_r420465928
2020-05-06 13:16:23 -04:00
F. Eugene Aumson
2922ebd095 asset-s/test: stop unnecessarily priming mock
Addresses review comment 93bdaba8ee (r419774170)
2020-05-05 17:17:47 -04:00
F. Eugene Aumson
a9e72085dd asset-s: fix bug handling RFQ-T skipBuyRequest
Addresses review comment https://github.com/0xProject/0x-monorepo/pull/2574#discussion_r419772045
2020-05-05 17:17:47 -04:00
F. Eugene Aumson
ed3d194c90 asset-s: ignore case verifying RFQT taker address
Do case INsensitive comparison when verifying that RFQ-T firm quote
contains the requested taker address.

This commit also introduces some changes around the RfqtRequestOpts
parameter.  Without these changes, there were errors (tsc or tslint?
can't remember) about takerAddress being possibly undefined.

Rather than asserting it yet again (which we're already doing via
assertTakerAddressOrThrow()), I decided to change the RfqtRequestOpts
param to be required, not optional.  Coincidentally, this brings the
requestRfqtFirmQuotesAsync() interface into alignment with the
requestRfqtIndicativeQuotesAsync() one, which already requires the
options parameter.

Addresses review comment https://github.com/0xProject/0x-monorepo/pull/2574#discussion_r419770087
2020-05-05 17:17:46 -04:00
F. Eugene Aumson
125c53827b asset-s: check RFQ expiry more canonically
For firm quotes, re-use orderCalculationUtils.willOrderExpire(), just
like utils.order_prune_utils.

For indicative quotes, duplicate the logic used in that
willOrderExpire() function, since it can't be re-used for an indicative
quote (it's not a full Order object), and since the logic is very
minimal.

Addresses review comment https://github.com/0xProject/0x-monorepo/pull/2574#discussion_r419768395
2020-05-05 17:16:48 -04:00
F. Eugene Aumson
38781807cd asset-s: simplify test util usage 2020-05-05 12:53:31 -04:00
F. Eugene Aumson
c046943269 asset-s: fix bug: expiry is BigNumber, not string 2020-05-05 12:43:41 -04:00
Lawrence Forman
fe36cd86bb Merge pull request #2573 from 0xProject/fix/contracts-zero-ex/initial-migration-self-destruct
ZeroEx: InitialMigration Race Condition/Self-destruct
2020-04-30 15:02:16 -04:00
F. Eugene Aumson
401410089c asset-s/QuoteRequestor: info log Objects, not strs
In the QuoteRequestor class, when _infoLogger() is used, log objects
directly, rather than stringifying them first.  This changes the 0x API
log rendering from

{"level":"info","time":1588209135290,"pid":13022,"hostname":"precision5510","msg":"{\"aggregatedRfqtLatencyMs\":4}","v":1}

to

{"level":"info","time":1588224481908,"pid":3637,"hostname":"precision5510","aggregatedRfqtLatencyMs":2,"v":1}

This facilitates parsing of these logs by Kibana.
2020-04-30 01:32:06 -04:00
F. Eugene Aumson
fa23337519 asset-swapper: Ran prettier 2020-04-29 17:50:16 -04:00
F. Eugene Aumson
ae5421f76e asset-s: Use expiryBufferMs to filter RFQ-T quotes 2020-04-29 17:24:51 -04:00
F. Eugene Aumson
a2e2b429d5 asset-s: exclude RFQ-T orders w/ bad takerAddress 2020-04-29 17:24:42 -04:00
F. Eugene Aumson
ac852b23b3 asset-s: allow disabling of buy req's for RFQ-T 2020-04-29 17:23:16 -04:00
F. Eugene Aumson
e12389a002 asset-s: don't ignore default SwapQuoter RFQT opts 2020-04-29 17:23:16 -04:00
F. Eugene Aumson
da18e42d2a asset-s: Fix prettier command to match monorepo's 2020-04-29 17:23:15 -04:00
F. Eugene Aumson
93bdaba8ee asset-s: skip RFQT makers not supporting reqd pair
Skip querying an RFQ-T maker for a quote when the requested asset pair
isn't supported by that maker.
2020-04-29 17:23:10 -04:00
F. Eugene Aumson
4cb08a61d5 asset-s: RFQT info logger; log maker response time 2020-04-29 17:22:59 -04:00
Lawrence Forman
133692ca92 @0x/contract-wrappers-test: Increase test timeout for CI 2020-04-29 17:11:00 -04:00
F. Eugene Aumson
4bcc4b3cf8 asset-s: relay expiration time in indicative quote 2020-04-29 15:45:35 -04:00
F. Eugene Aumson
4eb20ca4b6 asset-s/QuoteRequestor: use constructor assignment 2020-04-29 15:45:35 -04:00
Lawrence Forman
69f7343be5 @0x/contracts-zero-ex: Lock the caller of InitialMigration.deploy() and actually self-destruct. 2020-04-29 14:26:55 -04:00
F. Eugene Aumson
19b28a58d6 Merge pull request #2544 from 0xProject/fix/pyfail-dupe-docstrings
Python: unpin Sphinx dependency, clean up warnings
2020-04-29 13:53:18 -04:00
Lawrence Forman
3c33a93b9c Merge pull request #2572 from 0xProject/feat/contracts-zero-ex/syntactic-sugar-1
ZeroEx: Switch rich revert style.
2020-04-29 13:52:39 -04:00
Lawrence Forman
f2e16dfb21 @0x/contracts-zero-ex: Switch rich revert style.
`@0x/contracts-zero-ex`: Merge `FixinOwnable` -> `FixinCommon`.
2020-04-29 13:01:19 -04:00
F. Eugene Aumson
0f689e8051 Merge pull request #2571 from 0xProject/fix/pylint-upgrade
Python: adapt to latest version of pylint
2020-04-29 12:15:31 -04:00
F. Eugene Aumson
5b44e6ef64 Python: adapt to latest version of pylint 2020-04-29 10:10:18 -04:00
Lawrence Forman
49e4ade66f Merge pull request #2570 from 0xProject/fix/redeploy-sampler-on-kovan
`@0x/contract-addresses`: Redeploy sampler on kovan
2020-04-28 17:33:02 -04:00
Lawrence Forman
3bae27d039 @0x/contract-addresses: Redeploy sampler on kovan 2020-04-28 15:05:51 -04:00
Lawrence Forman
a77f0c606d Merge pull request #2569 from 0xProject/feat/contracts-zero-ex/iownable-compat
ZeroEx: IOwnable(V06) compatibility
2020-04-28 14:29:33 -04:00
Lawrence Forman
f1de64dcaf @0x/contracts-zero-ex: Make Ownable feature conform to IOwnable. 2020-04-28 12:16:30 -04:00
Lawrence Forman
feb672c3cd @0x/contracts-utils: Make IOwnableV06 conform to IOwnable. 2020-04-28 12:16:11 -04:00
mzhu25
a90b463a7d Merge pull request #2567 from 0xProject/fix/instanceof-array-isArray
instanceof Array -> Array.isArray
2020-04-28 01:03:02 -07:00
Jacob Evans
5f5f25c978 fix: contract-addresses ERC20BridgeSampler (#2568)
* fix: contract-addresses ERC20BridgeSampler

* CHANGELOG
2020-04-28 17:48:32 +10:00
Michael Zhu
351ea8bc1c instanceof Array -> Array.isArray 2020-04-27 18:28:56 -07:00
Jacob Evans
b34edcbf87 [asset-swapper] clip native fill data (#2565)
* [asset-swapper] clip native fill data

* Test for createFillPaths

* CHANGELOG
2020-04-25 08:44:48 +10:00
Alex Towle
160519e1fe Merge pull request #2566 from 0xProject/fix/dangling-promises-asset-swapper
[asset-swapper] Fixed dangling promises
2020-04-24 16:53:30 -05:00
Alex Towle
44d626e12e Changed style 2020-04-24 13:31:47 -05:00
Alex Towle
efb9dc51c9 Fix linting error 2020-04-24 13:07:15 -05:00
Alex Towle
deb51434fd Fixed dangling promises 2020-04-24 12:44:05 -05:00
Lawrence Forman
501070bfb0 Merge pull request #2564 from 0xProject/feat/contracts-zero-ex/consolidate-bootstrap-features
ZeroEx: Merge Migrate and Ownable Features
2020-04-24 01:43:04 -04:00
Lawrence Forman
712958d8c8 @0x/asset-swapper: Fix sporadically failing quote simulation tests. 2020-04-24 01:07:16 -04:00
Lawrence Forman
4d8d944fe5 @0x/contracts-utils: Update package.json 2020-04-24 01:06:44 -04:00
Lawrence Forman
0042e42160 @0x/contracts-zero-ex: Merge Migrate into Ownable 2020-04-24 01:06:44 -04:00
Lawrence Forman
85509ea251 @0x/utils: ZeroExRevertErrors.Migrate -> ZeroExRevertErrors.Ownable 2020-04-24 01:06:44 -04:00
Jacob Evans
6063854d06 Add Curve sUSD (#2563) 2020-04-24 07:06:36 +10:00
F. Eugene Aumson
456f8a90b1 Merge pull request #2562 from 0xProject/feature/rfqt-warning-logger
asset-swapper: support RFQ-T logger callback
2020-04-23 01:48:43 -04:00
F. Eugene Aumson
980246d07a asset-swapper: use lambda not .bind() 2020-04-23 01:11:15 -04:00
F. Eugene Aumson
141c30b173 asset-swapper: remove debug logging 2020-04-23 01:08:26 -04:00
F. Eugene Aumson
22f9b03fce asset-swapper: Remove superfluous conditional 2020-04-23 01:07:57 -04:00
Lawrence Forman
be2db504b9 Merge pull request #2561 from 0xProject/feat/contracts-zero-ex/unused-storage-id
ZeroEx: Add `Unused` to `StorageId` enum
2020-04-23 00:23:35 -04:00
Jacob Evans
cac6f5234f Collapse on-chain sources into DexForwarderBridge (#2560)
* Collapse on-chain sources into DexForwarderBridge

* Fix tests. CHANGELOG
2020-04-23 13:12:46 +10:00
F. Eugene Aumson
eb6b32b6ee asset-swapper: support RFQ-T logger callback
For use in integrations that have specific log formats to adhere to.
2020-04-22 20:59:17 -04:00
F. Eugene Aumson
07acc9529e Merge pull request #2555 from 0xProject/rfq-t-indicative
asset-swapper: RFQ-T indicative quotes
2020-04-22 16:34:02 -04:00
Lawrence Forman
f7f0152573 @0x/contracts-zero-ex: Add Unused to StorageId enum 2020-04-22 16:06:49 -04:00
F. Eugene Aumson
153533f1d5 Fix bug in prior revision: wrong asset data
I tried to get fancy back in 5effc6ec90.
I changed something more than the single refactor targetted by the
commit, and it broke things!  This reverts part of that commit,
restoring clean runs of 0x API tests.
2020-04-22 11:58:09 -04:00
F. Eugene Aumson
11622c586a asset-s: Add RfqtRequestOpts.isIndicative 2020-04-22 11:58:09 -04:00
Lawrence Forman
7396bb508a Merge pull request #2540 from 0xProject/feat/contracts/zero-ex
ZeroEx: Universal proxy
2020-04-21 23:37:35 -04:00
Lawrence Forman
7df6530f3a @0x/contracrts-zero-ex: Address more review comments. 2020-04-21 22:29:46 -04:00
Lawrence Forman
80787456fa @0x/contracts-zero-ex: Fix comments. 2020-04-21 22:29:46 -04:00
Lawrence Forman
4446ac1ca3 @0x/contracts-zero-ex: Use (scaled) enums for storage IDs 2020-04-21 22:29:46 -04:00
Lawrence Forman
220039ab00 @0x/contracts-zero-ex: Allow any call target to bootstrap(). 2020-04-21 22:29:46 -04:00
Lawrence Forman
12f2250ab5 @0x/contracts-zero-ex: bootstrap() is now a temporary feature, registered in the ZeroEx constructor.
`@0x/contracts-zero-ex`: `bootstrap()` de-registers itself and self-destructs once it's called.
`@0x/contracts-zero-ex`: `bootstrap()` now takes arbitrary call data, but the callee is fixed in an immutable.
`@0x/contracts-zero-ex`: `bootstrap()` caller is fixed in an immutable.
`@0x/contracts-zero-ex`: `bootstrap()` only calls a single target.
`@0x/contracts-zero-ex`: Renamed `BasicMigration` to `InitialMigration`.
`@0x/contracts-zero-ex`: `InitialMigration` is now the bootstrap target and multiplexes to the initial features.
`@0x/contracts-zero-ex`: Add `Migrate` feature and tests.
`@0x/contracts-zero-ex`: Re-organize contract locatins (remove `interfaces` folder).
2020-04-21 22:29:46 -04:00
Lawrence Forman
0c33aa16a1 @0x/utils: Add more ZeroEx rich reverts.
`@0x/utils: Display revert error payload in stack traces.
2020-04-21 22:29:46 -04:00
Lawrence Forman
72908b02fe @0x/contracts-zero-ex: Address review feedback.
`@0x/contracts-zero-ex`: Add target implementation address to `rollback()`.
`@0x/contracts-zero-ex`: Add storage ID uniqueness test.
`@0x/contracts-zero-ex`: Add rollback history querying functions to `SimpleFunctionRegistry`.
2020-04-21 22:29:46 -04:00
Lawrence Forman
223aa04424 @0x/utils: Change SimpleFunctionRegistry NoRollbackHistoryError to NotInRollbackHistoryError. 2020-04-21 22:29:46 -04:00
Lawrence Forman
e53248cca6 @0x/sol-compiler: Address review feedback. 2020-04-21 22:29:46 -04:00
Lawrence Forman
c11d661b39 @0x/contracts-zero-ex`: Create ZeroEx (proxy) contracts 2020-04-21 22:29:46 -04:00
Lawrence Forman
4212a08337 @0x/contracts-utils: Add solidity 0.6 contracts 2020-04-21 22:29:46 -04:00
Lawrence Forman
c0553fa9eb Add @0x/contracts-zero-ex project to monorepo.
Tweak circleci config to avoid running out of memory.
2020-04-21 22:29:46 -04:00
Lawrence Forman
7f26fafed7 @0x/utils: ZeroExRevertErrors. 2020-04-21 22:29:46 -04:00
Lawrence Forman
3e9309c003 @0x/sol-compiler: Strip receive functions from 0.6 ABI output 2020-04-21 22:29:46 -04:00
Lawrence Forman
1017707475 ethereum-types: Update MethodAbi definition for solidity 0.6 2020-04-21 22:29:46 -04:00
F. Eugene Aumson
e8ff5da209 asset-swapper: update CHANGELOG 2020-04-21 01:49:28 -04:00
F. Eugene Aumson
03ed3ac1b0 Merge branch 'development' into rfq-t-indicative 2020-04-21 00:50:50 -04:00
F. Eugene Aumson
2c97208e74 asset-s: simplify type with ?, not |undefined
Addresses review comment https://github.com/0xProject/0x-monorepo/pull/2555#discussion_r411081841
2020-04-21 00:49:30 -04:00
Jacob Evans
a458e81f8d ERC20BridgeSampler: Additional Buy support (#2551)
* ERC20BridgeSampler: Sample Curve Buy

* Fake Buy Kyber/PLP

* Deploy mainnet

* Add Kyber rates for buy tests

* CHANGELOGs

* Provide maxIterations and targetSlippage as options

* Cleanup ERC20BridgeSampler for re-use

* Redeploy Mainnet Kovan

* Feedback fixes

* Handle OOG/revert 0s

* Redeploy Mainnet refactor
2020-04-21 13:26:12 +10:00
F. Eugene Aumson
83289bc801 asset-s: consider falsey takerAddress as absent
Addresses review comment https://github.com/0xProject/0x-monorepo/pull/2555#discussion_r411543876
2020-04-20 22:56:44 -04:00
F. Eugene Aumson
ba2ac6a7b5 asset-s: Clarify indicative quote enablement
Addresses review comment https://github.com/0xProject/0x-monorepo/pull/2555#discussion_r411498729
2020-04-20 22:56:44 -04:00
F. Eugene Aumson
245b6da577 asset-s: Require RfqtRequestOpts.intentOnFilling
Addresses review comment https://github.com/0xProject/0x-monorepo/pull/2555#discussion_r411083497
2020-04-20 22:56:44 -04:00
F. Eugene Aumson
8875f924b0 asset-s: test requestRfqtIndicativeQuotesAsync 2020-04-20 22:56:44 -04:00
F. Eugene Aumson
ad7868ebe1 asset-s: clean up order faking for indicative RFQT
Addresses review comment https://github.com/0xProject/0x-monorepo/pull/2555#discussion_r411545804
2020-04-20 22:56:44 -04:00
F. Eugene Aumson
5effc6ec90 asset-swapper: extract method
Addresses review comment https://github.com/0xProject/0x-monorepo/pull/2555#discussion_r411514718
2020-04-20 22:56:43 -04:00
F. Eugene Aumson
4cc9ceabd2 asset-swapper: Rm unused ERC20BridgeSource.Rfqt
Addresses review comment https://github.com/0xProject/0x-monorepo/pull/2555#discussion_r410517580
2020-04-20 22:56:43 -04:00
F. Eugene Aumson
464c918134 asset-swapper: test RFQT indicative quote handling 2020-04-20 22:56:43 -04:00
F. Eugene Aumson
2456adcb68 asset-swapper: validate RFQT indicative quotes
Validate that the responses returned from maker endpoints both conform
to expected JSON schema data types and also have the expected asset
data, per the taker's request.
2020-04-20 22:56:43 -04:00
F. Eugene Aumson
45bc967f30 asset-swapper: Differentiate RFQT warning messages 2020-04-17 02:34:36 -04:00
F. Eugene Aumson
d6d4d29257 asset-swapper: RFQ-T indicative quotes
These changes have been exercised via mocha tests in the 0x-api repo.

Not sure why I had to add GetMarketOrdersRfqtOpts to the package
exports.  `yarn test:generate_docs:circleci` said:

$ node ./packages/monorepo-scripts/lib/doc_generate.js --package @0x/asset-swapper
GENERATE_DOCS: Generating Typedoc JSON for @0x/asset-swapper...
GENERATE_DOCS: Generating Typedoc Markdown for @0x/asset-swapper...
GENERATE_DOCS: Modifying Markdown To Exclude Unexported Items...
Error: @0x/asset-swapper package needs to export:
GetMarketOrdersRfqtOpts
From it's index.ts. If any are from external dependencies, then add them to the EXTERNAL_TYPE_MAP.
    at DocGenerateUtils._lookForMissingReferenceExportsThrowIfExists (/root/repo/packages/monorepo-scripts/lib/utils/doc_generate_utils.js:288:19)
    at DocGenerateUtils.<anonymous> (/root/repo/packages/monorepo-scripts/lib/utils/doc_generate_utils.js:255:34)
    at step (/root/repo/packages/monorepo-scripts/lib/utils/doc_generate_utils.js:32:23)
    at Object.next (/root/repo/packages/monorepo-scripts/lib/utils/doc_generate_utils.js:13:53)
    at fulfilled (/root/repo/packages/monorepo-scripts/lib/utils/doc_generate_utils.js:4:58)
    at <anonymous>
    at process._tickCallback (internal/process/next_tick.js:189:7)
2020-04-17 02:34:36 -04:00
F. Eugene Aumson
33fdfdc8c0 asset-swapper: Extract method inferQueryParams
For use in upcoming implementation of indicative quotes.
2020-04-17 01:18:46 -04:00
F. Eugene Aumson
80c8712b2a asset-swapper: Rm unused field in SwapQuoterOpts 2020-04-17 01:18:28 -04:00
F. Eugene Aumson
957e3eb93c asset-swapper: Restructure RFQ-T request options
There's one subtlety here: apiKey has been moved to be within the rfqt
namespace, after talking to Fabio and discovering that he only needs to
re-use the API key in 0x API, not in asset-swapper.
2020-04-17 01:18:07 -04:00
F. Eugene Aumson
110e1afa8e Merge pull request #2541 from 0xProject/rfq-t
asset-swapper: RFQ-T firm quotes
2020-04-15 15:24:48 -04:00
F. Eugene Aumson
1da8f68871 migrations: Add independent yarn prettier script 2020-04-15 14:17:03 -04:00
F. Eugene Aumson
513ddb4cca Merge branch 'development' into rfq-t 2020-04-15 11:12:30 -04:00
F. Eugene Aumson
3bdfcb8542 Update {asset-s,migrat,contract-ad}* CHANGELOGs 2020-04-15 01:47:13 -04:00
F. Eugene Aumson
aee758eca2 Fix bug: Stop ignoring default SwapQuoteRequestOps
SwapQuoter._getSwapQuoteAsync() was merging defaults into the options
sent into SwapQuoteCalculator.calculateMarket{Buy,Sell}SwapQuoteAsync(),
but it was using the unmerged options function parameter for the RFQ-T
options and also for the gas price option.
2020-04-15 01:47:01 -04:00
Steve Klebanoff
47ef7fffce RFQ-T: validate assetData & add more tests (#2552)
* test for returning a 200 with invalid data, and additonal logging for that case

* Ensure RFQ-T response has asset data we expect

* validate signed order schema

* give more descriptive variable names and test an unsigned order

* takeout unused var
2020-04-15 00:11:37 -04:00
F. Eugene Aumson
58d6256607 Bug fix: RFQ-T orders werent going through sorting 2020-04-13 12:53:08 -04:00
F. Eugene Aumson
b854fcdb72 Remove an unnecessary type annotation 2020-04-13 12:53:08 -04:00
F. Eugene Aumson
27ca75d94f Clarify parallelization of orderbook & RFQT
Addresses review comment https://github.com/0xProject/0x-monorepo/pull/2541#discussion_r406955099
2020-04-13 12:53:08 -04:00
F. Eugene Aumson
bb15f78af0 Validate maker endpoint responses with JSON Schema
Addresses review comment https://github.com/0xProject/0x-monorepo/pull/2541#discussion_r406957115
2020-04-13 12:53:08 -04:00
F. Eugene Aumson
ccc9e18132 Type Axios response with undefined, not void
Addresses review comment https://github.com/0xProject/0x-monorepo/pull/2541#discussion_r406956436
2020-04-13 12:53:08 -04:00
F. Eugene Aumson
d55108ab60 Eliminate unnecessary else
Addresses review comment https://github.com/0xProject/0x-monorepo/pull/2541#discussion_r405906319
2020-04-13 12:53:07 -04:00
Steve Klebanoff
84adbcb683 asset-swapper: Mockable axios for QuoteRequestor (#2549)
* Mockable axios for QuoteRequestor

* Move RFQT Mocker to src

* move MockedRfqtFirmQuoteResponse into types file

* fix import
2020-04-10 23:09:56 -04:00
F. Eugene Aumson
0cb5e4553b Await Axios response so we don't circumvent catch
Addresses review comment https://github.com/0xProject/0x-monorepo/pull/2541#discussion_r406604110
2020-04-10 15:34:06 -04:00
F. Eugene Aumson
264407b707 In Opts types, REQUIRE rfqt SUB-options
Addresses review comment https://github.com/0xProject/0x-monorepo/pull/2541#discussion_r406505994
2020-04-09 21:58:22 -04:00
F. Eugene Aumson
eb5ec58453 Add yarn prettier script, & call it from lint 2020-04-09 21:58:22 -04:00
F. Eugene Aumson
39c2a757be Promote a closure to a function
Addresses review comment https://github.com/0xProject/0x-monorepo/pull/2541#discussion_r405953107
2020-04-09 18:39:46 -04:00
F. Eugene Aumson
8cdc05f582 Promote max maker response time to a global option 2020-04-09 17:21:36 -04:00
F. Eugene Aumson
5f4778c852 Don't throw when RFQ-T client isn't whitelisted
Addresses review comments
https://github.com/0xProject/0x-monorepo/pull/2541#discussion_r405964457
and
https://github.com/0xProject/0x-monorepo/pull/2541#discussion_r406040453
2020-04-09 17:21:35 -04:00
F. Eugene Aumson
70add44fc1 Push RFQ-T opts to SwapQuoterReqOpts subnamespace
Addresses review comment https://github.com/0xProject/0x-monorepo/pull/2541#discussion_r405969509
2020-04-09 17:21:35 -04:00
F. Eugene Aumson
fa617d2e9d Demote public member to private
Addresses review comment https://github.com/0xProject/0x-monorepo/pull/2541#discussion_r405963834
2020-04-09 17:21:35 -04:00
F. Eugene Aumson
3c795d365d Demote instance member to just constructor a arg
Addresses review comment https://github.com/0xProject/0x-monorepo/pull/2541#discussion_r405963779
2020-04-09 17:21:35 -04:00
F. Eugene Aumson
93872ad7a3 Push RFQ-T opts to own SwapQuoterOpts subnamespace
Addresses review comment https://github.com/0xProject/0x-monorepo/pull/2541#discussion_r405963240
2020-04-09 17:21:35 -04:00
F. Eugene Aumson
227676c150 Remove unused intentOnFilling method parameter
Addresses review comments
https://github.com/0xProject/0x-monorepo/pull/2541#discussion_r405952889
and
https://github.com/0xProject/0x-monorepo/pull/2541#discussion_r406048104
2020-04-09 17:21:35 -04:00
F. Eugene Aumson
5f23833b43 rm unused SwapQuoteRequestOpts key enableRfqt
Addresses review comment https://github.com/0xProject/0x-monorepo/pull/2541#discussion_r406043111
2020-04-09 17:21:35 -04:00
F. Eugene Aumson
121d51b414 Use try...catch instead of Promise.catch()
Addresses review comments
https://github.com/0xProject/0x-monorepo/pull/2541#discussion_r405953735
and
https://github.com/0xProject/0x-monorepo/pull/2541#discussion_r405966703
2020-04-09 17:21:34 -04:00
Jacob Evans
0e196a59d9 Always use DFB in asset-swapper (#2542)
* Always use DFB in asset-swapper

* Clean up
2020-04-09 15:52:15 +10:00
F. Eugene Aumson
63bfd23310 Pass QuoteRequestor via SwapQuoteOpts not ctor arg
Addresses review comment https://github.com/0xProject/0x-monorepo/pull/2541#discussion_r405900525
2020-04-09 00:29:58 -04:00
F. Eugene Aumson
aadcf8fed0 Parallelize RFQ-T with orderbook query
Addresses review comment https://github.com/0xProject/0x-monorepo/pull/2541#discussion_r405905572
2020-04-09 00:29:57 -04:00
F. Eugene Aumson
37390e03b4 Use Array.push instead of Array.concat
Addresses review comment https://github.com/0xProject/0x-monorepo/pull/2541#discussion_r405905052
2020-04-09 00:09:10 -04:00
F. Eugene Aumson
98fc780ade Use map idiom instead of for loop
Addresses review comment https://github.com/0xProject/0x-monorepo/pull/2541#discussion_r405904035
2020-04-08 23:14:06 -04:00
F. Eugene Aumson
1670b21123 Use NULL_ADDRESS instead of literal
Addresses review comment https://github.com/0xProject/0x-monorepo/pull/2541#discussion_r405901406
2020-04-08 22:56:11 -04:00
F. Eugene Aumson
5602aacbd2 mk SwapQuoterOpt rfqtTakerApiKeyWhitelist optional
Addresses review comment https://github.com/0xProject/0x-monorepo/pull/2541#discussion_r405749147
2020-04-08 22:48:21 -04:00
F. Eugene Aumson
6ddbea207f Stop using 3rd party sphinx typehints plugin
Because sphinx itself supports typehints now, and a recent update to
plugin caused it to start spewing massive amounts of warnings.
2020-04-08 14:09:50 -04:00
F. Eugene Aumson
261bced822 Fix redundant docstrings and unpin sphinx
The latest version of Sphinx (documentation generation utility) was
giving a warning (which we were configured to treat as an error) about
there being multiple docstring definitions for the same class.  This had
never been flagged before.
2020-04-08 14:09:49 -04:00
Lawrence Forman
a80d1f861c Merge pull request #2536 from 0xProject/feat/asset-swapper/DexForwarderBridge-support
asset-swapper: DFB support + refactors
2020-04-07 14:35:01 -04:00
Lawrence Forman
c541340ef5 Update CHANGELOG.json
`@0x/contract-addresses`: Redeploy `DexForwarderBridge` on Mainnet with Gas Token freeing
`@0x/contract-addresses`: Revert to older Curve Bridge (without Gas Tokens)
2020-04-07 13:41:37 -04:00
Lawrence Forman
434af0ae64 @0x/contracts-asset-proxy: Update CHANGELOG 2020-04-07 13:38:35 -04:00
Jacob Evans
c6379ca1d4 Update DexForwarderBridge address 2020-04-07 12:35:18 -04:00
Jacob Evans
cdbcada49b Authorize sender adddress 2020-04-07 12:35:18 -04:00
Jacob Evans
282930cb9b Add GST support to DFB 2020-04-07 12:35:18 -04:00
Lawrence Forman
b09c751942 @0x/asset-swapper: Remove deprecated swap_quote_calculator tests 2020-04-07 12:35:18 -04:00
Lawrence Forman
b2047b90b3 @0x/asset-proxy: Fix failing test. 2020-04-07 12:35:18 -04:00
Lawrence Forman
0c8aec30bd @0x/asset-swapper: Fix linter lies. 2020-04-07 12:35:18 -04:00
Lawrence Forman
fafaa3e69b @0x/asset-swapper: Lint and remove @0x/contracts-asset-proxy dep. 2020-04-07 12:35:18 -04:00
Lawrence Forman
d19bb3de8d @0x/asset-swapper: Run prettier 2020-04-07 12:35:18 -04:00
Lawrence Forman
481136166c @0x/asset-swapper: Remove unused Order export from index.ts. 2020-04-07 12:35:18 -04:00
Lawrence Forman
4df81a0b9e @0x/asset-swapper: add quote fill simulation tests 2020-04-07 12:35:18 -04:00
Lawrence Forman
da1e9c2d97 @0x/asset-swapper: Add DFB support + refactor swap quote calculation utils 2020-04-07 12:35:18 -04:00
F. Eugene Aumson
4b5a02c246 asset-swapper, migrations: incl. prettier in lint 2020-04-07 01:41:47 -04:00
F. Eugene Aumson
0e1572cfd7 migrations: add yarn publish:private 2020-04-07 01:41:47 -04:00
F. Eugene Aumson
343caa1ff6 migrations: Deploy ERC20BridgeSampler 2020-04-07 01:41:47 -04:00
F. Eugene Aumson
403fb3826d asset-swapper: support firm RFQ-T quote requests 2020-04-07 01:41:47 -04:00
F. Eugene Aumson
3cdccb7b4e prep asset-swapper: rename variable 2020-04-07 00:48:25 -04:00
F. Eugene Aumson
d9be78cdb4 py/contract_wrappers: Pin sphinx to prev version (#2539) 2020-04-07 00:47:45 -04:00
F. Eugene Aumson
16dc8255e1 Pin pytests to ganache snapshot 6.0.0 (#2535) 2020-04-06 20:01:54 -04:00
Lawrence Forman
2086bfff25 Merge pull request #2532 from 0xProject/feat/sol-compiler/support-0.6
sol-compiler: 0.6 support
2020-04-01 15:07:18 -04:00
Lawrence Forman
b9a68c0b8e @0x/sol-compiler: Address review feedback. 2020-04-01 14:30:17 -04:00
Lawrence Forman
74647f0e88 @0x/sol-compiler: remove fs.promises usage 2020-04-01 13:42:48 -04:00
Lawrence Forman
6e29c8bea9 @0x/sol-compiler: Make source paths in output artifacts nicer if they're within modules.
`@0x/sol-compiler`: Makea Add v0.6 solidity test.
2020-04-01 13:42:48 -04:00
Lawrence Forman
b36373ab81 @0x/sol-compiler: Insert compiler version in input artifacts. 2020-04-01 13:42:48 -04:00
Lawrence Forman
dc437aacf1 @0x/sol-compiler`: Refactor + add solidity 0.6 support 2020-04-01 13:42:48 -04:00
Lawrence Forman
e19dae9b28 @0x/typescript-typings: Add version() to SolcInstance 2020-04-01 13:42:48 -04:00
Jacob Evans
424cbd4831 Forwarder Market sell specified amount or throw (#2521)
* Forwarder Market sell specified amount or throw

* Address feedback comments

* Break if we have only protocol fee remaining

* Lint

* Update deployed addresses

* Updated artifacts and wrappers

* [asset-swapper] Forwarder throws on market sell if amount not sold (#2534)
2020-03-31 16:25:34 +10:00
Lawrence Forman
350feed993 Merge pull request #2531 from 0xProject/feat/erc20-bridge-sampler/dev-utils-as-param
ERC20BridgeSampler: Pass in `DevUtils` address as a constructor arg
2020-03-30 18:02:33 -04:00
Jacob Evans
7ca4aa0ff4 [asset-swapper] Fix getBatchMarketBuyOrdersAsync (#2533) 2020-03-31 04:21:03 +10:00
Lawrence Forman
bf00e67245 Merge pull request #2525 from 0xProject/feat/bridge/DexForwarderBridge
DexForwarderBridge
2020-03-27 17:44:47 -04:00
Lawrence Forman
c5a6e49681 update ganache forwarder address 2020-03-27 16:50:11 -04:00
Lawrence Forman
a509af2875 @0x/contract-addresses: Add dexForwarderBridge address.
`@0x/migrations`: Add `dexForwarderBridge` address field.
2020-03-27 16:40:46 -04:00
Lawrence Forman
1f789bf396 @0x/contracts-asset-proxy: Add DexForwarderBridge.executeBridgeCall() test. 2020-03-27 16:39:57 -04:00
Lawrence Forman
0ccbc7d3d2 @0x/contracts-asset-proxy: Fix typos and remove BridgeTransferFromCallFailed event from DexForwarderBridge. 2020-03-27 16:39:57 -04:00
Lawrence Forman
f3c6f26f85 @0x/contracts-asset-proxy: Fix typo in DFB tests. 2020-03-27 16:39:57 -04:00
Lawrence Forman
338c358df2 @0x/contracts-asset-proxy: Address review comments. 2020-03-27 16:39:57 -04:00
Lawrence Forman
4bdaa48303 @0x/contracts-asset-proxy: Create DexForwarderBridge bridge contract. 2020-03-27 16:39:57 -04:00
Lawrence Forman
36267746da @0x/contracts-erc20-bridge-sampler: Cache DevUtils address in getOrderFillableTakerAssetAmounts. 2020-03-26 12:11:14 -04:00
Lawrence Forman
7775541eed @0x/contracts-integrations: Update ERC20BridgeSampler tests 2020-03-26 12:09:14 -04:00
Lawrence Forman
5029be4c83 @0x/contracts-erc20-bridge-sampler: Pass in DevUtils address as a constructor parameter 2020-03-26 11:58:25 -04:00
Jacob Evans
277dbacf68 Set GSTCollector address and deploy Curve (#2530)
* Set GSTCollector address and deploy Curve

* CHANGELOGs
2020-03-26 18:26:16 +10:00
Lawrence Forman
0fdfb03f3c Merge pull request #2529 from 0xProject/fix/contract-addresses/fix-dydx-bridge-mainnet-address
Fix DydxBridge addresses.
2020-03-25 23:30:00 -04:00
Lawrence Forman
17d81bf014 @0x/contract-addresses: Fix DydxBridge mainnet/kovan address.
`@0x/contract-addresses`: Lowercase GodsUnchained/broker addresses.
2020-03-25 22:40:18 -04:00
Jacob Evans
568e9be07e Gas Tokens in Bridges (#2523)
* Gas Tokens in Bridges

* Added freesGasTokensFromCollector.

To handle the case where GST2 is being traded and the balanceOf checks become confusing

* Update CHANGELOGs
2020-03-26 11:58:28 +10:00
Lawrence Forman
99b0a95f8a Merge pull request #2526 from 0xProject/fix/asset-swapper/optimizer-fee-bugs
AssetSwapper: Fix quote optimizer fee bug
2020-03-24 09:56:09 -04:00
Lawrence Forman
0fdd31892a @0x/asset-swapper: Fix quote optimizer bug not properly accounting for fees. 2020-03-20 15:59:48 -04:00
Lawrence Forman
7a682604f9 Merge pull request #2524 from 0xProject/feat/erc20-bridge/less-ambiguous-transfer-event-args
Rename `ERC20BridgeTransfer` event args
2020-03-13 23:04:57 -04:00
Lawrence Forman
ce96e35d7d @0x/contracts-asset-proxy: Rename ERC20BridgeTransfer event args to be less ambiguous. 2020-03-13 21:00:35 -04:00
Xianny
b7fb5394a7 add gitpkg to contract-wrappers (#2520) 2020-03-13 10:10:32 -07:00
Lawrence Forman
aaa62beca7 Merge pull request #2522 from 0xProject/fix/asset-swapper/fee-schedule
`@0x/asset-swapper`: Fix fee schedule not being scaled by gas price.
2020-03-13 01:14:23 -04:00
Lawrence Forman
2b58a7242b @0x/asset-swapper: Fix changelog. 2020-03-13 00:40:19 -04:00
Lawrence Forman
5ed919df79 @0x/asset-swapper: Fix fee schedule not being scaled by gas price. 2020-03-13 00:10:04 -04:00
Lawrence Forman
baf6372179 Merge pull request #2513 from 0xProject/feat/asset-swapper/death-to-reverts
Asset-swapper: Fallback orders + refactors
2020-03-12 18:45:27 -04:00
Lawrence Forman
1a9063a55b @0x/asset-swapper: Address review comments. 2020-03-11 12:24:32 -04:00
Lawrence Forman
87999f402f @0x/asset-swapper: Sort native path fills by ADJUSTED rate. 2020-03-11 01:17:23 -04:00
Lawrence Forman
109d466260 @0x/asset-swapper: Fix double bridgeSlippage on generated orders. 2020-03-10 23:02:41 -04:00
Lawrence Forman
37597eca75 @0x/asset-swapper: Fix getPathSize() and getAdjustedPathSize() bug.
`@0x/asset-swapper`: Add `maxFallbackSlippage` option.
2020-03-10 14:25:13 -04:00
Lawrence Forman
5fd767b739 @0x/instant: Fix changelog. 2020-03-10 13:25:39 -04:00
Lawrence Forman
0e7a473116 @0x/asset-swapper: Clean up source breakdown code a bit.
`@0x/asset-swapper`: Allow Kyber conflicts in fallback path.
2020-03-10 00:05:14 -04:00
Lawrence Forman
05bf55dca8 @0x/asset-swapper: Add gasSchedule option to SwapQuoter.
`@0x/asset-swapper`: Rename `fees` `SwapQuoter` option to `feeSchedule`.
2020-03-09 22:33:33 -04:00
Lawrence Forman
cc12ad8d86 @0x/asset-swapper: Only generate fallbacks for native orders in optimal path.
`@0x/asset-swapper`: Exclude conflicting sources across both optimal and fallback paths.
2020-03-09 21:44:30 -04:00
Lawrence Forman
847a7f470c @0x/instant: Fix for changed asset-swapper configs. 2020-03-09 21:44:30 -04:00
Lawrence Forman
95bebd6d1d @0x/asset-swapper: Clean up median price calls. 2020-03-09 21:44:30 -04:00
Lawrence Forman
8179a964ea @0x/asset-swapper: Reintroduce runLimit option.
`@0x/asset-swapper`: Make native fills one single path.
`@0x/asset-swapper`: Redo the optimizer algo again to be more thorough.
`@0x/asset-swapper`: Make `getMedianSellRate()` return `1` if maker token == taker token.
2020-03-09 21:44:30 -04:00
Lawrence Forman
d0805d4bbb @0x/asset-swapper: Rebase and fix some minor bugs. 2020-03-09 21:44:29 -04:00
Lawrence Forman
f901c401b7 rebase 2020-03-09 21:44:29 -04:00
Lawrence Forman
6ccadcb928 @0x/asset-swapper: Refactor market op utils.
`@0x/asset-swapper`: add fallback orders.
`@0x/asset-swapper`: Remove `noConflicts` and `dustThreshold` options.
`@0x/asset-swapper`: Add `allowFallback` option.
2020-03-09 21:44:29 -04:00
Daniel Pyrathon
58b6c25d5c Merge pull request #2519 from 0xProject/PirosB3-patch-1
Update addresses.json
2020-03-09 10:44:44 -07:00
Daniel Pyrathon
9cbab26202 added CHANGELOG changes 2020-03-09 10:36:32 -07:00
Daniel Pyrathon
74bcb468ca Update addresses.json 2020-03-09 10:23:20 -07:00
Daniel Pyrathon
07a6ba88f4 Merge pull request #2515 from 0xProject/PirosB3-patch-1
Update CHANGELOG.json
2020-03-06 13:44:22 -08:00
Daniel Pyrathon
49dff49993 Update CHANGELOG.json 2020-03-06 12:47:18 -08:00
Daniel Pyrathon
68207aac80 Merge pull request #2505 from 0xProject/feature/plp-integration
🔂 Liquidity Provider Asset Swapper integration
2020-03-06 12:34:45 -08:00
Francesco Agosti
64652b2ff0 Merge pull request #2514 from 0xProject/feat/add-gitpkg-to-contract-addresses
Add private:publish to contract-addresses
2020-03-06 12:17:22 -08:00
Daniel Pyrathon
659e8991de Completed feedback 2020-03-06 12:02:36 -08:00
fragosti
9f495b6dc9 Add private:publish to contract-addresses 2020-03-06 11:32:08 -08:00
Daniel Pyrathon
d8498134ad Merge branch 'development' of github.com:0xProject/0x-monorepo into feature/plp-integration
# Conflicts:
#	packages/contract-addresses/addresses.json
#	packages/contract-wrappers/package.json
2020-03-06 09:59:16 -08:00
Daniel Pyrathon
17b2320b0d remove unit tests that were ported to erc20-bridge-sampler package 2020-03-06 09:53:54 -08:00
Daniel Pyrathon
36c457f483 added unit tests for the Liquidity Provider 2020-03-06 09:47:17 -08:00
Lawrence Forman
b8ec7f5e26 Merge pull request #2512 from 0xProject/fix/contracts/bridges-usdt-fix
Bridges: USDT/KNC fix + ERC20BridgeTransfer events
2020-03-05 19:41:55 -05:00
Daniel Pyrathon
dbc5c0d5d8 moved unit tests to the appropriate sections 2020-03-05 16:29:34 -08:00
Daniel Pyrathon
fa886aa849 prettify and lint 2020-03-05 16:21:15 -08:00
Daniel Pyrathon
32e1ae2b18 added unit tests to avoid regression due to variable order 2020-03-05 16:07:49 -08:00
Daniel Pyrathon
61f03b0ea2 invert maker and taker token variable 2020-03-05 16:07:10 -08:00
Lawrence Forman
c47825a820 @0x/contract-addresses: Redeploy bridges. 2020-03-05 18:39:48 -05:00
Lawrence Forman
2d7cb63c7b @0x/contracts-asset-proxy: Address review comments. 2020-03-05 18:21:38 -05:00
Lawrence Forman
c3d4c13936 @0x/contracts-erc20: Switch LibERC20Token.approveIfBelowMax() to LibERC20Token.approveIfBelow().
`@0x/contracts-asset-proxy`: Use `LibERC20Token.approveIfBelow()` for bridge approvals.
2020-03-05 18:21:38 -05:00
Lawrence Forman
3f51b9322f @0x/contracts-asset-proxy: Emit ERC20BridgeTransfer events in bridges. 2020-03-05 18:21:38 -05:00
Lawrence Forman
b604e2bd4e @0x/contracts-erc20: Add LibERC20Token.approveIfBelowMax().
`@0x/contracts-asset-proxy`: Use `LibERC20Token.approveIfBelowMax` in all DEX bridges.
2020-03-05 18:21:38 -05:00
mzhu25
bcd92473d1 Merge pull request #2511 from 0xProject/feature/extensions/max-gasprice-orders
`@0x/contracts-extensions`: Maximum gas price contract
2020-03-05 12:30:03 -08:00
Michael Zhu
6f5bf9d146 Add artifacts, wrappers, and addresses 2020-03-05 10:53:02 -08:00
Michael Zhu
490094939f Address comments 2020-03-04 22:12:48 -08:00
Daniel Pyrathon
d0d7d2772f upgrades contracts-erc20-bridge-sampler dependency 2020-03-04 14:33:43 -08:00
Daniel Pyrathon
59091896b4 Merge branch 'development' of github.com:0xProject/0x-monorepo into feature/plp-integration
# Conflicts:
#	packages/asset-swapper/package.json
#	packages/asset-swapper/src/utils/market_operation_utils/sampler.ts
#	packages/asset-swapper/src/utils/market_operation_utils/types.ts
#	packages/asset-swapper/test/market_operation_utils_test.ts
2020-03-04 14:11:17 -08:00
Daniel Pyrathon
3eb1429a25 adds possibility to exclude PLP 2020-03-04 13:50:07 -08:00
Daniel Pyrathon
bc7504c469 refresh wrappers and artifacts 2020-03-04 08:24:35 -08:00
Daniel Pyrathon
99dc4b8e07 refactor more code 2020-03-04 08:17:01 -08:00
Daniel Pyrathon
807904bb86 addressed PR comments 2020-03-04 07:59:09 -08:00
Francesco Agosti
7b8c8348f4 Merge pull request #2502 from 0xProject/feat/gitpkg-asset-swapper
Install gitpkg in asset-swapper
2020-03-04 07:30:22 -08:00
Michael Zhu
9c5ac26170 Update changelog 2020-03-03 17:30:53 -08:00
Michael Zhu
5db065644c Add tooling and unit tests 2020-03-03 17:30:53 -08:00
Alex Towle
0cc3a99169 Merge pull request #2504 from 0xProject/feature/better_resolver_errors
Update resolver errors to include parent filename
2020-03-03 16:56:26 -08:00
Michael Zhu
2b1545145b MaximumGasPrice contract 2020-03-03 15:39:45 -08:00
Daniel Pyrathon
49b7c9c8a4 update sampler address 2020-03-03 14:02:15 -08:00
fragosti
114119f7c8 Build before publish 2020-03-03 13:45:25 -08:00
fragosti
b4ef866c10 Update gitpkg to use fork 2020-03-03 13:27:43 -08:00
Jacob Evans
15f75a08d5 Publish
- @0x/contracts-asset-proxy@3.2.5
 - @0x/contracts-broker@1.1.4
 - @0x/contracts-coordinator@3.1.5
 - @0x/contracts-dev-utils@1.3.3
 - @0x/contracts-erc1155@2.1.5
 - @0x/contracts-erc20-bridge-sampler@1.5.1
 - @0x/contracts-erc20@3.1.5
 - @0x/contracts-erc721@3.1.5
 - @0x/contracts-exchange-forwarder@4.2.5
 - @0x/contracts-exchange-libs@4.3.5
 - @0x/contracts-exchange@3.2.5
 - @0x/contracts-extensions@6.1.5
 - @0x/contracts-integrations@2.5.1
 - @0x/contracts-multisig@4.1.5
 - @0x/contracts-staking@2.0.12
 - @0x/contracts-test-utils@5.3.2
 - @0x/contracts-utils@4.4.3
 - 0x.js@9.1.5
 - @0x/asset-swapper@4.4.0
 - @0x/contract-addresses@4.9.0
 - @0x/contract-wrappers-test@12.2.13
 - @0x/contract-wrappers@13.6.3
 - @0x/instant@1.0.50
 - @0x/migrations@6.2.4
 - @0x/order-utils@10.2.4
 - @0x/orderbook@2.2.5
2020-03-03 18:26:46 +11:00
Jacob Evans
29f9c5473d Updated CHANGELOGS & MD docs 2020-03-03 18:26:14 +11:00
Jacob Evans
ea1528aea6 [asset-swapper] Add latest BUSD Curve (#2506)
* [asset-swapper] Add latest BUSD Curve

* Update Compound Curve
2020-03-03 17:53:35 +11:00
Daniel Pyrathon
18ce19a84d refactored imports 2020-03-02 11:03:11 -08:00
Daniel Pyrathon
b0fd78d68d added linting to the contracts 2020-03-02 10:48:52 -08:00
Daniel Pyrathon
8186d6277e fixed a bug with imports 2020-03-02 10:16:40 -08:00
Daniel Pyrathon
599af2b1a9 factored out interfaces in types.ts 2020-03-02 10:12:51 -08:00
Daniel Pyrathon
82de5adbe9 refactored sampler operations into a single external file 2020-03-02 10:06:43 -08:00
Daniel Pyrathon
82b0f85258 transformed the new artifacts 2020-03-02 10:01:06 -08:00
David Sun
cded58c30d Merge pull request #2491 from 0xProject/fix/instant/support-erc721
[FIX] Instant + Asset-swapper support for ERC721
2020-03-01 14:57:18 -05:00
David Sun
da17b49b81 added changelog 2020-03-01 13:54:14 -05:00
David Sun
4728cdfa7c added changelog 2020-03-01 13:36:56 -05:00
Alex Towle
d97b30dcee Improve error message for nested errors 2020-02-28 17:11:30 -08:00
Daniel Pyrathon
fa8e8ad52d Update artifacts after rename 2020-02-28 17:09:48 -08:00
Daniel Pyrathon
7495ac8111 performed a rename 2020-02-28 16:54:05 -08:00
Daniel Pyrathon
08619e2c06 re-generate ERC20BridgeSampler artifacts 2020-02-28 15:59:46 -08:00
Daniel Pyrathon
5d4bbd5b37 Merge branch 'development' of github.com:0xProject/0x-monorepo into feature/plp-integration
# Conflicts:
#	packages/asset-swapper/package.json
2020-02-28 15:50:34 -08:00
Daniel Pyrathon
9d2aef5006 Added linting and prettifying 2020-02-28 12:36:47 -08:00
Daniel Pyrathon
bcc3e5ebb0 refactor tests, and add more tests 2020-02-28 12:28:09 -08:00
Daniel Pyrathon
e5df51a83a tidy up tests, add other tests 2020-02-28 12:12:58 -08:00
David Sun
97fb843f01 prettier 2020-02-28 14:03:54 -05:00
David Sun
8afb044877 address feedback 2020-02-28 13:15:50 -05:00
David Sun
7f869868c9 prettier + lint 2020-02-28 13:13:46 -05:00
David Sun
31275228ac patch asset-swapper to support ERC721 2020-02-28 13:13:18 -05:00
Daniel Pyrathon
7181be8768 added more unit tests, reinforced existing tests, added more implementation 2020-02-28 10:02:18 -08:00
Lawrence Forman
3b446e887a Merge pull request #2503 from 0xProject/feat/deploy-erc20-bridge-sampler
Redeploy `ERC20BridgeSampler`
2020-02-28 12:01:06 -05:00
Lawrence Forman
431196c391 @0x/contract-addresses: Redeploy ERC20BridgeSampler. 2020-02-28 01:18:24 -05:00
Daniel Pyrathon
9608d8fb46 added more unit tests for PLP DEX sampling 2020-02-27 16:03:44 -08:00
mzhu25
d574ca1628 Merge pull request #2501 from 0xProject/fix/bridge-sampler/get-liquidity-provider-from-registry
Fix getLiquidityProviderFromRegistry
2020-02-27 14:09:28 -08:00
Daniel Pyrathon
8be60e2ff5 initial unit tests for DEX sampler 2020-02-27 14:00:08 -08:00
Daniel Pyrathon
3c0fd540b1 generated wrappers for ERC20 sampler 2020-02-27 13:53:52 -08:00
fragosti
23a7dc9a8a Install gitpkg in asset-swapper 2020-02-27 13:51:28 -08:00
Michael Zhu
f97e6892b6 Fix getLiquidityProviderFromRegistry 2020-02-27 13:39:03 -08:00
Jacob Evans
7742901e5c Publish
- @0x/contracts-asset-proxy@3.2.4
 - @0x/contracts-broker@1.1.3
 - @0x/contracts-coordinator@3.1.4
 - @0x/contracts-dev-utils@1.3.2
 - @0x/contracts-erc1155@2.1.4
 - @0x/contracts-erc20-bridge-sampler@1.5.0
 - @0x/contracts-erc20@3.1.4
 - @0x/contracts-erc721@3.1.4
 - @0x/contracts-exchange-forwarder@4.2.4
 - @0x/contracts-exchange-libs@4.3.4
 - @0x/contracts-exchange@3.2.4
 - @0x/contracts-extensions@6.1.4
 - @0x/contracts-integrations@2.5.0
 - @0x/contracts-multisig@4.1.4
 - @0x/contracts-staking@2.0.11
 - @0x/contracts-test-utils@5.3.1
 - @0x/contracts-utils@4.4.2
 - 0x.js@9.1.4
 - @0x/asset-swapper@4.3.2
 - @0x/contract-addresses@4.8.0
 - @0x/contract-wrappers-test@12.2.12
 - @0x/contract-wrappers@13.6.2
 - @0x/instant@1.0.49
 - @0x/migrations@6.2.3
 - @0x/order-utils@10.2.3
 - @0x/orderbook@2.2.4
2020-02-28 08:13:33 +11:00
Jacob Evans
de68cb25d0 Updated CHANGELOGS & MD docs 2020-02-28 08:13:09 +11:00
Daniel Pyrathon
77d7afe505 created DummyPLPRegistry and DummyPLP + generated wrappers for these new contracts and their respective interfaces 2020-02-27 12:52:13 -08:00
Daniel Pyrathon
68fb6c2c27 Merge pull request #2499 from 0xProject/feature/erc20-bridge-sampler/liquidity-provider-registry
`@0x/contracts-erc20-bridge-sampler`: LiquidityProviderRegistry
2020-02-27 12:37:10 -08:00
Michael Zhu
a47c031ad1 Catch reverts when calling registry 2020-02-27 11:23:25 -08:00
Michael Zhu
817049456c Get liquidity provider from registry in the sampler 2020-02-27 11:05:56 -08:00
Lawrence Forman
e1a061789f Merge pull request #2500 from 0xProject/fix/asset-swapper/native-order-prune
[asset-swapper] Fix native fill prune
2020-02-27 13:38:49 -05:00
Jacob Evans
28573ba772 [asset-swapper] Fix native fill prune 2020-02-27 16:42:20 +11:00
David Sun
880b9413f6 Merge pull request #2492 from 0xProject/fix/instant/constant-polling
[Fix] Instant call destroyAsync on unmount
2020-02-26 19:36:48 -05:00
mzhu25
9a7c4b21a9 @0x/contracts-erc20-bridge-sampler: Generic liquidity provider sampling (#2487)
* Add methods to Sampler contract to plug into generic on-chain liquidity provider
2020-02-26 11:54:48 -08:00
mzhu25
ac56038eca Add Broker, GodsUnchainedValidator, ChainlinkStopLimit to ContractAddresses interface (#2498) 2020-02-26 11:54:32 -08:00
Lawrence Forman
4dd2fb6903 Merge pull request #2478 from 0xProject/feat/contracts/integrations/chai-bridge-benchmarks
`@0x/contracts-integrations`: Add `ChaiBridge` and `DydxBridge` gas b…
2020-02-26 14:17:15 -05:00
Lawrence Forman
0baec61f06 @0x/contracts/integrations: Update wallets and add comments with last run gas costs to benchmarks. 2020-02-26 12:57:03 -05:00
Lawrence Forman
d4751788d1 @0x/contracts-integrations: Add ChaiBridge and DydxBridge gas benchmark tests. 2020-02-26 11:29:44 -05:00
Lawrence Forman
ae68c061d1 @0x/asset-proxy: Add more functions to IDydx.
`@0x/dev-utils`: Fix all the weird dydx base unit madness.
2020-02-26 11:29:26 -05:00
Lawrence Forman
b0387245f0 @0x/contracts-utils: Roll back additions to LibFractions.
`@0x/contracts-dev-utils`: Add `D18` library for working with base-10, 18-digit decimals.
`@0x/contracts-dev-utils`: Use `D18` library instead of `LibFractions` in `LibDydxBalance`.
2020-02-26 11:29:16 -05:00
Lawrence Forman
c2d06a4a23 Cherry pick dydx validation from #2456 2020-02-26 11:29:02 -05:00
Lawrence Forman
270108abb7 Cherry pick DevUtils refactor code from #2456 2020-02-26 11:26:57 -05:00
Lawrence Forman
e76c33232d Cherry-pick changes from feat/dev-utils/dydx-bridge-validation 2020-02-26 11:26:57 -05:00
Jacob Evans
58ff2dc492 Publish
- @0x/contracts-asset-proxy@3.2.3
 - @0x/contracts-broker@1.1.2
 - @0x/contracts-coordinator@3.1.3
 - @0x/contracts-dev-utils@1.3.1
 - @0x/contracts-erc1155@2.1.3
 - @0x/contracts-erc20-bridge-sampler@1.4.2
 - @0x/contracts-erc20@3.1.3
 - @0x/contracts-erc721@3.1.3
 - @0x/contracts-exchange-forwarder@4.2.3
 - @0x/contracts-exchange-libs@4.3.3
 - @0x/contracts-exchange@3.2.3
 - @0x/contracts-extensions@6.1.3
 - @0x/contracts-integrations@2.4.2
 - @0x/contracts-multisig@4.1.3
 - @0x/contracts-staking@2.0.10
 - @0x/contracts-utils@4.4.1
 - 0x.js@9.1.3
 - @0x/abi-gen@5.2.2
 - @0x/asset-swapper@4.3.1
 - @0x/contract-wrappers-test@12.2.11
 - @0x/instant@1.0.48
 - @0x/migrations@6.2.2
 - @0x/orderbook@2.2.3
 - @0x/sol-doc@3.1.6
2020-02-26 11:34:29 +11:00
Jacob Evans
13c45a0e96 Updated CHANGELOGS & MD docs 2020-02-26 11:34:00 +11:00
henrynguyen5
90cb86911a Update resolver errors to include parent filename 2020-02-25 18:40:45 -05:00
Jacob Evans
be7b1a1bd4 Include bin in npm publish (#2496)
* Include bin in npm publish

* Include bin in files

* Update CHANGELOG

* Changelog
2020-02-26 10:12:52 +11:00
Amir Bandeali
132a3c6705 Merge pull request #2495 from 0xProject/feat/defaults-should-save-standard-input
Update boilerplate
2020-02-25 10:56:26 -08:00
Amir
5e73257557 Set shouldSaveStandardInput to true in all compiler.json files 2020-02-25 10:04:19 -08:00
Amir
e83346fbbb Do not prettify Solidity 2020-02-25 10:04:19 -08:00
Jacob Evans
2dd47a2103 Publish
- @0x/contracts-asset-proxy@3.2.2
 - @0x/contracts-broker@1.1.1
 - @0x/contracts-coordinator@3.1.2
 - @0x/contracts-dev-utils@1.3.0
 - @0x/contracts-erc1155@2.1.2
 - @0x/contracts-erc20-bridge-sampler@1.4.1
 - @0x/contracts-erc20@3.1.2
 - @0x/contracts-erc721@3.1.2
 - @0x/contracts-exchange-forwarder@4.2.2
 - @0x/contracts-exchange-libs@4.3.2
 - @0x/contracts-exchange@3.2.2
 - @0x/contracts-extensions@6.1.2
 - @0x/contracts-integrations@2.4.1
 - @0x/contracts-multisig@4.1.2
 - @0x/contracts-staking@2.0.9
 - @0x/contracts-test-utils@5.3.0
 - @0x/contracts-utils@4.4.0
 - 0x.js@9.1.2
 - @0x/abi-gen@5.2.1
 - @0x/assert@3.0.7
 - @0x/asset-swapper@4.3.0
 - @0x/base-contract@6.2.1
 - @0x/connect@6.0.7
 - @0x/contract-addresses@4.7.0
 - @0x/contract-artifacts@3.6.1
 - @0x/contract-wrappers-test@12.2.10
 - @0x/contract-wrappers@13.6.1
 - @0x/contracts-gen@2.0.8
 - @0x/dev-utils@3.2.1
 - @0x/instant@1.0.47
 - @0x/json-schemas@5.0.7
 - @0x/migrations@6.2.1
 - @0x/monorepo-scripts@1.0.51
 - @0x/order-utils@10.2.2
 - @0x/orderbook@2.2.2
 - @0x/sol-compiler@4.0.8
 - @0x/sol-coverage@4.0.8
 - @0x/sol-doc@3.1.5
 - @0x/sol-profiler@4.0.8
 - @0x/sol-trace@3.0.8
 - @0x/sol-tracing-utils@7.0.8
 - @0x/sra-spec@3.0.7
 - @0x/subproviders@6.0.8
 - @0x/utils@5.4.1
 - @0x/web3-wrapper@7.0.7
2020-02-25 20:43:55 +11:00
Jacob Evans
f31e530b6e Updated CHANGELOGS & MD docs 2020-02-25 20:43:31 +11:00
Jacob Evans
eb50f3fa9c Xlab/fix/extra space (#2494)
* Fix extra space in `provider.send` signature from fabio. Fixes #2285.

* Fix style and update changelog.

Co-authored-by: Maxim <max@kc.vc>
2020-02-25 19:56:33 +11:00
Lawrence Forman
8417fe4fdb Merge pull request #2493 from 0xProject/feat/redeploy-devutils
Redeploy DevUtils
2020-02-25 00:40:58 -05:00
Lawrence Forman
0f1c15a6ca Asset-Swapper: Incorporate fees into fill path optimization (#2481)
* `@0x/asset-swapper`: Incorporate fees into fill optimization.

* `@0x/asset-swapper`: Address review comments.

* `@0x/asset-swapper`: Rebase and update tests for curve.

* `@0x/asset-swapper`: Bring back a form of native order pruning.
`@0x/asset-swapper`: Bring back dust thresholds.
`@0x/asset-swapper`: Avoid calling `getMedianSellRate()` if output token is ETH.

* Update devdoc for `fees` option

Co-authored-by: Lawrence Forman <me@merklejerk.com>
2020-02-25 14:47:33 +11:00
Lawrence Forman
9345c4fb7f @0x/contract-addresses: Update DevUtils addresses. 2020-02-24 12:47:33 -05:00
Lawrence Forman
5e0758917b @0x/contracts-utils: Update DevUtils address in DeploymentConstants. 2020-02-24 12:42:01 -05:00
David Sun
f56839ec6b call destroyAsync on unmount 2020-02-24 12:24:07 -05:00
Lawrence Forman
cbb23a42e2 Merge pull request #2466 from 0xProject/feat/contracts/dev-utils/dydx-validation
DevUtils: DydxBridge validation
2020-02-20 13:36:22 -07:00
Kim Persson
5a59c286d0 Merge pull request #2488 from 0xProject/kim/fix-readme-spelling
FIXES spelling in exchange readme
2020-02-20 17:27:32 +01:00
Kim Persson
2e8c600d7a FIXES spelling in exchange readme 2020-02-20 14:45:53 +01:00
Lawrence Forman
e851cb1cbc @0x/contracts-dev-utils: Move D18 out to @0x/contracts-utils. 2020-02-19 16:19:38 -05:00
Lawrence Forman
3da03da32a @0x/contracts-utils: Add D18 library. 2020-02-19 16:19:09 -05:00
Lawrence Forman
3ec8924e7f @0x/contracts-dev-utils: Rebase. 2020-02-19 16:02:35 -05:00
Lawrence Forman
a04722b612 @0x/contracts-integrations: Add USDC->DAI forked dydx bridge order validation. 2020-02-19 15:51:05 -05:00
Lawrence Forman
f9a7857a90 @0x/contracts-dev-utils: Address review comments. 2020-02-19 15:51:05 -05:00
Lawrence Forman
58f772c74e foo 2020-02-19 15:51:05 -05:00
Lawrence Forman
a425c7e260 Regenerate artifacts and wrappers 2020-02-19 15:50:10 -05:00
Lawrence Forman
809885afd0 @0x/contracts-asset-proxy: Add getMarketMarginPremium() to IDydx.
`@0x/contracts-dev-utils`: Handle dydx market premiums.
2020-02-19 15:49:41 -05:00
Lawrence Forman
bf9b4b993f @0x/contracts-test-utils: Fix blockchainTests fork config to work with other tests. 2020-02-19 15:49:41 -05:00
Lawrence Forman
d94a26f0f4 @0x/contracts-integrations: Add DydxBridge validation integration tests. 2020-02-19 15:49:41 -05:00
Lawrence Forman
bd9c9cedca @0x/contracts-test-utils: Add blockchainTests.config 2020-02-19 15:45:27 -05:00
Lawrence Forman
651e94bd94 @0x/asset-proxy: Add more functions to IDydx.
`@0x/dev-utils`: Fix all the weird dydx base unit madness.
2020-02-19 15:45:27 -05:00
Lawrence Forman
162b6f1a74 @0x/dev-utils: Fix dydx min CR not being +1.
`@0x/dev-utils`: Fix withdraw rate vs order conversion rate check .
2020-02-19 15:45:27 -05:00
Lawrence Forman
865a253eb5 @0x/contracts-utils: Roll back additions to LibFractions.
`@0x/contracts-dev-utils`: Add `D18` library for working with base-10, 18-digit decimals.
`@0x/contracts-dev-utils`: Use `D18` library instead of `LibFractions` in `LibDydxBalance`.
2020-02-19 15:45:27 -05:00
Lawrence Forman
9b3781abf1 Cherry pick dydx validation from #2456 2020-02-19 15:45:27 -05:00
Lawrence Forman
d89243a0d3 Cherry pick DevUtils refactor code from #2456 2020-02-19 15:44:59 -05:00
Lawrence Forman
b4cefc64b4 Cherry pick library linking code from #2456 2020-02-19 15:44:59 -05:00
Lawrence Forman
2fd26587e5 Cherry-pick changes from feat/dev-utils/dydx-bridge-validation 2020-02-19 15:44:59 -05:00
David Sun
282a351859 Merge pull request #2404 from 0xProject/feature/instant/fortmatic-integration
Formatic integration into instant
2020-02-18 13:58:10 -06:00
David Sun
a84b848ea9 prettier 2020-02-18 14:20:30 -05:00
David Sun
d329320fc2 linted 2020-02-18 14:02:48 -05:00
David Sun
bc096554b5 fixed webpack issues 2020-02-18 13:58:22 -05:00
David Sun
5902d878d8 fixed affiliate + fortmatic 2020-02-18 12:13:38 -05:00
Jacob Evans
4a133ca36f Publish
- @0x/contracts-asset-proxy@3.2.1
 - @0x/contracts-broker@1.1.0
 - @0x/contracts-coordinator@3.1.1
 - @0x/contracts-dev-utils@1.1.1
 - @0x/contracts-erc1155@2.1.1
 - @0x/contracts-erc20-bridge-sampler@1.4.0
 - @0x/contracts-erc20@3.1.1
 - @0x/contracts-erc721@3.1.1
 - @0x/contracts-exchange-forwarder@4.2.1
 - @0x/contracts-exchange-libs@4.3.1
 - @0x/contracts-exchange@3.2.1
 - @0x/contracts-extensions@6.1.1
 - @0x/contracts-integrations@2.4.0
 - @0x/contracts-multisig@4.1.1
 - @0x/contracts-staking@2.0.8
 - @0x/contracts-test-utils@5.1.5
 - @0x/contracts-utils@4.3.1
 - 0x.js@9.1.1
 - @0x/asset-swapper@4.2.0
 - @0x/contract-addresses@4.6.0
 - @0x/contract-artifacts@3.6.0
 - @0x/contract-wrappers-test@12.2.9
 - @0x/contract-wrappers@13.6.0
 - @0x/instant@1.0.46
 - @0x/migrations@6.2.0
 - @0x/order-utils@10.2.1
 - @0x/orderbook@2.2.1
2020-02-15 17:39:09 +11:00
Jacob Evans
f7252f919a Updated CHANGELOGS & MD docs 2020-02-15 17:38:47 +11:00
Jacob Evans
e05a03a842 Curve ERC20Bridge (#2480)
* Curve ERC20Bridge

* ERC20BridgeSampler Curve (#2483)

* ERC20Sampler Curve

* Use Bridge Sources for each Curve

* Support multiple versions of the Curve contract

* CHANGELOG and redeployed Curve (mainnet)

* Fix Market ops utils test

* Added Curve DAI USDC USDT TUSD

* Bump sampler gas limit default

* Decode the Curve in tests

* Disable Curve in Buy tests

* blockchainTests.fork.resets Curve and Sampler
2020-02-15 17:02:19 +11:00
mzhu25
dcce8276b8 Add decoders for broker and stop-limit data (#2484)
* Add decoders for broker and stop-limit data

* update changelogs

* Address comments
2020-02-14 17:38:43 -08:00
Alex Towle
fd47947e55 Merge pull request #2454 from 0xProject/fix/dev-utils/and-another-one
Another one...
2020-02-13 20:45:34 -08:00
Alex Towle
ae151df2eb Addressed amir's review feedback 2020-02-13 18:07:45 -08:00
Alex Towle
79de188683 Updated addresses again 2020-02-13 17:37:03 -08:00
Alex Towle
6e5c788e13 Added a test that fails for the old DevUtils 2020-02-13 17:37:03 -08:00
Alex Towle
f53606007d Updated DevUtils again 2020-02-13 17:37:03 -08:00
Greg Hysz
a4ac418bc9 Merge pull request #2479 from 0xProject/test/dydx-mainnet-tests/updateDeployment
Fixed dYdX Bridge Tests
2020-02-13 14:42:47 -08:00
Greg Hysen
a8c09d0bdb Updated contracts-integrations changelog. 2020-02-13 13:21:07 -08:00
Greg Hysen
871105a48a Fixed dYdX Bridge Tests 2020-02-13 13:19:26 -08:00
Fabio B
3b61129ade Update link to docs for web3-wrapper 2020-02-12 22:08:10 +01:00
mzhu25
f471c79b59 Chainlink stop-limit orders (#2473)
* Contracts for Chainlink stop-limit orders

* Tests and asset data utils

* Update contracts-integrations changelog

* Address comments

* Remove priceFreshness parameter

* Remove LibSafeMath

* fix typo

* Add ChainlinkStopLimit addresses to @0x/contract-addresses
2020-02-11 15:10:06 -08:00
Lawrence Forman
dfd9443f74 Merge pull request #2477 from 0xProject/feat/batched-sampler
ERC20BridgeSampler: batchCall()
2020-02-11 14:32:48 -07:00
Lawrence Forman
a36ff9e365 `@0x/asset-swapper: Address review comments. 2020-02-11 12:08:15 -07:00
Lawrence Forman
12e65bbf26 @0x/contracts-erc20-bridge-sampler: Fix failing tests. 2020-02-11 12:08:15 -07:00
Lawrence Forman
ab9841e60b @0x/contract-addresses: Update ERC20BridgeSampler addresses on mainnet and kovan. 2020-02-11 12:08:15 -07:00
Lawrence Forman
7a52f12e57 Rebase and update contract artifacts + wrappers. 2020-02-11 12:07:48 -07:00
Lawrence Forman
11fd4506ac @0x/asset-swapper: Fix failing asset-swapper test. 2020-02-11 12:07:48 -07:00
Lawrence Forman
0c9c68030e @0x/asset-swapper: Use batchCall() version of the ERC20BridgeSampler contract 2020-02-11 12:07:48 -07:00
Lawrence Forman
55d6eddbb2 @0x/contract-artifacts: Update IERC20BridgeSampler wrapper. 2020-02-11 12:07:48 -07:00
Lawrence Forman
8341e60edb @0x/contract-artifacts: Update ERC20BridgeSampler artifact. 2020-02-11 12:07:48 -07:00
Lawrence Forman
6273a1ca73 @0x/contracts-erc20-bridge-sampler: Remove wrapper functions and introduce batchCall(). 2020-02-11 12:07:48 -07:00
mzhu25
1b83ebdf89 Merge pull request #2469 from 0xProject/feature/broker/deployments
Broker-related updates to contract-artifacts, contract-wrappers, contract-addresses
2020-02-10 18:41:24 -08:00
Michael Zhu
fef7f0506f rebase 🙄 2020-02-10 17:38:16 -08:00
Michael Zhu
f44eb4e383 Update changelogs for Forwarder changes 2020-02-10 17:11:01 -08:00
Michael Zhu
05df485c4a Update Forwarder in contract-artifacts and contract-wrappers 2020-02-10 17:11:00 -08:00
Michael Zhu
44857c526b Remove DutchAuction and OrderValidator from python contract addresses 2020-02-10 17:10:36 -08:00
Michael Zhu
b8ad5d5d32 Update Forwarder addresses 2020-02-10 17:10:36 -08:00
Michael Zhu
e3e0d00e21 Add Broker and GodsUnchainedValidator to contract-wrappers 2020-02-10 17:10:14 -08:00
Michael Zhu
a9b1ea9690 Add Broker and GodsUnchainedValidator to contract-addresses 2020-02-10 17:09:34 -08:00
Michael Zhu
8e5dd0f8d9 Add Broker and GodsUnchainedValidator to contract-artifacts 2020-02-10 17:08:24 -08:00
David Sun
3b0c8f6d92 fortmatic patches 2020-02-09 21:08:46 -05:00
David Sun
21058c2227 changes to fetch account state behavior 2020-02-09 21:08:46 -05:00
David Sun
f3b8ae0781 fix for fortmatic 2020-02-09 21:08:46 -05:00
David Sun
d590b004c1 incomplete, fixes for heartbeater 2020-02-09 21:08:46 -05:00
David Sun
02e21141c6 added minor polish + bug fixes 2020-02-09 21:08:46 -05:00
David Sun
f839a3087d add yarn.lock 2020-02-09 21:08:46 -05:00
David Sun
f458815541 fixing + testing fortmatic integration 2020-02-09 21:08:46 -05:00
apane
7ba754d2a4 Fixs styling 2020-02-09 21:08:46 -05:00
apane
09706e4ae2 Fix metamask logo size on connect and on install 2020-02-09 21:08:46 -05:00
apane
d18de4c541 Fixs styling
Removes unused imports
2020-02-09 21:08:46 -05:00
apane
001c7bfdbc Fixs order details only when a wallet is connected 2020-02-09 21:08:46 -05:00
apane
d4e04dc712 Fix chevron icon
Fixs metamask icon size
2020-02-09 21:08:46 -05:00
apane
8650cb5217 Disables order details if no payment method is selected 2020-02-09 21:08:46 -05:00
apane
0eaaddeb95 Removes unused colors
Adds white background
Adds phone.svg
2020-02-09 21:08:46 -05:00
apane
1cf8663f20 Adds phone svg
Updates design of payment methods
2020-02-09 21:08:46 -05:00
apane
5130259552 Remove icon on connect button 2020-02-09 21:08:46 -05:00
apane
ba5e19a015 Fix lint errors
Remove icon
2020-02-09 21:08:46 -05:00
apane
c0400fa986 Removes onUnlockFormatic, just uses onUnlockGenericWallet
Removes unlockWalletWithFormaticProvider, now just uses unlockWalletAndDispatchToStore with getProviderStateBasedOnProviderType
Adds getProviderStateBasedOnProviderType
Adds orderSource to providerState type
2020-02-09 21:08:46 -05:00
apane
51179d10ce Adds webpack config to use env var
Updates env example
Adds unlockWalletWithFormaticProvider on connect
2020-02-09 21:08:46 -05:00
apane
78752f9178 Adds connect to formatic button if the user does not have metamask installed 2020-02-09 21:08:46 -05:00
apane
762db417d7 Adds setProviderState action
unlockWalletAndDispatchToStore now changes the provider state based on the provider type
Adds button to connect with fortmatic
Adds FORTMATIC_API_KEY constant
2020-02-09 21:08:45 -05:00
apane
85bdccbc06 Adds Fortmatic to providerType
Uses fortmatic as default provider
2020-02-09 21:08:45 -05:00
apane
9f8cb99340 Removes prompt formatic
Fixs wallet prompt, adds marginTop props, splits border into border and borderColor
Adds fortmaticPrimary and fortmaticSecondary prop colors
2020-02-09 21:08:45 -05:00
apane
87b90bb04b Adds fortmatic button
Adds fortmatic colors
2020-02-09 21:08:45 -05:00
apane
e961d88277 Adds fortmatic dependency 2020-02-09 21:08:45 -05:00
Jacob Evans
5754c11e34 Publish
- @0x/contracts-asset-proxy@3.2.0
 - @0x/contracts-broker@1.0.2
 - @0x/contracts-coordinator@3.1.0
 - @0x/contracts-dev-utils@1.1.0
 - @0x/contracts-erc1155@2.1.0
 - @0x/contracts-erc20-bridge-sampler@1.3.0
 - @0x/contracts-erc20@3.1.0
 - @0x/contracts-erc721@3.1.0
 - @0x/contracts-exchange-forwarder@4.2.0
 - @0x/contracts-exchange-libs@4.3.0
 - @0x/contracts-exchange@3.2.0
 - @0x/contracts-extensions@6.1.0
 - @0x/contracts-integrations@2.3.0
 - @0x/contracts-multisig@4.1.0
 - @0x/contracts-staking@2.0.7
 - @0x/contracts-test-utils@5.1.4
 - @0x/contracts-utils@4.3.0
 - 0x.js@9.1.0
 - @0x/abi-gen@5.2.0
 - @0x/assert@3.0.6
 - @0x/asset-swapper@4.1.2
 - @0x/base-contract@6.2.0
 - @0x/connect@6.0.6
 - @0x/contract-addresses@4.5.0
 - @0x/contract-artifacts@3.5.0
 - @0x/contract-wrappers-test@12.2.8
 - @0x/contract-wrappers@13.5.0
 - @0x/contracts-gen@2.0.7
 - @0x/dev-utils@3.2.0
 - ethereum-types@3.1.0
 - @0x/instant@1.0.45
 - @0x/json-schemas@5.0.6
 - @0x/migrations@6.1.0
 - @0x/monorepo-scripts@1.0.50
 - @0x/order-utils@10.2.0
 - @0x/orderbook@2.2.0
 - @0x/sol-compiler@4.0.7
 - @0x/sol-coverage@4.0.7
 - @0x/sol-doc@3.1.4
 - @0x/sol-profiler@4.0.7
 - @0x/sol-resolver@3.0.3
 - @0x/sol-trace@3.0.7
 - @0x/sol-tracing-utils@7.0.7
 - @0x/sra-spec@3.0.6
 - @0x/subproviders@6.0.7
 - @0x/types@3.1.2
 - @0x/typescript-typings@5.0.2
 - @0x/utils@5.4.0
 - @0x/web3-wrapper@7.0.6
2020-02-09 09:37:34 +10:00
Jacob Evans
7bd88c1bb8 Updated CHANGELOGS & MD docs 2020-02-09 09:37:04 +10:00
Lawrence Forman
445b686c6c Merge pull request #2463 from 0xProject/feat/abi-gen/library-linking
Support contracts with unlinked libraries
2020-02-08 00:23:57 -05:00
Lawrence Forman
0cb7b75214 Merge pull request #2464 from 0xProject/feat/contracts/dev-utils/public-libraries-refactor
DevUtils refactor into public libraries
2020-02-07 23:53:16 -05:00
Lawrence Forman
a08399dfee regenerate artifacts and wrappers 2020-02-07 23:23:23 -05:00
Lawrence Forman
4016808fa4 Cherry pick DevUtils refactor code from #2456 2020-02-07 23:23:23 -05:00
Lawrence Forman
8635849977 Address review comments and regenerate contract-wrappers 2020-02-07 23:22:58 -05:00
Lawrence Forman
1a9ed4d4fe Add es2018.promises tsconfig lib target. 2020-02-07 23:22:58 -05:00
Lawrence Forman
e7b3246dd0 Cherry pick library linking code from #2456 2020-02-07 23:22:58 -05:00
Lawrence Forman
19589aec57 Cherry-pick changes from feat/dev-utils/dydx-bridge-validation 2020-02-07 23:22:58 -05:00
Lawrence Forman
4d33ff0417 Cherry-pick changes from feat/dev-utils/dydx-bridge-validation 2020-02-07 23:22:58 -05:00
Lawrence Forman
93a5ab5b33 Merge pull request #2462 from 0xProject/fix-and-feat/restore-contract-tests-and-refactors
Fix contracts tests + refactors
2020-02-07 23:16:50 -05:00
Lawrence Forman
59ada06cdf Fix linter errors. 2020-02-07 22:39:56 -05:00
Lawrence Forman
ae650849b0 Rebase and address review comments. 2020-02-07 22:29:32 -05:00
Lawrence Forman
3e8f9a6b53 Cherry-pick changes from feat/dev-utils/dydx-bridge-validation 2020-02-07 22:10:10 -05:00
Lawrence Forman
79362b0dba Merge pull request #2476 from 0xProject/fix/erc20-bridge-sampler/dev-utils-gas-stipend
ERC20BridgeSampler: Catch DevUtils reverts
2020-02-07 10:08:40 -05:00
Lawrence Forman
3e3df06d57 @0x/contracts-erc20-bridge-sampler: Fix catching invalid opcode from DevUtils
`@0x/contract-addresses`: Update `ERC20BridgeSampler` mainnet and kovan addresses.
2020-02-07 03:07:33 -05:00
Lawrence Forman
6b220eb1c5 Merge pull request #2474 from 0xProject/feat/eth2dai-bridge/market-migration
Update Eth2Dai address
2020-02-07 02:42:29 -05:00
Lawrence Forman
a1c61cae11 @0x/contract-addresses: Redeploy ERC20BridgeSampler 2020-02-07 02:10:19 -05:00
Jacob Evans
d48a917bf3 [erc20-bridge-sampler] gas stipend for DevUtils 2020-02-07 16:57:11 +10:00
Lawrence Forman
646b6dafb2 @0x/contract-addresses Redeploy Eth2DaiBridge and ERC20BridgeSampler. 2020-02-07 01:56:59 -05:00
Lawrence Forman
8d10f33a3f @0x/contracts-utils: Update Eth2Dai address. 2020-02-07 01:56:59 -05:00
Jacob Evans
5d603b2f80 Publish
- @0x/contracts-asset-proxy@3.1.3
 - @0x/contracts-broker@1.0.1
 - @0x/contracts-coordinator@3.0.6
 - @0x/contracts-dev-utils@1.0.6
 - @0x/contracts-erc1155@2.0.6
 - @0x/contracts-erc20-bridge-sampler@1.2.1
 - @0x/contracts-erc20@3.0.6
 - @0x/contracts-erc721@3.0.6
 - @0x/contracts-exchange-forwarder@4.1.0
 - @0x/contracts-exchange-libs@4.2.0
 - @0x/contracts-exchange@3.1.2
 - @0x/contracts-extensions@6.0.0
 - @0x/contracts-integrations@2.2.3
 - @0x/contracts-multisig@4.0.6
 - @0x/contracts-staking@2.0.6
 - @0x/contracts-test-utils@5.1.3
 - @0x/contracts-utils@4.2.1
 - 0x.js@9.0.7
 - @0x/abi-gen@5.1.2
 - @0x/assert@3.0.5
 - @0x/asset-swapper@4.1.1
 - @0x/base-contract@6.1.2
 - @0x/connect@6.0.5
 - @0x/contract-artifacts@3.4.1
 - @0x/contract-wrappers-test@12.2.7
 - @0x/contract-wrappers@13.4.2
 - @0x/contracts-gen@2.0.6
 - @0x/dev-utils@3.1.3
 - @0x/instant@1.0.44
 - @0x/json-schemas@5.0.5
 - @0x/migrations@6.0.2
 - @0x/monorepo-scripts@1.0.49
 - @0x/order-utils@10.1.3
 - @0x/orderbook@2.1.2
 - @0x/sol-compiler@4.0.6
 - @0x/sol-coverage@4.0.6
 - @0x/sol-doc@3.1.3
 - @0x/sol-profiler@4.0.6
 - @0x/sol-trace@3.0.6
 - @0x/sol-tracing-utils@7.0.6
 - @0x/sra-spec@3.0.5
 - @0x/subproviders@6.0.6
 - @0x/utils@5.3.0
 - @0x/web3-wrapper@7.0.5
2020-02-06 21:24:29 +10:00
Jacob Evans
0e1b08ff54 Updated CHANGELOGS & MD docs 2020-02-06 21:24:05 +10:00
David Sun
befc22d718 [FIX] asset-swapper liquidity breakdown (#2472)
* changed divided

* added changelog

* prettier

Co-authored-by: Jacob Evans <dekz@dekz.net>
2020-02-06 15:09:39 +10:00
Jacob Evans
4a62e80967 [asset-swapper] Bump sampler gas limit and allow for override (#2471)
* [asset-swapper] Bump sampler gas limit and allow for override

* Fix imports

* Set to 36e6
2020-02-06 12:31:28 +10:00
Jacob Evans
ee9ef9f2c1 [asset-swapper] prune before dummy order creation (#2470) 2020-02-06 07:08:31 +10:00
mzhu25
93dcb68437 Merge pull request #2455 from 0xProject/feature/broker/gods-unchained
`@0x/contracts-broker`: Property-based Gods Unchained orders
2020-02-04 10:53:54 -08:00
Michael Zhu
0691cc7909 rename _transferEthRefund -> _unwrapAndTransferEth 2020-02-04 10:13:07 -08:00
Michael Zhu
d82f34fe59 add weth-related integration tests 2020-02-04 10:13:07 -08:00
Michael Zhu
d2313b30af Address PR feedback and add support for affiliate fees 2020-02-04 10:13:07 -08:00
Michael Zhu
329719472a Move LibAssetDataTransfer and MixinWeth(Utils) to contracts-extensions 2020-02-04 10:13:02 -08:00
Michael Zhu
a2fcab47d4 skip coordinator client test 2020-02-04 10:08:25 -08:00
Michael Zhu
4ab5951c25 Add comments 2020-02-04 10:08:25 -08:00
Michael Zhu
403cabb201 more integrations tests 2020-02-04 10:08:25 -08:00
Michael Zhu
3da7c5d3e2 Move LibAssetDataTransfer from forwarder to exchange-libs package 2020-02-04 10:08:21 -08:00
Michael Zhu
c5e0de51aa Add Broker rich errors 2020-02-04 10:06:12 -08:00
Michael Zhu
c581f1bba4 Update Broker README 2020-02-04 10:06:12 -08:00
Michael Zhu
b8ac9c2edd lint 2020-02-04 10:06:10 -08:00
Michael Zhu
1027ee2481 Broker integrations tests 2020-02-04 10:05:17 -08:00
Michael Zhu
2f311f7821 GodsUnchainedValidator unit tests 2020-02-04 10:04:19 -08:00
Michael Zhu
a98c95b514 Broker contracts 2020-02-04 10:04:19 -08:00
Michael Zhu
5bbbae5b23 create contracts-broker package 2020-02-04 10:04:19 -08:00
Jacob Evans
f9c9b9f924 Prevent docs dir from being completely removed 2020-02-04 20:29:16 +10:00
Jacob Evans
5921208ea6 Publish
- @0x/contracts-asset-proxy@3.1.2
 - @0x/contracts-coordinator@3.0.5
 - @0x/contracts-dev-utils@1.0.5
 - @0x/contracts-erc1155@2.0.5
 - @0x/contracts-erc20-bridge-sampler@1.2.0
 - @0x/contracts-erc20@3.0.5
 - @0x/contracts-erc721@3.0.5
 - @0x/contracts-exchange-forwarder@4.0.5
 - @0x/contracts-exchange-libs@4.1.1
 - @0x/contracts-exchange@3.1.1
 - @0x/contracts-extensions@5.1.4
 - @0x/contracts-integrations@2.2.2
 - @0x/contracts-multisig@4.0.5
 - @0x/contracts-staking@2.0.5
 - @0x/contracts-test-utils@5.1.2
 - @0x/contracts-utils@4.2.0
 - 0x.js@9.0.6
 - @0x/abi-gen@5.1.1
 - @0x/asset-swapper@4.1.0
 - @0x/base-contract@6.1.1
 - @0x/contract-addresses@4.4.0
 - @0x/contract-wrappers-test@12.2.6
 - @0x/contract-wrappers@13.4.1
 - @0x/contracts-gen@2.0.5
 - @0x/dev-utils@3.1.2
 - @0x/instant@1.0.43
 - @0x/migrations@6.0.1
 - @0x/monorepo-scripts@1.0.48
 - @0x/order-utils@10.1.2
 - @0x/orderbook@2.1.1
 - @0x/sol-compiler@4.0.5
 - @0x/sol-coverage@4.0.5
 - @0x/sol-doc@3.1.2
 - @0x/sol-profiler@4.0.5
 - @0x/sol-trace@3.0.5
 - @0x/sol-tracing-utils@7.0.5
 - @0x/subproviders@6.0.5
2020-02-04 20:22:07 +10:00
Jacob Evans
f89c78abd1 Updated CHANGELOGS & MD docs 2020-02-04 20:21:45 +10:00
David Sun
74d3b9334c Add liquidity source breakdown to asset-swapper (#2465)
* add liquidity source breakdown to asset-swapper

* remove debug line

* use OptimizedMarketOrder metadata

* updated change-log

* prettier + lint

* bug fixes

* fixes

* Prettier

* Fix types

Co-authored-by: Jacob Evans <dekz@dekz.net>
2020-02-04 19:03:28 +10:00
Xianny
919fc66b9d Stop hardcoding contract addresses (#2461)
* stop hardcoding contract addresses

* update changelog

* export ContractAddresses for docs
2020-02-04 17:49:45 +10:00
Francesco Agosti
400fb5a5bb Merge pull request #2468 from 0xProject/feat/fix-test-publish
Bump maxBuffer?
2020-02-03 19:59:03 -08:00
fragosti
3bb4f9085c Add post-instal step 2020-02-03 18:13:31 -08:00
Jacob Evans
714c6cec3c Bump maxBuffer? 2020-02-03 17:50:32 -08:00
Lawrence Forman
cb69921202 ERC20BridgeSampler: Unlock full sampling on Kovan (#2459)
* `@0x/contracts-utils`: Update kovan addresses in `DeploymentConstants`

* `@0x/contracts-erc20-bridge-sampler`: Make source IDs static on all networks, not inherited from `DeploymentConstants`.

* `@0x/contract-addresses`: Update `ERC20BridgeSampler` addresses on mainnet and kovan.

Co-authored-by: Lawrence Forman <me@merklejerk.com>
2020-01-31 11:27:28 -05:00
Jacob Evans
277a0adac9 [base-contract] throw string revert error (#2453) 2020-01-24 07:48:26 +10:00
Jacob Evans
02d14f504f Remove docs from sol-doc gitignore 2020-01-23 12:10:42 +10:00
Jacob Evans
1ab7664a60 Publish
- @0x/contracts-integrations@2.2.1
 - 0x.js@9.0.5
 - @0x/asset-swapper@4.0.1
 - @0x/instant@1.0.42
2020-01-23 11:58:27 +10:00
Jacob Evans
1be46ffb7e Updated CHANGELOGS & MD docs 2020-01-23 11:58:10 +10:00
Lawrence Forman
6ca52aed0d @0x/asset-swapper: Fix understimated protocol fee in worst case quote. (#2452) 2020-01-22 18:22:56 -05:00
Jacob Evans
74e20970e2 Create docs folder for sol-doc 2020-01-22 18:56:10 +10:00
Jacob Evans
93f2b6b4d8 Publish
- @0x/contracts-asset-proxy@3.1.1
 - @0x/contracts-coordinator@3.0.4
 - @0x/contracts-dev-utils@1.0.4
 - @0x/contracts-erc1155@2.0.4
 - @0x/contracts-erc20-bridge-sampler@1.1.0
 - @0x/contracts-erc20@3.0.4
 - @0x/contracts-erc721@3.0.4
 - @0x/contracts-exchange-forwarder@4.0.4
 - @0x/contracts-exchange-libs@4.1.0
 - @0x/contracts-exchange@3.1.0
 - @0x/contracts-extensions@5.1.3
 - @0x/contracts-integrations@2.2.0
 - @0x/contracts-multisig@4.0.4
 - @0x/contracts-staking@2.0.4
 - @0x/contracts-test-utils@5.1.1
 - @0x/contracts-utils@4.1.0
 - 0x.js@9.0.4
 - @0x/abi-gen@5.1.0
 - @0x/assert@3.0.4
 - @0x/asset-swapper@4.0.0
 - @0x/base-contract@6.1.0
 - @0x/connect@6.0.4
 - @0x/contract-addresses@4.3.0
 - @0x/contract-artifacts@3.4.0
 - @0x/contract-wrappers-test@12.2.5
 - @0x/contract-wrappers@13.4.0
 - @0x/contracts-gen@2.0.4
 - @0x/dev-utils@3.1.1
 - @0x/instant@1.0.41
 - @0x/json-schemas@5.0.4
 - @0x/migrations@6.0.0
 - @0x/monorepo-scripts@1.0.47
 - @0x/order-utils@10.1.1
 - @0x/orderbook@2.1.0
 - @0x/sol-compiler@4.0.4
 - @0x/sol-coverage@4.0.4
 - @0x/sol-doc@3.1.1
 - @0x/sol-profiler@4.0.4
 - @0x/sol-trace@3.0.4
 - @0x/sol-tracing-utils@7.0.4
 - @0x/sra-spec@3.0.4
 - @0x/subproviders@6.0.4
 - @0x/utils@5.2.0
 - @0x/web3-wrapper@7.0.4
2020-01-22 18:49:46 +10:00
Jacob Evans
00e616b57a Updated CHANGELOGS & MD docs 2020-01-22 18:49:24 +10:00
Jacob Evans
e436673304 [asset-swapper] Change Exchange sell to marketSellOrdersFillOrKill (#2450)
* Change Exchange sell to marketSellOrdersFillOrKill

* Update Changelog
2020-01-22 18:25:09 +10:00
James Towle
ce04d3ce41 Fix regression in DevUtils (#2449)
* fix bug in OrderTransferSimulationUtils causing failures for 721 assets

* Patched the regression and added tests

* Added regression test for fillable order

* Created a test for in and out of process ganache

* Split up DevUtils into two contracts

* Updated migration

* Remove the in and out of process ganache test

* Fixed contract addresses

* Appease linter

* Addressed review comments and updated artifacts, wrappers, and snapshots

* Fixed regression after refactor

* Update DevUtils and libTransactionDecoder contracts on mainnet and testnets

* Addressed @mzhu's review feedback

* Addressed @hysz's review feedback

* Updated devUtils address on testnets and mainnet after deployment

Co-authored-by: mzhu25 <mchl.zhu.96@gmail.com>
Co-authored-by: Fabio B <kandinsky454@protonmail.ch>
2020-01-22 12:54:10 +10:00
Jacob Evans
4e46bf4697 Merge pull request #2427 from 0xProject/feature/erc20-bridge-sampler/query-multiple-buys-sells
ERC20BridgeSampler: Allow for batching multiple buy/sell samples
2020-01-22 11:54:45 +10:00
Jacob Evans
9b95508f99 Merge pull request #2445 from 0xProject/feat/asset-swapper/better-best-price-quote
asset-swapper: provide more accurate best quote price
2020-01-22 11:16:40 +10:00
Jacob Evans
c8c24456c1 Fix prettier 2020-01-22 10:01:18 +10:00
Lawrence Forman
80a6e82e1b @0x/contracts-erc20-bridge-sampler: Fix linter error. 2020-01-21 17:47:27 -05:00
Lawrence Forman
80cec20d38 Update packages/asset-swapper/src/utils/swap_quote_calculator.ts
Co-Authored-By: Jacob Evans <jacob@dekz.net>
2020-01-21 16:53:02 -05:00
Lawrence Forman
26cb22020d Update packages/asset-swapper/src/utils/swap_quote_calculator.ts
Co-Authored-By: Jacob Evans <jacob@dekz.net>
2020-01-21 16:52:54 -05:00
Lawrence Forman
09d05d09c9 @0x/asset-swapper: Provide more accurate best quote price. 2020-01-21 15:48:35 +10:00
Jacob Evans
160c91f908 Rename to Batch 2020-01-21 15:48:35 +10:00
Jacob Evans
58f41bcd42 Update asset-swapper WIP 2020-01-21 15:46:31 +10:00
Jacob Evans
0235429995 Update contract addresses 2020-01-21 09:15:47 +10:00
Lawrence Forman
f79697e117 @0x/contract-wrappers: Fix linter error. 2020-01-20 13:30:58 +10:00
Lawrence Forman
6f0019c71e @0x/contract-wrappers: Update IERC20BridgeSampler wrapper. 2020-01-20 13:30:58 +10:00
Lawrence Forman
1a04a18245 @0x/contract-artifacts: Update IERC20BridgeSampler artifact. 2020-01-20 13:30:57 +10:00
Lawrence Forman
0cf3ff8209 @0x/contracts-erc20-bridge-sampler: Increase gas forwarded to kyber and eth2dai.
`@0x/contracts-erc20-bridge-sampler`: Bail as soon as any quote from a DEX fails.

`@0x/contracts-erc20-bridge-sampler`: Fix broken tests.
2020-01-20 13:30:57 +10:00
Lawrence Forman
7f56091fbd @0x/asset-swapper: Add exponential sampling, exposed by sampleDistributionBase.
`@0x/asset-swapper`: Disable ethgasstation polling in tests.
`@0x/asset-swapper`: Tweak default hyper parameters to be friendlier to big fills.
2020-01-20 13:30:57 +10:00
F. Eugene Aumson
391f9b31f6 wrappers.py: satisfy linter (rm unnecessary pass) 2020-01-20 13:30:56 +10:00
F. Eugene Aumson
1d7c0f504a abi-gen: ran black on CLI test Python output 2020-01-20 13:30:56 +10:00
F. Eugene Aumson
9cdc62f918 abi-gen: fix bug w/ 2D arrays of UDT's in Python
Fix bug in handling 2-dimensional arrays of user defined data types in
generated Python code.
2020-01-20 13:30:56 +10:00
F. Eugene Aumson
6027d0481e wrappers.py: fix clean not rm'ing gen'd code 2020-01-20 13:30:55 +10:00
F. Eugene Aumson
277fb92f9e abi-gen: exit when black fails to parse Python
Note: this is not the same case as when the black executable can't be
found; that case is still just a (non-fatal) warning.
2020-01-20 13:30:55 +10:00
Jacob Evans
79b6c3c1af Update CHANGELOGs 2020-01-20 13:30:55 +10:00
Jacob Evans
ad17174119 Rename to Batch 2020-01-20 13:30:54 +10:00
Jacob Evans
6c2692eec0 Enable batch fetching from orderbook. Refactor 2020-01-20 13:30:54 +10:00
Jacob Evans
08640e8575 Update asset-swapper WIP 2020-01-20 13:30:54 +10:00
Jacob Evans
4a2575136f Allow for batching multiple buy/sell samples 2020-01-20 13:30:52 +10:00
Jacob Evans
e792afad17 Merge pull request #2441 from 0xProject/kroeger/fix_function_name_in_readme
Fixed function name in README, network -> chain
2020-01-20 13:29:45 +10:00
Jacob Evans
5ecc4b027d Merge pull request #2448 from 0xProject/fix/python-latest-ganache
Fix/python latest ganache
2020-01-20 13:25:26 +10:00
Jacob Evans
bc540f0cf0 [python] change gas estimate expected 2020-01-20 12:53:34 +10:00
Jacob Evans
a24b14c465 Pull 0xorg/ganache-cli:6.0.0 in circleci 2020-01-20 12:06:28 +10:00
Jacob Evans
c3f36c3123 Change python to use latest ganache 2020-01-20 11:50:43 +10:00
fabioberger
1d34da7557 Remove -v3-beta from snapshot name 2020-01-19 20:10:06 +01:00
fabioberger
27d74a4327 Update ganache-cli version to Istanbul-compatible version 2020-01-19 20:09:50 +01:00
mzhu25
8a20cc682c Merge pull request #2446 from 0xProject/feature/contract-addresses/update-dev-utils-1-17-20
`@0x/contract-addresses`: update DevUtils addresses
2020-01-17 13:38:04 -08:00
mzhu25
9b20359e7b Merge pull request #2431 from 0xProject/feature/fuzz/revert-assertions
`@0x/contracts-integrations`: Negative assertions for fuzzing
2020-01-17 13:10:00 -08:00
Michael Zhu
8866d0ccef update contract-addresses changelog 2020-01-17 12:42:56 -08:00
Michael Zhu
7fa91a9971 update dev-utils addresses 2020-01-17 12:39:07 -08:00
Amir Bandeali
28d1f3eef0 Merge pull request #2440 from 0xProject/feat/dev-utils/chai-bridge-validation
Add ChaiBridge order balance/allowance checks to DevUtils
2020-01-17 11:46:27 -08:00
Amir
f321cf6655 Update DevUtils contract wrapper 2020-01-17 11:08:04 -08:00
Amir
14ade737da Fix linting errors 2020-01-17 10:47:17 -08:00
Amir
41b1b1f141 Skip failing dydxBridge tests 2020-01-17 10:47:17 -08:00
Amir
25dfd47d32 Fix Ganache migrations 2020-01-17 10:47:17 -08:00
Amir
6afa9c8b92 Add mainnet integration tests for checking balances/allowances of ChaiBridge orders using DevUtils 2020-01-17 10:00:16 -08:00
Amir
2fc449da4c Fix integrations tests build 2020-01-17 10:00:16 -08:00
Amir
5dd3b8cf9d Special case unlimited allowance for Chai 2020-01-17 09:59:03 -08:00
Amir
e834fa0050 Split Dai calculation and erc20 balance checks into separate functions 2020-01-17 09:59:03 -08:00
Amir
9a97401606 Add ChaiBridge allowance checks 2020-01-17 09:59:03 -08:00
Amir
410a3fef18 Add ChaiBridge balance checks to DevUtils 2020-01-17 09:59:03 -08:00
Amir Bandeali
969b9814d5 Merge pull request #2442 from 0xProject/feat/forwarder/1155-support
Add 1155 support to Forwarder
2020-01-16 11:41:20 -08:00
Amir
2275e27b87 Rename internal functions in LibAssetDataTransfer and fix tests 2020-01-15 18:33:02 -08:00
Amir
62b06cd204 Add tests for transfering ERC1155 tokens out 2020-01-15 18:33:02 -08:00
Amir
350934ca21 Remove unused params 2020-01-15 18:32:57 -08:00
mzhu25
6332673434 Merge pull request #2436 from 0xProject/fix/dev-utils/map-fixes
`@0x/contracts-dev-utils`: LibAssetData fixes
2020-01-15 16:10:11 -08:00
Michael Zhu
f217840998 address comments 2020-01-15 13:22:53 -08:00
Michael Zhu
089ec35ceb update changelog 2020-01-15 13:22:53 -08:00
Michael Zhu
fecd0b809e tslint be trippin 2020-01-15 13:20:54 -08:00
Michael Zhu
4707a46561 Add negative assertions for endEpoch 2020-01-15 13:20:54 -08:00
Michael Zhu
616533c5a8 Add negative assertions for moveStake 2020-01-15 13:20:54 -08:00
Michael Zhu
c5b2991821 fix bug in finalizePool 2020-01-15 13:20:54 -08:00
Michael Zhu
c36d0fdc7c invalidWithdrawDelegatorRewardsAssertion 2020-01-15 13:20:54 -08:00
Michael Zhu
544e09cf4b invalidUnstakeAssertion 2020-01-15 13:20:54 -08:00
Michael Zhu
c110dc9e6a generic assertion for TRANSFER_FAILED reverts; _invalidStake generator 2020-01-15 13:20:54 -08:00
Michael Zhu
3bf37d6afd invalidDecreaseStakingPoolOperatorShareAssertion 2020-01-15 13:20:54 -08:00
Michael Zhu
b80ae5796b invalidCreateStakingPoolAssertion 2020-01-15 13:20:54 -08:00
Michael Zhu
2083632299 Update addresses, artifact, wrapper 2020-01-15 10:38:57 -08:00
Amir
3ca2f8ac9e Split out transfer logic into library, add 1155 support 2020-01-14 20:27:12 -08:00
Greg Hysz
7172432084 Merge pull request #2443 from 0xProject/fix/abiDecoder/LogDecodingDynamicData
Fixes log decoding of dynamic data
2020-01-14 18:33:57 -08:00
Greg Hysz
0e6afd147f Merge pull request #2437 from 0xProject/test/contracts-integrations/fuzzOrderMatching
Fuzz order matching
2020-01-14 18:04:27 -08:00
Greg Hysen
46275a4f43 Minor fixes to order matching fuzz code 2020-01-14 17:32:10 -08:00
Michael Zhu
1dca378e03 add division-by-zero check for ERC1155 too 2020-01-14 16:32:18 -08:00
Greg Hysen
06669594b1 Updated changelogs. 2020-01-14 16:18:50 -08:00
Greg Hysen
c09ac58ac0 Fuzz testing for matchOrders and matchOrdersWithMaximalFill. 2020-01-14 16:17:43 -08:00
Greg Hysen
e01d32ef1a added order matching functions to Taker actor. 2020-01-14 16:17:43 -08:00
Greg Hysen
5ea3bcf59e Added matchOrders and matchOrdersWithMaximalFill to the reference functions. 2020-01-14 16:17:43 -08:00
Greg Hysen
aa8b14b7ee Added order martching to Maker actor. Also fixed the joinStakingPool to record the pool id. 2020-01-14 16:17:43 -08:00
Greg Hysen
e1722cf739 Updated changelogs 2020-01-14 15:01:02 -08:00
Greg Hysen
7a7f70e15d Updating tests after fixing log decoding 2020-01-14 14:17:45 -08:00
Greg Hysen
b3c3ec16e5 Fixed log decoding. Dynamic structures were not decoding properly. Now uses AbiEncoder from utils package. 2020-01-14 14:17:42 -08:00
Michael Zhu
149f863951 unbreak migrations cli 2020-01-14 09:15:17 -08:00
Michael Zhu
684d09faac refactor LibAssetData tests 2020-01-13 15:29:37 -08:00
Michael Zhu
8a42691c80 Add test cases 2020-01-13 14:10:55 -08:00
Michael Zhu
d591b3dd98 LibAssetData fixes 2020-01-13 14:10:55 -08:00
Alex Kroeger
a90fb4d8b6 Fixed function name in README, network -> chain 2020-01-13 13:33:54 -08:00
Lawrence Forman
ebd08d9c63 Contract wrappers: Catch empty reverts on live networks (#2433)
* `@0x/utils`: Allow strict decoding of return values.

* `@0x/base-contract`: Catch empty call reverts on live networks.
`@0x/abi-gen`: Catch empty call reverts on live networks.

* `@0x/contracts-integrations`: Add mainnet contract wrapper `callAsync()` revert behavior tests.

* `@0x/contract-wrappers`: Regenerate wrappers to catch empty reverts on live networks.

* Update CHANGELOGs

* `@0x/contracts-integrations`: Fix solidity linter errors.

* `@0x/abi-gen`: Regenerate test outputs.

* `@0x/base-contract`: Update CHANGELOG.

Co-authored-by: Lawrence Forman <me@merklejerk.com>
2020-01-13 15:33:45 -05:00
Lawrence Forman
71731d223b Update contract wrappers (esp Forwarder + asset-swapper) (#2432)
* `@0x/contract-artifacts`: Update artifacts.

* `@0x/contract-wrappers`: Regenerate wrappers.

* `@0x/migrations`: Update Forwarder migration.

* `@0x/asset-swapper`: Update forwarder fees for new forwarder contract.

* `@0x/dev-utils`: Make `"istanbul"` the default `hardfork` when creating a ganache provider.

* `@0x/asset-swapper`: Remove debug code.

* `@0x/asset-swapper`: Remove `getSmartContractParamsOrThrowAsync()` because why does it even exist?
`@0x/asset-swapper`: Fix broken tests.
`@0x/asset-swapper`: Correctly handle affiliate fees in `getCalldataOrThrow()`.

* `@0x/contract-wrappers`: Export `ExchangeOwnershipTransferredEventArgs`.
`@0x/0x.js`: Export `ExchangeOwnershipTransferredEventArgs`.
`@0x/asset-swapper`: Unexport `MethodAbi`, `ConstructorStateMutability`, and `StateMutability`.

* Update changelogs

* Update packages/migrations/CHANGELOG.json

Co-Authored-By: Jacob Evans <jacob@dekz.net>

* Update packages/asset-swapper/CHANGELOG.json

Co-Authored-By: Jacob Evans <jacob@dekz.net>

Co-authored-by: Lawrence Forman <me@merklejerk.com>
Co-authored-by: Jacob Evans <dekz@dekz.net>
2020-01-09 15:35:22 -05:00
David Sun
726ea5e01e Merge pull request #2430 from 0xProject/feature/instant/enable-aggregator
Instant: whitelist tokens using bridge orders array
2020-01-08 16:50:40 -08:00
David Sun
16c7d2964b typo 2020-01-08 16:17:25 -08:00
David Sun
5a6e494bda lint + prettier 2020-01-08 16:16:29 -08:00
David Sun
88c6d89fbb whitelist constants array 2020-01-08 13:55:53 -08:00
Lawrence Forman
de12da18da Exchange signature validation fuzz tests (#2425)
* `@0x/contracts-integrations`: Add Exchange signature validation fuzz tests.

* `@0x/contracts-integrations`: Switch from actor pattern to just pure function generators.

Co-authored-by: Lawrence Forman <me@merklejerk.com>
2020-01-07 17:35:25 -05:00
Amir Bandeali
8d10736934 Merge pull request #2390 from 0xProject/feat/forwarder/v2-backwards-compatibility
Make Forwarder backwards compatible with v2
2020-01-07 13:04:27 -08:00
Amir
2328e02d82 Redeploy Forwarder 2020-01-07 11:03:18 -08:00
Michael Zhu
87cd5fca90 address comments 2020-01-07 11:03:18 -08:00
Michael Zhu
b70cb726c5 remove _noTakerFee (i.e. disallow StaticCall takerFeeAssetData) 2020-01-07 11:03:18 -08:00
Michael Zhu
295811ed5a add integrations tests 2020-01-07 11:03:18 -08:00
Michael Zhu
4bc55551c6 Add unit tests 2020-01-07 11:03:18 -08:00
Michael Zhu
2b8c6dc8f9 Forwarder StaticCall and MultiAsset buy support 2020-01-07 11:03:18 -08:00
Amir Bandeali
8b27380feb Fix dep version 2020-01-07 11:03:18 -08:00
Amir Bandeali
8de3a90851 Update CHANGELOG 2020-01-07 11:03:18 -08:00
Amir Bandeali
f8bb94d721 Remove unnecessary BigNumber cast 2020-01-06 22:12:05 -08:00
Amir Bandeali
0c6d06e7bb Redeploy bridges and Forwarder on mainnet 2020-01-06 22:12:05 -08:00
Amir Bandeali
b0aa5d3af2 Check makerFeeAssetData length before attempting to read id 2020-01-06 22:12:05 -08:00
Amir Bandeali
27d09713fd Add forwarder mainnet tests 2020-01-06 22:12:05 -08:00
Amir Bandeali
ff18852879 Fix build 2020-01-06 22:12:05 -08:00
Amir Bandeali
e515c91e5e Do not attempt to transfer asset if fill failed 2020-01-06 22:12:05 -08:00
Amir Bandeali
1d5800c4f7 Fix WETH compilation 2020-01-06 22:12:05 -08:00
Amir Bandeali
de8f190945 Change erc-20 package compiler target to istanbul 2020-01-06 22:12:05 -08:00
Amir Bandeali
f371e3c8d3 Regenerate boilerplate 2020-01-06 22:12:05 -08:00
Amir Bandeali
b15a6290a7 Handle v2 order edge cases 2020-01-06 22:12:05 -08:00
Amir Bandeali
0f151db355 Enable istanbul in Ganache 2020-01-06 22:12:05 -08:00
Amir Bandeali
fa99b75d1f Redeploy Forwarder and all bridges 2020-01-06 22:12:05 -08:00
Amir Bandeali
4a299c1f39 Change EVM target to istanbul for all contract packages except erc-20 2020-01-06 22:12:05 -08:00
Amir Bandeali
30a2015a68 Fix build 2020-01-06 22:12:05 -08:00
Amir Bandeali
c7c8a4891f Update TS boilerplate 2020-01-06 22:12:05 -08:00
Amir Bandeali
fe9fc6b459 Allow v2 orders to be filled if their makerAssetFeeData field uses a v2 order id 2020-01-06 22:12:05 -08:00
Jacob Evans
2113fb490d Publish
- @0x/contracts-asset-proxy@3.1.0
 - @0x/contracts-coordinator@3.0.3
 - @0x/contracts-dev-utils@1.0.3
 - @0x/contracts-erc1155@2.0.3
 - @0x/contracts-erc20-bridge-sampler@1.0.3
 - @0x/contracts-erc20@3.0.3
 - @0x/contracts-erc721@3.0.3
 - @0x/contracts-exchange-forwarder@4.0.3
 - @0x/contracts-exchange-libs@4.0.3
 - @0x/contracts-exchange@3.0.3
 - @0x/contracts-extensions@5.1.2
 - @0x/contracts-integrations@2.1.0
 - @0x/contracts-multisig@4.0.3
 - @0x/contracts-staking@2.0.3
 - @0x/contracts-test-utils@5.1.0
 - @0x/contracts-utils@4.0.3
 - 0x.js@9.0.3
 - @0x/abi-gen@5.0.3
 - @0x/assert@3.0.3
 - @0x/asset-swapper@3.0.3
 - @0x/base-contract@6.0.3
 - @0x/connect@6.0.3
 - @0x/contract-addresses@4.2.0
 - @0x/contract-artifacts@3.3.0
 - @0x/contract-wrappers-test@12.2.4
 - @0x/contract-wrappers@13.3.0
 - @0x/contracts-gen@2.0.3
 - @0x/dev-utils@3.1.0
 - @0x/instant@1.0.40
 - @0x/json-schemas@5.0.3
 - @0x/migrations@5.1.0
 - @0x/monorepo-scripts@1.0.46
 - @0x/order-utils@10.1.0
 - @0x/orderbook@2.0.1
 - @0x/sol-compiler@4.0.3
 - @0x/sol-coverage@4.0.3
 - @0x/sol-doc@3.1.0
 - @0x/sol-profiler@4.0.3
 - @0x/sol-trace@3.0.3
 - @0x/sol-tracing-utils@7.0.3
 - @0x/sra-spec@3.0.3
 - @0x/subproviders@6.0.3
 - @0x/utils@5.1.2
 - @0x/web3-wrapper@7.0.3
2020-01-06 11:10:22 +10:00
Jacob Evans
0afedbd252 Updated CHANGELOGS & MD docs 2020-01-06 11:10:03 +10:00
Jacob Evans
3dec38450a Merge pull request #2396 from Arctek/patch-1
Fix circular reference
2020-01-06 10:29:19 +10:00
Jacob Evans
d7a00b05e3 Merge pull request #2423 from 0xProject/fix/migrations-docker-wget-timestamping
@0x/migrations/Dockerfile: Remove --timestamping arg from wget invocation
2020-01-06 10:27:35 +10:00
Lawrence Forman
ff2cc8c887 Add aggregator mainnet tests (#2407)
* `@0x/contracts-erc20-bridge-sampler`: Add gas limits to external quote calls.
`@0x/contract-addresses`: Point `erc20BridgeSampler` to new version.

* `@0x/contracts-utils`: Add kovan addresses to `DeploymentConstants`.
`@0x/contract-addresses`: Add kovan `ERC20BridgeSampler` address.

* `@0x/contracts-erc20-bridge-sampler`: Fix changelog.

* `@0x/asset-swapper`: Ignore zero sample results from the sampler contract.
`@0x/asset-swapper`: Allow skipping Uniswap when dealing with low precision amounts with `minUniswapDecimals` option.
`@0x/asset-swapper`: Increase default `runLimit` from `1024` to `4096`.
`@0x/asset-swapper`: Increase default `numSamples` from `8` to `10`
`@0x/asset-swapper`: Fix ordering of optimized orders.
`@0x/asset-swapper`: Fix best and worst quotes being reversed sometimes.
`@0x/asset-swapper`: Fix rounding of quoted asset amounts.

* `@0x/asset-swapper`: Change default `minUniswapDecimals` option from 8 to 7.

* `@0x/asset-swapper`: Revert uniswap decimals fix.

* `@0x/contracts-test-utils`: Add `blockchainTests.live()` for live network tests.
`@0x/contracts-test-utils`: Add modifiers to `blockchainTests.fork()`.
`@0x/contracts-integrations`: Add aggregator mainnet tests.

* `@0x/contracts-integrations`: Fix `fork/resets` modifier ordering on dydx tests.
`@0x/contracts-integrations`: Move and tweak aggregation tests.

* `@0x/contracts-integrations`: Handle non-responsive third-party SRA ordebooks with a little more grace.

* `@0x/contracts-integrations`: Fix linter error.

* `@0x/contracts-test-utils`: Consolidate fork provider logic into `mocha_blockchain.ts`.

* `@0x/contracts-integrations`: Run prettier on aggregation fill tests.

* `@0x/dev-utils`: Add `locked` to `Web3Config`.

* `@0x/contracts-integrations`: Update mainnet fork tests.
`@0x/contracts-test-utils`: Fix forked tests being skipped.
`@0x/contracts-erc20-bridge-sampler`: Regenerate artifacts.

* `@0x/contracts-test-utils`: Remove unecessary `locked` option when creating forked ganache provider.

* Fix redundant zero check

* Set fee amount in fillable amounts test

Co-authored-by: Jacob Evans <dekz@dekz.net>
2020-01-03 23:47:40 -05:00
Lawrence Forman
0571a96cea Fix asset-swapper bugs and misc improvements. (#2406)
* `@0x/contracts-erc20-bridge-sampler`: Add gas limits to external quote calls.
`@0x/contract-addresses`: Point `erc20BridgeSampler` to new version.

* `@0x/asset-swapper`: Ignore zero sample results from the sampler contract.
`@0x/asset-swapper`: Allow skipping Uniswap when dealing with low precision amounts with `minUniswapDecimals` option.
`@0x/asset-swapper`: Increase default `runLimit` from `1024` to `4096`.
`@0x/asset-swapper`: Increase default `numSamples` from `8` to `10`
`@0x/asset-swapper`: Fix ordering of optimized orders.
`@0x/asset-swapper`: Fix best and worst quotes being reversed sometimes.
`@0x/asset-swapper`: Fix rounding of quoted asset amounts.

* `@0x/contracts-utils`: Add kovan addresses to `DeploymentConstants`.
`@0x/contract-addresses`: Add kovan `ERC20BridgeSampler` address.

* `@0x/asset-swapper`: Change default `minUniswapDecimals` option from 8 to 7.

* `@0x/contracts-erc20-bridge-sampler`: Fix changelog.

* `@0x/asset-swapper`: Revert uniswap decimals fix.

* `@0x/asset-swapper`: Undo bridge slippage when computing best case quote.

* `@0x/asset-swapper`: Take asset data from input orders instead of output orders in quote result calculation.

* `@0x/asset-swapper`: Move `SAMPLER_CONTRACT_GAS_LIMIT` constant to `market_operation_utils/constants`.

* Compare equivalent asset data

* Fix redundant zero check

* Update CHANGELOG

* Set fee amount in fillable amounts test

Co-authored-by: Jacob Evans <dekz@dekz.net>
2020-01-03 23:21:39 -05:00
Lawrence Forman
b7b457b076 Generate (complete) solidity docs (#2391)
* `@0x/sol-doc`: New doc generator.

* `@0x/sol-compiler`: Be more tolerant of AST-only compilation targets.

* `@0x/contracts-exchange`: Add more devdoc comments.
`@0x/contracts-exchange-libs`: Add more devdoc comments.

* `@0x/sol-doc`: Update package script.

* `@0x/sol-doc`: Remove unused files and update package scripts to be easier to configure.

* Add more devdocs to contracts.

* `@0x/sol-doc`: Remove doc artifacts.

* `@0x/sol-doc`: Add `.gitignore` and `.npmignore`.

* `@0x/contracts-exchange`: Fix compilation errors.

* Fix more broken contracts.

* `@0x/contracts-erc20-bridge-sampler`: Fix failing tests.

* `@0x/contracts-asset-proxy`: Remove accidentally introduced hackathion file (lol).

* `@0x/sol-doc`: Prevent some inherited contracts from being included in docs unintentionally.

* `@0x/sol-doc`: Rename test file.

* `@0x/contracts-exchange`: Update `orderEpoch` devdoc.

* `@0x/sol-doc`: Tweak event and function docs.

* Update CODEOWNERS.

* `@0x/sol-doc` Tweak function md generation.

* `@0x/sol-doc`: add `transformDocs()` tests.

* `@0x/sol-doc`: add `extract_docs` tests.

* `@0x/sol-doc` Fix linter errors.

* `@0x/contracts-erc20-bridge-sampler`: Fix broken `ERC20BridgeSampler.sol` compile.

* `@0x/sol-doc` Fix mismatched `dev-utils` dep version.

* `@0x/sol-doc`: Add `gen_md` tests.

* `@0x/sol-doc`: Remove `fs.promises` calls.

* `@0x/sol-doc`: Fix linter errors.

* `@0x/sol-doc`: Export all relevant types and functions.

Co-authored-by: Lawrence Forman <me@merklejerk.com>
2020-01-03 22:59:18 -05:00
F. Eugene Aumson
d2c12005b2 Also publish versioned docker image tag
Not just `latest`
2020-01-03 16:51:02 -05:00
F. Eugene Aumson
25f26d7e5f Remove --timestamping arg from wget invocation 2020-01-03 12:40:40 -05:00
F. Eugene Aumson
9d5724e1a0 Fix 0xorg/ganache-cli docker image not supporting re-runs (#2420)
* Overwrite existing snapshot when unzipping

* Don't re-download snapshot if it isn't updated

* Update CHANGELOG.json
2020-01-02 20:19:06 -05:00
David Sun
784d23ec87 Merge pull request #2416 from 0xProject/feature/instant/disable-file-removal--in-s3
Instant - Added should_remove_files_in_s3 flag in discharge configuration
2019-12-22 20:54:43 -08:00
James Towle
709689a7ee Merge pull request #2417 from 0xProject/tests/fix/dev-utils-tests
Fixed the DevUtils tests
2019-12-21 16:55:33 -08:00
F. Eugene Aumson
35d5d3d995 Pare down Mesh env vars in Py test env (#2418) 2019-12-21 13:19:00 -05:00
Alex Towle
630a8d8a4e Addressed dorothy's nit 2019-12-20 19:14:52 -08:00
Alex Towle
54eb1d9055 Fixed the DevUtils tests 2019-12-20 15:51:45 -08:00
David Sun
cb63caea61 prettier 2019-12-20 12:57:40 -08:00
David Sun
8e046bb022 updated to new flag name 2019-12-20 12:07:59 -08:00
David Sun
189b53b8c4 added removal flag in configuration 2019-12-20 11:40:54 -08:00
Lawrence Forman
9b7277d464 Fix Kyber and Uniswap ERC20Bridges (#2412)
* `@0x/contracts-asset-proxy`: Fix `UniswapBridge` token -> token transfer logic.
`@0x/contract-addresses`: Update `UniswapBridge` mainnet address.

* `@0x/asset-proxy`: Fix `KyberBridge` incorrect `minConversionRate` calculation.

* `@0x/contract-addresses`: Update `KyberBridge` mainnet address.
2019-12-20 13:41:52 -05:00
F. Eugene Aumson
551a65c069 0x-sra-client.py: Fix bug in config_order, and other small improvements (#2399)
* Bug fix: unescape backslashes in regexes

Root problem is that there are too many backslashes in the SRA spec
itself.  See https://github.com/0xProject/0x-monorepo/issues/1727

This was previously fixed for heavily-tested endpoints (get and post
order, etc), but was only recently discovered for the get-order-config
endpoint.

* Demonstrate get_order_config()

* Rename DefaultApi to RelayerApi

* Simplify RelayerApi instantiation

* Document paylod and response schemas

* Stop caring which contracts are wrapped

* Increase platform agnosticism

* Update CHANGELOG

* Remove unnecessary f-string
2019-12-20 12:24:55 -05:00
F. Eugene Aumson
4c21a697f4 sra_client.py: Tweak Mesh block polling interval used in tests (#2413)
* Change Mesh block polling interval to 50ms

* Increase Mesh's Ethereum node RPC rate limit
2019-12-20 11:26:57 -05:00
Greg Hysz
a8506c07ae Merge pull request #2401 from 0xProject/feat/asset-proxy/DyDxBridgeTests
DydxBridge Contract Integration Tests
2019-12-19 22:16:44 -08:00
Greg Hysen
b0feb85b5c Fixed merge conflict 2019-12-19 21:36:43 -08:00
Greg Hysen
f371eba8ad Hardcoded address of ERC20BridgeProxy in unlocked accounts 2019-12-19 21:32:03 -08:00
Greg Hysen
265fa52ace Rounding error tests in DydxBridgeProxy 2019-12-19 21:32:03 -08:00
Greg Hysen
c1f5322d38 Added TestDydxUser contract - this is deployed to mainnent as the dYdX Account Owner for the mainnet integration tests. 2019-12-19 21:32:03 -08:00
Greg Hysen
4415e00b38 Added more integration tests for DydxBridge with the Exchange (demonstrates use cases) 2019-12-19 21:32:03 -08:00
Greg Hysen
d4e46c5a9c Updated Changelogs 2019-12-19 21:32:03 -08:00
Greg Hysen
bf5b9949fe Ran prettier 2019-12-19 21:32:03 -08:00
Greg Hysen
3c11a2b1da Increased mocha timeout for mainnet tests 2019-12-19 21:32:03 -08:00
Greg Hysen
1248868169 Added mainnet DydxBridge integration tests with dYdX SoloMargin contract 2019-12-19 21:32:03 -08:00
Greg Hysen
930b95a548 Added integration tests for DydxBridge with Exchange contract 2019-12-19 21:32:03 -08:00
Greg Hysen
27c9f68c7c Added dydx bridge to contract-addresses package 2019-12-19 21:32:02 -08:00
Greg Hysen
358d4d86a7 Added ERC20BridgeProxy.transferFrom tests for DydxBridge 2019-12-19 21:31:07 -08:00
Lawrence Forman
d55eea2239 ERC20BridgeSampler: Gas limits (#2405)
* `@0x/contracts-erc20-bridge-sampler`: Add gas limits to external quote calls.
`@0x/contract-addresses`: Point `erc20BridgeSampler` to new version.

* `@0x/contracts-utils`: Add kovan addresses to `DeploymentConstants`.
`@0x/contract-addresses`: Add kovan `ERC20BridgeSampler` address.

* `@0x/contracts-erc20-bridge-sampler`: Fix changelog.

* `@0x/contracts-erc20-bridge-contracts`: Fix invalid CHANGELOG json (I hope).
2019-12-20 00:08:39 -05:00
David Sun
4507954ea5 Merge pull request #2410 from 0xProject/fix/instant/coverage
Fix bundlewatch for instant and passing static-test
2019-12-19 22:37:42 -05:00
David Sun
8e0a83f8d8 bundlewatch 2019-12-19 19:20:24 -08:00
David Sun
b6ec09e6cf Merge pull request #2409 from 0xProject/feature/instant/minor-fixes-dai-aggregator
Fixes for instant (DAI + disable aggregator functionality)
2019-12-19 20:21:59 -05:00
David Sun
ed4e90623d more fixes 2019-12-19 16:49:20 -08:00
David Sun
38cdb48748 fixes 2019-12-19 16:36:00 -08:00
James Towle
71bfe9b745 Merge pull request #2402 from 0xProject/deploy/dev-utils/12-18-2019
Added artifacts, addresses, and wrappers
2019-12-19 14:38:01 -08:00
Alex Towle
9e7645a167 Removed hand-written timestamps 2019-12-19 13:26:00 -08:00
Alex Towle
6dccc37143 Removed forbidden fields in artifact 2019-12-19 11:40:49 -08:00
Alex Towle
3310310d8c Added artifacts, addresses, and wrappers 2019-12-19 10:32:01 -08:00
Greg Hysz
abb499aad8 Merge pull request #2403 from 0xProject/fix/circle/yarnInstall
Fix Circle builds
2019-12-19 10:24:48 -08:00
Greg Hysen
1afc09b08a Workaround for https://github.com/yarnpkg/yarn/issues/7773 2019-12-19 01:12:46 -08:00
Alex Browne
0e86d72f05 Merge pull request #2384 from 0xProject/update-code-owners-contracts-albrow
Update CODEOWNERS
2019-12-18 13:48:31 -08:00
mzhu25
c9857a2764 Merge pull request #2392 from 0xProject/feature/fuzz/better-input-gen
`@0x/contracts-integrations`: Better input generation for fuzzing
2019-12-18 12:03:23 -08:00
Michael Zhu
701ba3902c add comments 2019-12-18 11:38:33 -08:00
Michael Zhu
bb3ec970a9 lint 2019-12-18 11:38:33 -08:00
Michael Zhu
1d023e6db5 Add optional parameter to sample and sampleSize 2019-12-18 11:38:33 -08:00
Michael Zhu
1bd906ecb3 Add optional distribution parameter to Pseudorandom.integer, use Kumaraswamy distribution for operator share 2019-12-18 11:38:33 -08:00
James Towle
7cbffdb86b Merge pull request #2400 from 0xProject/feature/dev-utils/duplicate-erc721-bug-fix
Duplicate ERC721 Bug Fix
2019-12-18 10:46:27 -08:00
Alex Towle
b979196ffd Remove the taker patch 2019-12-17 19:02:57 -08:00
Alex Towle
2949db5f49 Fixed the bug and added tests that fail without the patch 2019-12-17 19:02:57 -08:00
Alex Towle
47c3ed9705 Fixed the bug and moved "contracts-tests" to "contracts-integrations" 2019-12-17 19:02:57 -08:00
xianny
51ca3109eb Publish
- @0x/contracts-asset-proxy@3.0.2
 - @0x/contracts-coordinator@3.0.2
 - @0x/contracts-dev-utils@1.0.2
 - @0x/contracts-erc1155@2.0.2
 - @0x/contracts-erc20-bridge-sampler@1.0.2
 - @0x/contracts-erc20@3.0.2
 - @0x/contracts-erc721@3.0.2
 - @0x/contracts-exchange-forwarder@4.0.2
 - @0x/contracts-exchange-libs@4.0.2
 - @0x/contracts-exchange@3.0.2
 - @0x/contracts-extensions@5.1.1
 - @0x/contracts-integrations@2.0.2
 - @0x/contracts-multisig@4.0.2
 - @0x/contracts-staking@2.0.2
 - @0x/contracts-test-utils@5.0.1
 - @0x/contracts-tests@0.0.8
 - @0x/contracts-utils@4.0.2
 - 0x.js@9.0.2
 - @0x/abi-gen@5.0.2
 - @0x/assert@3.0.2
 - @0x/asset-swapper@3.0.2
 - @0x/base-contract@6.0.2
 - @0x/connect@6.0.2
 - @0x/contract-addresses@4.1.0
 - @0x/contract-artifacts@3.2.0
 - @0x/contract-wrappers-test@12.2.3
 - @0x/contract-wrappers@13.2.0
 - @0x/contracts-gen@2.0.2
 - @0x/dev-utils@3.0.2
 - @0x/instant@1.0.39
 - @0x/json-schemas@5.0.2
 - @0x/migrations@5.0.2
 - @0x/monorepo-scripts@1.0.45
 - @0x/order-utils@10.0.1
 - @0x/orderbook@2.0.0
 - @0x/sol-compiler@4.0.2
 - @0x/sol-coverage@4.0.2
 - @0x/sol-doc@3.0.2
 - @0x/sol-profiler@4.0.2
 - @0x/sol-resolver@3.0.2
 - @0x/sol-trace@3.0.2
 - @0x/sol-tracing-utils@7.0.2
 - @0x/sra-spec@3.0.2
 - @0x/subproviders@6.0.2
 - @0x/types@3.1.1
 - @0x/typescript-typings@5.0.1
 - @0x/utils@5.1.1
 - @0x/web3-wrapper@7.0.2
2019-12-16 16:05:16 -08:00
xianny
2bcb79dc44 Updated CHANGELOGS & MD docs 2019-12-16 16:05:03 -08:00
xianny
ecec985649 pin python regex version 2019-12-16 14:22:48 -08:00
Lawrence Forman
994908549d Asset-swapper aggregator utils (#2353)
* `@0x/asset-swapper`: Add ERC20Bridge aggregator library.

* `@0x/asset-swapper`: Finish off `aggregate.ts`.

* `@0x/types`: Add `OrderWithoutDomain` type.

* `@0x/asset-swapper`: Add testing infra for sampler/aggregator.

* `@0x/types`: Add `SignedOrderWithoutDomain` type.

* `@0x/asset-swapper`: Update aggregator to take and return orders with signatures.

* `@0x/asset-swapper`: Fix broken aggregator tests.

* `@0x/asset-swapper`: Pass the sampler contract into aggregator entry points.

* `@0x/contract-artifacts`: Add `IERC20BridgeSampler` artifact.

* `@0x/contract-wrappers`: Add `IERC20BridgeSampler` wrapper.

* `@0x/asset-swapper`: Address review comments.

* fixed testing

* refactored aggregate.ts and embeded into asset-swapper

* added adjusted rates for taker and maker fees

* remove PrunedSignedOrders

* updated contract-addresses and addressed some other todos

* streamlined logic

* patched in lawrences changes

* renamed aggregator utils and removed market_utils.ts

* added ack heartbeats

* fixed bug

* patches

* added dummy order things

* Dummy with valid sig

* Tweak gas price calculation to wei

* added test coverage and fixed bugs

* fixed migrations

* Fix CHANGELOGs and types export

* Deploy latest ERC20BridgeSampler on Mainnet

* `@0x/types` Revert CHANGELOG.

* `@0x/asset-swapper`: Address review comments.
`@0x/contract-addresses`: Make kyber lowercase.

* made protocol fee multiplier async

* `@0x/asset-swapper: Fix build errors and do some code cleanup.

* use assetDataUtils where possible
2019-12-16 12:35:58 -08:00
Arctek
e00f059a4a Fix circular refence 2019-12-14 16:00:05 +10:30
Greg Hysz
6808e0d531 Merge pull request #2365 from 0xProject/feat/asset-proxy/DyDxBridge
dYdX Bridge
2019-12-13 13:46:06 -08:00
Greg Hysen
410c95308a Updated dydx account encoding to assume that all actions are on partial balances 2019-12-13 12:02:23 -08:00
Greg Hysen
bec1f23616 Fixed merge conflicts 2019-12-13 11:06:16 -08:00
Greg Hysen
34596b7f83 Use safeGetPartialAmountFloor 2019-12-13 10:58:22 -08:00
Greg Hysen
5ca7169ee5 Reverted to version of dydx bridge that only allows from to be the account owner 2019-12-13 10:58:22 -08:00
Greg Hysen
3300aaa1b9 Refactored so that deposits are done from taker asset data and withdrawals from maker asset data. 2019-12-13 10:58:22 -08:00
Greg Hysen
54afc8a4a1 Fixed merge conflicts 2019-12-13 10:58:22 -08:00
Greg Hysen
f19f4310f4 Updating bridge to work w/o MultiAssetProxy 2019-12-13 10:57:57 -08:00
Greg Hysen
444125a7e1 Simplified the dydx bridge implememtation that does not use the bridge as the maker. 2019-12-13 10:57:57 -08:00
Greg Hysen
56cbb69401 DyDx bridge implementation using contract as maker with signature validation. 2019-12-13 10:56:54 -08:00
Lawrence Forman
70870ffcd2 Swallow reverts in ERC20BridgeSampler (#2395)
* `@0x/erc20-bridge-sampler`: Do not query empty/unsigned orders. Swallow revets on DEX quotes.

* `@0x/contracts-utils`: Add `DEV_UTILS_ADDRESS` and `KYBER_ETH_ADDRESS` to `DeploymentConstants`.

* `@0x/contracts-erc20-bridge-sampler`: Address review comments.
2019-12-13 10:53:25 -08:00
mzhu25
a556d91673 Merge pull request #2387 from 0xProject/feature/fuzz/staking-rewards
`@0x/contracts-integrations`: Staking rewards fuzz test
2019-12-12 15:43:29 -08:00
Michael Zhu
8ecbde8e1e Chagne StoredBalance functions to not mutate in place 2019-12-12 15:21:42 -08:00
Michael Zhu
a24b293818 register actors in the SimulationEnvironment constructor 2019-12-12 14:38:07 -08:00
Xianny
cab5ebf94b re-enable coordinator client tests (#2394) 2019-12-12 14:36:52 -08:00
Jacob Evans
a54b5baef2 Merge pull request #2393 from 0xProject/feature/orderbook-orderstore-async
orderbook: Make OrderStore async for use in db adapter
2019-12-12 10:30:17 -08:00
Jacob Evans
c324fe204e Make OrderStore async for use in db adapter
CHANGELOGS
2019-12-12 09:43:07 -08:00
Amir Bandeali
37d972ed9e Merge pull request #2389 from 0xProject/feat/contracts/mainnet-fork
Allow mainnet fork to be used for contract tests
2019-12-11 22:50:09 -08:00
Michael Zhu
e4a3b1cb05 fix bug in LibFractions reference function 2019-12-11 18:12:02 -08:00
Michael Zhu
49538f272e address comments 2019-12-11 16:54:48 -08:00
mzhu25
1283232144 Merge pull request #2372 from 0xProject/feature/fuzz/prng
`@0x/contracts-integrations`: Seeded RNG and simulation logging
2019-12-11 10:23:08 -08:00
Michael Zhu
2f9891f0aa fix CI failures 2019-12-10 00:32:48 -08:00
Michael Zhu
865a2b1fb0 add/update comments 2019-12-09 23:45:38 -08:00
Michael Zhu
1fde62eeb6 fix bug in finalizePool 2019-12-09 23:45:38 -08:00
Michael Zhu
6754cd48e2 refactor + fix lint 2019-12-09 23:45:38 -08:00
Michael Zhu
ccb477687a fixing bugs 2019-12-09 23:45:38 -08:00
Michael Zhu
be0e6c8925 Staking rewards simulation/fuzz test 2019-12-09 23:45:38 -08:00
Michael Zhu
1c2cb947c0 Add assertion generators to keeper, staker, taker mixins for the new function assertions 2019-12-09 23:45:38 -08:00
Michael Zhu
4663eec950 Add function assertions required for staking rewards fuzzing: withdrawDelegatorRewards, finalizePool, and endEpoch. Also adds payProtocolFee-related assertions to fillOrder 2019-12-09 23:45:37 -08:00
Michael Zhu
fff3c1eb36 update pool membership simulation to use multiple makers and takers, partial fills 2019-12-09 23:43:16 -08:00
Michael Zhu
4b7434d1e8 post-rebase lockfile update 2019-12-09 23:42:32 -08:00
Michael Zhu
8cc35a60e6 Add yarn command to run a specific fuzz test 2019-12-09 23:42:32 -08:00
Michael Zhu
130653a1aa move logger, pseudorandom, wrapper_interfaces to framework/utils/ 2019-12-09 23:42:32 -08:00
Michael Zhu
1dcbebd130 lint 2019-12-09 23:42:32 -08:00
Michael Zhu
faf306ad23 Simulation logging, hopefully address function assertion lifetime issue 2019-12-09 23:42:32 -08:00
Michael Zhu
d11cdcd5d2 Use seeded rng for simulations 2019-12-09 23:42:32 -08:00
Amir Bandeali
0e59bd0bf3 Add mainnet config tests 2019-12-09 16:16:22 -08:00
Amir Bandeali
c0c6154ec1 Add fork option to describe and blockchainTests 2019-12-09 16:14:41 -08:00
Amir Bandeali
cb5384c2fb Use fork configs if FORK_RPC_URL env var is set 2019-12-09 16:14:41 -08:00
Amir Bandeali
038c836fe5 Rename fillorder_test to fill_order_test 2019-12-09 16:14:41 -08:00
xianny
6b0f3570b9 Publish
- @0x/contracts-asset-proxy@3.0.1
 - @0x/contracts-coordinator@3.0.1
 - @0x/contracts-dev-utils@1.0.1
 - @0x/contracts-erc1155@2.0.1
 - @0x/contracts-erc20-bridge-sampler@1.0.1
 - @0x/contracts-erc20@3.0.1
 - @0x/contracts-erc721@3.0.1
 - @0x/contracts-exchange-forwarder@4.0.1
 - @0x/contracts-exchange-libs@4.0.1
 - @0x/contracts-exchange@3.0.1
 - @0x/contracts-extensions@5.1.0
 - @0x/contracts-integrations@2.0.1
 - @0x/contracts-multisig@4.0.1
 - @0x/contracts-staking@2.0.1
 - @0x/contracts-test-utils@5.0.0
 - @0x/contracts-tests@0.0.7
 - @0x/contracts-utils@4.0.1
 - 0x.js@9.0.1
 - @0x/abi-gen@5.0.1
 - @0x/assert@3.0.1
 - @0x/asset-swapper@3.0.1
 - @0x/base-contract@6.0.1
 - @0x/connect@6.0.1
 - @0x/contract-artifacts@3.1.0
 - @0x/contract-wrappers-test@12.2.2
 - @0x/contract-wrappers@13.1.0
 - @0x/contracts-gen@2.0.1
 - @0x/dev-utils@3.0.1
 - @0x/instant@1.0.38
 - @0x/json-schemas@5.0.1
 - @0x/migrations@5.0.1
 - @0x/monorepo-scripts@1.0.44
 - @0x/order-utils@10.0.0
 - @0x/orderbook@1.0.1
 - @0x/sol-compiler@4.0.1
 - @0x/sol-coverage@4.0.1
 - @0x/sol-doc@3.0.1
 - @0x/sol-profiler@4.0.1
 - @0x/sol-resolver@3.0.1
 - @0x/sol-trace@3.0.1
 - @0x/sol-tracing-utils@7.0.1
 - @0x/sra-spec@3.0.1
 - @0x/subproviders@6.0.1
 - @0x/types@3.1.0
 - @0x/utils@5.1.0
 - @0x/web3-wrapper@7.0.1
2019-12-09 14:53:19 -08:00
xianny
71de0d04f3 Updated CHANGELOGS & MD docs 2019-12-09 14:53:05 -08:00
Xianny
99debff5d2 Add syntactic sugar for assetDataUtils (#2388)
* add syntactic sugar for assetDataUtils
2019-12-09 13:55:58 -08:00
Amir Bandeali
3bac6fcb27 Merge pull request #2377 from 0xProject/feat/forwarder/multi-affiliate-fees
Forwarder affiliate fee usability improvements
2019-12-08 19:13:28 -08:00
Amir Bandeali
4b842b81a0 Address PR feedback 2019-12-08 16:28:00 -08:00
Amir Bandeali
e2e4d048ab Update tests to use new Forwarder interface 2019-12-04 21:23:55 -08:00
Amir Bandeali
5574c368cd Allow different ETh fees to be specified for different feeRecipient addresses 2019-12-04 21:23:55 -08:00
Amir Bandeali
0d34f7b92e Add EthFeeLengthMismatchError 2019-12-04 21:23:55 -08:00
Amir Bandeali
5be0632e01 Add tests with multiple fee recipients 2019-12-04 21:23:55 -08:00
Amir Bandeali
79ea0bf9f4 Allow affiliate fee to be split between multiple fee recipient addresses 2019-12-04 21:23:54 -08:00
Amir Bandeali
b1929cb688 Update affiliate fee tests 2019-12-04 21:23:54 -08:00
Amir Bandeali
5ad98700e5 Remove FeePercentageTooLargeError rich revert 2019-12-04 21:22:54 -08:00
Amir Bandeali
a54624b697 Do not return ethFeePaid 2019-12-04 21:22:54 -08:00
Amir Bandeali
ca34c865af Remove max fee percentage for affiliate fees 2019-12-04 21:22:54 -08:00
Amir Bandeali
dde57b1eca Make affiliate fee a flat amount 2019-12-04 21:22:54 -08:00
Amir Bandeali
264b06938e Merge pull request #2378 from 0xProject/feat/bridges/chai-bridge
Implement ChaiBridge
2019-12-04 16:25:46 -08:00
John Johnson
99edb303e2 Merge pull request #2386 from 0xProject/feature/fix-unbound-provider
Fix unbound method in provider standardizer
2019-12-04 15:44:22 -08:00
John Johnson
104cc24dfc Fixing unbound provider (metamask v7.7 incorrectly binds this) 2019-12-04 15:09:00 -08:00
Xianny
fcbcbac889 Remove assetDataUtils everywhere (#2373)
* remove assetDataUtils everywhere

* export IAssetDataContract from @0x/contract-wrappers to allow @0x/instant to decode asset data  synchronously

* export generic function `decodeAssetDataOrThrow` and add ERC20Bridge support

* export `hexUtils` from order-utils instead of contracts-test-utils
2019-12-04 13:08:08 -08:00
mzhu25
b86d19028c Merge pull request #2366 from 0xProject/feature/fuzz/makers-and-takers
Pool Member Fuzz Tests
2019-12-04 11:12:55 -08:00
F. Eugene Aumson
4f17a251d3 Python publish for v3 (#2383)
* Remove pre-release suffixes from version numbers

* For wrapper test, pull latest ganache image first

* For wrapper test, unpin ganache, use beta snapshot

* In docs, advise using beta ganache snapshot

Because we haven't yet published the non-beta snapshot

* Unpin package interdependencies

* unpin tests from beta 0xorg/ganache-cli version

* use beta ganache snapshot

* Set release date in CHANGELOGs

* In testing deployment, stop testing pre-releases

* Include rmtree("build") in all clean commands

* Fix clean not cleaning what it thought it was

* In monorepo script, install pkgs 1st then dev deps

* Stop pinning ganache snapshot version

* In test setup, wait longer for mesh to start up

* Fix broken hyperlinks in docs

* fix missing \n that was breaking doc rendering

* In monorepo script comment, fix typo, and clarify
2019-12-04 08:42:00 -08:00
Alex Browne
731a823cc2 Update CODEOWNERS
Remove albrow as code owner for the `contract-addresses` and `contract-artifacts` packages. It's been a long time since I've worked on these packages and I am no longer the best person to review changes to them.
2019-12-03 17:19:08 -08:00
Michael Zhu
3d79fe2bf4 post-rebase lockfile update 2019-12-03 15:34:59 -08:00
Alex Towle
474399154f Addressed last review comment 2019-12-03 14:41:53 -08:00
Alex Towle
19f5153d0e Addressed some review feedback 2019-12-03 14:41:53 -08:00
Alex Towle
ce11271866 Appease the linter 2019-12-03 14:40:18 -08:00
Alex Towle
86cf353296 Improved the fuzz test 2019-12-03 14:40:07 -08:00
Alex Towle
36df5dc721 Implemented a hacky version of the fillOrder fuzz tests 2019-12-03 14:40:07 -08:00
Alex Towle
1e44a9c942 Made function assertions work with the new wrappers 2019-12-03 14:39:29 -08:00
mzhu25
8685cf9036 Merge pull request #2357 from 0xProject/refactor/integrations/transaction-tests
`@0x/contracts-integrations`: Transaction integration tests
2019-12-03 11:04:11 -08:00
Michael Zhu
2232870b09 address comments 2019-12-03 10:35:59 -08:00
Amir Bandeali
b68acd101e Fix failing tests 2019-12-03 08:46:47 -08:00
Amir Bandeali
173ba9b2b5 Add ChaiBridge unit tests 2019-12-02 16:42:17 -08:00
Amir Bandeali
64ed1f87d3 Rethrow custom error string if draw call fails 2019-12-02 16:42:17 -08:00
Michael Zhu
1ca085ec4a address comments 2019-12-02 15:39:03 -08:00
Michael Zhu
e332b7535c prettier 2019-12-02 15:39:02 -08:00
Michael Zhu
79eb613b3e Use AbiEncoder for methodAbiToFunctionSignature 2019-12-02 15:39:02 -08:00
Michael Zhu
5a79ec28d1 transaction protocol fee integration tests 2019-12-02 15:39:02 -08:00
Michael Zhu
97e65a02c0 fix test nesting 2019-12-02 15:39:02 -08:00
Michael Zhu
e87c786b77 fix dataItemsToABIString 2019-12-02 15:39:02 -08:00
Michael Zhu
251d30d47f refactor transaction integration tests to use new framework 2019-12-02 15:39:02 -08:00
Amir Bandeali
7a3f878c11 Add ChaiBridge to boilerplate 2019-12-01 15:57:01 -08:00
Amir Bandeali
b8439598bc Remove redundant getters from bridges 2019-12-01 15:55:27 -08:00
Amir Bandeali
7fb0818923 Implement ChaiBridge 2019-12-01 15:54:58 -08:00
Amir Bandeali
a7c435adc4 Add mainnet deployment addresses for Dai, Chai, and ERC20BridgeProxy 2019-12-01 15:40:29 -08:00
990 changed files with 76290 additions and 20345 deletions

View File

@@ -23,7 +23,7 @@ jobs:
# command: npm set prefix=/home/circleci/npm && echo 'export PATH=$HOME/circleci/npm/bin:$PATH' >> /home/circleci/.bashrc
- run:
name: install-yarn
command: npm install --global yarn@1.17.0
command: npm install --force --global yarn@1.17.0
- run:
name: yarn
command: yarn --frozen-lockfile --ignore-engines install || yarn --frozen-lockfile --ignore-engines install
@@ -38,17 +38,7 @@ jobs:
path: ~/repo/packages/abi-gen/test-cli/output
- store_artifacts:
path: ~/repo/packages/contract-wrappers/generated_docs
test-contracts-ganache:
resource_class: medium+
docker:
- image: nikolaik/python-nodejs:python3.7-nodejs8
working_directory: ~/repo
steps:
- restore_cache:
keys:
- repo-{{ .Environment.CIRCLE_SHA1 }}
- run: yarn wsrun test:circleci @0x/contracts-multisig @0x/contracts-utils @0x/contracts-exchange-libs @0x/contracts-erc20 @0x/contracts-erc721 @0x/contracts-erc1155 @0x/contracts-extensions @0x/contracts-asset-proxy @0x/contracts-exchange @0x/contracts-exchange-forwarder @0x/contracts-coordinator @0x/contracts-tests @0x/contracts-staking
test-exchange-ganache-3.0:
test-exchange-ganache:
resource_class: medium+
docker:
- image: nikolaik/python-nodejs:python3.7-nodejs8
@@ -58,7 +48,7 @@ jobs:
keys:
- repo-{{ .Environment.CIRCLE_SHA1 }}
- run: yarn wsrun test:circleci @0x/contracts-exchange
test-integrations-ganache-3.0:
test-integrations-ganache:
resource_class: medium+
docker:
- image: nikolaik/python-nodejs:python3.7-nodejs8
@@ -68,7 +58,7 @@ jobs:
keys:
- repo-{{ .Environment.CIRCLE_SHA1 }}
- run: yarn wsrun test:circleci @0x/contracts-integrations
test-contracts-rest-ganache-3.0:
test-contracts-staking-ganache:
resource_class: medium+
docker:
- image: nikolaik/python-nodejs:python3.7-nodejs8
@@ -77,11 +67,17 @@ jobs:
- restore_cache:
keys:
- repo-{{ .Environment.CIRCLE_SHA1 }}
- run: yarn wsrun test:circleci @0x/contracts-multisig @0x/contracts-utils @0x/contracts-exchange-libs @0x/contracts-erc20 @0x/contracts-erc721 @0x/contracts-erc1155 @0x/contracts-asset-proxy @0x/contracts-exchange-forwarder @0x/contracts-tests @0x/contracts-staking @0x/contracts-coordinator @0x/contracts-erc20-bridge-sampler
# TODO(dorothy-zbornak): Re-enable after updating this package for
# 3.0. At that time, also remove exclusion from monorepo
# package.json's test script.
# - run: yarn wsrun test:circleci @0x/contracts-extensions
- run: yarn wsrun test:circleci @0x/contracts-staking
test-contracts-rest-ganache:
resource_class: medium+
docker:
- image: nikolaik/python-nodejs:python3.7-nodejs8
working_directory: ~/repo
steps:
- restore_cache:
keys:
- repo-{{ .Environment.CIRCLE_SHA1 }}
- run: yarn wsrun test:circleci @0x/contracts-multisig @0x/contracts-utils @0x/contracts-exchange-libs @0x/contracts-erc20 @0x/contracts-erc721 @0x/contracts-erc1155 @0x/contracts-asset-proxy @0x/contracts-exchange-forwarder @0x/contracts-coordinator @0x/contracts-erc20-bridge-sampler @0x/contracts-broker @0x/contracts-zero-ex
test-publish:
resource_class: medium+
docker:
@@ -193,20 +189,16 @@ jobs:
working_directory: ~/repo
docker:
- image: nikolaik/python-nodejs:python3.7-nodejs8
- image: 0xorg/ganache-cli:4.4.0-beta.1
- image: 0xorg/ganache-cli:6.0.0
environment:
VERSION: latest
SNAPSHOT_NAME: 0x_ganache_snapshot-v3-beta
VERSION: '6.0.0'
- image: 0xorg/mesh:0xV3
environment:
ETHEREUM_RPC_URL: 'http://localhost:8545'
ETHEREUM_NETWORK_ID: '50'
ETHEREUM_CHAIN_ID: '1337'
USE_BOOTSTRAP_LIST: 'true'
VERBOSITY: 3
PRIVATE_KEY_PATH: ''
BLOCK_POLLING_INTERVAL: '5s'
P2P_LISTEN_PORT: '60557'
VERBOSITY: 5
BLOCK_POLLING_INTERVAL: '50ms'
ETHEREUM_RPC_MAX_REQUESTS_PER_24_HR_UTC: '1778000'
command: |
sh -c "waitForGanache () { until printf 'POST /\r\nContent-Length: 26\r\n\r\n{\"method\":\"net_listening\"}' | nc localhost 8545 | grep true; do continue; done }; waitForGanache && ./mesh"
- image: 0xorg/launch-kit-backend:v3
@@ -219,7 +211,7 @@ jobs:
TAKER_FEE_UNIT_AMOUNT: 0
MESH_ENDPOINT: 'ws://localhost:60557'
command: |
sh -c "waitForMesh () { sleep 5; }; waitForMesh && node_modules/.bin/forever ts/lib/index.js"
sh -c "waitForMesh () { sleep 30; }; waitForMesh && node_modules/.bin/forever ts/lib/index.js"
steps:
- checkout
- restore_cache:
@@ -423,13 +415,16 @@ workflows:
main:
jobs:
- build
- test-exchange-ganache-3.0:
- test-exchange-ganache:
requires:
- build
- test-integrations-ganache-3.0:
- test-integrations-ganache:
requires:
- build
- test-contracts-rest-ganache-3.0:
- test-contracts-staking-ganache:
requires:
- build
- test-contracts-rest-ganache:
requires:
- build
- test-rest:
@@ -446,8 +441,9 @@ workflows:
- build
- submit-coverage:
requires:
- test-contracts-rest-ganache-3.0
- test-exchange-ganache-3.0
- test-contracts-rest-ganache
- test-contracts-staking-ganache
- test-exchange-ganache
- test-rest
- static-tests
- test-python:

37
.gitignore vendored
View File

@@ -79,6 +79,8 @@ TODO.md
.vscode
# generated contract artifacts/
contracts/broker/generated-artifacts/
contracts/broker/test/generated-artifacts/
contracts/erc20-bridge-sampler/generated-artifacts/
contracts/erc20-bridge-sampler/test/generated-artifacts/
contracts/integrations/generated-artifacts/
@@ -109,10 +111,13 @@ contracts/exchange-forwarder/generated-artifacts/
contracts/exchange-forwarder/test/generated-artifacts/
contracts/dev-utils/generated-artifacts/
contracts/dev-utils/test/generated-artifacts/
contracts/zero-ex/generated-artifacts/
contracts/zero-ex/test/generated-artifacts/
packages/sol-tracing-utils/test/fixtures/artifacts/
python-packages/contract_artifacts/src/zero_ex/contract_artifacts/artifacts/
# generated truffle contract artifacts/
contracts/broker/build/
contracts/erc20-bridge-sampler/build/
contracts/staking/build/
contracts/coordinator/build/
@@ -129,6 +134,8 @@ contracts/exchange-forwarder/build/
contracts/dev-utils/build/
# generated contract wrappers
contracts/broker/generated-wrappers/
contracts/broker/test/generated-wrappers/
packages/python-contract-wrappers/generated/
contracts/erc20-bridge-sampler/generated-wrappers/
contracts/erc20-bridge-sampler/test/generated-wrappers/
@@ -160,33 +167,9 @@ contracts/exchange-forwarder/generated-wrappers/
contracts/exchange-forwarder/test/generated-wrappers/
contracts/dev-utils/generated-wrappers/
contracts/dev-utils/test/generated-wrappers/
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/dev_utils/__init__.py
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/erc20_token/__init__.py
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/exchange/__init__.py
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/asset_proxy_owner/__init__.py
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/coordinator/__init__.py
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/coordinator_registry/__init__.py
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/dummy_erc20_token/__init__.py
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/dummy_erc721_token/__init__.py
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/dutch_auction/__init__.py
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/erc1155_mintable/__init__.py
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/erc1155_proxy/__init__.py
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/erc20_bridge_proxy/__init__.py
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/erc20_proxy/__init__.py
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/erc721_proxy/__init__.py
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/erc721_token/__init__.py
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/forwarder/__init__.py
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/i_asset_proxy/__init__.py
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/i_validator/__init__.py
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/i_wallet/__init__.py
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/multi_asset_proxy/__init__.py
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/order_validator/__init__.py
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/staking/__init__.py
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/staking_proxy/__init__.py
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/static_call_proxy/__init__.py
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/weth9/__init__.py
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/zrx_token/__init__.py
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/zrx_vault/__init__.py
contracts/zero-ex/generated-wrappers/
contracts/zero-ex/test/generated-wrappers/
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/*/__init__.py
# solc-bin in sol-compiler
packages/sol-compiler/solc_bin/

View File

@@ -1,5 +1,9 @@
lib
.nyc_output
/contracts/broker/generated-wrappers
/contracts/broker/test/generated-wrappers
/contracts/broker/generated-artifacts
/contracts/broker/test/generated-artifacts
/contracts/integrations/generated-wrappers
/contracts/integrations/test/generated-wrappers
/contracts/integrations/generated-artifacts
@@ -60,6 +64,10 @@ lib
/contracts/dev-utils/test/generated-wrappers
/contracts/dev-utils/generated-artifacts
/contracts/dev-utils/test/generated-artifacts
/contracts/zero-ex/generated-wrappers
/contracts/zero-ex/test/generated-wrappers
/contracts/zero-ex/generated-artifacts
/contracts/zero-ex/test/generated-artifacts
/contracts/staking/build/
/contracts/coordinator/build/
/contracts/exchange/build/
@@ -87,3 +95,4 @@ packages/abi-gen/test-cli/fixtures/artifacts/AbiGenDummy.json
packages/abi-gen/test-cli/fixtures/artifacts/LibDummy.json
packages/abi-gen/test-cli/fixtures/artifacts/TestLibDummy.json
packages/*/docs
*.sol

View File

@@ -14,8 +14,8 @@ packages/abi-gen/ @feuGeneA
packages/base-contract/ @xianny
packages/connect/ @fragosti
packages/abi-gen-templates/ @feuGeneA @xianny
packages/contract-addresses/ @albrow
packages/contract-artifacts/ @albrow
packages/contract-addresses/ @abandeali1
packages/contract-artifacts/ @abandeali1
packages/dev-utils/ @LogvinovLeon @fabioberger
packages/devnet/ @albrow
packages/ethereum-types/ @LogvinovLeon

View File

@@ -1,4 +1,176 @@
[
{
"version": "3.3.0",
"changes": [
{
"note": "Use `LibERC20Token.approveIfBelow()` in DEX bridges for for approvals.",
"pr": 2512
},
{
"note": "Emit `ERC20BridgeTransfer` events in bridges.",
"pr": 2512
},
{
"note": "Change names of `ERC20BridgeTransfer` args to be less ambiguous.",
"pr": 2524
},
{
"note": "Added `MixinGasToken` allowing Gas Tokens to be freed",
"pr": 2523
},
{
"note": "Add `DexForwaderBridge` bridge contract.",
"pr": 2525
},
{
"note": "Add `UniswapV2Bridge` bridge contract.",
"pr": 2590
},
{
"note": "Add Gas Token freeing to `DexForwarderBridge` contract.",
"pr": 2536
}
],
"timestamp": 1592969527
},
{
"timestamp": 1583220306,
"version": "3.2.5",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1582837861,
"version": "3.2.4",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1582677073,
"version": "3.2.3",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1582623685,
"version": "3.2.2",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1581748629,
"version": "3.2.1",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"version": "3.2.0",
"changes": [
{
"note": "Add more types and functions to `IDydx`",
"pr": 2466
},
{
"note": "Rename `DydxBrigeAction.accountId` to `DydxBridgeAction.accountIdx`",
"pr": 2466
},
{
"note": "Fix broken tests.",
"pr": 2462
},
{
"note": "Remove dependency on `@0x/contracts-dev-utils`",
"pr": 2462
},
{
"note": "Add asset data decoding functions",
"pr": 2462
},
{
"note": "Add `setOperators()` to `IDydx`",
"pr": 2462
}
],
"timestamp": 1581204851
},
{
"timestamp": 1580988106,
"version": "3.1.3",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1580811564,
"version": "3.1.2",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1579682890,
"version": "3.1.1",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"version": "3.1.0",
"changes": [
{
"note": "Integration tests for DydxBridge with ERC20BridgeProxy.",
"pr": 2401
},
{
"note": "Fix `UniswapBridge` token -> token transfer call.",
"pr": 2412
},
{
"note": "Fix `KyberBridge` incorrect `minConversionRate` calculation.",
"pr": 2412
}
],
"timestamp": 1578272714
},
{
"timestamp": 1576540892,
"version": "3.0.2",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1575931811,
"version": "3.0.1",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"version": "3.0.0",
"changes": [
@@ -55,6 +227,10 @@
{
"note": "Implement `KyberBridge`.",
"pr": 2352
},
{
"note": "Implement `DydxBridge`.",
"pr": 2365
}
],
"timestamp": 1575290197

View File

@@ -5,6 +5,71 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v3.3.0 - _June 24, 2020_
* Use `LibERC20Token.approveIfBelow()` in DEX bridges for for approvals. (#2512)
* Emit `ERC20BridgeTransfer` events in bridges. (#2512)
* Change names of `ERC20BridgeTransfer` args to be less ambiguous. (#2524)
* Added `MixinGasToken` allowing Gas Tokens to be freed (#2523)
* Add `DexForwaderBridge` bridge contract. (#2525)
* Add `UniswapV2Bridge` bridge contract. (#2590)
* Add Gas Token freeing to `DexForwarderBridge` contract. (#2536)
## v3.2.5 - _March 3, 2020_
* Dependencies updated
## v3.2.4 - _February 27, 2020_
* Dependencies updated
## v3.2.3 - _February 26, 2020_
* Dependencies updated
## v3.2.2 - _February 25, 2020_
* Dependencies updated
## v3.2.1 - _February 15, 2020_
* Dependencies updated
## v3.2.0 - _February 8, 2020_
* Add more types and functions to `IDydx` (#2466)
* Rename `DydxBrigeAction.accountId` to `DydxBridgeAction.accountIdx` (#2466)
* Fix broken tests. (#2462)
* Remove dependency on `@0x/contracts-dev-utils` (#2462)
* Add asset data decoding functions (#2462)
* Add `setOperators()` to `IDydx` (#2462)
## v3.1.3 - _February 6, 2020_
* Dependencies updated
## v3.1.2 - _February 4, 2020_
* Dependencies updated
## v3.1.1 - _January 22, 2020_
* Dependencies updated
## v3.1.0 - _January 6, 2020_
* Integration tests for DydxBridge with ERC20BridgeProxy. (#2401)
* Fix `UniswapBridge` token -> token transfer call. (#2412)
* Fix `KyberBridge` incorrect `minConversionRate` calculation. (#2412)
## v3.0.2 - _December 17, 2019_
* Dependencies updated
## v3.0.1 - _December 9, 2019_
* Dependencies updated
## v3.0.0 - _December 2, 2019_
* Implement `KyberBridge`. (#2352)
@@ -22,6 +87,7 @@ CHANGELOG
## v2.3.0-beta.4 - _December 2, 2019_
* Implement `KyberBridge`. (#2352)
* Implement `DydxBridge`. (#2365)
## v2.3.0-beta.3 - _November 20, 2019_

View File

@@ -3,8 +3,9 @@
"contractsDir": "./contracts",
"useDockerisedSolc": false,
"isOfflineMode": false,
"shouldSaveStandardInput": true,
"compilerSettings": {
"evmVersion": "constantinople",
"evmVersion": "istanbul",
"optimizer": {
"enabled": true,
"runs": 1000000,

View File

@@ -0,0 +1,75 @@
/*
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.5.9;
pragma experimental ABIEncoderV2;
import "../interfaces/IERC20Bridge.sol";
import "../interfaces/IChai.sol";
import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol";
import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol";
// solhint-disable space-after-comma
contract ChaiBridge is
IERC20Bridge,
DeploymentConstants
{
/// @dev Withdraws `amount` of `from` address's Dai from the Chai contract.
/// Transfers `amount` of Dai to `to` address.
/// @param from Address to transfer asset from.
/// @param to Address to transfer asset to.
/// @param amount Amount of asset to transfer.
/// @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)
{
// Ensure that only the `ERC20BridgeProxy` can call this function.
require(
msg.sender == _getERC20BridgeProxyAddress(),
"ChaiBridge/ONLY_CALLABLE_BY_ERC20_BRIDGE_PROXY"
);
// Withdraw `from` address's Dai.
// NOTE: This contract must be approved to spend Chai on behalf of `from`.
bytes memory drawCalldata = abi.encodeWithSelector(
IChai(address(0)).draw.selector,
from,
amount
);
(bool success,) = _getChaiAddress().call(drawCalldata);
require(
success,
"ChaiBridge/DRAW_DAI_FAILED"
);
// Transfer Dai to `to`
// This will never fail if the `draw` call was successful
IERC20Token(_getDaiAddress()).transfer(to, amount);
return BRIDGE_SUCCESS;
}
}

View File

@@ -0,0 +1,128 @@
/*
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.5.9;
pragma experimental ABIEncoderV2;
import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol";
import "@0x/contracts-erc20/contracts/src/LibERC20Token.sol";
import "@0x/contracts-exchange-libs/contracts/src/IWallet.sol";
import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol";
import "../interfaces/IERC20Bridge.sol";
import "../interfaces/ICurve.sol";
import "./MixinGasToken.sol";
// solhint-disable not-rely-on-time
// solhint-disable space-after-comma
contract CurveBridge is
IERC20Bridge,
IWallet,
DeploymentConstants,
MixinGasToken
{
struct CurveBridgeData {
address curveAddress;
int128 fromCoinIdx;
int128 toCoinIdx;
int128 version;
}
/// @dev Callback for `ICurve`. Tries to buy `amount` of
/// `toTokenAddress` tokens by selling the entirety of the opposing asset
/// (DAI, USDC) to the Curve contract, then transfers the bought
/// tokens to `to`.
/// @param toTokenAddress The token to give to `to` (i.e DAI, USDC, USDT).
/// @param from The maker (this contract).
/// @param to The recipient of the bought tokens.
/// @param amount Minimum amount of `toTokenAddress` tokens to buy.
/// @param bridgeData The abi-encoeded "from" token address.
/// @return success The magic bytes if successful.
function bridgeTransferFrom(
address toTokenAddress,
address from,
address to,
uint256 amount,
bytes calldata bridgeData
)
external
freesGasTokensFromCollector
returns (bytes4 success)
{
// Decode the bridge data to get the Curve metadata.
CurveBridgeData memory data = abi.decode(bridgeData, (CurveBridgeData));
address fromTokenAddress = ICurve(data.curveAddress).underlying_coins(data.fromCoinIdx);
require(toTokenAddress != fromTokenAddress, "CurveBridge/INVALID_PAIR");
uint256 fromTokenBalance = IERC20Token(fromTokenAddress).balanceOf(address(this));
// Grant an allowance to the exchange to spend `fromTokenAddress` token.
LibERC20Token.approveIfBelow(fromTokenAddress, data.curveAddress, fromTokenBalance);
// Try to sell all of this contract's `fromTokenAddress` token balance.
if (data.version == 0) {
ICurve(data.curveAddress).exchange_underlying(
data.fromCoinIdx,
data.toCoinIdx,
// dx
fromTokenBalance,
// min dy
amount,
// expires
block.timestamp + 1
);
} else {
ICurve(data.curveAddress).exchange_underlying(
data.fromCoinIdx,
data.toCoinIdx,
// dx
fromTokenBalance,
// min dy
amount
);
}
uint256 toTokenBalance = IERC20Token(toTokenAddress).balanceOf(address(this));
// Transfer the converted `toToken`s to `to`.
LibERC20Token.transfer(toTokenAddress, to, toTokenBalance);
emit ERC20BridgeTransfer(
fromTokenAddress,
toTokenAddress,
fromTokenBalance,
toTokenBalance,
from,
to
);
return BRIDGE_SUCCESS;
}
/// @dev `SignatureType.Wallet` callback, so that this bridge can be the maker
/// and sign for itself in orders. Always succeeds.
/// @return magicValue Magic success bytes, always.
function isValidSignature(
bytes32,
bytes calldata
)
external
view
returns (bytes4 magicValue)
{
return LEGACY_WALLET_MAGIC_VALUE;
}
}

View File

@@ -0,0 +1,201 @@
/*
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.5.9;
pragma experimental ABIEncoderV2;
import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol";
import "@0x/contracts-erc20/contracts/src/LibERC20Token.sol";
import "@0x/contracts-exchange-libs/contracts/src/IWallet.sol";
import "@0x/contracts-exchange-libs/contracts/src/LibMath.sol";
import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol";
import "@0x/contracts-utils/contracts/src/LibBytes.sol";
import "@0x/contracts-utils/contracts/src/LibSafeMath.sol";
import "../interfaces/IERC20Bridge.sol";
import "./MixinGasToken.sol";
// solhint-disable space-after-comma, indent
contract DexForwarderBridge is
IERC20Bridge,
IWallet,
DeploymentConstants,
MixinGasToken
{
using LibSafeMath for uint256;
/// @dev Data needed to reconstruct a bridge call.
struct BridgeCall {
address target;
uint256 inputTokenAmount;
uint256 outputTokenAmount;
bytes bridgeData;
}
/// @dev Intermediate state variables used by `bridgeTransferFrom()`, in
/// struct form to get around stack limits.
struct TransferFromState {
address inputToken;
uint256 initialInputTokenBalance;
uint256 callInputTokenAmount;
uint256 callOutputTokenAmount;
uint256 totalInputTokenSold;
BridgeCall[] calls;
}
/// @dev Spends this contract's entire balance of input tokens by forwarding
/// them to other bridges. Reverts if the entire balance is not spent.
/// @param outputToken The token being bought.
/// @param to The recipient of the bought tokens.
/// @param bridgeData The abi-encoded input token address.
/// @return success The magic bytes if successful.
function bridgeTransferFrom(
address outputToken,
address /* from */,
address to,
uint256 /* amount */,
bytes calldata bridgeData
)
external
freesGasTokensFromCollector
returns (bytes4 success)
{
require(msg.sender == _getERC20BridgeProxyAddress(), "DexForwarderBridge/SENDER_NOT_AUTHORIZED");
TransferFromState memory state;
(
state.inputToken,
state.calls
) = abi.decode(bridgeData, (address, BridgeCall[]));
state.initialInputTokenBalance = IERC20Token(state.inputToken).balanceOf(address(this));
for (uint256 i = 0; i < state.calls.length; ++i) {
// Stop if the we've sold all our input tokens.
if (state.totalInputTokenSold >= state.initialInputTokenBalance) {
break;
}
// Compute token amounts.
state.callInputTokenAmount = LibSafeMath.min256(
state.calls[i].inputTokenAmount,
state.initialInputTokenBalance.safeSub(state.totalInputTokenSold)
);
state.callOutputTokenAmount = LibMath.getPartialAmountFloor(
state.callInputTokenAmount,
state.calls[i].inputTokenAmount,
state.calls[i].outputTokenAmount
);
// Execute the call in a new context so we can recoup transferred
// funds by reverting.
(bool didSucceed, ) = address(this)
.call(abi.encodeWithSelector(
this.executeBridgeCall.selector,
state.calls[i].target,
to,
state.inputToken,
outputToken,
state.callInputTokenAmount,
state.callOutputTokenAmount,
state.calls[i].bridgeData
));
if (didSucceed) {
// Increase the amount of tokens sold.
state.totalInputTokenSold = state.totalInputTokenSold.safeAdd(
state.callInputTokenAmount
);
}
}
// Revert if we were not able to sell our entire input token balance.
require(
state.totalInputTokenSold >= state.initialInputTokenBalance,
"DexForwarderBridge/INCOMPLETE_FILL"
);
// Always succeed.
return BRIDGE_SUCCESS;
}
/// @dev Transfers `inputToken` token to a bridge contract then calls
/// its `bridgeTransferFrom()`. This is executed in separate context
/// so we can revert the transfer on error. This can only be called
// by this contract itself.
/// @param bridge The bridge contract.
/// @param to The recipient of `outputToken` tokens.
/// @param inputToken The input token.
/// @param outputToken The output token.
/// @param inputTokenAmount The amount of input tokens to transfer to `bridge`.
/// @param outputTokenAmount The amount of expected output tokens to be sent
/// to `to` by `bridge`.
function executeBridgeCall(
address bridge,
address to,
address inputToken,
address outputToken,
uint256 inputTokenAmount,
uint256 outputTokenAmount,
bytes calldata bridgeData
)
external
{
// Must be called through `bridgeTransferFrom()`.
require(msg.sender == address(this), "DexForwarderBridge/ONLY_SELF");
// `bridge` must not be this contract.
require(bridge != address(this));
// Get the starting balance of output tokens for `to`.
uint256 initialRecipientBalance = IERC20Token(outputToken).balanceOf(to);
// Transfer input tokens to the bridge.
LibERC20Token.transfer(inputToken, bridge, inputTokenAmount);
// Call the bridge.
(bool didSucceed, bytes memory resultData) =
bridge.call(abi.encodeWithSelector(
IERC20Bridge(0).bridgeTransferFrom.selector,
outputToken,
bridge,
to,
outputTokenAmount,
bridgeData
));
// Revert if the call failed or not enough tokens were bought.
// This will also undo the token transfer.
require(
didSucceed
&& resultData.length == 32
&& LibBytes.readBytes32(resultData, 0) == bytes32(BRIDGE_SUCCESS)
&& IERC20Token(outputToken).balanceOf(to).safeSub(initialRecipientBalance) >= outputTokenAmount
);
}
/// @dev `SignatureType.Wallet` callback, so that this bridge can be the maker
/// and sign for itself in orders. Always succeeds.
/// @return magicValue Magic success bytes, always.
function isValidSignature(
bytes32,
bytes calldata
)
external
view
returns (bytes4 magicValue)
{
return LEGACY_WALLET_MAGIC_VALUE;
}
}

View File

@@ -0,0 +1,242 @@
/*
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.5.9;
pragma experimental ABIEncoderV2;
import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol";
import "@0x/contracts-utils/contracts/src/LibSafeMath.sol";
import "@0x/contracts-exchange-libs/contracts/src/LibMath.sol";
import "../interfaces/IERC20Bridge.sol";
import "../interfaces/IDydxBridge.sol";
import "../interfaces/IDydx.sol";
contract DydxBridge is
IERC20Bridge,
IDydxBridge,
DeploymentConstants
{
using LibSafeMath for uint256;
/// @dev Callback for `IERC20Bridge`. Deposits or withdraws tokens from a dydx account.
/// Notes:
/// 1. This bridge must be set as an operator of the input dydx account.
/// 2. This function may only be called in the context of the 0x Exchange.
/// 3. The maker or taker of the 0x order must be the dydx account owner.
/// 4. Deposits into dydx are made from the `from` address.
/// 5. Withdrawals from dydx are made to the `to` address.
/// 6. Calling this function must always withdraw at least `amount`,
/// otherwise the `ERC20Bridge` will revert.
/// @param from The sender of the tokens and owner of the dydx account.
/// @param to The recipient of the tokens.
/// @param amount Minimum amount of `toTokenAddress` tokens to deposit or withdraw.
/// @param encodedBridgeData An abi-encoded `BridgeData` struct.
/// @return success The magic bytes if successful.
function bridgeTransferFrom(
address, /* toTokenAddress */
address from,
address to,
uint256 amount,
bytes calldata encodedBridgeData
)
external
returns (bytes4 success)
{
// Ensure that only the `ERC20BridgeProxy` can call this function.
require(
msg.sender == _getERC20BridgeProxyAddress(),
"DydxBridge/ONLY_CALLABLE_BY_ERC20_BRIDGE_PROXY"
);
// Decode bridge data.
(BridgeData memory bridgeData) = abi.decode(encodedBridgeData, (BridgeData));
// The dydx accounts are owned by the `from` address.
IDydx.AccountInfo[] memory accounts = _createAccounts(from, bridgeData);
// Create dydx actions to run on the dydx accounts.
IDydx.ActionArgs[] memory actions = _createActions(
from,
to,
amount,
bridgeData
);
// Run operation. This will revert on failure.
IDydx(_getDydxAddress()).operate(accounts, actions);
return BRIDGE_SUCCESS;
}
/// @dev Creates an array of accounts for dydx to operate on.
/// All accounts must belong to the same owner.
/// @param accountOwner Owner of the dydx account.
/// @param bridgeData A `BridgeData` struct.
function _createAccounts(
address accountOwner,
BridgeData memory bridgeData
)
internal
returns (IDydx.AccountInfo[] memory accounts)
{
uint256[] memory accountNumbers = bridgeData.accountNumbers;
uint256 nAccounts = accountNumbers.length;
accounts = new IDydx.AccountInfo[](nAccounts);
for (uint256 i = 0; i < nAccounts; ++i) {
accounts[i] = IDydx.AccountInfo({
owner: accountOwner,
number: accountNumbers[i]
});
}
}
/// @dev Creates an array of actions to carry out on dydx.
/// @param depositFrom Deposit value from this address (owner of the dydx account).
/// @param withdrawTo Withdraw value to this address.
/// @param amount The amount of value available to operate on.
/// @param bridgeData A `BridgeData` struct.
function _createActions(
address depositFrom,
address withdrawTo,
uint256 amount,
BridgeData memory bridgeData
)
internal
returns (IDydx.ActionArgs[] memory actions)
{
BridgeAction[] memory bridgeActions = bridgeData.actions;
uint256 nBridgeActions = bridgeActions.length;
actions = new IDydx.ActionArgs[](nBridgeActions);
for (uint256 i = 0; i < nBridgeActions; ++i) {
// Cache current bridge action.
BridgeAction memory bridgeAction = bridgeActions[i];
// Scale amount, if conversion rate is set.
uint256 scaledAmount;
if (bridgeAction.conversionRateDenominator > 0) {
scaledAmount = LibMath.safeGetPartialAmountFloor(
bridgeAction.conversionRateNumerator,
bridgeAction.conversionRateDenominator,
amount
);
} else {
scaledAmount = amount;
}
// Construct dydx action.
if (bridgeAction.actionType == BridgeActionType.Deposit) {
// Deposit tokens from the account owner into their dydx account.
actions[i] = _createDepositAction(
depositFrom,
scaledAmount,
bridgeAction
);
} else if (bridgeAction.actionType == BridgeActionType.Withdraw) {
// Withdraw tokens from dydx to the `otherAccount`.
actions[i] = _createWithdrawAction(
withdrawTo,
scaledAmount,
bridgeAction
);
} else {
// If all values in the `Action` enum are handled then this
// revert is unreachable: Solidity will revert when casting
// from `uint8` to `Action`.
revert("DydxBridge/UNRECOGNIZED_BRIDGE_ACTION");
}
}
}
/// @dev Returns a dydx `DepositAction`.
/// @param depositFrom Deposit tokens from this address who is also the account owner.
/// @param amount of tokens to deposit.
/// @param bridgeAction A `BridgeAction` struct.
/// @return depositAction The encoded dydx action.
function _createDepositAction(
address depositFrom,
uint256 amount,
BridgeAction memory bridgeAction
)
internal
pure
returns (
IDydx.ActionArgs memory depositAction
)
{
// Create dydx amount.
IDydx.AssetAmount memory dydxAmount = IDydx.AssetAmount({
sign: true, // true if positive.
denomination: IDydx.AssetDenomination.Wei, // Wei => actual token amount held in account.
ref: IDydx.AssetReference.Delta, // Delta => a relative amount.
value: amount // amount to deposit.
});
// Create dydx deposit action.
depositAction = IDydx.ActionArgs({
actionType: IDydx.ActionType.Deposit, // deposit tokens.
amount: dydxAmount, // amount to deposit.
accountIdx: bridgeAction.accountIdx, // index in the `accounts` when calling `operate`.
primaryMarketId: bridgeAction.marketId, // indicates which token to deposit.
otherAddress: depositFrom, // deposit from the account owner.
// unused parameters
secondaryMarketId: 0,
otherAccountIdx: 0,
data: hex''
});
}
/// @dev Returns a dydx `WithdrawAction`.
/// @param withdrawTo Withdraw tokens to this address.
/// @param amount of tokens to withdraw.
/// @param bridgeAction A `BridgeAction` struct.
/// @return withdrawAction The encoded dydx action.
function _createWithdrawAction(
address withdrawTo,
uint256 amount,
BridgeAction memory bridgeAction
)
internal
pure
returns (
IDydx.ActionArgs memory withdrawAction
)
{
// Create dydx amount.
IDydx.AssetAmount memory amountToWithdraw = IDydx.AssetAmount({
sign: false, // false if negative.
denomination: IDydx.AssetDenomination.Wei, // Wei => actual token amount held in account.
ref: IDydx.AssetReference.Delta, // Delta => a relative amount.
value: amount // amount to withdraw.
});
// Create withdraw action.
withdrawAction = IDydx.ActionArgs({
actionType: IDydx.ActionType.Withdraw, // withdraw tokens.
amount: amountToWithdraw, // amount to withdraw.
accountIdx: bridgeAction.accountIdx, // index in the `accounts` when calling `operate`.
primaryMarketId: bridgeAction.marketId, // indicates which token to withdraw.
otherAddress: withdrawTo, // withdraw tokens to this address.
// unused parameters
secondaryMarketId: 0,
otherAccountIdx: 0,
data: hex''
});
}
}

View File

@@ -38,13 +38,14 @@ contract Eth2DaiBridge is
/// (DAI or WETH) to the Eth2Dai contract, then transfers the bought
/// tokens to `to`.
/// @param toTokenAddress The token to give to `to` (either DAI or WETH).
/// @param from The maker (this contract).
/// @param to The recipient of the bought tokens.
/// @param amount Minimum amount of `toTokenAddress` tokens to buy.
/// @param bridgeData The abi-encoeded "from" token address.
/// @return success The magic bytes if successful.
function bridgeTransferFrom(
address toTokenAddress,
address /* from */,
address from,
address to,
uint256 amount,
bytes calldata bridgeData
@@ -55,19 +56,29 @@ contract Eth2DaiBridge is
// Decode the bridge data to get the `fromTokenAddress`.
(address fromTokenAddress) = abi.decode(bridgeData, (address));
IEth2Dai exchange = _getEth2DaiContract();
IEth2Dai exchange = IEth2Dai(_getEth2DaiAddress());
uint256 fromTokenBalance = IERC20Token(fromTokenAddress).balanceOf(address(this));
// Grant an allowance to the exchange to spend `fromTokenAddress` token.
LibERC20Token.approve(fromTokenAddress, address(exchange), uint256(-1));
LibERC20Token.approveIfBelow(fromTokenAddress, address(exchange), fromTokenBalance);
// Try to sell all of this contract's `fromTokenAddress` token balance.
uint256 boughtAmount = exchange.sellAllAmount(
fromTokenAddress,
IERC20Token(fromTokenAddress).balanceOf(address(this)),
fromTokenBalance,
toTokenAddress,
amount
);
// Transfer the converted `toToken`s to `to`.
LibERC20Token.transfer(toTokenAddress, to, boughtAmount);
emit ERC20BridgeTransfer(
fromTokenAddress,
toTokenAddress,
fromTokenBalance,
boughtAmount,
from,
to
);
return BRIDGE_SUCCESS;
}
@@ -84,14 +95,4 @@ contract Eth2DaiBridge is
{
return LEGACY_WALLET_MAGIC_VALUE;
}
/// @dev Overridable way to get the eth2dai contract.
/// @return exchange The Eth2Dai exchange contract.
function _getEth2DaiContract()
internal
view
returns (IEth2Dai exchange)
{
return IEth2Dai(_getEth2DaiAddress());
}
}

View File

@@ -24,6 +24,7 @@ import "@0x/contracts-erc20/contracts/src/interfaces/IEtherToken.sol";
import "@0x/contracts-erc20/contracts/src/LibERC20Token.sol";
import "@0x/contracts-exchange-libs/contracts/src/IWallet.sol";
import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol";
import "@0x/contracts-utils/contracts/src/LibSafeMath.sol";
import "../interfaces/IERC20Bridge.sol";
import "../interfaces/IKyberNetworkProxy.sol";
@@ -34,6 +35,8 @@ contract KyberBridge is
IWallet,
DeploymentConstants
{
using LibSafeMath for uint256;
// @dev Structure used internally to get around stack limits.
struct TradeState {
IKyberNetworkProxy kyber;
@@ -41,6 +44,7 @@ contract KyberBridge is
address fromTokenAddress;
uint256 fromTokenBalance;
uint256 payableAmount;
uint256 conversionRate;
}
/// @dev Kyber ETH pseudo-address.
@@ -62,13 +66,14 @@ contract KyberBridge is
/// to the `KyberNetworkProxy` contract, then transfers the bought
/// tokens to `to`.
/// @param toTokenAddress The token to give to `to`.
/// @param from The maker (this contract).
/// @param to The recipient of the bought tokens.
/// @param amount Minimum amount of `toTokenAddress` tokens to buy.
/// @param bridgeData The abi-encoeded "from" token address.
/// @return success The magic bytes if successful.
function bridgeTransferFrom(
address toTokenAddress,
address /* from */,
address from,
address to,
uint256 amount,
bytes calldata bridgeData
@@ -77,15 +82,27 @@ contract KyberBridge is
returns (bytes4 success)
{
TradeState memory state;
state.kyber = _getKyberContract();
state.weth = _getWETHContract();
state.kyber = IKyberNetworkProxy(_getKyberNetworkProxyAddress());
state.weth = IEtherToken(_getWethAddress());
// Decode the bridge data to get the `fromTokenAddress`.
(state.fromTokenAddress) = abi.decode(bridgeData, (address));
// Query the balance of "from" tokens.
state.fromTokenBalance = IERC20Token(state.fromTokenAddress).balanceOf(address(this));
if (state.fromTokenBalance == 0) {
// Return failure if no input tokens.
return BRIDGE_FAILED;
}
// Compute the conversion rate, expressed in 18 decimals.
// The sequential notation is to get around stack limits.
state.conversionRate = KYBER_RATE_BASE;
state.conversionRate = state.conversionRate.safeMul(amount);
state.conversionRate = state.conversionRate.safeMul(
10 ** uint256(LibERC20Token.decimals(state.fromTokenAddress))
);
state.conversionRate = state.conversionRate.safeDiv(state.fromTokenBalance);
state.conversionRate = state.conversionRate.safeDiv(
10 ** uint256(LibERC20Token.decimals(toTokenAddress))
);
if (state.fromTokenAddress == toTokenAddress) {
// Just transfer the tokens if they're the same.
LibERC20Token.transfer(state.fromTokenAddress, to, state.fromTokenBalance);
@@ -93,7 +110,11 @@ contract KyberBridge is
} else if (state.fromTokenAddress != address(state.weth)) {
// If the input token is not WETH, grant an allowance to the exchange
// to spend them.
LibERC20Token.approve(state.fromTokenAddress, address(state.kyber), uint256(-1));
LibERC20Token.approveIfBelow(
state.fromTokenAddress,
address(state.kyber),
state.fromTokenBalance
);
} else {
// If the input token is WETH, unwrap it and attach it to the call.
state.fromTokenAddress = KYBER_ETH_ADDRESS;
@@ -118,7 +139,7 @@ contract KyberBridge is
uint256(-1),
// Compute the minimum conversion rate, which is expressed in units with
// 18 decimal places.
(KYBER_RATE_BASE * amount) / state.fromTokenBalance,
state.conversionRate,
// No affiliate address.
address(0)
);
@@ -127,6 +148,15 @@ contract KyberBridge is
state.weth.deposit.value(boughtAmount)();
state.weth.transfer(to, boughtAmount);
}
emit ERC20BridgeTransfer(
state.fromTokenAddress == KYBER_ETH_ADDRESS ? address(state.weth) : state.fromTokenAddress,
toTokenAddress,
state.fromTokenBalance,
boughtAmount,
from,
to
);
return BRIDGE_SUCCESS;
}
@@ -143,24 +173,4 @@ contract KyberBridge is
{
return LEGACY_WALLET_MAGIC_VALUE;
}
/// @dev Overridable way to get the `KyberNetworkProxy` contract.
/// @return kyber The `IKyberNetworkProxy` contract.
function _getKyberContract()
internal
view
returns (IKyberNetworkProxy kyber)
{
return IKyberNetworkProxy(_getKyberNetworkProxyAddress());
}
/// @dev Overridable way to get the WETH contract.
/// @return weth The WETH contract.
function _getWETHContract()
internal
view
returns (IEtherToken weth)
{
return IEtherToken(_getWETHAddress());
}
}

View File

@@ -0,0 +1,55 @@
/*
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.5.16;
import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol";
import "../interfaces/IGasToken.sol";
contract MixinGasToken is
DeploymentConstants
{
/// @dev Frees gas tokens based on the amount of gas consumed in the function
modifier freesGasTokens {
uint256 gasBefore = gasleft();
_;
IGasToken gst = IGasToken(_getGstAddress());
if (address(gst) != address(0)) {
// (gasUsed + FREE_BASE) / (2 * REIMBURSE - FREE_TOKEN)
// 14154 24000 6870
uint256 value = (gasBefore - gasleft() + 14154) / 41130;
gst.freeUpTo(value);
}
}
/// @dev Frees gas tokens using the balance of `from`. Amount freed is based
/// on the gas consumed in the function
modifier freesGasTokensFromCollector() {
uint256 gasBefore = gasleft();
_;
IGasToken gst = IGasToken(_getGstAddress());
if (address(gst) != address(0)) {
// (gasUsed + FREE_BASE) / (2 * REIMBURSE - FREE_TOKEN)
// 14154 24000 6870
uint256 value = (gasBefore - gasleft() + 14154) / 41130;
gst.freeFromUpTo(_getGstCollectorAddress(), value);
}
}
}

View File

@@ -38,10 +38,11 @@ contract UniswapBridge is
{
// Struct to hold `bridgeTransferFrom()` local variables in memory and to avoid
// stack overflows.
struct WithdrawToState {
struct TransferState {
IUniswapExchange exchange;
uint256 fromTokenBalance;
IEtherToken weth;
uint256 boughtAmount;
}
// solhint-disable no-empty-blocks
@@ -55,13 +56,14 @@ contract UniswapBridge is
/// `toTokenAddress` tokens by selling the entirety of the `fromTokenAddress`
/// token encoded in the bridge data.
/// @param toTokenAddress The token to buy and transfer to `to`.
/// @param from The maker (this contract).
/// @param to The recipient of the bought tokens.
/// @param amount Minimum amount of `toTokenAddress` tokens to buy.
/// @param bridgeData The abi-encoded "from" token address.
/// @return success The magic bytes if successful.
function bridgeTransferFrom(
address toTokenAddress,
address /* from */,
address from,
address to,
uint256 amount,
bytes calldata bridgeData
@@ -70,7 +72,7 @@ contract UniswapBridge is
returns (bytes4 success)
{
// State memory object to avoid stack overflows.
WithdrawToState memory state;
TransferState memory state;
// Decode the bridge data to get the `fromTokenAddress`.
(address fromTokenAddress) = abi.decode(bridgeData, (address));
@@ -88,7 +90,7 @@ contract UniswapBridge is
// Get our balance of `fromTokenAddress` token.
state.fromTokenBalance = IERC20Token(fromTokenAddress).balanceOf(address(this));
// Get the weth contract.
state.weth = getWethContract();
state.weth = IEtherToken(_getWethAddress());
// Convert from WETH to a token.
if (fromTokenAddress == address(state.weth)) {
@@ -96,7 +98,7 @@ contract UniswapBridge is
state.weth.withdraw(state.fromTokenBalance);
// Buy as much of `toTokenAddress` token with ETH as possible and
// transfer it to `to`.
state.exchange.ethToTokenTransferInput.value(state.fromTokenBalance)(
state.boughtAmount = state.exchange.ethToTokenTransferInput.value(state.fromTokenBalance)(
// Minimum buy amount.
amount,
// Expires after this block.
@@ -108,9 +110,9 @@ contract UniswapBridge is
// Convert from a token to WETH.
} else if (toTokenAddress == address(state.weth)) {
// Grant the exchange an allowance.
_grantExchangeAllowance(state.exchange, fromTokenAddress);
_grantExchangeAllowance(state.exchange, fromTokenAddress, state.fromTokenBalance);
// Buy as much ETH with `fromTokenAddress` token as possible.
uint256 ethBought = state.exchange.tokenToEthSwapInput(
state.boughtAmount = state.exchange.tokenToEthSwapInput(
// Sell all tokens we hold.
state.fromTokenBalance,
// Minimum buy amount.
@@ -119,23 +121,23 @@ contract UniswapBridge is
block.timestamp
);
// Wrap the ETH.
state.weth.deposit.value(ethBought)();
state.weth.deposit.value(state.boughtAmount)();
// Transfer the WETH to `to`.
IEtherToken(toTokenAddress).transfer(to, ethBought);
IEtherToken(toTokenAddress).transfer(to, state.boughtAmount);
// Convert from one token to another.
} else {
// Grant the exchange an allowance.
_grantExchangeAllowance(state.exchange, fromTokenAddress);
_grantExchangeAllowance(state.exchange, fromTokenAddress, state.fromTokenBalance);
// Buy as much `toTokenAddress` token with `fromTokenAddress` token
// and transfer it to `to`.
state.exchange.tokenToTokenTransferInput(
state.boughtAmount = state.exchange.tokenToTokenTransferInput(
// Sell all tokens we hold.
state.fromTokenBalance,
// Minimum buy amount.
amount,
// No minimum intermediate ETH buy amount.
0,
// Must buy at least 1 intermediate ETH.
1,
// Expires after this block.
block.timestamp,
// Recipient is `to`.
@@ -144,6 +146,15 @@ contract UniswapBridge is
toTokenAddress
);
}
emit ERC20BridgeTransfer(
fromTokenAddress,
toTokenAddress,
state.fromTokenBalance,
state.boughtAmount,
from,
to
);
return BRIDGE_SUCCESS;
}
@@ -161,34 +172,23 @@ contract UniswapBridge is
return LEGACY_WALLET_MAGIC_VALUE;
}
/// @dev Overridable way to get the weth contract.
/// @return token The WETH contract.
function getWethContract()
public
view
returns (IEtherToken token)
{
return IEtherToken(_getWETHAddress());
}
/// @dev Overridable way to get the uniswap exchange factory contract.
/// @return factory The exchange factory contract.
function getUniswapExchangeFactoryContract()
public
view
returns (IUniswapExchangeFactory factory)
{
return IUniswapExchangeFactory(_getUniswapExchangeFactoryAddress());
}
/// @dev Grants an unlimited allowance to the exchange for its token
/// on behalf of this contract.
/// @param exchange The Uniswap token exchange.
/// @param tokenAddress The token address for the exchange.
function _grantExchangeAllowance(IUniswapExchange exchange, address tokenAddress)
/// @param minimumAllowance The minimum necessary allowance.
function _grantExchangeAllowance(
IUniswapExchange exchange,
address tokenAddress,
uint256 minimumAllowance
)
private
{
LibERC20Token.approve(tokenAddress, address(exchange), uint256(-1));
LibERC20Token.approveIfBelow(
tokenAddress,
address(exchange),
minimumAllowance
);
}
/// @dev Retrieves the uniswap exchange for a given token pair.
@@ -207,11 +207,12 @@ contract UniswapBridge is
{
address exchangeTokenAddress = fromTokenAddress;
// Whichever isn't WETH is the exchange token.
if (fromTokenAddress == address(getWethContract())) {
if (fromTokenAddress == _getWethAddress()) {
exchangeTokenAddress = toTokenAddress;
}
exchange = IUniswapExchange(
getUniswapExchangeFactoryContract().getExchange(exchangeTokenAddress)
IUniswapExchangeFactory(_getUniswapExchangeFactoryAddress())
.getExchange(exchangeTokenAddress)
);
require(address(exchange) != address(0), "NO_UNISWAP_EXCHANGE_FOR_TOKEN");
return exchange;

View File

@@ -0,0 +1,135 @@
/*
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.5.9;
pragma experimental ABIEncoderV2;
import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol";
import "@0x/contracts-erc20/contracts/src/interfaces/IEtherToken.sol";
import "@0x/contracts-erc20/contracts/src/LibERC20Token.sol";
import "@0x/contracts-exchange-libs/contracts/src/IWallet.sol";
import "@0x/contracts-utils/contracts/src/LibAddressArray.sol";
import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol";
import "../interfaces/IUniswapV2Router01.sol";
import "../interfaces/IERC20Bridge.sol";
// solhint-disable space-after-comma
// solhint-disable not-rely-on-time
contract UniswapV2Bridge is
IERC20Bridge,
IWallet,
DeploymentConstants
{
struct TransferState {
address[] path;
uint256 fromTokenBalance;
}
/// @dev Callback for `IERC20Bridge`. Tries to buy `amount` of
/// `toTokenAddress` tokens by selling the entirety of the `fromTokenAddress`
/// token encoded in the bridge data.
/// @param toTokenAddress The token to buy and transfer to `to`.
/// @param from The maker (this contract).
/// @param to The recipient of the bought tokens.
/// @param amount Minimum amount of `toTokenAddress` tokens to buy.
/// @param bridgeData The abi-encoded path of token addresses. Last element must be toTokenAddress
/// @return success The magic bytes if successful.
function bridgeTransferFrom(
address toTokenAddress,
address from,
address to,
uint256 amount,
bytes calldata bridgeData
)
external
returns (bytes4 success)
{
// hold variables to get around stack depth limitations
TransferState memory state;
// Decode the bridge data to get the `fromTokenAddress`.
// solhint-disable indent
state.path = abi.decode(bridgeData, (address[]));
// solhint-enable indent
require(state.path.length >= 2, "UniswapV2Bridge/PATH_LENGTH_MUST_BE_AT_LEAST_TWO");
require(state.path[state.path.length - 1] == toTokenAddress, "UniswapV2Bridge/LAST_ELEMENT_OF_PATH_MUST_MATCH_OUTPUT_TOKEN");
// Just transfer the tokens if they're the same.
if (state.path[0] == toTokenAddress) {
LibERC20Token.transfer(state.path[0], to, amount);
return BRIDGE_SUCCESS;
}
// Get our balance of `fromTokenAddress` token.
state.fromTokenBalance = IERC20Token(state.path[0]).balanceOf(address(this));
// Grant the Uniswap router an allowance.
LibERC20Token.approveIfBelow(
state.path[0],
_getUniswapV2Router01Address(),
state.fromTokenBalance
);
// Buy as much `toTokenAddress` token with `fromTokenAddress` token
// and transfer it to `to`.
IUniswapV2Router01 router = IUniswapV2Router01(_getUniswapV2Router01Address());
uint[] memory amounts = router.swapExactTokensForTokens(
// Sell all tokens we hold.
state.fromTokenBalance,
// Minimum buy amount.
amount,
// Convert `fromTokenAddress` to `toTokenAddress`.
state.path,
// Recipient is `to`.
to,
// Expires after this block.
block.timestamp
);
emit ERC20BridgeTransfer(
// input token
state.path[0],
// output token
toTokenAddress,
// input token amount
state.fromTokenBalance,
// output token amount
amounts[amounts.length - 1],
from,
to
);
return BRIDGE_SUCCESS;
}
/// @dev `SignatureType.Wallet` callback, so that this bridge can be the maker
/// and sign for itself in orders. Always succeeds.
/// @return magicValue Success bytes, always.
function isValidSignature(
bytes32,
bytes calldata
)
external
view
returns (bytes4 magicValue)
{
return LEGACY_WALLET_MAGIC_VALUE;
}
}

View File

@@ -0,0 +1,66 @@
/*
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.5.9;
import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol";
contract PotLike {
function chi() external returns (uint256);
function rho() external returns (uint256);
function drip() external returns (uint256);
function join(uint256) external;
function exit(uint256) external;
}
// The actual Chai contract can be found here: https://github.com/dapphub/chai
contract IChai is
IERC20Token
{
/// @dev Withdraws Dai owned by `src`
/// @param src Address that owns Dai.
/// @param wad Amount of Dai to withdraw.
function draw(
address src,
uint256 wad
)
external;
/// @dev Queries Dai balance of Chai holder.
/// @param usr Address of Chai holder.
/// @return Dai balance.
function dai(address usr)
external
returns (uint256);
/// @dev Queries the Pot contract used by the Chai contract.
function pot()
external
returns (PotLike);
/// @dev Deposits Dai in exchange for Chai
/// @param dst Address to receive Chai.
/// @param wad Amount of Dai to deposit.
function join(
address dst,
uint256 wad
)
external;
}

View File

@@ -0,0 +1,86 @@
/*
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.5.9;
// solhint-disable func-name-mixedcase
interface ICurve {
/// @dev Sell `sellAmount` of `fromToken` token and receive `toToken` token.
/// This function exists on early versions of Curve (USDC/DAI)
/// @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.
/// @param deadline The time in seconds when this operation should expire.
function exchange_underlying(
int128 i,
int128 j,
uint256 sellAmount,
uint256 minBuyAmount,
uint256 deadline
)
external;
/// @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`
/// @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,192 @@
/*
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.5.9;
pragma experimental ABIEncoderV2;
interface IDydx {
/// @dev Represents the unique key that specifies an account
struct AccountInfo {
address owner; // The address that owns the account
uint256 number; // A nonce that allows a single address to control many accounts
}
enum ActionType {
Deposit, // supply tokens
Withdraw, // borrow tokens
Transfer, // transfer balance between accounts
Buy, // buy an amount of some token (externally)
Sell, // sell an amount of some token (externally)
Trade, // trade tokens against another account
Liquidate, // liquidate an undercollateralized or expiring account
Vaporize, // use excess tokens to zero-out a completely negative account
Call // send arbitrary data to an address
}
/// @dev Arguments that are passed to Solo in an ordered list as part of a single operation.
/// Each ActionArgs has an actionType which specifies which action struct that this data will be
/// parsed into before being processed.
struct ActionArgs {
ActionType actionType;
uint256 accountIdx;
AssetAmount amount;
uint256 primaryMarketId;
uint256 secondaryMarketId;
address otherAddress;
uint256 otherAccountIdx;
bytes data;
}
enum AssetDenomination {
Wei, // the amount is denominated in wei
Par // the amount is denominated in par
}
enum AssetReference {
Delta, // the amount is given as a delta from the current value
Target // the amount is given as an exact number to end up at
}
struct AssetAmount {
bool sign; // true if positive
AssetDenomination denomination;
AssetReference ref;
uint256 value;
}
struct D256 {
uint256 value;
}
struct Value {
uint256 value;
}
struct Price {
uint256 value;
}
struct OperatorArg {
address operator;
bool trusted;
}
/// @dev The global risk parameters that govern the health and security of the system
struct RiskParams {
// Required ratio of over-collateralization
D256 marginRatio;
// Percentage penalty incurred by liquidated accounts
D256 liquidationSpread;
// Percentage of the borrower's interest fee that gets passed to the suppliers
D256 earningsRate;
// The minimum absolute borrow value of an account
// There must be sufficient incentivize to liquidate undercollateralized accounts
Value minBorrowedValue;
}
/// @dev The main entry-point to Solo that allows users and contracts to manage accounts.
/// Take one or more actions on one or more accounts. The msg.sender must be the owner or
/// operator of all accounts except for those being liquidated, vaporized, or traded with.
/// One call to operate() is considered a singular "operation". Account collateralization is
/// ensured only after the completion of the entire operation.
/// @param accounts A list of all accounts that will be used in this operation. Cannot contain
/// duplicates. In each action, the relevant account will be referred-to by its
/// index in the list.
/// @param actions An ordered list of all actions that will be taken in this operation. The
/// actions will be processed in order.
function operate(
AccountInfo[] calldata accounts,
ActionArgs[] calldata actions
)
external;
// @dev Approves/disapproves any number of operators. An operator is an external address that has the
// same permissions to manipulate an account as the owner of the account. Operators are simply
// addresses and therefore may either be externally-owned Ethereum accounts OR smart contracts.
// Operators are also able to act as AutoTrader contracts on behalf of the account owner if the
// operator is a smart contract and implements the IAutoTrader interface.
// @param args A list of OperatorArgs which have an address and a boolean. The boolean value
// denotes whether to approve (true) or revoke approval (false) for that address.
function setOperators(OperatorArg[] calldata args) external;
/// @dev Return true if a particular address is approved as an operator for an owner's accounts.
/// Approved operators can act on the accounts of the owner as if it were the operator's own.
/// @param owner The owner of the accounts
/// @param operator The possible operator
/// @return isLocalOperator True if operator is approved for owner's accounts
function getIsLocalOperator(
address owner,
address operator
)
external
view
returns (bool isLocalOperator);
/// @dev Get the ERC20 token address for a market.
/// @param marketId The market to query
/// @return tokenAddress The token address
function getMarketTokenAddress(
uint256 marketId
)
external
view
returns (address tokenAddress);
/// @dev Get all risk parameters in a single struct.
/// @return riskParams All global risk parameters
function getRiskParams()
external
view
returns (RiskParams memory riskParams);
/// @dev Get the price of the token for a market.
/// @param marketId The market to query
/// @return price The price of each atomic unit of the token
function getMarketPrice(
uint256 marketId
)
external
view
returns (Price memory price);
/// @dev Get the margin premium for a market. A margin premium makes it so that any positions that
/// include the market require a higher collateralization to avoid being liquidated.
/// @param marketId The market to query
/// @return premium The market's margin premium
function getMarketMarginPremium(uint256 marketId)
external
view
returns (D256 memory premium);
/// @dev Get the total supplied and total borrowed values of an account adjusted by the marginPremium
/// of each market. Supplied values are divided by (1 + marginPremium) for each market and
/// borrowed values are multiplied by (1 + marginPremium) for each market. Comparing these
/// adjusted values gives the margin-ratio of the account which will be compared to the global
/// margin-ratio when determining if the account can be liquidated.
/// @param account The account to query
/// @return supplyValue The supplied value of the account (adjusted for marginPremium)
/// @return borrowValue The borrowed value of the account (adjusted for marginPremium)
function getAdjustedAccountValues(
AccountInfo calldata account
)
external
view
returns (Value memory supplyValue, Value memory borrowValue);
}

View File

@@ -0,0 +1,42 @@
/*
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.5.9;
interface IDydxBridge {
/// @dev This is the subset of `IDydx.ActionType` that are supported by the bridge.
enum BridgeActionType {
Deposit, // Deposit tokens into dydx account.
Withdraw // Withdraw tokens from dydx account.
}
struct BridgeAction {
BridgeActionType actionType; // Action to run on dydx account.
uint256 accountIdx; // Index in `BridgeData.accountNumbers` for this action.
uint256 marketId; // Market to operate on.
uint256 conversionRateNumerator; // Optional. If set, transfer amount is scaled by (conversionRateNumerator/conversionRateDenominator).
uint256 conversionRateDenominator; // Optional. If set, transfer amount is scaled by (conversionRateNumerator/conversionRateDenominator).
}
struct BridgeData {
uint256[] accountNumbers; // Account number used to identify the owner's specific account.
BridgeAction[] actions; // Actions to carry out on the owner's accounts.
}
}

View File

@@ -21,16 +21,32 @@ pragma solidity ^0.5.9;
contract IERC20Bridge {
// @dev Result of a successful bridge call.
/// @dev Result of a successful bridge call.
bytes4 constant internal BRIDGE_SUCCESS = 0xdc1600f3;
/// @dev Emitted when a trade occurs.
/// @param inputToken The token the bridge is converting from.
/// @param outputToken The token the bridge is converting to.
/// @param inputTokenAmount Amount of input token.
/// @param outputTokenAmount Amount of output token.
/// @param from The `from` address in `bridgeTransferFrom()`
/// @param to The `to` address in `bridgeTransferFrom()`
event ERC20BridgeTransfer(
address inputToken,
address outputToken,
uint256 inputTokenAmount,
uint256 outputTokenAmount,
address from,
address to
);
/// @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 `0x37708e9b` if successful.
/// @return success The magic bytes `0xdc1600f3` if successful.
function bridgeTransferFrom(
address tokenAddress,
address from,

View File

@@ -0,0 +1,40 @@
/*
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.5.15;
import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol";
contract IGasToken is IERC20Token {
/// @dev Frees up to `value` sub-tokens
/// @param value The amount of tokens to free
/// @return How many tokens were freed
function freeUpTo(uint256 value) external returns (uint256 freed);
/// @dev Frees up to `value` sub-tokens owned by `from`
/// @param from The owner of tokens to spend
/// @param value The amount of tokens to free
/// @return How many tokens were freed
function freeFromUpTo(address from, uint256 value) external returns (uint256 freed);
/// @dev Mints `value` amount of tokens
/// @param value The amount of tokens to mint
function mint(uint256 value) external;
}

View File

@@ -0,0 +1,40 @@
/*
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.5.9;
interface IUniswapV2Router01 {
/// @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 amountIn The amount of input tokens to send.
/// @param amountOutMin The minimum amount of output tokens that must be received for the transaction not to revert.
/// @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 to Recipient of the output tokens.
/// @param deadline Unix timestamp after which the transaction will revert.
/// @return amounts The input token amount and all subsequent output token amounts.
function swapExactTokensForTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external returns (uint[] memory amounts);
}

View File

@@ -0,0 +1,80 @@
/*
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.5.9;
pragma experimental ABIEncoderV2;
import "../src/bridges/ChaiBridge.sol";
import "@0x/contracts-erc20/contracts/src/ERC20Token.sol";
contract TestChaiDai is
ERC20Token
{
address private constant ALWAYS_REVERT_ADDRESS = address(1);
function draw(
address from,
uint256 amount
)
external
{
if (from == ALWAYS_REVERT_ADDRESS) {
revert();
}
balances[msg.sender] += amount;
}
}
contract TestChaiBridge is
ChaiBridge
{
address public testChaiDai;
address private constant ALWAYS_REVERT_ADDRESS = address(1);
constructor()
public
{
testChaiDai = address(new TestChaiDai());
}
function _getDaiAddress()
internal
view
returns (address)
{
return testChaiDai;
}
function _getChaiAddress()
internal
view
returns (address)
{
return testChaiDai;
}
function _getERC20BridgeProxyAddress()
internal
view
returns (address)
{
return msg.sender == ALWAYS_REVERT_ADDRESS ? address(0) : msg.sender;
}
}

View File

@@ -0,0 +1,244 @@
/*
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.5.9;
pragma experimental ABIEncoderV2;
import "../src/bridges/DexForwarderBridge.sol";
import "@0x/contracts-utils/contracts/src/LibSafeMath.sol";
interface ITestDexForwarderBridge {
event BridgeTransferFromCalled(
address caller,
uint256 inputTokenBalance,
address inputToken,
address outputToken,
address from,
address to,
uint256 amount
);
event TokenTransferCalled(
address from,
address to,
uint256 amount
);
function emitBridgeTransferFromCalled(
address caller,
uint256 inputTokenBalance,
address inputToken,
address outputToken,
address from,
address to,
uint256 amount
) external;
function emitTokenTransferCalled(
address from,
address to,
uint256 amount
) external;
}
interface ITestDexForwarderBridgeTestToken {
function transfer(address to, uint256 amount)
external
returns (bool);
function mint(address to, uint256 amount)
external;
function balanceOf(address owner) external view returns (uint256);
}
contract TestDexForwarderBridgeTestBridge {
bytes4 private _returnCode;
string private _revertError;
uint256 private _transferAmount;
ITestDexForwarderBridge private _testContract;
constructor(bytes4 returnCode, string memory revertError) public {
_testContract = ITestDexForwarderBridge(msg.sender);
_returnCode = returnCode;
_revertError = revertError;
}
function setTransferAmount(uint256 amount) external {
_transferAmount = amount;
}
function bridgeTransferFrom(
address outputToken,
address from,
address to,
uint256 amount,
bytes memory bridgeData
)
public
returns (bytes4 success)
{
if (bytes(_revertError).length != 0) {
revert(_revertError);
}
address inputToken = abi.decode(bridgeData, (address));
_testContract.emitBridgeTransferFromCalled(
msg.sender,
ITestDexForwarderBridgeTestToken(inputToken).balanceOf(address(this)),
inputToken,
outputToken,
from,
to,
amount
);
ITestDexForwarderBridgeTestToken(outputToken).mint(to, _transferAmount);
return _returnCode;
}
}
contract TestDexForwarderBridgeTestToken {
using LibSafeMath for uint256;
mapping(address => uint256) public balanceOf;
ITestDexForwarderBridge private _testContract;
constructor() public {
_testContract = ITestDexForwarderBridge(msg.sender);
}
function transfer(address to, uint256 amount)
external
returns (bool)
{
balanceOf[msg.sender] = balanceOf[msg.sender].safeSub(amount);
balanceOf[to] = balanceOf[to].safeAdd(amount);
_testContract.emitTokenTransferCalled(msg.sender, to, amount);
return true;
}
function mint(address owner, uint256 amount)
external
{
balanceOf[owner] = balanceOf[owner].safeAdd(amount);
}
function setBalance(address owner, uint256 amount)
external
{
balanceOf[owner] = amount;
}
}
contract TestDexForwarderBridge is
ITestDexForwarderBridge,
DexForwarderBridge
{
address private AUTHORIZED_ADDRESS; // solhint-disable-line var-name-mixedcase
function setAuthorized(address authorized)
public
{
AUTHORIZED_ADDRESS = authorized;
}
function createBridge(
bytes4 returnCode,
string memory revertError
)
public
returns (address bridge)
{
return address(new TestDexForwarderBridgeTestBridge(returnCode, revertError));
}
function createToken() public returns (address token) {
return address(new TestDexForwarderBridgeTestToken());
}
function setTokenBalance(address token, address owner, uint256 amount) public {
TestDexForwarderBridgeTestToken(token).setBalance(owner, amount);
}
function setBridgeTransferAmount(address bridge, uint256 amount) public {
TestDexForwarderBridgeTestBridge(bridge).setTransferAmount(amount);
}
function emitBridgeTransferFromCalled(
address caller,
uint256 inputTokenBalance,
address inputToken,
address outputToken,
address from,
address to,
uint256 amount
)
public
{
emit BridgeTransferFromCalled(
caller,
inputTokenBalance,
inputToken,
outputToken,
from,
to,
amount
);
}
function emitTokenTransferCalled(
address from,
address to,
uint256 amount
)
public
{
emit TokenTransferCalled(
from,
to,
amount
);
}
function balanceOf(address token, address owner) public view returns (uint256) {
return TestDexForwarderBridgeTestToken(token).balanceOf(owner);
}
function _getGstAddress()
internal
view
returns (address gst)
{
return address(0);
}
function _getERC20BridgeProxyAddress()
internal
view
returns (address erc20BridgeProxyAddress)
{
return AUTHORIZED_ADDRESS;
}
}

View File

@@ -0,0 +1,246 @@
/*
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.5.9;
pragma experimental ABIEncoderV2;
import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol";
import "../src/bridges/DydxBridge.sol";
// solhint-disable no-empty-blocks
contract TestDydxBridgeToken {
uint256 private constant INIT_HOLDER_BALANCE = 10 * 10**18; // 10 tokens
mapping (address => uint256) private _balances;
/// @dev Sets initial balance of token holders.
constructor(address[] memory holders)
public
{
for (uint256 i = 0; i != holders.length; ++i) {
_balances[holders[i]] = INIT_HOLDER_BALANCE;
}
_balances[msg.sender] = INIT_HOLDER_BALANCE;
}
/// @dev Basic transferFrom implementation.
function transferFrom(address from, address to, uint256 amount)
external
returns (bool)
{
if (_balances[from] < amount || _balances[to] + amount < _balances[to]) {
return false;
}
_balances[from] -= amount;
_balances[to] += amount;
return true;
}
/// @dev Returns balance of `holder`.
function balanceOf(address holder)
external
view
returns (uint256)
{
return _balances[holder];
}
}
// solhint-disable space-after-comma
contract TestDydxBridge is
IDydx,
DydxBridge
{
address private constant ALWAYS_REVERT_ADDRESS = address(1);
address private _testTokenAddress;
bool private _shouldRevertOnOperate;
event OperateAccount(
address owner,
uint256 number
);
event OperateAction(
ActionType actionType,
uint256 accountIdx,
bool amountSign,
AssetDenomination amountDenomination,
AssetReference amountRef,
uint256 amountValue,
uint256 primaryMarketId,
uint256 secondaryMarketId,
address otherAddress,
uint256 otherAccountId,
bytes data
);
constructor(address[] memory holders)
public
{
// Deploy a test token. This represents the asset being deposited/withdrawn from dydx.
_testTokenAddress = address(new TestDydxBridgeToken(holders));
}
/// @dev Simulates `operate` in dydx contract.
/// Emits events so that arguments can be validated client-side.
function operate(
AccountInfo[] calldata accounts,
ActionArgs[] calldata actions
)
external
{
if (_shouldRevertOnOperate) {
revert("TestDydxBridge/SHOULD_REVERT_ON_OPERATE");
}
for (uint i = 0; i < accounts.length; ++i) {
emit OperateAccount(
accounts[i].owner,
accounts[i].number
);
}
for (uint i = 0; i < actions.length; ++i) {
emit OperateAction(
actions[i].actionType,
actions[i].accountIdx,
actions[i].amount.sign,
actions[i].amount.denomination,
actions[i].amount.ref,
actions[i].amount.value,
actions[i].primaryMarketId,
actions[i].secondaryMarketId,
actions[i].otherAddress,
actions[i].otherAccountIdx,
actions[i].data
);
if (actions[i].actionType == IDydx.ActionType.Withdraw) {
require(
IERC20Token(_testTokenAddress).transferFrom(
address(this),
actions[i].otherAddress,
actions[i].amount.value
),
"TestDydxBridge/WITHDRAW_FAILED"
);
} else if (actions[i].actionType == IDydx.ActionType.Deposit) {
require(
IERC20Token(_testTokenAddress).transferFrom(
actions[i].otherAddress,
address(this),
actions[i].amount.value
),
"TestDydxBridge/DEPOSIT_FAILED"
);
} else {
revert("TestDydxBridge/UNSUPPORTED_ACTION");
}
}
}
/// @dev If `true` then subsequent calls to `operate` will revert.
function setRevertOnOperate(bool shouldRevert)
external
{
_shouldRevertOnOperate = shouldRevert;
}
/// @dev Returns test token.
function getTestToken()
external
returns (address)
{
return _testTokenAddress;
}
/// @dev Unused.
function setOperators(OperatorArg[] calldata args) external {}
/// @dev Unused.
function getIsLocalOperator(
address owner,
address operator
)
external
view
returns (bool isLocalOperator)
{}
/// @dev Unused.
function getMarketTokenAddress(
uint256 marketId
)
external
view
returns (address tokenAddress)
{}
/// @dev Unused.
function getRiskParams()
external
view
returns (RiskParams memory riskParams)
{}
/// @dev Unsused.
function getMarketPrice(
uint256 marketId
)
external
view
returns (Price memory price)
{}
/// @dev Unsused
function getMarketMarginPremium(uint256 marketId)
external
view
returns (IDydx.D256 memory premium)
{}
/// @dev Unused.
function getAdjustedAccountValues(
AccountInfo calldata account
)
external
view
returns (Value memory supplyValue, Value memory borrowValue)
{}
/// @dev overrides `_getDydxAddress()` from `DeploymentConstants` to return this address.
function _getDydxAddress()
internal
view
returns (address)
{
return address(this);
}
/// @dev overrides `_getERC20BridgeProxyAddress()` from `DeploymentConstants` for testing.
function _getERC20BridgeProxyAddress()
internal
view
returns (address)
{
return msg.sender == ALWAYS_REVERT_ADDRESS ? address(0) : msg.sender;
}
}

View File

@@ -110,6 +110,10 @@ contract TestToken {
return true;
}
function allowance(address, address) external view returns (uint256) {
return 0;
}
/// @dev Retrieve the balance for `owner`.
function balanceOf(address owner)
external
@@ -192,11 +196,11 @@ contract TestEth2DaiBridge is
}
// @dev This contract will double as the Eth2Dai contract.
function _getEth2DaiContract()
function _getEth2DaiAddress()
internal
view
returns (IEth2Dai)
returns (address)
{
return IEth2Dai(address(this));
return address(this);
}
}

View File

@@ -67,9 +67,11 @@ interface ITestContract {
/// @dev A minimalist ERC20/WETH token.
contract TestToken {
uint8 public decimals;
ITestContract private _testContract;
constructor() public {
constructor(uint8 decimals_) public {
decimals = decimals_;
_testContract = ITestContract(msg.sender);
}
@@ -108,6 +110,10 @@ contract TestToken {
return _testContract.wethDeposit.value(msg.value)(msg.sender);
}
function allowance(address, address) external view returns (uint256) {
return 0;
}
function balanceOf(address owner)
external
view
@@ -165,7 +171,7 @@ contract TestKyberBridge is
uint256 private _nextFillAmount;
constructor() public {
weth = IEtherToken(address(new TestToken()));
weth = IEtherToken(address(new TestToken(18)));
}
/// @dev Implementation of `IKyberNetworkProxy.trade()`
@@ -195,11 +201,11 @@ contract TestKyberBridge is
return _nextFillAmount;
}
function createToken()
function createToken(uint8 decimals)
external
returns (address tokenAddress)
{
return address(new TestToken());
return address(new TestToken(decimals));
}
function setNextFillAmount(uint256 amount)
@@ -303,20 +309,20 @@ contract TestKyberBridge is
}
// @dev overridden to point to this contract.
function _getKyberContract()
function _getKyberNetworkProxyAddress()
internal
view
returns (IKyberNetworkProxy kyber)
returns (address)
{
return IKyberNetworkProxy(address(this));
return address(this);
}
// @dev overridden to point to test WETH.
function _getWETHContract()
function _getWethAddress()
internal
view
returns (IEtherToken weth_)
returns (address)
{
return weth;
return address(weth);
}
}

View File

@@ -224,6 +224,10 @@ contract TestToken {
TestEventsRaiser(msg.sender).raiseWethWithdraw(amount);
}
function allowance(address, address) external view returns (uint256) {
return 0;
}
/// @dev Retrieve the balance for `owner`.
function balanceOf(address owner)
external
@@ -413,20 +417,20 @@ contract TestUniswapBridge is
}
// @dev Use `wethToken`.
function getWethContract()
public
function _getWethAddress()
internal
view
returns (IEtherToken)
returns (address)
{
return IEtherToken(address(wethToken));
return address(wethToken);
}
// @dev This contract will double as the Uniswap contract.
function getUniswapExchangeFactoryContract()
public
function _getUniswapExchangeFactoryAddress()
internal
view
returns (IUniswapExchangeFactory)
returns (address)
{
return IUniswapExchangeFactory(address(this));
return address(this);
}
}

View File

@@ -0,0 +1,253 @@
/*
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.5.9;
pragma experimental ABIEncoderV2;
import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol";
import "@0x/contracts-utils/contracts/src/LibSafeMath.sol";
import "@0x/contracts-utils/contracts/src/LibAddressArray.sol";
import "../src/bridges/UniswapV2Bridge.sol";
import "../src/interfaces/IUniswapV2Router01.sol";
contract TestEventsRaiser {
event TokenTransfer(
address token,
address from,
address to,
uint256 amount
);
event TokenApprove(
address spender,
uint256 allowance
);
event SwapExactTokensForTokensInput(
uint amountIn,
uint amountOutMin,
address toTokenAddress,
address to,
uint deadline
);
function raiseTokenTransfer(
address from,
address to,
uint256 amount
)
external
{
emit TokenTransfer(
msg.sender,
from,
to,
amount
);
}
function raiseTokenApprove(address spender, uint256 allowance) external {
emit TokenApprove(spender, allowance);
}
function raiseSwapExactTokensForTokensInput(
uint amountIn,
uint amountOutMin,
address toTokenAddress,
address to,
uint deadline
) external
{
emit SwapExactTokensForTokensInput(
amountIn,
amountOutMin,
toTokenAddress,
to,
deadline
);
}
}
/// @dev A minimalist ERC20 token.
contract TestToken {
using LibSafeMath for uint256;
mapping (address => uint256) public balances;
string private _nextRevertReason;
/// @dev Set the balance for `owner`.
function setBalance(address owner, uint256 balance)
external
payable
{
balances[owner] = balance;
}
/// @dev Just emits a TokenTransfer event on the caller
function transfer(address to, uint256 amount)
external
returns (bool)
{
TestEventsRaiser(msg.sender).raiseTokenTransfer(msg.sender, to, amount);
return true;
}
/// @dev Just emits a TokenApprove event on the caller
function approve(address spender, uint256 allowance)
external
returns (bool)
{
TestEventsRaiser(msg.sender).raiseTokenApprove(spender, allowance);
return true;
}
function allowance(address, address) external view returns (uint256) {
return 0;
}
/// @dev Retrieve the balance for `owner`.
function balanceOf(address owner)
external
view
returns (uint256)
{
return balances[owner];
}
}
/// @dev Mock the UniswapV2Router01 contract
contract TestRouter is
IUniswapV2Router01
{
string private _nextRevertReason;
/// @dev Set the revert reason for `swapExactTokensForTokens`.
function setRevertReason(string calldata reason)
external
{
_nextRevertReason = reason;
}
function swapExactTokensForTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external returns (uint[] memory amounts)
{
_revertIfReasonExists();
amounts = new uint[](path.length);
amounts[0] = amountIn;
amounts[amounts.length - 1] = amountOutMin;
TestEventsRaiser(msg.sender).raiseSwapExactTokensForTokensInput(
// tokens sold
amountIn,
// tokens bought
amountOutMin,
// output token (toTokenAddress)
path[path.length - 1],
// recipient
to,
// deadline
deadline
);
}
function _revertIfReasonExists()
private
view
{
if (bytes(_nextRevertReason).length != 0) {
revert(_nextRevertReason);
}
}
}
/// @dev UniswapV2Bridge overridden to mock tokens and Uniswap router
contract TestUniswapV2Bridge is
UniswapV2Bridge,
TestEventsRaiser
{
// Token address to TestToken instance.
mapping (address => TestToken) private _testTokens;
// TestRouter instance.
TestRouter private _testRouter;
constructor() public {
_testRouter = new TestRouter();
}
function setRouterRevertReason(string calldata revertReason)
external
{
_testRouter.setRevertReason(revertReason);
}
/// @dev Sets the balance of this contract for an existing token.
/// The wei attached will be the balance.
function setTokenBalance(address tokenAddress, uint256 balance)
external
{
TestToken token = _testTokens[tokenAddress];
token.setBalance(address(this), balance);
}
/// @dev Create a new token
/// @param tokenAddress The token address. If zero, one will be created.
function createToken(
address tokenAddress
)
external
returns (TestToken token)
{
token = TestToken(tokenAddress);
if (tokenAddress == address(0)) {
token = new TestToken();
}
_testTokens[address(token)] = token;
return token;
}
function getRouterAddress()
external
view
returns (address)
{
return address(_testRouter);
}
function _getUniswapV2Router01Address()
internal
view
returns (address)
{
return address(_testRouter);
}
}

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/contracts-asset-proxy",
"version": "3.0.0",
"version": "3.3.0",
"engines": {
"node": ">=6.12"
},
@@ -38,8 +38,7 @@
"docs:json": "typedoc --excludePrivate --excludeExternals --excludeProtected --ignoreCompilerErrors --target ES5 --tsconfig typedoc-tsconfig.json --json $JSON_FILE_PATH $PROJECT_FILES"
},
"config": {
"publicInterfaceContracts": "ERC1155Proxy,ERC20Proxy,ERC721Proxy,MultiAssetProxy,StaticCallProxy,ERC20BridgeProxy,Eth2DaiBridge,IAssetData,IAssetProxy,UniswapBridge,KyberBridge,TestStaticCallTarget",
"abis": "./test/generated-artifacts/@(ERC1155Proxy|ERC20BridgeProxy|ERC20Proxy|ERC721Proxy|Eth2DaiBridge|IAssetData|IAssetProxy|IAssetProxyDispatcher|IAuthorizable|IERC20Bridge|IEth2Dai|IKyberNetworkProxy|IUniswapExchange|IUniswapExchangeFactory|KyberBridge|MixinAssetProxyDispatcher|MixinAuthorizable|MultiAssetProxy|Ownable|StaticCallProxy|TestERC20Bridge|TestEth2DaiBridge|TestKyberBridge|TestStaticCallTarget|TestUniswapBridge|UniswapBridge).json",
"abis": "./test/generated-artifacts/@(ChaiBridge|CurveBridge|DexForwarderBridge|DydxBridge|ERC1155Proxy|ERC20BridgeProxy|ERC20Proxy|ERC721Proxy|Eth2DaiBridge|IAssetData|IAssetProxy|IAssetProxyDispatcher|IAuthorizable|IChai|ICurve|IDydx|IDydxBridge|IERC20Bridge|IEth2Dai|IGasToken|IKyberNetworkProxy|IUniswapExchange|IUniswapExchangeFactory|IUniswapV2Router01|KyberBridge|MixinAssetProxyDispatcher|MixinAuthorizable|MixinGasToken|MultiAssetProxy|Ownable|StaticCallProxy|TestChaiBridge|TestDexForwarderBridge|TestDydxBridge|TestERC20Bridge|TestEth2DaiBridge|TestKyberBridge|TestStaticCallTarget|TestUniswapBridge|TestUniswapV2Bridge|UniswapBridge|UniswapV2Bridge).json",
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually."
},
"repository": {
@@ -52,15 +51,15 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/protocol/README.md",
"devDependencies": {
"@0x/abi-gen": "^5.0.0",
"@0x/contracts-gen": "^2.0.0",
"@0x/contracts-test-utils": "^4.0.0",
"@0x/contracts-utils": "^4.0.0",
"@0x/dev-utils": "^3.0.0",
"@0x/sol-compiler": "^4.0.0",
"@0x/abi-gen": "^5.3.0",
"@0x/contract-wrappers": "^13.7.0",
"@0x/contracts-gen": "^2.0.9",
"@0x/contracts-test-utils": "^5.3.3",
"@0x/contracts-utils": "^4.5.0",
"@0x/dev-utils": "^3.2.2",
"@0x/sol-compiler": "^4.1.0",
"@0x/ts-doc-gen": "^0.0.22",
"@0x/tslint-config": "^4.0.0",
"@0x/types": "^3.0.0",
"@types/lodash": "4.14.104",
"@types/mocha": "^5.2.7",
"@types/node": "*",
@@ -80,16 +79,17 @@
"typescript": "3.0.1"
},
"dependencies": {
"@0x/base-contract": "^6.0.0",
"@0x/contracts-dev-utils": "^1.0.0",
"@0x/contracts-erc1155": "^2.0.0",
"@0x/contracts-erc20": "^3.0.0",
"@0x/contracts-erc721": "^3.0.0",
"@0x/order-utils": "^9.0.0",
"@0x/typescript-typings": "^5.0.0",
"@0x/utils": "^5.0.0",
"@0x/web3-wrapper": "^7.0.0",
"ethereum-types": "^3.0.0",
"@0x/base-contract": "^6.2.2",
"@0x/contracts-erc1155": "^2.1.6",
"@0x/contracts-erc20": "^3.2.0",
"@0x/contracts-erc721": "^3.1.6",
"@0x/contracts-exchange-libs": "^4.3.6",
"@0x/order-utils": "^10.2.5",
"@0x/types": "^3.1.3",
"@0x/typescript-typings": "^5.1.0",
"@0x/utils": "^5.5.0",
"@0x/web3-wrapper": "^7.1.0",
"ethereum-types": "^3.1.1",
"lodash": "^4.17.11"
},
"publishConfig": {

View File

@@ -5,6 +5,10 @@
*/
import { ContractArtifact } from 'ethereum-types';
import * as ChaiBridge from '../generated-artifacts/ChaiBridge.json';
import * as CurveBridge from '../generated-artifacts/CurveBridge.json';
import * as DexForwarderBridge from '../generated-artifacts/DexForwarderBridge.json';
import * as DydxBridge from '../generated-artifacts/DydxBridge.json';
import * as ERC1155Proxy from '../generated-artifacts/ERC1155Proxy.json';
import * as ERC20BridgeProxy from '../generated-artifacts/ERC20BridgeProxy.json';
import * as ERC20Proxy from '../generated-artifacts/ERC20Proxy.json';
@@ -12,22 +16,78 @@ import * as ERC721Proxy from '../generated-artifacts/ERC721Proxy.json';
import * as Eth2DaiBridge from '../generated-artifacts/Eth2DaiBridge.json';
import * as IAssetData from '../generated-artifacts/IAssetData.json';
import * as IAssetProxy from '../generated-artifacts/IAssetProxy.json';
import * as IAssetProxyDispatcher from '../generated-artifacts/IAssetProxyDispatcher.json';
import * as IAuthorizable from '../generated-artifacts/IAuthorizable.json';
import * as IChai from '../generated-artifacts/IChai.json';
import * as ICurve from '../generated-artifacts/ICurve.json';
import * as IDydx from '../generated-artifacts/IDydx.json';
import * as IDydxBridge from '../generated-artifacts/IDydxBridge.json';
import * as IERC20Bridge from '../generated-artifacts/IERC20Bridge.json';
import * as IEth2Dai from '../generated-artifacts/IEth2Dai.json';
import * as IGasToken from '../generated-artifacts/IGasToken.json';
import * as IKyberNetworkProxy from '../generated-artifacts/IKyberNetworkProxy.json';
import * as IUniswapExchange from '../generated-artifacts/IUniswapExchange.json';
import * as IUniswapExchangeFactory from '../generated-artifacts/IUniswapExchangeFactory.json';
import * as IUniswapV2Router01 from '../generated-artifacts/IUniswapV2Router01.json';
import * as KyberBridge from '../generated-artifacts/KyberBridge.json';
import * as MixinAssetProxyDispatcher from '../generated-artifacts/MixinAssetProxyDispatcher.json';
import * as MixinAuthorizable from '../generated-artifacts/MixinAuthorizable.json';
import * as MixinGasToken from '../generated-artifacts/MixinGasToken.json';
import * as MultiAssetProxy from '../generated-artifacts/MultiAssetProxy.json';
import * as Ownable from '../generated-artifacts/Ownable.json';
import * as StaticCallProxy from '../generated-artifacts/StaticCallProxy.json';
import * as TestChaiBridge from '../generated-artifacts/TestChaiBridge.json';
import * as TestDexForwarderBridge from '../generated-artifacts/TestDexForwarderBridge.json';
import * as TestDydxBridge from '../generated-artifacts/TestDydxBridge.json';
import * as TestERC20Bridge from '../generated-artifacts/TestERC20Bridge.json';
import * as TestEth2DaiBridge from '../generated-artifacts/TestEth2DaiBridge.json';
import * as TestKyberBridge from '../generated-artifacts/TestKyberBridge.json';
import * as TestStaticCallTarget from '../generated-artifacts/TestStaticCallTarget.json';
import * as TestUniswapBridge from '../generated-artifacts/TestUniswapBridge.json';
import * as TestUniswapV2Bridge from '../generated-artifacts/TestUniswapV2Bridge.json';
import * as UniswapBridge from '../generated-artifacts/UniswapBridge.json';
import * as UniswapV2Bridge from '../generated-artifacts/UniswapV2Bridge.json';
export const artifacts = {
MixinAssetProxyDispatcher: MixinAssetProxyDispatcher as ContractArtifact,
MixinAuthorizable: MixinAuthorizable as ContractArtifact,
Ownable: Ownable as ContractArtifact,
ERC1155Proxy: ERC1155Proxy as ContractArtifact,
ERC20BridgeProxy: ERC20BridgeProxy as ContractArtifact,
ERC20Proxy: ERC20Proxy as ContractArtifact,
ERC721Proxy: ERC721Proxy as ContractArtifact,
MultiAssetProxy: MultiAssetProxy as ContractArtifact,
StaticCallProxy: StaticCallProxy as ContractArtifact,
ERC20BridgeProxy: ERC20BridgeProxy as ContractArtifact,
ChaiBridge: ChaiBridge as ContractArtifact,
CurveBridge: CurveBridge as ContractArtifact,
DexForwarderBridge: DexForwarderBridge as ContractArtifact,
DydxBridge: DydxBridge as ContractArtifact,
Eth2DaiBridge: Eth2DaiBridge as ContractArtifact,
KyberBridge: KyberBridge as ContractArtifact,
MixinGasToken: MixinGasToken as ContractArtifact,
UniswapBridge: UniswapBridge as ContractArtifact,
UniswapV2Bridge: UniswapV2Bridge as ContractArtifact,
IAssetData: IAssetData as ContractArtifact,
IAssetProxy: IAssetProxy as ContractArtifact,
UniswapBridge: UniswapBridge as ContractArtifact,
KyberBridge: KyberBridge as ContractArtifact,
IAssetProxyDispatcher: IAssetProxyDispatcher as ContractArtifact,
IAuthorizable: IAuthorizable as ContractArtifact,
IChai: IChai as ContractArtifact,
ICurve: ICurve as ContractArtifact,
IDydx: IDydx as ContractArtifact,
IDydxBridge: IDydxBridge as ContractArtifact,
IERC20Bridge: IERC20Bridge as ContractArtifact,
IEth2Dai: IEth2Dai as ContractArtifact,
IGasToken: IGasToken as ContractArtifact,
IKyberNetworkProxy: IKyberNetworkProxy as ContractArtifact,
IUniswapExchange: IUniswapExchange as ContractArtifact,
IUniswapExchangeFactory: IUniswapExchangeFactory as ContractArtifact,
IUniswapV2Router01: IUniswapV2Router01 as ContractArtifact,
TestChaiBridge: TestChaiBridge as ContractArtifact,
TestDexForwarderBridge: TestDexForwarderBridge as ContractArtifact,
TestDydxBridge: TestDydxBridge as ContractArtifact,
TestERC20Bridge: TestERC20Bridge as ContractArtifact,
TestEth2DaiBridge: TestEth2DaiBridge as ContractArtifact,
TestKyberBridge: TestKyberBridge as ContractArtifact,
TestStaticCallTarget: TestStaticCallTarget as ContractArtifact,
TestUniswapBridge: TestUniswapBridge as ContractArtifact,
TestUniswapV2Bridge: TestUniswapV2Bridge as ContractArtifact,
};

View File

@@ -0,0 +1,112 @@
import { AssetProxyId } from '@0x/types';
import { BigNumber, hexUtils } from '@0x/utils';
import { IAssetDataContract } from './wrappers';
const assetDataIface = new IAssetDataContract('0x0000000000000000000000000000000000000000', { isEIP1193: true } as any);
/**
* Get the proxy ID from encoded asset data.
*/
export function getAssetDataProxyId(encoded: string): AssetProxyId {
// tslint:disable-next-line: no-unnecessary-type-assertion
return hexUtils.slice(encoded, 0, 4) as AssetProxyId;
}
/**
* Decode ERC20 asset data.
*/
export function decodeERC20AssetData(encoded: string): string {
return assetDataIface.getABIDecodedTransactionData<string>('ERC20Token', encoded);
}
/**
* Decode ERC721 asset data.
*/
export function decodeERC721AssetData(encoded: string): [string, BigNumber] {
return assetDataIface.getABIDecodedTransactionData<[string, BigNumber]>('ERC721Token', encoded);
}
/**
* Decode ERC1155 asset data.
*/
export function decodeERC1155AssetData(encoded: string): [string, BigNumber[], BigNumber[], string] {
return assetDataIface.getABIDecodedTransactionData<[string, BigNumber[], BigNumber[], string]>(
'ERC1155Assets',
encoded,
);
}
/**
* Decode MultiAsset asset data.
*/
export function decodeMultiAssetData(encoded: string): [BigNumber[], string[]] {
return assetDataIface.getABIDecodedTransactionData<[BigNumber[], string[]]>('MultiAsset', encoded);
}
/**
* Decode StaticCall asset data.
*/
export function decodeStaticCallAssetData(encoded: string): [string, string, string] {
return assetDataIface.getABIDecodedTransactionData<[string, string, string]>('StaticCall', encoded);
}
/**
* Decode ERC20Bridge asset data.
*/
export function decodeERC20BridgeAssetData(encoded: string): [string, string, string] {
return assetDataIface.getABIDecodedTransactionData<[string, string, string]>('ERC20Bridge', encoded);
}
/**
* Encode ERC20 asset data.
*/
export function encodeERC20AssetData(tokenAddress: string): string {
return assetDataIface.ERC20Token(tokenAddress).getABIEncodedTransactionData();
}
/**
* Encode ERC721 asset data.
*/
export function encodeERC721AssetData(tokenAddress: string, tokenId: BigNumber): string {
return assetDataIface.ERC721Token(tokenAddress, tokenId).getABIEncodedTransactionData();
}
/**
* Encode ERC1155 asset data.
*/
export function encodeERC1155AssetData(
tokenAddress: string,
tokenIds: BigNumber[],
values: BigNumber[],
callbackData: string,
): string {
return assetDataIface.ERC1155Assets(tokenAddress, tokenIds, values, callbackData).getABIEncodedTransactionData();
}
/**
* Encode MultiAsset asset data.
*/
export function encodeMultiAssetData(values: BigNumber[], nestedAssetData: string[]): string {
return assetDataIface.MultiAsset(values, nestedAssetData).getABIEncodedTransactionData();
}
/**
* Encode StaticCall asset data.
*/
export function encodeStaticCallAssetData(
staticCallTargetAddress: string,
staticCallData: string,
expectedReturnDataHash: string,
): string {
return assetDataIface
.StaticCall(staticCallTargetAddress, staticCallData, expectedReturnDataHash)
.getABIEncodedTransactionData();
}
/**
* Encode ERC20Bridge asset data.
*/
export function encodeERC20BridgeAssetData(tokenAddress: string, bridgeAddress: string, bridgeData: string): string {
return assetDataIface.ERC20Bridge(tokenAddress, bridgeAddress, bridgeData).getABIEncodedTransactionData();
}

View File

@@ -0,0 +1,27 @@
import { AbiEncoder, BigNumber } from '@0x/utils';
export interface DexForwarderBridgeCall {
target: string;
inputTokenAmount: BigNumber;
outputTokenAmount: BigNumber;
bridgeData: string;
}
export interface DexForwaderBridgeData {
inputToken: string;
calls: DexForwarderBridgeCall[];
}
export const dexForwarderBridgeDataEncoder = AbiEncoder.create([
{ name: 'inputToken', type: 'address' },
{
name: 'calls',
type: 'tuple[]',
components: [
{ name: 'target', type: 'address' },
{ name: 'inputTokenAmount', type: 'uint256' },
{ name: 'outputTokenAmount', type: 'uint256' },
{ name: 'bridgeData', type: 'bytes' },
],
},
]);

View File

@@ -0,0 +1,40 @@
import { AbiEncoder, BigNumber } from '@0x/utils';
export enum DydxBridgeActionType {
Deposit,
Withdraw,
}
export interface DydxBridgeAction {
actionType: DydxBridgeActionType;
accountIdx: BigNumber;
marketId: BigNumber;
conversionRateNumerator: BigNumber;
conversionRateDenominator: BigNumber;
}
export interface DydxBridgeData {
accountNumbers: BigNumber[];
actions: DydxBridgeAction[];
}
export const dydxBridgeDataEncoder = AbiEncoder.create([
{
name: 'bridgeData',
type: 'tuple',
components: [
{ name: 'accountNumbers', type: 'uint256[]' },
{
name: 'actions',
type: 'tuple[]',
components: [
{ name: 'actionType', type: 'uint8' },
{ name: 'accountIdx', type: 'uint256' },
{ name: 'marketId', type: 'uint256' },
{ name: 'conversionRateNumerator', type: 'uint256' },
{ name: 'conversionRateDenominator', type: 'uint256' },
],
},
],
},
]);

View File

@@ -1,4 +1,3 @@
import { DevUtilsContract } from '@0x/contracts-dev-utils';
import { artifacts as erc1155Artifacts, ERC1155MintableContract, Erc1155Wrapper } from '@0x/contracts-erc1155';
import {
constants,
@@ -15,7 +14,7 @@ import * as _ from 'lodash';
import { artifacts } from './artifacts';
import { ERC1155ProxyContract, IAssetProxyContract } from './wrappers';
import { ERC1155ProxyContract, IAssetDataContract, IAssetProxyContract } from './wrappers';
export class ERC1155ProxyWrapper {
private readonly _tokenOwnerAddresses: string[];
@@ -28,7 +27,7 @@ export class ERC1155ProxyWrapper {
private readonly _logDecoder: LogDecoder;
private readonly _dummyTokenWrappers: Erc1155Wrapper[];
private readonly _assetProxyInterface: IAssetProxyContract;
private readonly _devUtils: DevUtilsContract;
private readonly _assetDataInterface: IAssetDataContract;
private _proxyContract?: ERC1155ProxyContract;
private _proxyIdIfExists?: string;
private _initialTokenIdsByOwner: ERC1155HoldingsByOwner = { fungible: {}, nonFungible: {} };
@@ -40,7 +39,7 @@ export class ERC1155ProxyWrapper {
this._logDecoder = new LogDecoder(this._web3Wrapper, allArtifacts);
this._dummyTokenWrappers = [];
this._assetProxyInterface = new IAssetProxyContract(constants.NULL_ADDRESS, provider);
this._devUtils = new DevUtilsContract(constants.NULL_ADDRESS, provider);
this._assetDataInterface = new IAssetDataContract(constants.NULL_ADDRESS, provider);
this._tokenOwnerAddresses = tokenOwnerAddresses;
this._contractOwnerAddress = contractOwnerAddress;
this._fungibleTokenIds = [];
@@ -60,7 +59,7 @@ export class ERC1155ProxyWrapper {
txDefaults,
artifacts,
);
const erc1155Wrapper = new Erc1155Wrapper(erc1155Contract, this._provider, this._contractOwnerAddress);
const erc1155Wrapper = new Erc1155Wrapper(erc1155Contract, this._contractOwnerAddress);
this._dummyTokenWrappers.push(erc1155Wrapper);
}
return this._dummyTokenWrappers;
@@ -113,9 +112,9 @@ export class ERC1155ProxyWrapper {
this._validateProxyContractExistsOrThrow();
const assetData =
assetData_ === undefined
? await this._devUtils
.encodeERC1155AssetData(contractAddress, tokensToTransfer, valuesToTransfer, receiverCallbackData)
.callAsync()
? this._assetDataInterface
.ERC1155Assets(contractAddress, tokensToTransfer, valuesToTransfer, receiverCallbackData)
.getABIEncodedTransactionData()
: assetData_;
const data = this._assetProxyInterface
.transferFrom(assetData, from, to, valueMultiplier)
@@ -167,9 +166,9 @@ export class ERC1155ProxyWrapper {
this._validateProxyContractExistsOrThrow();
const assetData =
assetData_ === undefined
? await this._devUtils
.encodeERC1155AssetData(contractAddress, tokensToTransfer, valuesToTransfer, receiverCallbackData)
.callAsync()
? this._assetDataInterface
.ERC1155Assets(contractAddress, tokensToTransfer, valuesToTransfer, receiverCallbackData)
.getABIEncodedTransactionData()
: assetData_;
const data = this._assetProxyInterface
.transferFrom(assetData, from, to, valueMultiplier)

View File

@@ -1,4 +1,3 @@
import { DevUtilsContract } from '@0x/contracts-dev-utils';
import { artifacts as erc20Artifacts, DummyERC20TokenContract } from '@0x/contracts-erc20';
import { constants, ERC20BalancesByOwner, txDefaults } from '@0x/contracts-test-utils';
import { BigNumber } from '@0x/utils';
@@ -7,14 +6,14 @@ import * as _ from 'lodash';
import { artifacts } from './artifacts';
import { ERC20ProxyContract } from './wrappers';
import { ERC20ProxyContract, IAssetDataContract } from './wrappers';
export class ERC20Wrapper {
private readonly _tokenOwnerAddresses: string[];
private readonly _contractOwnerAddress: string;
private readonly _provider: ZeroExProvider;
private readonly _dummyTokenContracts: DummyERC20TokenContract[];
private readonly _devUtils: DevUtilsContract;
private readonly _assetDataInterface: IAssetDataContract;
private _proxyContract?: ERC20ProxyContract;
private _proxyIdIfExists?: string;
/**
@@ -29,7 +28,7 @@ export class ERC20Wrapper {
this._provider = provider;
this._tokenOwnerAddresses = tokenOwnerAddresses;
this._contractOwnerAddress = contractOwnerAddress;
this._devUtils = new DevUtilsContract(constants.NULL_ADDRESS, provider);
this._assetDataInterface = new IAssetDataContract(constants.NULL_ADDRESS, provider);
}
public async deployDummyTokensAsync(
numberToDeploy: number,
@@ -145,7 +144,7 @@ export class ERC20Wrapper {
return tokenAddresses;
}
private async _getTokenContractFromAssetDataAsync(assetData: string): Promise<DummyERC20TokenContract> {
const [proxyId, tokenAddress] = await this._devUtils.decodeERC20AssetData(assetData).callAsync(); // tslint:disable-line:no-unused-variable
const tokenAddress = this._assetDataInterface.getABIDecodedTransactionData<string>('ERC20Token', assetData); // tslint:disable-line:no-unused-variable
const tokenContractIfExists = _.find(this._dummyTokenContracts, c => c.address === tokenAddress);
if (tokenContractIfExists === undefined) {
throw new Error(`Token: ${tokenAddress} was not deployed through ERC20Wrapper`);

View File

@@ -1,14 +1,20 @@
export { artifacts } from './artifacts';
export {
ChaiBridgeContract,
ERC1155ProxyContract,
ERC20BridgeProxyContract,
ERC20ProxyContract,
ERC721ProxyContract,
Eth2DaiBridgeContract,
DydxBridgeContract,
IAssetDataContract,
IAssetProxyContract,
IChaiContract,
IDydxContract,
KyberBridgeContract,
MultiAssetProxyContract,
StaticCallProxyContract,
TestDydxBridgeContract,
TestStaticCallTargetContract,
UniswapBridgeContract,
} from './wrappers';
@@ -19,6 +25,7 @@ export { ERC1155ProxyWrapper } from './erc1155_proxy_wrapper';
export { ERC1155MintableContract, Erc1155Wrapper } from '@0x/contracts-erc1155';
export { DummyERC20TokenContract } from '@0x/contracts-erc20';
export { DummyERC721TokenContract } from '@0x/contracts-erc721';
export { AssetProxyId } from '@0x/types';
export {
ERC1155HoldingsByOwner,
ERC20BalancesByOwner,
@@ -49,6 +56,7 @@ export {
OutputField,
ParamDescription,
EvmBytecodeOutput,
EvmBytecodeOutputLinkReferences,
AbiDefinition,
FunctionAbi,
EventAbi,
@@ -62,3 +70,22 @@ export {
TupleDataItem,
StateMutability,
} from 'ethereum-types';
export {
decodeERC1155AssetData,
decodeERC20AssetData,
decodeERC20BridgeAssetData,
decodeERC721AssetData,
decodeMultiAssetData,
decodeStaticCallAssetData,
encodeERC1155AssetData,
encodeERC20AssetData,
encodeERC20BridgeAssetData,
encodeERC721AssetData,
encodeMultiAssetData,
encodeStaticCallAssetData,
getAssetDataProxyId,
} from './asset_data';
export * from './dydx_bridge_encoder';
export * from './dex_forwarder_bridge';

View File

@@ -3,6 +3,10 @@
* Warning: This file is auto-generated by contracts-gen. Don't edit manually.
* -----------------------------------------------------------------------------
*/
export * from '../generated-wrappers/chai_bridge';
export * from '../generated-wrappers/curve_bridge';
export * from '../generated-wrappers/dex_forwarder_bridge';
export * from '../generated-wrappers/dydx_bridge';
export * from '../generated-wrappers/erc1155_proxy';
export * from '../generated-wrappers/erc20_bridge_proxy';
export * from '../generated-wrappers/erc20_proxy';
@@ -10,8 +14,34 @@ export * from '../generated-wrappers/erc721_proxy';
export * from '../generated-wrappers/eth2_dai_bridge';
export * from '../generated-wrappers/i_asset_data';
export * from '../generated-wrappers/i_asset_proxy';
export * from '../generated-wrappers/i_asset_proxy_dispatcher';
export * from '../generated-wrappers/i_authorizable';
export * from '../generated-wrappers/i_chai';
export * from '../generated-wrappers/i_curve';
export * from '../generated-wrappers/i_dydx';
export * from '../generated-wrappers/i_dydx_bridge';
export * from '../generated-wrappers/i_erc20_bridge';
export * from '../generated-wrappers/i_eth2_dai';
export * from '../generated-wrappers/i_gas_token';
export * from '../generated-wrappers/i_kyber_network_proxy';
export * from '../generated-wrappers/i_uniswap_exchange';
export * from '../generated-wrappers/i_uniswap_exchange_factory';
export * from '../generated-wrappers/i_uniswap_v2_router01';
export * from '../generated-wrappers/kyber_bridge';
export * from '../generated-wrappers/mixin_asset_proxy_dispatcher';
export * from '../generated-wrappers/mixin_authorizable';
export * from '../generated-wrappers/mixin_gas_token';
export * from '../generated-wrappers/multi_asset_proxy';
export * from '../generated-wrappers/ownable';
export * from '../generated-wrappers/static_call_proxy';
export * from '../generated-wrappers/test_chai_bridge';
export * from '../generated-wrappers/test_dex_forwarder_bridge';
export * from '../generated-wrappers/test_dydx_bridge';
export * from '../generated-wrappers/test_erc20_bridge';
export * from '../generated-wrappers/test_eth2_dai_bridge';
export * from '../generated-wrappers/test_kyber_bridge';
export * from '../generated-wrappers/test_static_call_target';
export * from '../generated-wrappers/test_uniswap_bridge';
export * from '../generated-wrappers/test_uniswap_v2_bridge';
export * from '../generated-wrappers/uniswap_bridge';
export * from '../generated-wrappers/uniswap_v2_bridge';

View File

@@ -5,6 +5,10 @@
*/
import { ContractArtifact } from 'ethereum-types';
import * as ChaiBridge from '../test/generated-artifacts/ChaiBridge.json';
import * as CurveBridge from '../test/generated-artifacts/CurveBridge.json';
import * as DexForwarderBridge from '../test/generated-artifacts/DexForwarderBridge.json';
import * as DydxBridge from '../test/generated-artifacts/DydxBridge.json';
import * as ERC1155Proxy from '../test/generated-artifacts/ERC1155Proxy.json';
import * as ERC20BridgeProxy from '../test/generated-artifacts/ERC20BridgeProxy.json';
import * as ERC20Proxy from '../test/generated-artifacts/ERC20Proxy.json';
@@ -14,23 +18,35 @@ import * as IAssetData from '../test/generated-artifacts/IAssetData.json';
import * as IAssetProxy from '../test/generated-artifacts/IAssetProxy.json';
import * as IAssetProxyDispatcher from '../test/generated-artifacts/IAssetProxyDispatcher.json';
import * as IAuthorizable from '../test/generated-artifacts/IAuthorizable.json';
import * as IChai from '../test/generated-artifacts/IChai.json';
import * as ICurve from '../test/generated-artifacts/ICurve.json';
import * as IDydx from '../test/generated-artifacts/IDydx.json';
import * as IDydxBridge from '../test/generated-artifacts/IDydxBridge.json';
import * as IERC20Bridge from '../test/generated-artifacts/IERC20Bridge.json';
import * as IEth2Dai from '../test/generated-artifacts/IEth2Dai.json';
import * as IGasToken from '../test/generated-artifacts/IGasToken.json';
import * as IKyberNetworkProxy from '../test/generated-artifacts/IKyberNetworkProxy.json';
import * as IUniswapExchange from '../test/generated-artifacts/IUniswapExchange.json';
import * as IUniswapExchangeFactory from '../test/generated-artifacts/IUniswapExchangeFactory.json';
import * as IUniswapV2Router01 from '../test/generated-artifacts/IUniswapV2Router01.json';
import * as KyberBridge from '../test/generated-artifacts/KyberBridge.json';
import * as MixinAssetProxyDispatcher from '../test/generated-artifacts/MixinAssetProxyDispatcher.json';
import * as MixinAuthorizable from '../test/generated-artifacts/MixinAuthorizable.json';
import * as MixinGasToken from '../test/generated-artifacts/MixinGasToken.json';
import * as MultiAssetProxy from '../test/generated-artifacts/MultiAssetProxy.json';
import * as Ownable from '../test/generated-artifacts/Ownable.json';
import * as StaticCallProxy from '../test/generated-artifacts/StaticCallProxy.json';
import * as TestChaiBridge from '../test/generated-artifacts/TestChaiBridge.json';
import * as TestDexForwarderBridge from '../test/generated-artifacts/TestDexForwarderBridge.json';
import * as TestDydxBridge from '../test/generated-artifacts/TestDydxBridge.json';
import * as TestERC20Bridge from '../test/generated-artifacts/TestERC20Bridge.json';
import * as TestEth2DaiBridge from '../test/generated-artifacts/TestEth2DaiBridge.json';
import * as TestKyberBridge from '../test/generated-artifacts/TestKyberBridge.json';
import * as TestStaticCallTarget from '../test/generated-artifacts/TestStaticCallTarget.json';
import * as TestUniswapBridge from '../test/generated-artifacts/TestUniswapBridge.json';
import * as TestUniswapV2Bridge from '../test/generated-artifacts/TestUniswapV2Bridge.json';
import * as UniswapBridge from '../test/generated-artifacts/UniswapBridge.json';
import * as UniswapV2Bridge from '../test/generated-artifacts/UniswapV2Bridge.json';
export const artifacts = {
MixinAssetProxyDispatcher: MixinAssetProxyDispatcher as ContractArtifact,
MixinAuthorizable: MixinAuthorizable as ContractArtifact,
@@ -41,21 +57,37 @@ export const artifacts = {
ERC721Proxy: ERC721Proxy as ContractArtifact,
MultiAssetProxy: MultiAssetProxy as ContractArtifact,
StaticCallProxy: StaticCallProxy as ContractArtifact,
ChaiBridge: ChaiBridge as ContractArtifact,
CurveBridge: CurveBridge as ContractArtifact,
DexForwarderBridge: DexForwarderBridge as ContractArtifact,
DydxBridge: DydxBridge as ContractArtifact,
Eth2DaiBridge: Eth2DaiBridge as ContractArtifact,
KyberBridge: KyberBridge as ContractArtifact,
MixinGasToken: MixinGasToken as ContractArtifact,
UniswapBridge: UniswapBridge as ContractArtifact,
UniswapV2Bridge: UniswapV2Bridge as ContractArtifact,
IAssetData: IAssetData as ContractArtifact,
IAssetProxy: IAssetProxy as ContractArtifact,
IAssetProxyDispatcher: IAssetProxyDispatcher as ContractArtifact,
IAuthorizable: IAuthorizable as ContractArtifact,
IChai: IChai as ContractArtifact,
ICurve: ICurve as ContractArtifact,
IDydx: IDydx as ContractArtifact,
IDydxBridge: IDydxBridge as ContractArtifact,
IERC20Bridge: IERC20Bridge as ContractArtifact,
IEth2Dai: IEth2Dai as ContractArtifact,
IGasToken: IGasToken as ContractArtifact,
IKyberNetworkProxy: IKyberNetworkProxy as ContractArtifact,
IUniswapExchange: IUniswapExchange as ContractArtifact,
IUniswapExchangeFactory: IUniswapExchangeFactory as ContractArtifact,
IUniswapV2Router01: IUniswapV2Router01 as ContractArtifact,
TestChaiBridge: TestChaiBridge as ContractArtifact,
TestDexForwarderBridge: TestDexForwarderBridge as ContractArtifact,
TestDydxBridge: TestDydxBridge as ContractArtifact,
TestERC20Bridge: TestERC20Bridge as ContractArtifact,
TestEth2DaiBridge: TestEth2DaiBridge as ContractArtifact,
TestKyberBridge: TestKyberBridge as ContractArtifact,
TestStaticCallTarget: TestStaticCallTarget as ContractArtifact,
TestUniswapBridge: TestUniswapBridge as ContractArtifact,
TestUniswapV2Bridge: TestUniswapV2Bridge as ContractArtifact,
};

View File

@@ -1,35 +1,20 @@
import { chaiSetup, expectTransactionFailedAsync, provider, txDefaults, web3Wrapper } from '@0x/contracts-test-utils';
import { BlockchainLifecycle } from '@0x/dev-utils';
import { blockchainTests, expect, provider, txDefaults, web3Wrapper } from '@0x/contracts-test-utils';
import { RevertReason } from '@0x/types';
import { BigNumber } from '@0x/utils';
import * as chai from 'chai';
import * as _ from 'lodash';
import { artifacts } from './artifacts';
import { MixinAuthorizableContract } from './wrappers';
chaiSetup.configure();
const expect = chai.expect;
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
describe('Authorizable', () => {
blockchainTests.resets('Authorizable', () => {
let owner: string;
let notOwner: string;
let address: string;
let authorizable: MixinAuthorizableContract;
before(async () => {
await blockchainLifecycle.startAsync();
});
after(async () => {
await blockchainLifecycle.revertAsync();
});
before(async () => {
const accounts = await web3Wrapper.getAvailableAddressesAsync();
[owner, address, notOwner] = _.slice(accounts, 0, 3);
[owner, address, notOwner] = accounts.slice(0, 3);
authorizable = await MixinAuthorizableContract.deployFrom0xArtifactAsync(
artifacts.MixinAuthorizable,
provider,
@@ -38,20 +23,10 @@ describe('Authorizable', () => {
);
});
beforeEach(async () => {
await blockchainLifecycle.startAsync();
});
afterEach(async () => {
await blockchainLifecycle.revertAsync();
});
describe('addAuthorizedAddress', () => {
it('should revert if not called by owner', async () => {
await expectTransactionFailedAsync(
authorizable.addAuthorizedAddress(notOwner).sendTransactionAsync({ from: notOwner }),
RevertReason.OnlyContractOwner,
);
const tx = authorizable.addAuthorizedAddress(notOwner).sendTransactionAsync({ from: notOwner });
return expect(tx).to.revertWith(RevertReason.OnlyContractOwner);
});
it('should allow owner to add an authorized address', async () => {
@@ -62,20 +37,16 @@ describe('Authorizable', () => {
it('should revert if owner attempts to authorize a duplicate address', async () => {
await authorizable.addAuthorizedAddress(address).awaitTransactionSuccessAsync({ from: owner });
return expectTransactionFailedAsync(
authorizable.addAuthorizedAddress(address).sendTransactionAsync({ from: owner }),
RevertReason.TargetAlreadyAuthorized,
);
const tx = authorizable.addAuthorizedAddress(address).sendTransactionAsync({ from: owner });
return expect(tx).to.revertWith(RevertReason.TargetAlreadyAuthorized);
});
});
describe('removeAuthorizedAddress', () => {
it('should revert if not called by owner', async () => {
await authorizable.addAuthorizedAddress(address).awaitTransactionSuccessAsync({ from: owner });
await expectTransactionFailedAsync(
authorizable.removeAuthorizedAddress(address).sendTransactionAsync({ from: notOwner }),
RevertReason.OnlyContractOwner,
);
const tx = authorizable.removeAuthorizedAddress(address).sendTransactionAsync({ from: notOwner });
return expect(tx).to.revertWith(RevertReason.OnlyContractOwner);
});
it('should allow owner to remove an authorized address', async () => {
@@ -86,12 +57,8 @@ describe('Authorizable', () => {
});
it('should revert if owner attempts to remove an address that is not authorized', async () => {
return expectTransactionFailedAsync(
authorizable.removeAuthorizedAddress(address).sendTransactionAsync({
from: owner,
}),
RevertReason.TargetNotAuthorized,
);
const tx = authorizable.removeAuthorizedAddress(address).sendTransactionAsync({ from: owner });
return expect(tx).to.revertWith(RevertReason.TargetNotAuthorized);
});
});
@@ -99,33 +66,27 @@ describe('Authorizable', () => {
it('should revert if not called by owner', async () => {
await authorizable.addAuthorizedAddress(address).awaitTransactionSuccessAsync({ from: owner });
const index = new BigNumber(0);
await expectTransactionFailedAsync(
authorizable.removeAuthorizedAddressAtIndex(address, index).sendTransactionAsync({
from: notOwner,
}),
RevertReason.OnlyContractOwner,
);
const tx = authorizable
.removeAuthorizedAddressAtIndex(address, index)
.sendTransactionAsync({ from: notOwner });
return expect(tx).to.revertWith(RevertReason.OnlyContractOwner);
});
it('should revert if index is >= authorities.length', async () => {
await authorizable.addAuthorizedAddress(address).awaitTransactionSuccessAsync({ from: owner });
const index = new BigNumber(1);
return expectTransactionFailedAsync(
authorizable.removeAuthorizedAddressAtIndex(address, index).sendTransactionAsync({
from: owner,
}),
RevertReason.IndexOutOfBounds,
);
const tx = authorizable
.removeAuthorizedAddressAtIndex(address, index)
.sendTransactionAsync({ from: owner });
return expect(tx).to.revertWith(RevertReason.IndexOutOfBounds);
});
it('should revert if owner attempts to remove an address that is not authorized', async () => {
const index = new BigNumber(0);
return expectTransactionFailedAsync(
authorizable.removeAuthorizedAddressAtIndex(address, index).sendTransactionAsync({
from: owner,
}),
RevertReason.TargetNotAuthorized,
);
const tx = authorizable
.removeAuthorizedAddressAtIndex(address, index)
.sendTransactionAsync({ from: owner });
return expect(tx).to.revertWith(RevertReason.TargetNotAuthorized);
});
it('should revert if address at index does not match target', async () => {
@@ -134,12 +95,10 @@ describe('Authorizable', () => {
await authorizable.addAuthorizedAddress(address1).awaitTransactionSuccessAsync({ from: owner });
await authorizable.addAuthorizedAddress(address2).awaitTransactionSuccessAsync({ from: owner });
const address1Index = new BigNumber(0);
return expectTransactionFailedAsync(
authorizable.removeAuthorizedAddressAtIndex(address2, address1Index).sendTransactionAsync({
from: owner,
}),
RevertReason.AuthorizedAddressMismatch,
);
const tx = authorizable
.removeAuthorizedAddressAtIndex(address2, address1Index)
.sendTransactionAsync({ from: owner });
return expect(tx).to.revertWith(RevertReason.AuthorizedAddressMismatch);
});
it('should allow owner to remove an authorized address', async () => {

View File

@@ -0,0 +1,60 @@
import { ERC20TokenContract } from '@0x/contracts-erc20';
import { blockchainTests, constants, expect, randomAddress } from '@0x/contracts-test-utils';
import { AssetProxyId, RevertReason } from '@0x/types';
import { BigNumber } from '@0x/utils';
import { artifacts } from './artifacts';
import { TestChaiBridgeContract } from './wrappers';
blockchainTests.resets('ChaiBridge unit tests', env => {
let chaiBridgeContract: TestChaiBridgeContract;
let testDaiContract: ERC20TokenContract;
let fromAddress: string;
let toAddress: string;
const alwaysRevertAddress = '0x0000000000000000000000000000000000000001';
const amount = new BigNumber(1);
before(async () => {
[fromAddress, toAddress] = await env.getAccountAddressesAsync();
chaiBridgeContract = await TestChaiBridgeContract.deployFrom0xArtifactAsync(
artifacts.TestChaiBridge,
env.provider,
env.txDefaults,
artifacts,
);
const testChaiDaiAddress = await chaiBridgeContract.testChaiDai().callAsync();
testDaiContract = new ERC20TokenContract(testChaiDaiAddress, env.provider, env.txDefaults);
});
describe('bridgeTransferFrom()', () => {
it('fails if not called by ERC20BridgeProxy', async () => {
return expect(
chaiBridgeContract
.bridgeTransferFrom(randomAddress(), fromAddress, toAddress, amount, constants.NULL_BYTES)
.awaitTransactionSuccessAsync({ from: alwaysRevertAddress }),
).to.revertWith(RevertReason.ChaiBridgeOnlyCallableByErc20BridgeProxy);
});
it('returns magic bytes upon success', async () => {
const magicBytes = await chaiBridgeContract
.bridgeTransferFrom(randomAddress(), fromAddress, toAddress, amount, constants.NULL_BYTES)
.callAsync();
expect(magicBytes).to.eq(AssetProxyId.ERC20Bridge);
});
it('should increase the Dai balance of `toAddress` by `amount` if successful', async () => {
const initialBalance = await testDaiContract.balanceOf(toAddress).callAsync();
await chaiBridgeContract
.bridgeTransferFrom(randomAddress(), fromAddress, toAddress, amount, constants.NULL_BYTES)
.awaitTransactionSuccessAsync();
const endBalance = await testDaiContract.balanceOf(toAddress).callAsync();
expect(endBalance).to.bignumber.eq(initialBalance.plus(amount));
});
it('fails if the `chai.draw` call fails', async () => {
return expect(
chaiBridgeContract
.bridgeTransferFrom(randomAddress(), alwaysRevertAddress, toAddress, amount, constants.NULL_BYTES)
.awaitTransactionSuccessAsync(),
).to.revertWith(RevertReason.ChaiBridgeDrawDaiFailed);
});
});
});

View File

@@ -0,0 +1,356 @@
import { ContractTxFunctionObj } from '@0x/contract-wrappers';
import {
blockchainTests,
constants,
expect,
filterLogsToArguments,
getRandomInteger,
randomAddress,
shortZip,
} from '@0x/contracts-test-utils';
import { BigNumber, hexUtils, NULL_ADDRESS } from '@0x/utils';
import { DecodedLogs } from 'ethereum-types';
import * as _ from 'lodash';
import { DexForwarderBridgeCall, dexForwarderBridgeDataEncoder } from '../src/dex_forwarder_bridge';
import { artifacts } from './artifacts';
import {
TestDexForwarderBridgeBridgeTransferFromCalledEventArgs as BtfCalledEventArgs,
TestDexForwarderBridgeContract,
TestDexForwarderBridgeEvents as TestEvents,
} from './wrappers';
const { ZERO_AMOUNT } = constants;
blockchainTests.resets('DexForwarderBridge unit tests', env => {
let testContract: TestDexForwarderBridgeContract;
let inputToken: string;
let outputToken: string;
const BRIDGE_SUCCESS = '0xdc1600f3';
const BRIDGE_FAILURE = '0xffffffff';
const BRIDGE_REVERT_ERROR = 'oopsie';
const INCOMPLETE_FILL_REVERT = 'DexForwarderBridge/INCOMPLETE_FILL';
const NOT_AUTHORIZED_REVERT = 'DexForwarderBridge/SENDER_NOT_AUTHORIZED';
const DEFAULTS = {
toAddress: randomAddress(),
};
before(async () => {
testContract = await TestDexForwarderBridgeContract.deployFrom0xArtifactAsync(
artifacts.TestDexForwarderBridge,
env.provider,
env.txDefaults,
artifacts,
);
// Create test tokens.
[inputToken, outputToken] = [
await callAndTransactAsync(testContract.createToken()),
await callAndTransactAsync(testContract.createToken()),
];
await callAndTransactAsync(testContract.setAuthorized(env.txDefaults.from as string));
});
async function callAndTransactAsync<TResult>(fnCall: ContractTxFunctionObj<TResult>): Promise<TResult> {
const result = await fnCall.callAsync();
await fnCall.awaitTransactionSuccessAsync({}, { shouldValidate: false });
return result;
}
function getRandomBridgeCall(
bridgeAddress: string,
fields: Partial<DexForwarderBridgeCall> = {},
): DexForwarderBridgeCall {
return {
target: bridgeAddress,
inputTokenAmount: getRandomInteger(1, '100e18'),
outputTokenAmount: getRandomInteger(1, '100e18'),
bridgeData: hexUtils.leftPad(inputToken),
...fields,
};
}
describe('bridgeTransferFrom()', () => {
let goodBridgeCalls: DexForwarderBridgeCall[];
let revertingBridgeCall: DexForwarderBridgeCall;
let failingBridgeCall: DexForwarderBridgeCall;
let allBridgeCalls: DexForwarderBridgeCall[];
let totalFillableOutputAmount: BigNumber;
let totalFillableInputAmount: BigNumber;
let recipientOutputBalance: BigNumber;
beforeEach(async () => {
goodBridgeCalls = [];
for (let i = 0; i < 4; ++i) {
goodBridgeCalls.push(await createBridgeCallAsync({ returnCode: BRIDGE_SUCCESS }));
}
revertingBridgeCall = await createBridgeCallAsync({ revertError: BRIDGE_REVERT_ERROR });
failingBridgeCall = await createBridgeCallAsync({ returnCode: BRIDGE_FAILURE });
allBridgeCalls = _.shuffle([failingBridgeCall, revertingBridgeCall, ...goodBridgeCalls]);
totalFillableInputAmount = BigNumber.sum(...goodBridgeCalls.map(c => c.inputTokenAmount));
totalFillableOutputAmount = BigNumber.sum(...goodBridgeCalls.map(c => c.outputTokenAmount));
// Grant the taker some output tokens.
await testContract.setTokenBalance(
outputToken,
DEFAULTS.toAddress,
(recipientOutputBalance = getRandomInteger(1, '100e18')),
);
});
async function setForwarderInputBalanceAsync(amount: BigNumber): Promise<void> {
await testContract
.setTokenBalance(inputToken, testContract.address, amount)
.awaitTransactionSuccessAsync({}, { shouldValidate: false });
}
async function createBridgeCallAsync(
opts: Partial<{
returnCode: string;
revertError: string;
callFields: Partial<DexForwarderBridgeCall>;
outputFillAmount: BigNumber;
}>,
): Promise<DexForwarderBridgeCall> {
const { returnCode, revertError, callFields, outputFillAmount } = {
returnCode: BRIDGE_SUCCESS,
revertError: '',
...opts,
};
const bridge = await callAndTransactAsync(testContract.createBridge(returnCode, revertError));
const call = getRandomBridgeCall(bridge, callFields);
await testContract
.setBridgeTransferAmount(call.target, outputFillAmount || call.outputTokenAmount)
.awaitTransactionSuccessAsync({}, { shouldValidate: false });
return call;
}
async function callBridgeTransferFromAsync(opts: {
bridgeData: string;
sellAmount?: BigNumber;
buyAmount?: BigNumber;
}): Promise<DecodedLogs> {
// Fund the forwarder with input tokens to sell.
await setForwarderInputBalanceAsync(opts.sellAmount || totalFillableInputAmount);
const call = testContract.bridgeTransferFrom(
outputToken,
testContract.address,
DEFAULTS.toAddress,
opts.buyAmount || totalFillableOutputAmount,
opts.bridgeData,
);
const returnCode = await call.callAsync();
if (returnCode !== BRIDGE_SUCCESS) {
throw new Error('Expected BRIDGE_SUCCESS');
}
const receipt = await call.awaitTransactionSuccessAsync({}, { shouldValidate: false });
// tslint:disable-next-line: no-unnecessary-type-assertion
return receipt.logs as DecodedLogs;
}
it('succeeds with no bridge calls and no input balance', async () => {
const bridgeData = dexForwarderBridgeDataEncoder.encode({
inputToken,
calls: [],
});
await callBridgeTransferFromAsync({ bridgeData, sellAmount: ZERO_AMOUNT });
});
it('succeeds with bridge calls and no input balance', async () => {
const bridgeData = dexForwarderBridgeDataEncoder.encode({
inputToken,
calls: allBridgeCalls,
});
await callBridgeTransferFromAsync({ bridgeData, sellAmount: ZERO_AMOUNT });
});
it('fails with no bridge calls and an input balance', async () => {
const bridgeData = dexForwarderBridgeDataEncoder.encode({
inputToken,
calls: [],
});
return expect(callBridgeTransferFromAsync({ bridgeData, sellAmount: new BigNumber(1) })).to.revertWith(
INCOMPLETE_FILL_REVERT,
);
});
it('fails if entire input token balance is not consumed', async () => {
const bridgeData = dexForwarderBridgeDataEncoder.encode({
inputToken,
calls: allBridgeCalls,
});
return expect(
callBridgeTransferFromAsync({
bridgeData,
sellAmount: totalFillableInputAmount.plus(1),
}),
).to.revertWith(INCOMPLETE_FILL_REVERT);
});
it('fails if not authorized', async () => {
const calls = goodBridgeCalls.slice(0, 1);
const bridgeData = dexForwarderBridgeDataEncoder.encode({
inputToken,
calls,
});
await callAndTransactAsync(testContract.setAuthorized(NULL_ADDRESS));
return expect(callBridgeTransferFromAsync({ bridgeData, sellAmount: new BigNumber(1) })).to.revertWith(
NOT_AUTHORIZED_REVERT,
);
});
it('succeeds with one bridge call', async () => {
const calls = goodBridgeCalls.slice(0, 1);
const bridgeData = dexForwarderBridgeDataEncoder.encode({
inputToken,
calls,
});
await callBridgeTransferFromAsync({ bridgeData, sellAmount: calls[0].inputTokenAmount });
});
it('succeeds with many bridge calls', async () => {
const calls = goodBridgeCalls;
const bridgeData = dexForwarderBridgeDataEncoder.encode({
inputToken,
calls,
});
await callBridgeTransferFromAsync({ bridgeData });
});
it('swallows a failing bridge call', async () => {
const calls = _.shuffle([...goodBridgeCalls, failingBridgeCall]);
const bridgeData = dexForwarderBridgeDataEncoder.encode({
inputToken,
calls,
});
await callBridgeTransferFromAsync({ bridgeData });
});
it('consumes input tokens for output tokens', async () => {
const calls = allBridgeCalls;
const bridgeData = dexForwarderBridgeDataEncoder.encode({
inputToken,
calls,
});
await callBridgeTransferFromAsync({ bridgeData });
const currentBridgeInputBalance = await testContract
.balanceOf(inputToken, testContract.address)
.callAsync();
expect(currentBridgeInputBalance).to.bignumber.eq(0);
const currentRecipientOutputBalance = await testContract
.balanceOf(outputToken, DEFAULTS.toAddress)
.callAsync();
expect(currentRecipientOutputBalance).to.bignumber.eq(totalFillableOutputAmount);
});
it("transfers only up to each call's input amount to each bridge", async () => {
const calls = goodBridgeCalls;
const bridgeData = dexForwarderBridgeDataEncoder.encode({
inputToken,
calls,
});
const logs = await callBridgeTransferFromAsync({ bridgeData });
const btfs = filterLogsToArguments<BtfCalledEventArgs>(logs, TestEvents.BridgeTransferFromCalled);
for (const [call, btf] of shortZip(goodBridgeCalls, btfs)) {
expect(btf.inputTokenBalance).to.bignumber.eq(call.inputTokenAmount);
}
});
it('transfers only up to outstanding sell amount to each bridge', async () => {
// Prepend an extra bridge call.
const calls = [
await createBridgeCallAsync({
callFields: {
inputTokenAmount: new BigNumber(1),
outputTokenAmount: new BigNumber(1),
},
}),
...goodBridgeCalls,
];
const bridgeData = dexForwarderBridgeDataEncoder.encode({
inputToken,
calls,
});
const logs = await callBridgeTransferFromAsync({ bridgeData });
const btfs = filterLogsToArguments<BtfCalledEventArgs>(logs, TestEvents.BridgeTransferFromCalled);
expect(btfs).to.be.length(goodBridgeCalls.length + 1);
// The last call will receive 1 less token.
const lastCall = calls.slice(-1)[0];
const lastBtf = btfs.slice(-1)[0];
expect(lastBtf.inputTokenBalance).to.bignumber.eq(lastCall.inputTokenAmount.minus(1));
});
it('recoups funds from a bridge that fails', async () => {
// Prepend a call that will take the whole input amount but will
// fail.
const badCall = await createBridgeCallAsync({
callFields: { inputTokenAmount: totalFillableInputAmount },
returnCode: BRIDGE_FAILURE,
});
const calls = [badCall, ...goodBridgeCalls];
const bridgeData = dexForwarderBridgeDataEncoder.encode({
inputToken,
calls,
});
const logs = await callBridgeTransferFromAsync({ bridgeData });
const btfs = filterLogsToArguments<BtfCalledEventArgs>(logs, TestEvents.BridgeTransferFromCalled);
expect(btfs).to.be.length(goodBridgeCalls.length);
});
it('recoups funds from a bridge that reverts', async () => {
// Prepend a call that will take the whole input amount but will
// revert.
const badCall = await createBridgeCallAsync({
callFields: { inputTokenAmount: totalFillableInputAmount },
revertError: BRIDGE_REVERT_ERROR,
});
const calls = [badCall, ...goodBridgeCalls];
const bridgeData = dexForwarderBridgeDataEncoder.encode({
inputToken,
calls,
});
const logs = await callBridgeTransferFromAsync({ bridgeData });
const btfs = filterLogsToArguments<BtfCalledEventArgs>(logs, TestEvents.BridgeTransferFromCalled);
expect(btfs).to.be.length(goodBridgeCalls.length);
});
it('recoups funds from a bridge that under-pays', async () => {
// Prepend a call that will take the whole input amount but will
// underpay the output amount..
const badCall = await createBridgeCallAsync({
callFields: {
inputTokenAmount: totalFillableInputAmount,
outputTokenAmount: new BigNumber(2),
},
outputFillAmount: new BigNumber(1),
});
const calls = [badCall, ...goodBridgeCalls];
const bridgeData = dexForwarderBridgeDataEncoder.encode({
inputToken,
calls,
});
const logs = await callBridgeTransferFromAsync({ bridgeData });
const btfs = filterLogsToArguments<BtfCalledEventArgs>(logs, TestEvents.BridgeTransferFromCalled);
expect(btfs).to.be.length(goodBridgeCalls.length);
});
});
describe('executeBridgeCall()', () => {
it('cannot be called externally', async () => {
return expect(
testContract
.executeBridgeCall(
randomAddress(),
randomAddress(),
randomAddress(),
randomAddress(),
new BigNumber(1),
new BigNumber(1),
constants.NULL_BYTES,
)
.callAsync(),
).to.revertWith('DexForwarderBridge/ONLY_SELF');
});
});
});

View File

@@ -0,0 +1,399 @@
import { LibMathRevertErrors } from '@0x/contracts-exchange-libs';
import { blockchainTests, constants, expect, verifyEventsFromLogs } from '@0x/contracts-test-utils';
import { AssetProxyId, RevertReason } from '@0x/types';
import { BigNumber } from '@0x/utils';
import * as _ from 'lodash';
import { DydxBridgeActionType, DydxBridgeData, dydxBridgeDataEncoder } from '../src/dydx_bridge_encoder';
import { ERC20BridgeProxyContract, IAssetDataContract } from '../src/wrappers';
import { artifacts } from './artifacts';
import { TestDydxBridgeContract, TestDydxBridgeEvents } from './wrappers';
blockchainTests.resets('DydxBridge unit tests', env => {
const defaultAccountNumber = new BigNumber(1);
const marketId = new BigNumber(2);
const defaultAmount = new BigNumber(4);
const notAuthorized = '0x0000000000000000000000000000000000000001';
const defaultDepositAction = {
actionType: DydxBridgeActionType.Deposit,
accountIdx: constants.ZERO_AMOUNT,
marketId,
conversionRateNumerator: constants.ZERO_AMOUNT,
conversionRateDenominator: constants.ZERO_AMOUNT,
};
const defaultWithdrawAction = {
actionType: DydxBridgeActionType.Withdraw,
accountIdx: constants.ZERO_AMOUNT,
marketId,
conversionRateNumerator: constants.ZERO_AMOUNT,
conversionRateDenominator: constants.ZERO_AMOUNT,
};
let testContract: TestDydxBridgeContract;
let testProxyContract: ERC20BridgeProxyContract;
let assetDataEncoder: IAssetDataContract;
let owner: string;
let authorized: string;
let accountOwner: string;
let receiver: string;
before(async () => {
// Get accounts
const accounts = await env.web3Wrapper.getAvailableAddressesAsync();
[owner, authorized, accountOwner, receiver] = accounts;
// Deploy dydx bridge
testContract = await TestDydxBridgeContract.deployFrom0xArtifactAsync(
artifacts.TestDydxBridge,
env.provider,
env.txDefaults,
artifacts,
[accountOwner, receiver],
);
// Deploy test erc20 bridge proxy
testProxyContract = await ERC20BridgeProxyContract.deployFrom0xArtifactAsync(
artifacts.ERC20BridgeProxy,
env.provider,
env.txDefaults,
artifacts,
);
await testProxyContract.addAuthorizedAddress(authorized).awaitTransactionSuccessAsync({ from: owner });
// Setup asset data encoder
assetDataEncoder = new IAssetDataContract(constants.NULL_ADDRESS, env.provider);
});
describe('bridgeTransferFrom()', () => {
const callBridgeTransferFrom = async (
from: string,
to: string,
amount: BigNumber,
bridgeData: DydxBridgeData,
sender: string,
): Promise<string> => {
const returnValue = await testContract
.bridgeTransferFrom(
constants.NULL_ADDRESS,
from,
to,
amount,
dydxBridgeDataEncoder.encode({ bridgeData }),
)
.callAsync({ from: sender });
return returnValue;
};
const executeBridgeTransferFromAndVerifyEvents = async (
from: string,
to: string,
amount: BigNumber,
bridgeData: DydxBridgeData,
sender: string,
): Promise<void> => {
// Execute transaction.
const txReceipt = await testContract
.bridgeTransferFrom(
constants.NULL_ADDRESS,
from,
to,
amount,
dydxBridgeDataEncoder.encode({ bridgeData }),
)
.awaitTransactionSuccessAsync({ from: sender });
// Verify `OperateAccount` event.
const expectedOperateAccountEvents = [];
for (const accountNumber of bridgeData.accountNumbers) {
expectedOperateAccountEvents.push({
owner: accountOwner,
number: accountNumber,
});
}
verifyEventsFromLogs(txReceipt.logs, expectedOperateAccountEvents, TestDydxBridgeEvents.OperateAccount);
// Verify `OperateAction` event.
const weiDenomination = 0;
const deltaAmountRef = 0;
const expectedOperateActionEvents = [];
for (const action of bridgeData.actions) {
expectedOperateActionEvents.push({
actionType: action.actionType as number,
accountIdx: action.accountIdx,
amountSign: action.actionType === DydxBridgeActionType.Deposit ? true : false,
amountDenomination: weiDenomination,
amountRef: deltaAmountRef,
amountValue: action.conversionRateDenominator.gt(0)
? amount
.times(action.conversionRateNumerator)
.dividedToIntegerBy(action.conversionRateDenominator)
: amount,
primaryMarketId: marketId,
secondaryMarketId: constants.ZERO_AMOUNT,
otherAddress: action.actionType === DydxBridgeActionType.Deposit ? from : to,
otherAccountId: constants.ZERO_AMOUNT,
data: '0x',
});
}
verifyEventsFromLogs(txReceipt.logs, expectedOperateActionEvents, TestDydxBridgeEvents.OperateAction);
};
it('succeeds when calling with zero amount', async () => {
const bridgeData = {
accountNumbers: [defaultAccountNumber],
actions: [defaultDepositAction],
};
await executeBridgeTransferFromAndVerifyEvents(
accountOwner,
receiver,
constants.ZERO_AMOUNT,
bridgeData,
authorized,
);
});
it('succeeds when calling with no accounts', async () => {
const bridgeData = {
accountNumbers: [],
actions: [defaultDepositAction],
};
await executeBridgeTransferFromAndVerifyEvents(
accountOwner,
receiver,
defaultAmount,
bridgeData,
authorized,
);
});
it('succeeds when calling with no actions', async () => {
const bridgeData = {
accountNumbers: [defaultAccountNumber],
actions: [],
};
await executeBridgeTransferFromAndVerifyEvents(
accountOwner,
receiver,
defaultAmount,
bridgeData,
authorized,
);
});
it('succeeds when calling `operate` with the `deposit` action and a single account', async () => {
const bridgeData = {
accountNumbers: [defaultAccountNumber],
actions: [defaultDepositAction],
};
await executeBridgeTransferFromAndVerifyEvents(
accountOwner,
receiver,
defaultAmount,
bridgeData,
authorized,
);
});
it('succeeds when calling `operate` with the `deposit` action and multiple accounts', async () => {
const bridgeData = {
accountNumbers: [defaultAccountNumber, defaultAccountNumber.plus(1)],
actions: [defaultDepositAction],
};
await executeBridgeTransferFromAndVerifyEvents(
accountOwner,
receiver,
defaultAmount,
bridgeData,
authorized,
);
});
it('succeeds when calling `operate` with the `withdraw` action and a single account', async () => {
const bridgeData = {
accountNumbers: [defaultAccountNumber],
actions: [defaultWithdrawAction],
};
await executeBridgeTransferFromAndVerifyEvents(
accountOwner,
receiver,
defaultAmount,
bridgeData,
authorized,
);
});
it('succeeds when calling `operate` with the `withdraw` action and multiple accounts', async () => {
const bridgeData = {
accountNumbers: [defaultAccountNumber, defaultAccountNumber.plus(1)],
actions: [defaultWithdrawAction],
};
await executeBridgeTransferFromAndVerifyEvents(
accountOwner,
receiver,
defaultAmount,
bridgeData,
authorized,
);
});
it('succeeds when calling `operate` with the `deposit` action and multiple accounts', async () => {
const bridgeData = {
accountNumbers: [defaultAccountNumber, defaultAccountNumber.plus(1)],
actions: [defaultWithdrawAction, defaultDepositAction],
};
await executeBridgeTransferFromAndVerifyEvents(
accountOwner,
receiver,
defaultAmount,
bridgeData,
authorized,
);
});
it('succeeds when calling `operate` with multiple actions under a single account', async () => {
const bridgeData = {
accountNumbers: [defaultAccountNumber],
actions: [defaultWithdrawAction, defaultDepositAction],
};
await executeBridgeTransferFromAndVerifyEvents(
accountOwner,
receiver,
defaultAmount,
bridgeData,
authorized,
);
});
it('succeeds when scaling the `amount` to deposit', async () => {
const conversionRateNumerator = new BigNumber(1);
const conversionRateDenominator = new BigNumber(2);
const bridgeData = {
accountNumbers: [defaultAccountNumber],
actions: [
defaultWithdrawAction,
{
...defaultDepositAction,
conversionRateNumerator,
conversionRateDenominator,
},
],
};
await executeBridgeTransferFromAndVerifyEvents(
accountOwner,
receiver,
defaultAmount,
bridgeData,
authorized,
);
});
it('succeeds when scaling the `amount` to withdraw', async () => {
const conversionRateNumerator = new BigNumber(1);
const conversionRateDenominator = new BigNumber(2);
const bridgeData = {
accountNumbers: [defaultAccountNumber],
actions: [
defaultDepositAction,
{
...defaultWithdrawAction,
conversionRateNumerator,
conversionRateDenominator,
},
],
};
await executeBridgeTransferFromAndVerifyEvents(
accountOwner,
receiver,
defaultAmount,
bridgeData,
authorized,
);
});
it('reverts if not called by the ERC20 Bridge Proxy', async () => {
const bridgeData = {
accountNumbers: [defaultAccountNumber],
actions: [defaultDepositAction],
};
const callBridgeTransferFromPromise = callBridgeTransferFrom(
accountOwner,
receiver,
defaultAmount,
bridgeData,
notAuthorized,
);
const expectedError = RevertReason.DydxBridgeOnlyCallableByErc20BridgeProxy;
return expect(callBridgeTransferFromPromise).to.revertWith(expectedError);
});
it('should return magic bytes if call succeeds', async () => {
const bridgeData = {
accountNumbers: [defaultAccountNumber],
actions: [defaultDepositAction],
};
const returnValue = await callBridgeTransferFrom(
accountOwner,
receiver,
defaultAmount,
bridgeData,
authorized,
);
expect(returnValue).to.equal(AssetProxyId.ERC20Bridge);
});
it('should revert when `Operate` reverts', async () => {
// Set revert flag.
await testContract.setRevertOnOperate(true).awaitTransactionSuccessAsync();
// Execute transfer.
const bridgeData = {
accountNumbers: [defaultAccountNumber],
actions: [defaultDepositAction],
};
const tx = callBridgeTransferFrom(accountOwner, receiver, defaultAmount, bridgeData, authorized);
const expectedError = 'TestDydxBridge/SHOULD_REVERT_ON_OPERATE';
return expect(tx).to.revertWith(expectedError);
});
it('should revert when there is a rounding error', async () => {
// Setup a rounding error
const conversionRateNumerator = new BigNumber(5318);
const conversionRateDenominator = new BigNumber(47958);
const amount = new BigNumber(9000);
const bridgeData = {
accountNumbers: [defaultAccountNumber],
actions: [
defaultDepositAction,
{
...defaultWithdrawAction,
conversionRateNumerator,
conversionRateDenominator,
},
],
};
// Execute transfer and assert error.
const tx = callBridgeTransferFrom(accountOwner, receiver, amount, bridgeData, authorized);
const expectedError = new LibMathRevertErrors.RoundingError(
conversionRateNumerator,
conversionRateDenominator,
amount,
);
return expect(tx).to.revertWith(expectedError);
});
});
describe('ERC20BridgeProxy.transferFrom()', () => {
const bridgeData = {
accountNumbers: [defaultAccountNumber],
actions: [defaultWithdrawAction],
};
let assetData: string;
before(async () => {
const testTokenAddress = await testContract.getTestToken().callAsync();
assetData = assetDataEncoder
.ERC20Bridge(testTokenAddress, testContract.address, dydxBridgeDataEncoder.encode({ bridgeData }))
.getABIEncodedTransactionData();
});
it('should succeed if `bridgeTransferFrom` succeeds', async () => {
await testProxyContract
.transferFrom(assetData, accountOwner, receiver, defaultAmount)
.awaitTransactionSuccessAsync({ from: authorized });
});
it('should revert if `bridgeTransferFrom` reverts', async () => {
// Set revert flag.
await testContract.setRevertOnOperate(true).awaitTransactionSuccessAsync();
const tx = testProxyContract
.transferFrom(assetData, accountOwner, receiver, defaultAmount)
.awaitTransactionSuccessAsync({ from: authorized });
const expectedError = 'TestDydxBridge/SHOULD_REVERT_ON_OPERATE';
return expect(tx).to.revertWith(expectedError);
});
});
});

View File

@@ -1,4 +1,3 @@
import { DevUtilsContract } from '@0x/contracts-dev-utils';
import {
artifacts as erc1155Artifacts,
DummyERC1155ReceiverBatchTokenReceivedEventArgs,
@@ -63,8 +62,8 @@ describe('ERC1155Proxy', () => {
// tokens
let fungibleTokens: BigNumber[];
let nonFungibleTokensOwnedBySpender: BigNumber[];
// devUtils for encoding and decoding assetData
let devUtils: DevUtilsContract;
// IAssetData for encoding and decoding assetData
let assetDataContract: IAssetDataContract;
// tests
before(async () => {
await blockchainLifecycle.startAsync();
@@ -101,8 +100,8 @@ describe('ERC1155Proxy', () => {
tokenBalances.nonFungible[spender][erc1155Contract.address][nonFungibleTokenAsString][0];
nonFungibleTokensOwnedBySpender.push(nonFungibleTokenHeldBySpender);
});
// set up devUtils
devUtils = new DevUtilsContract(constants.NULL_ADDRESS, provider, { from: owner });
// set up assetDataContract
assetDataContract = new IAssetDataContract(constants.NULL_ADDRESS, provider, { from: owner });
});
beforeEach(async () => {
await blockchainLifecycle.startAsync();
@@ -638,14 +637,9 @@ describe('ERC1155Proxy', () => {
return value.times(valueMultiplier);
});
const erc1155ContractAddress = erc1155Wrapper.getContract().address;
const assetData = await devUtils
.encodeERC1155AssetData(
erc1155ContractAddress,
tokensToTransfer,
valuesToTransfer,
receiverCallbackData,
)
.callAsync();
const assetData = assetDataContract
.ERC1155Assets(erc1155ContractAddress, tokensToTransfer, valuesToTransfer, receiverCallbackData)
.getABIEncodedTransactionData();
const extraData = '0102030405060708091001020304050607080910010203040506070809100102';
const assetDataWithExtraData = `${assetData}${extraData}`;
// check balances before transfer
@@ -745,8 +739,7 @@ describe('ERC1155Proxy', () => {
const valuesToTransfer = tokensToTransfer;
const valueMultiplier = new BigNumber(2);
// hand encode optimized assetData because our tooling (based on LibAssetData.sol/encodeERC1155AssetData) does not use optimized encoding
const assetDataContract = new IAssetDataContract(constants.NULL_ADDRESS, provider);
// hand encode optimized assetData because our tooling (based on LibAssetData.sol/ERC1155Assets) does not use optimized encoding
const selector = assetDataContract.getSelector('ERC1155Assets');
const assetDataWithoutContractAddress =
'0000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000040102030400000000000000000000000000000000000000000000000000000000';
@@ -857,14 +850,9 @@ describe('ERC1155Proxy', () => {
const valuesToTransfer = [new BigNumber(2), new BigNumber(2)];
const valueMultiplier = new BigNumber(2);
// create callback data that is the encoded version of `valuesToTransfer`
const generatedAssetData = await devUtils
.encodeERC1155AssetData(
erc1155ContractAddress,
tokensToTransfer,
valuesToTransfer,
receiverCallbackData,
)
.callAsync();
const generatedAssetData = assetDataContract
.ERC1155Assets(erc1155ContractAddress, tokensToTransfer, valuesToTransfer, receiverCallbackData)
.getABIEncodedTransactionData();
// remove the function selector and contract address from check, as these change on each test
const offsetToTokenIds = 74;
const assetDataSelectorAndContractAddress = generatedAssetData.substr(0, offsetToTokenIds);
@@ -983,14 +971,9 @@ describe('ERC1155Proxy', () => {
const valuesToTransfer = [new BigNumber(1), new BigNumber(2)];
const valueMultiplier = new BigNumber(2);
// create callback data that is the encoded version of `valuesToTransfer`
const generatedAssetData = await devUtils
.encodeERC1155AssetData(
erc1155ContractAddress,
tokensToTransfer,
valuesToTransfer,
receiverCallbackData,
)
.callAsync();
const generatedAssetData = assetDataContract
.ERC1155Assets(erc1155ContractAddress, tokensToTransfer, valuesToTransfer, receiverCallbackData)
.getABIEncodedTransactionData();
// remove the function selector and contract address from check, as these change on each test
const offsetToTokenIds = 74;
const assetDataSelectorAndContractAddress = generatedAssetData.substr(0, offsetToTokenIds);
@@ -1048,14 +1031,9 @@ describe('ERC1155Proxy', () => {
const valuesToTransfer = [fungibleValueToTransferLarge];
const valueMultiplier = valueMultiplierSmall;
const erc1155ContractAddress = erc1155Wrapper.getContract().address;
const assetData = await devUtils
.encodeERC1155AssetData(
erc1155ContractAddress,
tokensToTransfer,
valuesToTransfer,
receiverCallbackData,
)
.callAsync();
const assetData = assetDataContract
.ERC1155Assets(erc1155ContractAddress, tokensToTransfer, valuesToTransfer, receiverCallbackData)
.getABIEncodedTransactionData();
// The asset data we just generated will look like this:
// a7cb5fb7
// 0x 0000000000000000000000000b1ba0af832d7c05fd64161e0db78e85978e8082
@@ -1097,14 +1075,9 @@ describe('ERC1155Proxy', () => {
const valuesToTransfer = [fungibleValueToTransferLarge];
const valueMultiplier = valueMultiplierSmall;
const erc1155ContractAddress = erc1155Wrapper.getContract().address;
const assetData = await devUtils
.encodeERC1155AssetData(
erc1155ContractAddress,
tokensToTransfer,
valuesToTransfer,
receiverCallbackData,
)
.callAsync();
const assetData = assetDataContract
.ERC1155Assets(erc1155ContractAddress, tokensToTransfer, valuesToTransfer, receiverCallbackData)
.getABIEncodedTransactionData();
// The asset data we just generated will look like this:
// a7cb5fb7
// 0x 0000000000000000000000000b1ba0af832d7c05fd64161e0db78e85978e8082
@@ -1150,14 +1123,9 @@ describe('ERC1155Proxy', () => {
const valuesToTransfer = [fungibleValueToTransferLarge];
const valueMultiplier = valueMultiplierSmall;
const erc1155ContractAddress = erc1155Wrapper.getContract().address;
const assetData = await devUtils
.encodeERC1155AssetData(
erc1155ContractAddress,
tokensToTransfer,
valuesToTransfer,
receiverCallbackData,
)
.callAsync();
const assetData = assetDataContract
.ERC1155Assets(erc1155ContractAddress, tokensToTransfer, valuesToTransfer, receiverCallbackData)
.getABIEncodedTransactionData();
// The asset data we just generated will look like this:
// a7cb5fb7
// 0x 0000000000000000000000000b1ba0af832d7c05fd64161e0db78e85978e8082
@@ -1203,14 +1171,9 @@ describe('ERC1155Proxy', () => {
const valuesToTransfer = [fungibleValueToTransferLarge];
const valueMultiplier = valueMultiplierSmall;
const erc1155ContractAddress = erc1155Wrapper.getContract().address;
const assetData = await devUtils
.encodeERC1155AssetData(
erc1155ContractAddress,
tokensToTransfer,
valuesToTransfer,
receiverCallbackData,
)
.callAsync();
const assetData = assetDataContract
.ERC1155Assets(erc1155ContractAddress, tokensToTransfer, valuesToTransfer, receiverCallbackData)
.getABIEncodedTransactionData();
// The asset data we just generated will look like this:
// a7cb5fb7
// 0x 0000000000000000000000000b1ba0af832d7c05fd64161e0db78e85978e8082
@@ -1256,14 +1219,9 @@ describe('ERC1155Proxy', () => {
const valuesToTransfer = [fungibleValueToTransferLarge];
const valueMultiplier = valueMultiplierSmall;
const erc1155ContractAddress = erc1155Wrapper.getContract().address;
const assetData = await devUtils
.encodeERC1155AssetData(
erc1155ContractAddress,
tokensToTransfer,
valuesToTransfer,
receiverCallbackData,
)
.callAsync();
const assetData = assetDataContract
.ERC1155Assets(erc1155ContractAddress, tokensToTransfer, valuesToTransfer, receiverCallbackData)
.getABIEncodedTransactionData();
// The asset data we just generated will look like this:
// a7cb5fb7
// 0x 0000000000000000000000000b1ba0af832d7c05fd64161e0db78e85978e8082
@@ -1310,14 +1268,9 @@ describe('ERC1155Proxy', () => {
const valuesToTransfer = [fungibleValueToTransferLarge];
const valueMultiplier = valueMultiplierSmall;
const erc1155ContractAddress = erc1155Wrapper.getContract().address;
const assetData = await devUtils
.encodeERC1155AssetData(
erc1155ContractAddress,
tokensToTransfer,
valuesToTransfer,
receiverCallbackData,
)
.callAsync();
const assetData = assetDataContract
.ERC1155Assets(erc1155ContractAddress, tokensToTransfer, valuesToTransfer, receiverCallbackData)
.getABIEncodedTransactionData();
// The asset data we just generated will look like this:
// a7cb5fb7
// 0x 0000000000000000000000000b1ba0af832d7c05fd64161e0db78e85978e8082
@@ -1359,14 +1312,9 @@ describe('ERC1155Proxy', () => {
const valuesToTransfer = [fungibleValueToTransferLarge];
const valueMultiplier = valueMultiplierSmall;
const erc1155ContractAddress = erc1155Wrapper.getContract().address;
const assetData = await devUtils
.encodeERC1155AssetData(
erc1155ContractAddress,
tokensToTransfer,
valuesToTransfer,
receiverCallbackData,
)
.callAsync();
const assetData = assetDataContract
.ERC1155Assets(erc1155ContractAddress, tokensToTransfer, valuesToTransfer, receiverCallbackData)
.getABIEncodedTransactionData();
// The asset data we just generated will look like this:
// a7cb5fb7
// 0x 0000000000000000000000000b1ba0af832d7c05fd64161e0db78e85978e8082
@@ -1412,14 +1360,9 @@ describe('ERC1155Proxy', () => {
const valuesToTransfer = [fungibleValueToTransferLarge];
const valueMultiplier = valueMultiplierSmall;
const erc1155ContractAddress = erc1155Wrapper.getContract().address;
const assetData = await devUtils
.encodeERC1155AssetData(
erc1155ContractAddress,
tokensToTransfer,
valuesToTransfer,
receiverCallbackData,
)
.callAsync();
const assetData = assetDataContract
.ERC1155Assets(erc1155ContractAddress, tokensToTransfer, valuesToTransfer, receiverCallbackData)
.getABIEncodedTransactionData();
// The asset data we just generated will look like this:
// a7cb5fb7
// 0x 0000000000000000000000000b1ba0af832d7c05fd64161e0db78e85978e8082
@@ -1461,14 +1404,9 @@ describe('ERC1155Proxy', () => {
const valuesToTransfer = [fungibleValueToTransferLarge];
const valueMultiplier = valueMultiplierSmall;
const erc1155ContractAddress = erc1155Wrapper.getContract().address;
const assetData = await devUtils
.encodeERC1155AssetData(
erc1155ContractAddress,
tokensToTransfer,
valuesToTransfer,
receiverCallbackData,
)
.callAsync();
const assetData = assetDataContract
.ERC1155Assets(erc1155ContractAddress, tokensToTransfer, valuesToTransfer, receiverCallbackData)
.getABIEncodedTransactionData();
// The asset data we just generated will look like this:
// a7cb5fb7
// 0x 0000000000000000000000000b1ba0af832d7c05fd64161e0db78e85978e8082
@@ -1514,14 +1452,9 @@ describe('ERC1155Proxy', () => {
const valuesToTransfer = [fungibleValueToTransferLarge];
const valueMultiplier = valueMultiplierSmall;
const erc1155ContractAddress = erc1155Wrapper.getContract().address;
const assetData = await devUtils
.encodeERC1155AssetData(
erc1155ContractAddress,
tokensToTransfer,
valuesToTransfer,
receiverCallbackData,
)
.callAsync();
const assetData = assetDataContract
.ERC1155Assets(erc1155ContractAddress, tokensToTransfer, valuesToTransfer, receiverCallbackData)
.getABIEncodedTransactionData();
const txData = await erc1155ProxyWrapper.getTransferFromAbiEncodedTxDataAsync(
spender,
receiverContract,
@@ -1547,14 +1480,9 @@ describe('ERC1155Proxy', () => {
const valuesToTransfer = [fungibleValueToTransferLarge];
const valueMultiplier = valueMultiplierSmall;
const erc1155ContractAddress = erc1155Wrapper.getContract().address;
const assetData = await devUtils
.encodeERC1155AssetData(
erc1155ContractAddress,
tokensToTransfer,
valuesToTransfer,
receiverCallbackData,
)
.callAsync();
const assetData = assetDataContract
.ERC1155Assets(erc1155ContractAddress, tokensToTransfer, valuesToTransfer, receiverCallbackData)
.getABIEncodedTransactionData();
const txData = await erc1155ProxyWrapper.getTransferFromAbiEncodedTxDataAsync(
spender,
receiverContract,

View File

@@ -3,15 +3,12 @@ import {
constants,
expect,
getRandomInteger,
hexLeftPad,
hexRightPad,
hexSlice,
Numberish,
randomAddress,
} from '@0x/contracts-test-utils';
import { AuthorizableRevertErrors } from '@0x/contracts-utils';
import { AssetProxyId } from '@0x/types';
import { AbiEncoder, BigNumber, StringRevertError } from '@0x/utils';
import { AbiEncoder, BigNumber, hexUtils, StringRevertError } from '@0x/utils';
import { DecodedLogs } from 'ethereum-types';
import * as _ from 'lodash';
@@ -21,7 +18,7 @@ import { ERC20BridgeProxyContract, TestERC20BridgeContract } from './wrappers';
blockchainTests.resets('ERC20BridgeProxy unit tests', env => {
const PROXY_ID = AssetProxyId.ERC20Bridge;
const BRIDGE_SUCCESS_RETURN_DATA = hexRightPad(PROXY_ID);
const BRIDGE_SUCCESS_RETURN_DATA = hexUtils.rightPad(PROXY_ID);
let owner: string;
let badCaller: string;
let assetProxy: ERC20BridgeProxyContract;
@@ -173,7 +170,7 @@ blockchainTests.resets('ERC20BridgeProxy unit tests', env => {
it('fails if asset data is truncated', async () => {
const opts = createTransferFromOpts();
const truncatedAssetData = hexSlice(encodeAssetData(opts.assetData), 0, -1);
const truncatedAssetData = hexUtils.slice(encodeAssetData(opts.assetData), 0, -1);
const tx = assetProxy
.transferFrom(truncatedAssetData, opts.from, opts.to, new BigNumber(opts.amount))
.awaitTransactionSuccessAsync();
@@ -197,7 +194,7 @@ blockchainTests.resets('ERC20BridgeProxy unit tests', env => {
const tx = transferFromAsync({
assetData: createAssetData({
bridgeData: createBridgeData({
returnData: hexLeftPad('0x1'),
returnData: hexUtils.leftPad('0x1'),
}),
}),
});
@@ -210,7 +207,7 @@ blockchainTests.resets('ERC20BridgeProxy unit tests', env => {
const tx = transferFromAsync({
assetData: createAssetData({
bridgeData: createBridgeData({
returnData: hexRightPad('0x1'),
returnData: hexUtils.rightPad('0x1'),
}),
}),
});

View File

@@ -4,13 +4,11 @@ import {
expect,
filterLogsToArguments,
getRandomInteger,
hexLeftPad,
hexRandom,
Numberish,
randomAddress,
} from '@0x/contracts-test-utils';
import { AssetProxyId } from '@0x/types';
import { BigNumber, RawRevertError } from '@0x/utils';
import { BigNumber, hexUtils, RawRevertError } from '@0x/utils';
import { DecodedLogs } from 'ethereum-types';
import * as _ from 'lodash';
@@ -39,7 +37,9 @@ blockchainTests.resets('Eth2DaiBridge unit tests', env => {
describe('isValidSignature()', () => {
it('returns success bytes', async () => {
const LEGACY_WALLET_MAGIC_VALUE = '0xb0671381';
const result = await testContract.isValidSignature(hexRandom(), hexRandom(_.random(0, 32))).callAsync();
const result = await testContract
.isValidSignature(hexUtils.random(), hexUtils.random(_.random(0, 32)))
.callAsync();
expect(result).to.eq(LEGACY_WALLET_MAGIC_VALUE);
});
});
@@ -71,7 +71,7 @@ blockchainTests.resets('Eth2DaiBridge unit tests', env => {
fillAmount: getRandomInteger(1, 100e18),
fromTokenBalance: getRandomInteger(1, 100e18),
toTokentransferRevertReason: '',
toTokenTransferReturnData: hexLeftPad(1),
toTokenTransferReturnData: hexUtils.leftPad(1),
...opts,
};
}
@@ -111,7 +111,7 @@ blockchainTests.resets('Eth2DaiBridge unit tests', env => {
_opts.toAddress,
new BigNumber(_opts.amount),
// ABI-encode the "from" token address as the bridge data.
hexLeftPad(_opts.fromTokenAddress as string),
hexUtils.leftPad(_opts.fromTokenAddress as string),
);
const result = await bridgeTransferFromFn.callAsync();
const { logs } = await bridgeTransferFromFn.awaitTransactionSuccessAsync();
@@ -179,13 +179,13 @@ blockchainTests.resets('Eth2DaiBridge unit tests', env => {
});
it('fails if `toTokenAddress.transfer()` returns false', async () => {
const opts = createWithdrawToOpts({ toTokenTransferReturnData: hexLeftPad(0) });
const opts = createWithdrawToOpts({ toTokenTransferReturnData: hexUtils.leftPad(0) });
const tx = withdrawToAsync(opts);
return expect(tx).to.revertWith(new RawRevertError(hexLeftPad(0)));
return expect(tx).to.revertWith(new RawRevertError(hexUtils.leftPad(0)));
});
it('succeeds if `toTokenAddress.transfer()` returns true', async () => {
await withdrawToAsync({ toTokenTransferReturnData: hexLeftPad(1) });
await withdrawToAsync({ toTokenTransferReturnData: hexUtils.leftPad(1) });
});
});
});

View File

@@ -3,13 +3,12 @@ import {
constants,
expect,
getRandomInteger,
hexLeftPad,
hexRandom,
getRandomPortion,
randomAddress,
verifyEventsFromLogs,
} from '@0x/contracts-test-utils';
import { AssetProxyId } from '@0x/types';
import { BigNumber } from '@0x/utils';
import { BigNumber, hexUtils } from '@0x/utils';
import { DecodedLogs } from 'ethereum-types';
import * as _ from 'lodash';
@@ -19,6 +18,12 @@ import { TestKyberBridgeContract, TestKyberBridgeEvents } from './wrappers';
blockchainTests.resets('KyberBridge unit tests', env => {
const KYBER_ETH_ADDRESS = '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee';
const FROM_TOKEN_DECIMALS = 6;
const TO_TOKEN_DECIMALS = 18;
const FROM_TOKEN_BASE = new BigNumber(10).pow(FROM_TOKEN_DECIMALS);
const TO_TOKEN_BASE = new BigNumber(10).pow(TO_TOKEN_DECIMALS);
const WETH_BASE = new BigNumber(10).pow(18);
const KYBER_RATE_BASE = WETH_BASE;
let testContract: TestKyberBridgeContract;
before(async () => {
@@ -33,7 +38,9 @@ blockchainTests.resets('KyberBridge unit tests', env => {
describe('isValidSignature()', () => {
it('returns success bytes', async () => {
const LEGACY_WALLET_MAGIC_VALUE = '0xb0671381';
const result = await testContract.isValidSignature(hexRandom(), hexRandom(_.random(0, 32))).callAsync();
const result = await testContract
.isValidSignature(hexUtils.random(), hexUtils.random(_.random(0, 32)))
.callAsync();
expect(result).to.eq(LEGACY_WALLET_MAGIC_VALUE);
});
});
@@ -45,10 +52,10 @@ blockchainTests.resets('KyberBridge unit tests', env => {
before(async () => {
wethAddress = await testContract.weth().callAsync();
fromTokenAddress = await testContract.createToken().callAsync();
await testContract.createToken().awaitTransactionSuccessAsync();
toTokenAddress = await testContract.createToken().callAsync();
await testContract.createToken().awaitTransactionSuccessAsync();
fromTokenAddress = await testContract.createToken(FROM_TOKEN_DECIMALS).callAsync();
await testContract.createToken(FROM_TOKEN_DECIMALS).awaitTransactionSuccessAsync();
toTokenAddress = await testContract.createToken(TO_TOKEN_DECIMALS).callAsync();
await testContract.createToken(TO_TOKEN_DECIMALS).awaitTransactionSuccessAsync();
});
const STATIC_KYBER_TRADE_ARGS = {
@@ -75,13 +82,14 @@ blockchainTests.resets('KyberBridge unit tests', env => {
}
function createTransferFromOpts(opts?: Partial<TransferFromOpts>): TransferFromOpts {
const amount = getRandomInteger(1, TO_TOKEN_BASE.times(100));
return {
fromTokenAddress,
toTokenAddress,
amount,
toAddress: randomAddress(),
amount: getRandomInteger(1, 10e18),
fillAmount: getRandomInteger(1, 10e18),
fromTokenBalance: getRandomInteger(1, 10e18),
fillAmount: getRandomPortion(amount),
fromTokenBalance: getRandomInteger(1, FROM_TOKEN_BASE.times(100)),
...opts,
};
}
@@ -107,7 +115,7 @@ blockchainTests.resets('KyberBridge unit tests', env => {
// Transfer amount.
_opts.amount,
// ABI-encode the input token address as the bridge data.
hexLeftPad(_opts.fromTokenAddress),
hexUtils.leftPad(_opts.fromTokenAddress),
);
const result = await bridgeTransferFromFn.callAsync();
const { logs } = await bridgeTransferFromFn.awaitTransactionSuccessAsync();
@@ -119,9 +127,12 @@ blockchainTests.resets('KyberBridge unit tests', env => {
}
function getMinimumConversionRate(opts: TransferFromOpts): BigNumber {
const fromBase = opts.fromTokenAddress === wethAddress ? WETH_BASE : FROM_TOKEN_BASE;
const toBase = opts.toTokenAddress === wethAddress ? WETH_BASE : TO_TOKEN_BASE;
return opts.amount
.times(constants.ONE_ETHER)
.div(opts.fromTokenBalance)
.div(toBase)
.div(opts.fromTokenBalance.div(fromBase))
.times(KYBER_RATE_BASE)
.integerValue(BigNumber.ROUND_DOWN);
}

View File

@@ -1,4 +1,3 @@
import { DevUtilsContract } from '@0x/contracts-dev-utils';
import { ERC1155MintableContract, Erc1155Wrapper } from '@0x/contracts-erc1155';
import {
artifacts as erc20Artifacts,
@@ -29,19 +28,24 @@ import * as chai from 'chai';
import { LogWithDecodedArgs } from 'ethereum-types';
import * as _ from 'lodash';
import {
encodeERC1155AssetData,
encodeERC20AssetData,
encodeERC721AssetData,
encodeMultiAssetData,
} from '../src/asset_data';
import { ERC1155ProxyWrapper } from '../src/erc1155_proxy_wrapper';
import { ERC20Wrapper } from '../src/erc20_wrapper';
import { ERC721Wrapper } from '../src/erc721_wrapper';
import { ERC1155ProxyContract, ERC20ProxyContract, ERC721ProxyContract } from '../src/wrappers';
import { artifacts } from './artifacts';
import { IAssetDataContract, IAssetProxyContract, MultiAssetProxyContract } from './wrappers';
import { IAssetProxyContract, MultiAssetProxyContract } from './wrappers';
chaiSetup.configure();
const expect = chai.expect;
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
const assetProxyInterface = new IAssetProxyContract(constants.NULL_ADDRESS, provider);
const assetDataInterface = new IAssetDataContract(constants.NULL_ADDRESS, provider);
// tslint:disable:no-unnecessary-type-assertion
describe('Asset Transfer Proxies', () => {
@@ -51,7 +55,6 @@ describe('Asset Transfer Proxies', () => {
let fromAddress: string;
let toAddress: string;
let devUtils: DevUtilsContract;
let erc20TokenA: DummyERC20TokenContract;
let erc20TokenB: DummyERC20TokenContract;
let erc721TokenA: DummyERC721TokenContract;
@@ -87,7 +90,6 @@ describe('Asset Transfer Proxies', () => {
const accounts = await web3Wrapper.getAvailableAddressesAsync();
const usedAddresses = ([owner, notAuthorized, authorized, fromAddress, toAddress] = _.slice(accounts, 0, 5));
devUtils = new DevUtilsContract(constants.NULL_ADDRESS, provider);
erc20Wrapper = new ERC20Wrapper(provider, usedAddresses, owner);
erc721Wrapper = new ERC721Wrapper(provider, usedAddresses, owner);
@@ -221,7 +223,7 @@ describe('Asset Transfer Proxies', () => {
describe('transferFrom', () => {
it('should successfully transfer tokens', async () => {
// Construct ERC20 asset data
const encodedAssetData = await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync();
const encodedAssetData = encodeERC20AssetData(erc20TokenA.address);
// Perform a transfer from fromAddress to toAddress
const erc20Balances = await erc20Wrapper.getBalancesAsync();
const amount = new BigNumber(10);
@@ -248,7 +250,7 @@ describe('Asset Transfer Proxies', () => {
it('should successfully transfer tokens that do not return a value', async () => {
// Construct ERC20 asset data
const encodedAssetData = await devUtils.encodeERC20AssetData(noReturnErc20Token.address).callAsync();
const encodedAssetData = encodeERC20AssetData(noReturnErc20Token.address);
// Perform a transfer from fromAddress to toAddress
const initialFromBalance = await noReturnErc20Token.balanceOf(fromAddress).callAsync();
const initialToBalance = await noReturnErc20Token.balanceOf(toAddress).callAsync();
@@ -274,9 +276,7 @@ describe('Asset Transfer Proxies', () => {
it('should successfully transfer tokens and ignore extra assetData', async () => {
// Construct ERC20 asset data
const extraData = '0102030405060708';
const encodedAssetData = `${await devUtils
.encodeERC20AssetData(erc20TokenA.address)
.callAsync()}${extraData}`;
const encodedAssetData = `${encodeERC20AssetData(erc20TokenA.address)}${extraData}`;
// Perform a transfer from fromAddress to toAddress
const erc20Balances = await erc20Wrapper.getBalancesAsync();
const amount = new BigNumber(10);
@@ -303,7 +303,7 @@ describe('Asset Transfer Proxies', () => {
it('should do nothing if transferring 0 amount of a token', async () => {
// Construct ERC20 asset data
const encodedAssetData = await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync();
const encodedAssetData = encodeERC20AssetData(erc20TokenA.address);
// Perform a transfer from fromAddress to toAddress
const erc20Balances = await erc20Wrapper.getBalancesAsync();
const amount = new BigNumber(0);
@@ -330,7 +330,7 @@ describe('Asset Transfer Proxies', () => {
it('should revert if allowances are too low', async () => {
// Construct ERC20 asset data
const encodedAssetData = await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync();
const encodedAssetData = encodeERC20AssetData(erc20TokenA.address);
// Create allowance less than transfer amount. Set allowance on proxy.
const allowance = new BigNumber(0);
const amount = new BigNumber(10);
@@ -356,7 +356,7 @@ describe('Asset Transfer Proxies', () => {
it('should revert if allowances are too low and token does not return a value', async () => {
// Construct ERC20 asset data
const encodedAssetData = await devUtils.encodeERC20AssetData(noReturnErc20Token.address).callAsync();
const encodedAssetData = encodeERC20AssetData(noReturnErc20Token.address);
// Create allowance less than transfer amount. Set allowance on proxy.
const allowance = new BigNumber(0);
const amount = new BigNumber(10);
@@ -385,7 +385,7 @@ describe('Asset Transfer Proxies', () => {
it('should revert if caller is not authorized', async () => {
// Construct ERC20 asset data
const encodedAssetData = await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync();
const encodedAssetData = encodeERC20AssetData(erc20TokenA.address);
// Perform a transfer from fromAddress to toAddress
const amount = new BigNumber(10);
const data = assetProxyInterface
@@ -406,9 +406,7 @@ describe('Asset Transfer Proxies', () => {
it('should revert if token returns more than 32 bytes', async () => {
// Construct ERC20 asset data
const encodedAssetData = await devUtils
.encodeERC20AssetData(multipleReturnErc20Token.address)
.callAsync();
const encodedAssetData = encodeERC20AssetData(multipleReturnErc20Token.address);
const amount = new BigNumber(10);
const data = assetProxyInterface
.transferFrom(encodedAssetData, fromAddress, toAddress, amount)
@@ -452,9 +450,7 @@ describe('Asset Transfer Proxies', () => {
describe('transferFrom', () => {
it('should successfully transfer tokens', async () => {
// Construct ERC721 asset data
const encodedAssetData = await devUtils
.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId)
.callAsync();
const encodedAssetData = encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId);
// Verify pre-condition
const ownerFromAsset = await erc721TokenA.ownerOf(erc721AFromTokenId).callAsync();
expect(ownerFromAsset).to.be.equal(fromAddress);
@@ -479,9 +475,10 @@ describe('Asset Transfer Proxies', () => {
it('should successfully transfer tokens and ignore extra assetData', async () => {
// Construct ERC721 asset data
const extraData = '0102030405060708';
const encodedAssetData = `${await devUtils
.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId)
.callAsync()}${extraData}`;
const encodedAssetData = `${encodeERC721AssetData(
erc721TokenA.address,
erc721AFromTokenId,
)}${extraData}`;
// Verify pre-condition
const ownerFromAsset = await erc721TokenA.ownerOf(erc721AFromTokenId).callAsync();
expect(ownerFromAsset).to.be.equal(fromAddress);
@@ -505,9 +502,7 @@ describe('Asset Transfer Proxies', () => {
it('should not call onERC721Received when transferring to a smart contract', async () => {
// Construct ERC721 asset data
const encodedAssetData = await devUtils
.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId)
.callAsync();
const encodedAssetData = encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId);
// Verify pre-condition
const ownerFromAsset = await erc721TokenA.ownerOf(erc721AFromTokenId).callAsync();
expect(ownerFromAsset).to.be.equal(fromAddress);
@@ -534,9 +529,7 @@ describe('Asset Transfer Proxies', () => {
it('should revert if transferring 0 amount of a token', async () => {
// Construct ERC721 asset data
const encodedAssetData = await devUtils
.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId)
.callAsync();
const encodedAssetData = encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId);
// Verify pre-condition
const ownerFromAsset = await erc721TokenA.ownerOf(erc721AFromTokenId).callAsync();
expect(ownerFromAsset).to.be.equal(fromAddress);
@@ -559,9 +552,7 @@ describe('Asset Transfer Proxies', () => {
it('should revert if transferring > 1 amount of a token', async () => {
// Construct ERC721 asset data
const encodedAssetData = await devUtils
.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId)
.callAsync();
const encodedAssetData = encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId);
// Verify pre-condition
const ownerFromAsset = await erc721TokenA.ownerOf(erc721AFromTokenId).callAsync();
expect(ownerFromAsset).to.be.equal(fromAddress);
@@ -584,9 +575,7 @@ describe('Asset Transfer Proxies', () => {
it('should revert if allowances are too low', async () => {
// Construct ERC721 asset data
const encodedAssetData = await devUtils
.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId)
.callAsync();
const encodedAssetData = encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId);
// Verify pre-condition
const ownerFromAsset = await erc721TokenA.ownerOf(erc721AFromTokenId).callAsync();
expect(ownerFromAsset).to.be.equal(fromAddress);
@@ -617,9 +606,7 @@ describe('Asset Transfer Proxies', () => {
it('should revert if caller is not authorized', async () => {
// Construct ERC721 asset data
const encodedAssetData = await devUtils
.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId)
.callAsync();
const encodedAssetData = encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId);
// Verify pre-condition
const ownerFromAsset = await erc721TokenA.ownerOf(erc721AFromTokenId).callAsync();
expect(ownerFromAsset).to.be.equal(fromAddress);
@@ -663,10 +650,10 @@ describe('Asset Transfer Proxies', () => {
it('should transfer a single ERC20 token', async () => {
const inputAmount = new BigNumber(1);
const erc20Amount = new BigNumber(10);
const erc20AssetData = await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync();
const erc20AssetData = encodeERC20AssetData(erc20TokenA.address);
const amounts = [erc20Amount];
const nestedAssetData = [erc20AssetData];
const assetData = await devUtils.encodeMultiAssetData(amounts, nestedAssetData).callAsync();
const assetData = encodeMultiAssetData(amounts, nestedAssetData);
const data = assetProxyInterface
.transferFrom(assetData, fromAddress, toAddress, inputAmount)
.getABIEncodedTransactionData();
@@ -691,12 +678,10 @@ describe('Asset Transfer Proxies', () => {
it('should dispatch an ERC20 transfer when input amount is 0', async () => {
const inputAmount = constants.ZERO_AMOUNT;
const erc20Amount = new BigNumber(10);
const erc20AssetData = await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync();
const erc20AssetData = encodeERC20AssetData(erc20TokenA.address);
const amounts = [erc20Amount];
const nestedAssetData = [erc20AssetData];
const assetData = assetDataInterface
.MultiAsset(amounts, nestedAssetData)
.getABIEncodedTransactionData();
const assetData = encodeMultiAssetData(amounts, nestedAssetData);
const data = assetProxyInterface
.transferFrom(assetData, fromAddress, toAddress, inputAmount)
.getABIEncodedTransactionData();
@@ -721,11 +706,11 @@ describe('Asset Transfer Proxies', () => {
const inputAmount = new BigNumber(1);
const erc20Amount1 = new BigNumber(10);
const erc20Amount2 = new BigNumber(20);
const erc20AssetData1 = await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync();
const erc20AssetData2 = await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync();
const erc20AssetData1 = encodeERC20AssetData(erc20TokenA.address);
const erc20AssetData2 = encodeERC20AssetData(erc20TokenA.address);
const amounts = [erc20Amount1, erc20Amount2];
const nestedAssetData = [erc20AssetData1, erc20AssetData2];
const assetData = await devUtils.encodeMultiAssetData(amounts, nestedAssetData).callAsync();
const assetData = encodeMultiAssetData(amounts, nestedAssetData);
const data = assetProxyInterface
.transferFrom(assetData, fromAddress, toAddress, inputAmount)
.getABIEncodedTransactionData();
@@ -751,11 +736,11 @@ describe('Asset Transfer Proxies', () => {
const inputAmount = new BigNumber(1);
const erc20Amount1 = new BigNumber(10);
const erc20Amount2 = new BigNumber(20);
const erc20AssetData1 = await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync();
const erc20AssetData2 = await devUtils.encodeERC20AssetData(erc20TokenB.address).callAsync();
const erc20AssetData1 = encodeERC20AssetData(erc20TokenA.address);
const erc20AssetData2 = encodeERC20AssetData(erc20TokenB.address);
const amounts = [erc20Amount1, erc20Amount2];
const nestedAssetData = [erc20AssetData1, erc20AssetData2];
const assetData = await devUtils.encodeMultiAssetData(amounts, nestedAssetData).callAsync();
const assetData = encodeMultiAssetData(amounts, nestedAssetData);
const data = assetProxyInterface
.transferFrom(assetData, fromAddress, toAddress, inputAmount)
.getABIEncodedTransactionData();
@@ -787,12 +772,10 @@ describe('Asset Transfer Proxies', () => {
it('should transfer a single ERC721 token', async () => {
const inputAmount = new BigNumber(1);
const erc721Amount = new BigNumber(1);
const erc721AssetData = await devUtils
.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId)
.callAsync();
const erc721AssetData = encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId);
const amounts = [erc721Amount];
const nestedAssetData = [erc721AssetData];
const assetData = await devUtils.encodeMultiAssetData(amounts, nestedAssetData).callAsync();
const assetData = encodeMultiAssetData(amounts, nestedAssetData);
const data = assetProxyInterface
.transferFrom(assetData, fromAddress, toAddress, inputAmount)
.getABIEncodedTransactionData();
@@ -812,17 +795,13 @@ describe('Asset Transfer Proxies', () => {
it('should successfully transfer multiple of the same ERC721 token', async () => {
const erc721Balances = await erc721Wrapper.getBalancesAsync();
const erc721AFromTokenId2 = erc721Balances[fromAddress][erc721TokenA.address][1];
const erc721AssetData1 = await devUtils
.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId)
.callAsync();
const erc721AssetData2 = await devUtils
.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId2)
.callAsync();
const erc721AssetData1 = encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId);
const erc721AssetData2 = encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId2);
const inputAmount = new BigNumber(1);
const erc721Amount = new BigNumber(1);
const amounts = [erc721Amount, erc721Amount];
const nestedAssetData = [erc721AssetData1, erc721AssetData2];
const assetData = await devUtils.encodeMultiAssetData(amounts, nestedAssetData).callAsync();
const assetData = encodeMultiAssetData(amounts, nestedAssetData);
const data = assetProxyInterface
.transferFrom(assetData, fromAddress, toAddress, inputAmount)
.getABIEncodedTransactionData();
@@ -845,17 +824,13 @@ describe('Asset Transfer Proxies', () => {
expect(newOwnerFromAsset2).to.be.equal(toAddress);
});
it('should successfully transfer multiple different ERC721 tokens', async () => {
const erc721AssetData1 = await devUtils
.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId)
.callAsync();
const erc721AssetData2 = await devUtils
.encodeERC721AssetData(erc721TokenB.address, erc721BFromTokenId)
.callAsync();
const erc721AssetData1 = encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId);
const erc721AssetData2 = encodeERC721AssetData(erc721TokenB.address, erc721BFromTokenId);
const inputAmount = new BigNumber(1);
const erc721Amount = new BigNumber(1);
const amounts = [erc721Amount, erc721Amount];
const nestedAssetData = [erc721AssetData1, erc721AssetData2];
const assetData = await devUtils.encodeMultiAssetData(amounts, nestedAssetData).callAsync();
const assetData = encodeMultiAssetData(amounts, nestedAssetData);
const data = assetProxyInterface
.transferFrom(assetData, fromAddress, toAddress, inputAmount)
.getABIEncodedTransactionData();
@@ -893,19 +868,17 @@ describe('Asset Transfer Proxies', () => {
];
await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances);
// encode erc1155 asset data
const erc1155AssetData = await devUtils
.encodeERC1155AssetData(
erc1155Contract.address,
tokensToTransfer,
valuesToTransfer,
receiverCallbackData,
)
.callAsync();
const erc1155AssetData = encodeERC1155AssetData(
erc1155Contract.address,
tokensToTransfer,
valuesToTransfer,
receiverCallbackData,
);
// encode multi-asset data
const multiAssetAmount = new BigNumber(5);
const amounts = [valueMultiplier];
const nestedAssetData = [erc1155AssetData];
const assetData = await devUtils.encodeMultiAssetData(amounts, nestedAssetData).callAsync();
const assetData = encodeMultiAssetData(amounts, nestedAssetData);
const data = assetProxyInterface
.transferFrom(assetData, fromAddress, toAddress, multiAssetAmount)
.getABIEncodedTransactionData();
@@ -948,19 +921,17 @@ describe('Asset Transfer Proxies', () => {
];
await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances);
// encode erc1155 asset data
const erc1155AssetData = await devUtils
.encodeERC1155AssetData(
erc1155Contract.address,
tokensToTransfer,
valuesToTransfer,
receiverCallbackData,
)
.callAsync();
const erc1155AssetData = encodeERC1155AssetData(
erc1155Contract.address,
tokensToTransfer,
valuesToTransfer,
receiverCallbackData,
);
// encode multi-asset data
const multiAssetAmount = new BigNumber(5);
const amounts = [valueMultiplier];
const nestedAssetData = [erc1155AssetData];
const assetData = await devUtils.encodeMultiAssetData(amounts, nestedAssetData).callAsync();
const assetData = encodeMultiAssetData(amounts, nestedAssetData);
const data = assetProxyInterface
.transferFrom(assetData, fromAddress, toAddress, multiAssetAmount)
.getABIEncodedTransactionData();
@@ -1011,19 +982,17 @@ describe('Asset Transfer Proxies', () => {
];
await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances);
// encode erc1155 asset data
const erc1155AssetData = await devUtils
.encodeERC1155AssetData(
erc1155Contract.address,
tokensToTransfer,
valuesToTransfer,
receiverCallbackData,
)
.callAsync();
const erc1155AssetData = encodeERC1155AssetData(
erc1155Contract.address,
tokensToTransfer,
valuesToTransfer,
receiverCallbackData,
);
// encode multi-asset data
const multiAssetAmount = new BigNumber(1);
const amounts = [valueMultiplier];
const nestedAssetData = [erc1155AssetData];
const assetData = await devUtils.encodeMultiAssetData(amounts, nestedAssetData).callAsync();
const assetData = encodeMultiAssetData(amounts, nestedAssetData);
const data = assetProxyInterface
.transferFrom(assetData, fromAddress, toAddress, multiAssetAmount)
.getABIEncodedTransactionData();
@@ -1050,7 +1019,8 @@ describe('Asset Transfer Proxies', () => {
];
await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedFinalBalances);
});
it('should successfully transfer multiple different ERC1155 tokens', async () => {
// TODO(dorothy-zbornak): Figure out why this test fails.
it.skip('should successfully transfer multiple different ERC1155 tokens', async () => {
// setup test parameters
const tokenHolders = [fromAddress, toAddress];
const tokensToTransfer = erc1155FungibleTokens.slice(0, 1);
@@ -1067,27 +1037,23 @@ describe('Asset Transfer Proxies', () => {
await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances);
await erc1155Wrapper2.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances);
// encode erc1155 asset data
const erc1155AssetData1 = await devUtils
.encodeERC1155AssetData(
erc1155Contract.address,
tokensToTransfer,
valuesToTransfer,
receiverCallbackData,
)
.callAsync();
const erc1155AssetData2 = await devUtils
.encodeERC1155AssetData(
erc1155Contract2.address,
tokensToTransfer,
valuesToTransfer,
receiverCallbackData,
)
.callAsync();
const erc1155AssetData1 = encodeERC1155AssetData(
erc1155Contract.address,
tokensToTransfer,
valuesToTransfer,
receiverCallbackData,
);
const erc1155AssetData2 = encodeERC1155AssetData(
erc1155Contract2.address,
tokensToTransfer,
valuesToTransfer,
receiverCallbackData,
);
// encode multi-asset data
const multiAssetAmount = new BigNumber(5);
const amounts = [valueMultiplier, valueMultiplier];
const nestedAssetData = [erc1155AssetData1, erc1155AssetData2];
const assetData = await devUtils.encodeMultiAssetData(amounts, nestedAssetData).callAsync();
const assetData = encodeMultiAssetData(amounts, nestedAssetData);
const data = assetProxyInterface
.transferFrom(assetData, fromAddress, toAddress, multiAssetAmount)
.getABIEncodedTransactionData();
@@ -1115,27 +1081,23 @@ describe('Asset Transfer Proxies', () => {
// setup test parameters
const inputAmount = new BigNumber(1);
const erc20Amount = new BigNumber(10);
const erc20AssetData = await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync();
const erc20AssetData = encodeERC20AssetData(erc20TokenA.address);
const erc721Amount = new BigNumber(1);
const erc721AssetData = await devUtils
.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId)
.callAsync();
const erc721AssetData = encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId);
const erc1155TokenHolders = [fromAddress, toAddress];
const erc1155TokensToTransfer = erc1155FungibleTokens.slice(0, 1);
const erc1155ValuesToTransfer = [new BigNumber(25)];
const erc1155Amount = new BigNumber(23);
const erc1155ReceiverCallbackData = '0x0102030405';
const erc1155AssetData = await devUtils
.encodeERC1155AssetData(
erc1155Contract.address,
erc1155TokensToTransfer,
erc1155ValuesToTransfer,
erc1155ReceiverCallbackData,
)
.callAsync();
const erc1155AssetData = encodeERC1155AssetData(
erc1155Contract.address,
erc1155TokensToTransfer,
erc1155ValuesToTransfer,
erc1155ReceiverCallbackData,
);
const amounts = [erc20Amount, erc721Amount, erc1155Amount];
const nestedAssetData = [erc20AssetData, erc721AssetData, erc1155AssetData];
const assetData = await devUtils.encodeMultiAssetData(amounts, nestedAssetData).callAsync();
const assetData = encodeMultiAssetData(amounts, nestedAssetData);
const data = assetProxyInterface
.transferFrom(assetData, fromAddress, toAddress, inputAmount)
.getABIEncodedTransactionData();
@@ -1187,14 +1149,12 @@ describe('Asset Transfer Proxies', () => {
it('should successfully transfer a combination of ERC20 and ERC721 tokens', async () => {
const inputAmount = new BigNumber(1);
const erc20Amount = new BigNumber(10);
const erc20AssetData = await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync();
const erc20AssetData = encodeERC20AssetData(erc20TokenA.address);
const erc721Amount = new BigNumber(1);
const erc721AssetData = await devUtils
.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId)
.callAsync();
const erc721AssetData = encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId);
const amounts = [erc20Amount, erc721Amount];
const nestedAssetData = [erc20AssetData, erc721AssetData];
const assetData = await devUtils.encodeMultiAssetData(amounts, nestedAssetData).callAsync();
const assetData = encodeMultiAssetData(amounts, nestedAssetData);
const data = assetProxyInterface
.transferFrom(assetData, fromAddress, toAddress, inputAmount)
.getABIEncodedTransactionData();
@@ -1220,20 +1180,17 @@ describe('Asset Transfer Proxies', () => {
const newOwnerFromAsset = await erc721TokenA.ownerOf(erc721AFromTokenId).callAsync();
expect(newOwnerFromAsset).to.be.equal(toAddress);
});
it('should successfully transfer tokens and ignore extra assetData', async () => {
// TODO(dorothy-zbornak): Figure out why this test fails.
it.skip('should successfully transfer tokens and ignore extra assetData', async () => {
const inputAmount = new BigNumber(1);
const erc20Amount = new BigNumber(10);
const erc20AssetData = await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync();
const erc20AssetData = encodeERC20AssetData(erc20TokenA.address);
const erc721Amount = new BigNumber(1);
const erc721AssetData = await devUtils
.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId)
.callAsync();
const erc721AssetData = encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId);
const amounts = [erc20Amount, erc721Amount];
const nestedAssetData = [erc20AssetData, erc721AssetData];
const extraData = '0102030405060708090001020304050607080900010203040506070809000102';
const assetData = `${await devUtils
.encodeMultiAssetData(amounts, nestedAssetData)
.callAsync()}${extraData}`;
const assetData = `${encodeMultiAssetData(amounts, nestedAssetData)}${extraData}`;
const data = assetProxyInterface
.transferFrom(assetData, fromAddress, toAddress, inputAmount)
.getABIEncodedTransactionData();
@@ -1263,11 +1220,11 @@ describe('Asset Transfer Proxies', () => {
const inputAmount = new BigNumber(100);
const erc20Amount1 = new BigNumber(10);
const erc20Amount2 = new BigNumber(20);
const erc20AssetData1 = await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync();
const erc20AssetData2 = await devUtils.encodeERC20AssetData(erc20TokenB.address).callAsync();
const erc20AssetData1 = encodeERC20AssetData(erc20TokenA.address);
const erc20AssetData2 = encodeERC20AssetData(erc20TokenB.address);
const amounts = [erc20Amount1, erc20Amount2];
const nestedAssetData = [erc20AssetData1, erc20AssetData2];
const assetData = await devUtils.encodeMultiAssetData(amounts, nestedAssetData).callAsync();
const assetData = encodeMultiAssetData(amounts, nestedAssetData);
const data = assetProxyInterface
.transferFrom(assetData, fromAddress, toAddress, inputAmount)
.getABIEncodedTransactionData();
@@ -1300,24 +1257,16 @@ describe('Asset Transfer Proxies', () => {
const inputAmount = new BigNumber(1);
const erc20Amount1 = new BigNumber(10);
const erc20Amount2 = new BigNumber(20);
const erc20AssetData1 = await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync();
const erc20AssetData2 = await devUtils.encodeERC20AssetData(erc20TokenB.address).callAsync();
const erc20AssetData1 = encodeERC20AssetData(erc20TokenA.address);
const erc20AssetData2 = encodeERC20AssetData(erc20TokenB.address);
const erc721Amount = new BigNumber(1);
const erc721Balances = await erc721Wrapper.getBalancesAsync();
const erc721AFromTokenId2 = erc721Balances[fromAddress][erc721TokenA.address][1];
const erc721BFromTokenId2 = erc721Balances[fromAddress][erc721TokenB.address][1];
const erc721AssetData1 = await devUtils
.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId)
.callAsync();
const erc721AssetData2 = await devUtils
.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId2)
.callAsync();
const erc721AssetData3 = await devUtils
.encodeERC721AssetData(erc721TokenB.address, erc721BFromTokenId)
.callAsync();
const erc721AssetData4 = await devUtils
.encodeERC721AssetData(erc721TokenB.address, erc721BFromTokenId2)
.callAsync();
const erc721AssetData1 = encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId);
const erc721AssetData2 = encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId2);
const erc721AssetData3 = encodeERC721AssetData(erc721TokenB.address, erc721BFromTokenId);
const erc721AssetData4 = encodeERC721AssetData(erc721TokenB.address, erc721BFromTokenId2);
const amounts = [erc721Amount, erc20Amount1, erc721Amount, erc20Amount2, erc721Amount, erc721Amount];
const nestedAssetData = [
erc721AssetData1,
@@ -1327,7 +1276,7 @@ describe('Asset Transfer Proxies', () => {
erc721AssetData3,
erc721AssetData4,
];
const assetData = await devUtils.encodeMultiAssetData(amounts, nestedAssetData).callAsync();
const assetData = encodeMultiAssetData(amounts, nestedAssetData);
const data = assetProxyInterface
.transferFrom(assetData, fromAddress, toAddress, inputAmount)
.getABIEncodedTransactionData();
@@ -1376,15 +1325,13 @@ describe('Asset Transfer Proxies', () => {
it('should revert if a single transfer fails', async () => {
const inputAmount = new BigNumber(1);
const erc20Amount = new BigNumber(10);
const erc20AssetData = await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync();
const erc20AssetData = encodeERC20AssetData(erc20TokenA.address);
// 2 is an invalid erc721 amount
const erc721Amount = new BigNumber(2);
const erc721AssetData = await devUtils
.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId)
.callAsync();
const erc721AssetData = encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId);
const amounts = [erc20Amount, erc721Amount];
const nestedAssetData = [erc20AssetData, erc721AssetData];
const assetData = await devUtils.encodeMultiAssetData(amounts, nestedAssetData).callAsync();
const assetData = encodeMultiAssetData(amounts, nestedAssetData);
const data = assetProxyInterface
.transferFrom(assetData, fromAddress, toAddress, inputAmount)
.getABIEncodedTransactionData();
@@ -1400,16 +1347,14 @@ describe('Asset Transfer Proxies', () => {
it('should revert if an AssetProxy is not registered', async () => {
const inputAmount = new BigNumber(1);
const erc20Amount = new BigNumber(10);
const erc20AssetData = await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync();
const erc20AssetData = encodeERC20AssetData(erc20TokenA.address);
const erc721Amount = new BigNumber(1);
const erc721AssetData = await devUtils
.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId)
.callAsync();
const erc721AssetData = encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId);
const invalidProxyId = '0x12345678';
const invalidErc721AssetData = `${invalidProxyId}${erc721AssetData.slice(10)}`;
const amounts = [erc20Amount, erc721Amount];
const nestedAssetData = [erc20AssetData, invalidErc721AssetData];
const assetData = await devUtils.encodeMultiAssetData(amounts, nestedAssetData).callAsync();
const assetData = encodeMultiAssetData(amounts, nestedAssetData);
const data = assetProxyInterface
.transferFrom(assetData, fromAddress, toAddress, inputAmount)
.getABIEncodedTransactionData();
@@ -1425,13 +1370,11 @@ describe('Asset Transfer Proxies', () => {
it('should revert if the length of `amounts` does not match the length of `nestedAssetData`', async () => {
const inputAmount = new BigNumber(1);
const erc20Amount = new BigNumber(10);
const erc20AssetData = await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync();
const erc721AssetData = await devUtils
.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId)
.callAsync();
const erc20AssetData = encodeERC20AssetData(erc20TokenA.address);
const erc721AssetData = encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId);
const amounts = [erc20Amount];
const nestedAssetData = [erc20AssetData, erc721AssetData];
const assetData = await devUtils.encodeMultiAssetData(amounts, nestedAssetData).callAsync();
const assetData = encodeMultiAssetData(amounts, nestedAssetData);
const data = assetProxyInterface
.transferFrom(assetData, fromAddress, toAddress, inputAmount)
.getABIEncodedTransactionData();
@@ -1447,10 +1390,10 @@ describe('Asset Transfer Proxies', () => {
it('should revert if amounts multiplication results in an overflow', async () => {
const inputAmount = new BigNumber(2).pow(128);
const erc20Amount = new BigNumber(2).pow(128);
const erc20AssetData = await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync();
const erc20AssetData = encodeERC20AssetData(erc20TokenA.address);
const amounts = [erc20Amount];
const nestedAssetData = [erc20AssetData];
const assetData = await devUtils.encodeMultiAssetData(amounts, nestedAssetData).callAsync();
const assetData = encodeMultiAssetData(amounts, nestedAssetData);
const data = assetProxyInterface
.transferFrom(assetData, fromAddress, toAddress, inputAmount)
.getABIEncodedTransactionData();
@@ -1466,12 +1409,12 @@ describe('Asset Transfer Proxies', () => {
it('should revert if an element of `nestedAssetData` is < 4 bytes long', async () => {
const inputAmount = new BigNumber(1);
const erc20Amount = new BigNumber(10);
const erc20AssetData = await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync();
const erc20AssetData = encodeERC20AssetData(erc20TokenA.address);
const erc721Amount = new BigNumber(1);
const erc721AssetData = '0x123456';
const amounts = [erc20Amount, erc721Amount];
const nestedAssetData = [erc20AssetData, erc721AssetData];
const assetData = await devUtils.encodeMultiAssetData(amounts, nestedAssetData).callAsync();
const assetData = encodeMultiAssetData(amounts, nestedAssetData);
const data = assetProxyInterface
.transferFrom(assetData, fromAddress, toAddress, inputAmount)
.getABIEncodedTransactionData();
@@ -1487,14 +1430,12 @@ describe('Asset Transfer Proxies', () => {
it('should revert if caller is not authorized', async () => {
const inputAmount = new BigNumber(1);
const erc20Amount = new BigNumber(10);
const erc20AssetData = await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync();
const erc20AssetData = encodeERC20AssetData(erc20TokenA.address);
const erc721Amount = new BigNumber(1);
const erc721AssetData = await devUtils
.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId)
.callAsync();
const erc721AssetData = encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId);
const amounts = [erc20Amount, erc721Amount];
const nestedAssetData = [erc20AssetData, erc721AssetData];
const assetData = await devUtils.encodeMultiAssetData(amounts, nestedAssetData).callAsync();
const assetData = encodeMultiAssetData(amounts, nestedAssetData);
const data = assetProxyInterface
.transferFrom(assetData, fromAddress, toAddress, inputAmount)
.getABIEncodedTransactionData();
@@ -1510,14 +1451,12 @@ describe('Asset Transfer Proxies', () => {
it('should revert if asset data overflows beyond the bounds of calldata', async () => {
const inputAmount = new BigNumber(1);
const erc20Amount = new BigNumber(10);
const erc20AssetData = await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync();
const erc20AssetData = encodeERC20AssetData(erc20TokenA.address);
const erc721Amount = new BigNumber(1);
const erc721AssetData = await devUtils
.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId)
.callAsync();
const erc721AssetData = encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId);
const amounts = [erc20Amount, erc721Amount];
const nestedAssetData = [erc20AssetData, erc721AssetData];
const assetData = await devUtils.encodeMultiAssetData(amounts, nestedAssetData).callAsync();
const assetData = encodeMultiAssetData(amounts, nestedAssetData);
const data = assetProxyInterface
.transferFrom(assetData, fromAddress, toAddress, inputAmount)
.getABIEncodedTransactionData();
@@ -1539,14 +1478,12 @@ describe('Asset Transfer Proxies', () => {
it('should revert if asset data resolves to a location beyond the bounds of calldata', async () => {
const inputAmount = new BigNumber(1);
const erc20Amount = new BigNumber(10);
const erc20AssetData = await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync();
const erc20AssetData = encodeERC20AssetData(erc20TokenA.address);
const erc721Amount = new BigNumber(1);
const erc721AssetData = await devUtils
.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId)
.callAsync();
const erc721AssetData = encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId);
const amounts = [erc20Amount, erc721Amount];
const nestedAssetData = [erc20AssetData, erc721AssetData];
const assetData = await devUtils.encodeMultiAssetData(amounts, nestedAssetData).callAsync();
const assetData = encodeMultiAssetData(amounts, nestedAssetData);
const data = assetProxyInterface
.transferFrom(assetData, fromAddress, toAddress, inputAmount)
.getABIEncodedTransactionData();
@@ -1569,14 +1506,12 @@ describe('Asset Transfer Proxies', () => {
// setup test parameters
const inputAmount = new BigNumber(1);
const erc20Amount = new BigNumber(10);
const erc20AssetData = await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync();
const erc20AssetData = encodeERC20AssetData(erc20TokenA.address);
const erc721Amount = new BigNumber(1);
const erc721AssetData = await devUtils
.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId)
.callAsync();
const erc721AssetData = encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId);
const amounts = [erc20Amount, erc721Amount];
const nestedAssetData = [erc20AssetData, erc721AssetData];
const assetData = await devUtils.encodeMultiAssetData(amounts, nestedAssetData).callAsync();
const assetData = encodeMultiAssetData(amounts, nestedAssetData);
const extraData = '01';
const assetDataWithExtraData = `${assetData}${extraData}`;
const badData = assetProxyInterface

View File

@@ -1,8 +1,6 @@
import { DevUtilsContract } from '@0x/contracts-dev-utils';
import {
chaiSetup,
constants,
expectTransactionFailedAsync,
expectTransactionFailedWithoutReasonAsync,
provider,
txDefaults,
@@ -16,7 +14,12 @@ import * as ethUtil from 'ethereumjs-util';
import { artifacts } from './artifacts';
import { IAssetProxyContract, StaticCallProxyContract, TestStaticCallTargetContract } from './wrappers';
import {
IAssetDataContract,
IAssetProxyContract,
StaticCallProxyContract,
TestStaticCallTargetContract,
} from './wrappers';
chaiSetup.configure();
const expect = chai.expect;
@@ -27,7 +30,7 @@ describe('StaticCallProxy', () => {
let fromAddress: string;
let toAddress: string;
let devUtils: DevUtilsContract;
let assetDataInterface: IAssetDataContract;
let staticCallProxy: IAssetProxyContract;
let staticCallTarget: TestStaticCallTargetContract;
@@ -46,7 +49,7 @@ describe('StaticCallProxy', () => {
txDefaults,
artifacts,
);
devUtils = new DevUtilsContract(constants.NULL_ADDRESS, provider);
assetDataInterface = new IAssetDataContract(constants.NULL_ADDRESS, provider);
staticCallProxy = new IAssetProxyContract(
staticCallProxyWithoutTransferFrom.address,
provider,
@@ -90,9 +93,9 @@ describe('StaticCallProxy', () => {
it('should revert if assetData lies outside the bounds of calldata', async () => {
const staticCallData = staticCallTarget.noInputFunction().getABIEncodedTransactionData();
const expectedResultHash = constants.KECCAK256_NULL;
const assetData = await devUtils
.encodeStaticCallAssetData(staticCallTarget.address, staticCallData, expectedResultHash)
.callAsync();
const assetData = assetDataInterface
.StaticCall(staticCallTarget.address, staticCallData, expectedResultHash)
.getABIEncodedTransactionData();
const txData = staticCallProxy
.transferFrom(assetData, fromAddress, toAddress, amount)
.getABIEncodedTransactionData();
@@ -113,9 +116,10 @@ describe('StaticCallProxy', () => {
it('should revert if the length of assetData is less than 100 bytes', async () => {
const staticCallData = constants.NULL_BYTES;
const expectedResultHash = constants.KECCAK256_NULL;
const assetData = (await devUtils
.encodeStaticCallAssetData(staticCallTarget.address, staticCallData, expectedResultHash)
.callAsync()).slice(0, -128);
const assetData = assetDataInterface
.StaticCall(staticCallTarget.address, staticCallData, expectedResultHash)
.getABIEncodedTransactionData()
.slice(0, -128);
const assetDataByteLen = (assetData.length - 2) / 2;
expect((assetDataByteLen - 4) % 32).to.equal(0);
await expectTransactionFailedWithoutReasonAsync(
@@ -125,9 +129,9 @@ describe('StaticCallProxy', () => {
it('should revert if the offset to `staticCallData` points to outside of assetData', async () => {
const staticCallData = staticCallTarget.noInputFunction().getABIEncodedTransactionData();
const expectedResultHash = constants.KECCAK256_NULL;
const assetData = await devUtils
.encodeStaticCallAssetData(staticCallTarget.address, staticCallData, expectedResultHash)
.callAsync();
const assetData = assetDataInterface
.StaticCall(staticCallTarget.address, staticCallData, expectedResultHash)
.getABIEncodedTransactionData();
const offsetToStaticCallData = '0000000000000000000000000000000000000000000000000000000000000060';
const assetDataEndBuffer = ethUtil.toBuffer((assetData.length - 2) / 2 - 4);
const paddedAssetDataEndBuffer = ethUtil.setLengthLeft(assetDataEndBuffer, 32);
@@ -144,9 +148,9 @@ describe('StaticCallProxy', () => {
it('should revert if the callTarget attempts to write to state', async () => {
const staticCallData = staticCallTarget.updateState().getABIEncodedTransactionData();
const expectedResultHash = constants.KECCAK256_NULL;
const assetData = await devUtils
.encodeStaticCallAssetData(staticCallTarget.address, staticCallData, expectedResultHash)
.callAsync();
const assetData = assetDataInterface
.StaticCall(staticCallTarget.address, staticCallData, expectedResultHash)
.getABIEncodedTransactionData();
await expectTransactionFailedWithoutReasonAsync(
staticCallProxy.transferFrom(assetData, fromAddress, toAddress, amount).sendTransactionAsync(),
);
@@ -154,32 +158,30 @@ describe('StaticCallProxy', () => {
it('should revert with data provided by the callTarget if the staticcall reverts', async () => {
const staticCallData = staticCallTarget.assertEvenNumber(new BigNumber(1)).getABIEncodedTransactionData();
const expectedResultHash = constants.KECCAK256_NULL;
const assetData = await devUtils
.encodeStaticCallAssetData(staticCallTarget.address, staticCallData, expectedResultHash)
.callAsync();
await expectTransactionFailedAsync(
staticCallProxy.transferFrom(assetData, fromAddress, toAddress, amount).sendTransactionAsync(),
RevertReason.TargetNotEven,
);
const assetData = assetDataInterface
.StaticCall(staticCallTarget.address, staticCallData, expectedResultHash)
.getABIEncodedTransactionData();
return expect(
staticCallProxy.transferFrom(assetData, fromAddress, toAddress, amount).awaitTransactionSuccessAsync(),
).to.revertWith(RevertReason.TargetNotEven);
});
it('should revert if the hash of the output is different than expected expected', async () => {
const staticCallData = staticCallTarget.isOddNumber(new BigNumber(0)).getABIEncodedTransactionData();
const trueAsBuffer = ethUtil.toBuffer('0x0000000000000000000000000000000000000000000000000000000000000001');
const expectedResultHash = ethUtil.bufferToHex(ethUtil.sha3(trueAsBuffer));
const assetData = await devUtils
.encodeStaticCallAssetData(staticCallTarget.address, staticCallData, expectedResultHash)
.callAsync();
await expectTransactionFailedAsync(
staticCallProxy.transferFrom(assetData, fromAddress, toAddress, amount).sendTransactionAsync(),
RevertReason.UnexpectedStaticCallResult,
);
const assetData = assetDataInterface
.StaticCall(staticCallTarget.address, staticCallData, expectedResultHash)
.getABIEncodedTransactionData();
return expect(
staticCallProxy.transferFrom(assetData, fromAddress, toAddress, amount).awaitTransactionSuccessAsync(),
).to.revertWith(RevertReason.UnexpectedStaticCallResult);
});
it('should be successful if a function call with no inputs and no outputs is successful', async () => {
const staticCallData = staticCallTarget.noInputFunction().getABIEncodedTransactionData();
const expectedResultHash = constants.KECCAK256_NULL;
const assetData = await devUtils
.encodeStaticCallAssetData(staticCallTarget.address, staticCallData, expectedResultHash)
.callAsync();
const assetData = assetDataInterface
.StaticCall(staticCallTarget.address, staticCallData, expectedResultHash)
.getABIEncodedTransactionData();
await staticCallProxy
.transferFrom(assetData, fromAddress, toAddress, amount)
.awaitTransactionSuccessAsync();
@@ -187,9 +189,9 @@ describe('StaticCallProxy', () => {
it('should be successful if the staticCallTarget is not a contract and no return value is expected', async () => {
const staticCallData = '0x0102030405060708';
const expectedResultHash = constants.KECCAK256_NULL;
const assetData = await devUtils
.encodeStaticCallAssetData(toAddress, staticCallData, expectedResultHash)
.callAsync();
const assetData = assetDataInterface
.StaticCall(toAddress, staticCallData, expectedResultHash)
.getABIEncodedTransactionData();
await staticCallProxy
.transferFrom(assetData, fromAddress, toAddress, amount)
.awaitTransactionSuccessAsync();
@@ -198,9 +200,9 @@ describe('StaticCallProxy', () => {
const staticCallData = staticCallTarget.isOddNumber(new BigNumber(1)).getABIEncodedTransactionData();
const trueAsBuffer = ethUtil.toBuffer('0x0000000000000000000000000000000000000000000000000000000000000001');
const expectedResultHash = ethUtil.bufferToHex(ethUtil.sha3(trueAsBuffer));
const assetData = await devUtils
.encodeStaticCallAssetData(staticCallTarget.address, staticCallData, expectedResultHash)
.callAsync();
const assetData = assetDataInterface
.StaticCall(staticCallTarget.address, staticCallData, expectedResultHash)
.getABIEncodedTransactionData();
await staticCallProxy
.transferFrom(assetData, fromAddress, toAddress, amount)
.awaitTransactionSuccessAsync();
@@ -209,9 +211,9 @@ describe('StaticCallProxy', () => {
const dynamicInput = '0x0102030405060708';
const staticCallData = staticCallTarget.dynamicInputFunction(dynamicInput).getABIEncodedTransactionData();
const expectedResultHash = constants.KECCAK256_NULL;
const assetData = await devUtils
.encodeStaticCallAssetData(staticCallTarget.address, staticCallData, expectedResultHash)
.callAsync();
const assetData = assetDataInterface
.StaticCall(staticCallTarget.address, staticCallData, expectedResultHash)
.getABIEncodedTransactionData();
await staticCallProxy
.transferFrom(assetData, fromAddress, toAddress, amount)
.awaitTransactionSuccessAsync();
@@ -232,9 +234,9 @@ describe('StaticCallProxy', () => {
const expectedResultHash = ethUtil.bufferToHex(
ethUtil.sha3(ethUtil.toBuffer(encodedExpectedResultWithOffset)),
);
const assetData = await devUtils
.encodeStaticCallAssetData(staticCallTarget.address, staticCallData, expectedResultHash)
.callAsync();
const assetData = assetDataInterface
.StaticCall(staticCallTarget.address, staticCallData, expectedResultHash)
.getABIEncodedTransactionData();
await staticCallProxy
.transferFrom(assetData, fromAddress, toAddress, amount)
.awaitTransactionSuccessAsync();

View File

@@ -5,13 +5,11 @@ import {
filterLogs,
filterLogsToArguments,
getRandomInteger,
hexLeftPad,
hexRandom,
Numberish,
randomAddress,
} from '@0x/contracts-test-utils';
import { AssetProxyId } from '@0x/types';
import { BigNumber } from '@0x/utils';
import { BigNumber, hexUtils } from '@0x/utils';
import { DecodedLogs } from 'ethereum-types';
import * as _ from 'lodash';
@@ -46,7 +44,9 @@ blockchainTests.resets('UniswapBridge unit tests', env => {
describe('isValidSignature()', () => {
it('returns success bytes', async () => {
const LEGACY_WALLET_MAGIC_VALUE = '0xb0671381';
const result = await testContract.isValidSignature(hexRandom(), hexRandom(_.random(0, 32))).callAsync();
const result = await testContract
.isValidSignature(hexUtils.random(), hexUtils.random(_.random(0, 32)))
.callAsync();
expect(result).to.eq(LEGACY_WALLET_MAGIC_VALUE);
});
});
@@ -126,7 +126,7 @@ blockchainTests.resets('UniswapBridge unit tests', env => {
// The amount to transfer to "to"
new BigNumber(_opts.amount),
// ABI-encoded "from" token address.
hexLeftPad(_opts.fromTokenAddress),
hexUtils.leftPad(_opts.fromTokenAddress),
);
const result = await bridgeTransferFromFn.callAsync();
const receipt = await bridgeTransferFromFn.awaitTransactionSuccessAsync();
@@ -176,7 +176,7 @@ blockchainTests.resets('UniswapBridge unit tests', env => {
expect(calls[0].exchange).to.eq(exchangeAddress);
expect(calls[0].tokensSold).to.bignumber.eq(opts.fromTokenBalance);
expect(calls[0].minTokensBought).to.bignumber.eq(opts.amount);
expect(calls[0].minEthBought).to.bignumber.eq(0);
expect(calls[0].minEthBought).to.bignumber.eq(1);
expect(calls[0].deadline).to.bignumber.eq(blockTime);
expect(calls[0].recipient).to.eq(opts.toAddress);
expect(calls[0].toTokenAddress).to.eq(opts.toTokenAddress);
@@ -208,7 +208,7 @@ blockchainTests.resets('UniswapBridge unit tests', env => {
randomAddress(),
randomAddress(),
getRandomInteger(1, 1e18),
hexLeftPad(randomAddress()),
hexUtils.leftPad(randomAddress()),
)
.awaitTransactionSuccessAsync();
return expect(tx).to.eventually.be.rejectedWith('NO_UNISWAP_EXCHANGE_FOR_TOKEN');
@@ -282,7 +282,7 @@ blockchainTests.resets('UniswapBridge unit tests', env => {
randomAddress(),
randomAddress(),
getRandomInteger(1, 1e18),
hexLeftPad(wethTokenAddress),
hexUtils.leftPad(wethTokenAddress),
)
.awaitTransactionSuccessAsync();
return expect(tx).to.eventually.be.rejectedWith('NO_UNISWAP_EXCHANGE_FOR_TOKEN');
@@ -342,7 +342,7 @@ blockchainTests.resets('UniswapBridge unit tests', env => {
randomAddress(),
randomAddress(),
getRandomInteger(1, 1e18),
hexLeftPad(randomAddress()),
hexUtils.leftPad(randomAddress()),
)
.awaitTransactionSuccessAsync();
return expect(tx).to.eventually.be.rejectedWith('NO_UNISWAP_EXCHANGE_FOR_TOKEN');

View File

@@ -0,0 +1,216 @@
import {
blockchainTests,
constants,
expect,
filterLogsToArguments,
getRandomInteger,
randomAddress,
} from '@0x/contracts-test-utils';
import { AssetProxyId } from '@0x/types';
import { AbiEncoder, BigNumber, hexUtils } from '@0x/utils';
import { DecodedLogs } from 'ethereum-types';
import * as _ from 'lodash';
import { artifacts } from './artifacts';
import {
TestUniswapV2BridgeContract,
TestUniswapV2BridgeEvents as ContractEvents,
TestUniswapV2BridgeSwapExactTokensForTokensInputEventArgs as SwapExactTokensForTokensArgs,
TestUniswapV2BridgeTokenApproveEventArgs as TokenApproveArgs,
TestUniswapV2BridgeTokenTransferEventArgs as TokenTransferArgs,
} from './wrappers';
blockchainTests.resets('UniswapV2 unit tests', env => {
const FROM_TOKEN_DECIMALS = 6;
const TO_TOKEN_DECIMALS = 18;
const FROM_TOKEN_BASE = new BigNumber(10).pow(FROM_TOKEN_DECIMALS);
const TO_TOKEN_BASE = new BigNumber(10).pow(TO_TOKEN_DECIMALS);
let testContract: TestUniswapV2BridgeContract;
before(async () => {
testContract = await TestUniswapV2BridgeContract.deployFrom0xArtifactAsync(
artifacts.TestUniswapV2Bridge,
env.provider,
env.txDefaults,
artifacts,
);
});
describe('isValidSignature()', () => {
it('returns success bytes', async () => {
const LEGACY_WALLET_MAGIC_VALUE = '0xb0671381';
const result = await testContract
.isValidSignature(hexUtils.random(), hexUtils.random(_.random(0, 32)))
.callAsync();
expect(result).to.eq(LEGACY_WALLET_MAGIC_VALUE);
});
});
describe('bridgeTransferFrom()', () => {
interface TransferFromOpts {
tokenAddressesPath: string[];
toAddress: string;
// Amount to pass into `bridgeTransferFrom()`
amount: BigNumber;
// Token balance of the bridge.
fromTokenBalance: BigNumber;
// Router reverts with this reason
routerRevertReason: string;
}
interface TransferFromResult {
opts: TransferFromOpts;
result: string;
logs: DecodedLogs;
blocktime: number;
}
function createTransferFromOpts(opts?: Partial<TransferFromOpts>): TransferFromOpts {
const amount = getRandomInteger(1, TO_TOKEN_BASE.times(100));
return {
tokenAddressesPath: Array(2).fill(constants.NULL_ADDRESS),
amount,
toAddress: randomAddress(),
fromTokenBalance: getRandomInteger(1, FROM_TOKEN_BASE.times(100)),
routerRevertReason: '',
...opts,
};
}
const bridgeDataEncoder = AbiEncoder.create('(address[])');
async function transferFromAsync(opts?: Partial<TransferFromOpts>): Promise<TransferFromResult> {
const _opts = createTransferFromOpts(opts);
for (let i = 0; i < _opts.tokenAddressesPath.length; i++) {
const createFromTokenFn = testContract.createToken(_opts.tokenAddressesPath[i]);
_opts.tokenAddressesPath[i] = await createFromTokenFn.callAsync();
await createFromTokenFn.awaitTransactionSuccessAsync();
}
// Set the token balance for the token we're converting from.
await testContract
.setTokenBalance(_opts.tokenAddressesPath[0], _opts.fromTokenBalance)
.awaitTransactionSuccessAsync();
// Set revert reason for the router.
await testContract.setRouterRevertReason(_opts.routerRevertReason).awaitTransactionSuccessAsync();
// Call bridgeTransferFrom().
const bridgeTransferFromFn = testContract.bridgeTransferFrom(
// Output token
_opts.tokenAddressesPath[_opts.tokenAddressesPath.length - 1],
// Random maker address.
randomAddress(),
// Recipient address.
_opts.toAddress,
// Transfer amount.
_opts.amount,
// ABI-encode the input token address as the bridge data. // FIXME
bridgeDataEncoder.encode([_opts.tokenAddressesPath]),
);
const result = await bridgeTransferFromFn.callAsync();
const receipt = await bridgeTransferFromFn.awaitTransactionSuccessAsync();
return {
opts: _opts,
result,
logs: (receipt.logs as any) as DecodedLogs,
blocktime: await env.web3Wrapper.getBlockTimestampAsync(receipt.blockNumber),
};
}
it('returns magic bytes on success', async () => {
const { result } = await transferFromAsync();
expect(result).to.eq(AssetProxyId.ERC20Bridge);
});
it('performs transfer when both tokens are the same', async () => {
const createTokenFn = testContract.createToken(constants.NULL_ADDRESS);
const tokenAddress = await createTokenFn.callAsync();
await createTokenFn.awaitTransactionSuccessAsync();
const { opts, result, logs } = await transferFromAsync({
tokenAddressesPath: [tokenAddress, tokenAddress],
});
expect(result).to.eq(AssetProxyId.ERC20Bridge, 'asset proxy id');
const transfers = filterLogsToArguments<TokenTransferArgs>(logs, ContractEvents.TokenTransfer);
expect(transfers.length).to.eq(1);
expect(transfers[0].token).to.eq(tokenAddress, 'input token address');
expect(transfers[0].from).to.eq(testContract.address);
expect(transfers[0].to).to.eq(opts.toAddress, 'recipient address');
expect(transfers[0].amount).to.bignumber.eq(opts.amount, 'amount');
});
describe('token -> token', async () => {
it('calls UniswapV2Router01.swapExactTokensForTokens()', async () => {
const { opts, result, logs, blocktime } = await transferFromAsync();
expect(result).to.eq(AssetProxyId.ERC20Bridge, 'asset proxy id');
const transfers = filterLogsToArguments<SwapExactTokensForTokensArgs>(
logs,
ContractEvents.SwapExactTokensForTokensInput,
);
expect(transfers.length).to.eq(1);
expect(transfers[0].toTokenAddress).to.eq(
opts.tokenAddressesPath[opts.tokenAddressesPath.length - 1],
'output token address',
);
expect(transfers[0].to).to.eq(opts.toAddress, 'recipient address');
expect(transfers[0].amountIn).to.bignumber.eq(opts.fromTokenBalance, 'input token amount');
expect(transfers[0].amountOutMin).to.bignumber.eq(opts.amount, 'output token amount');
expect(transfers[0].deadline).to.bignumber.eq(blocktime, 'deadline');
});
it('sets allowance for "from" token', async () => {
const { logs } = await transferFromAsync();
const approvals = filterLogsToArguments<TokenApproveArgs>(logs, ContractEvents.TokenApprove);
const routerAddress = await testContract.getRouterAddress().callAsync();
expect(approvals.length).to.eq(1);
expect(approvals[0].spender).to.eq(routerAddress);
expect(approvals[0].allowance).to.bignumber.eq(constants.MAX_UINT256);
});
it('sets allowance for "from" token on subsequent calls', async () => {
const { opts } = await transferFromAsync();
const { logs } = await transferFromAsync(opts);
const approvals = filterLogsToArguments<TokenApproveArgs>(logs, ContractEvents.TokenApprove);
const routerAddress = await testContract.getRouterAddress().callAsync();
expect(approvals.length).to.eq(1);
expect(approvals[0].spender).to.eq(routerAddress);
expect(approvals[0].allowance).to.bignumber.eq(constants.MAX_UINT256);
});
it('fails if the router fails', async () => {
const revertReason = 'FOOBAR';
const tx = transferFromAsync({
routerRevertReason: revertReason,
});
return expect(tx).to.eventually.be.rejectedWith(revertReason);
});
});
describe('token -> token -> token', async () => {
it('calls UniswapV2Router01.swapExactTokensForTokens()', async () => {
const { opts, result, logs, blocktime } = await transferFromAsync({
tokenAddressesPath: Array(3).fill(constants.NULL_ADDRESS),
});
expect(result).to.eq(AssetProxyId.ERC20Bridge, 'asset proxy id');
const transfers = filterLogsToArguments<SwapExactTokensForTokensArgs>(
logs,
ContractEvents.SwapExactTokensForTokensInput,
);
expect(transfers.length).to.eq(1);
expect(transfers[0].toTokenAddress).to.eq(
opts.tokenAddressesPath[opts.tokenAddressesPath.length - 1],
'output token address',
);
expect(transfers[0].to).to.eq(opts.toAddress, 'recipient address');
expect(transfers[0].amountIn).to.bignumber.eq(opts.fromTokenBalance, 'input token amount');
expect(transfers[0].amountOutMin).to.bignumber.eq(opts.amount, 'output token amount');
expect(transfers[0].deadline).to.bignumber.eq(blocktime, 'deadline');
});
});
});
});

View File

@@ -3,6 +3,10 @@
* Warning: This file is auto-generated by contracts-gen. Don't edit manually.
* -----------------------------------------------------------------------------
*/
export * from '../test/generated-wrappers/chai_bridge';
export * from '../test/generated-wrappers/curve_bridge';
export * from '../test/generated-wrappers/dex_forwarder_bridge';
export * from '../test/generated-wrappers/dydx_bridge';
export * from '../test/generated-wrappers/erc1155_proxy';
export * from '../test/generated-wrappers/erc20_bridge_proxy';
export * from '../test/generated-wrappers/erc20_proxy';
@@ -12,20 +16,32 @@ export * from '../test/generated-wrappers/i_asset_data';
export * from '../test/generated-wrappers/i_asset_proxy';
export * from '../test/generated-wrappers/i_asset_proxy_dispatcher';
export * from '../test/generated-wrappers/i_authorizable';
export * from '../test/generated-wrappers/i_chai';
export * from '../test/generated-wrappers/i_curve';
export * from '../test/generated-wrappers/i_dydx';
export * from '../test/generated-wrappers/i_dydx_bridge';
export * from '../test/generated-wrappers/i_erc20_bridge';
export * from '../test/generated-wrappers/i_eth2_dai';
export * from '../test/generated-wrappers/i_gas_token';
export * from '../test/generated-wrappers/i_kyber_network_proxy';
export * from '../test/generated-wrappers/i_uniswap_exchange';
export * from '../test/generated-wrappers/i_uniswap_exchange_factory';
export * from '../test/generated-wrappers/i_uniswap_v2_router01';
export * from '../test/generated-wrappers/kyber_bridge';
export * from '../test/generated-wrappers/mixin_asset_proxy_dispatcher';
export * from '../test/generated-wrappers/mixin_authorizable';
export * from '../test/generated-wrappers/mixin_gas_token';
export * from '../test/generated-wrappers/multi_asset_proxy';
export * from '../test/generated-wrappers/ownable';
export * from '../test/generated-wrappers/static_call_proxy';
export * from '../test/generated-wrappers/test_chai_bridge';
export * from '../test/generated-wrappers/test_dex_forwarder_bridge';
export * from '../test/generated-wrappers/test_dydx_bridge';
export * from '../test/generated-wrappers/test_erc20_bridge';
export * from '../test/generated-wrappers/test_eth2_dai_bridge';
export * from '../test/generated-wrappers/test_kyber_bridge';
export * from '../test/generated-wrappers/test_static_call_target';
export * from '../test/generated-wrappers/test_uniswap_bridge';
export * from '../test/generated-wrappers/test_uniswap_v2_bridge';
export * from '../test/generated-wrappers/uniswap_bridge';
export * from '../test/generated-wrappers/uniswap_v2_bridge';

View File

@@ -84,7 +84,7 @@ module.exports = {
solc: {
version: '0.5.9',
settings: {
evmVersion: 'constantinople',
evmVersion: 'istanbul',
optimizer: {
enabled: true,
runs: 1000000,

View File

@@ -3,6 +3,10 @@
"compilerOptions": { "outDir": "lib", "rootDir": ".", "resolveJsonModule": true },
"include": ["./src/**/*", "./test/**/*", "./generated-wrappers/**/*"],
"files": [
"generated-artifacts/ChaiBridge.json",
"generated-artifacts/CurveBridge.json",
"generated-artifacts/DexForwarderBridge.json",
"generated-artifacts/DydxBridge.json",
"generated-artifacts/ERC1155Proxy.json",
"generated-artifacts/ERC20BridgeProxy.json",
"generated-artifacts/ERC20Proxy.json",
@@ -10,11 +14,41 @@
"generated-artifacts/Eth2DaiBridge.json",
"generated-artifacts/IAssetData.json",
"generated-artifacts/IAssetProxy.json",
"generated-artifacts/IAssetProxyDispatcher.json",
"generated-artifacts/IAuthorizable.json",
"generated-artifacts/IChai.json",
"generated-artifacts/ICurve.json",
"generated-artifacts/IDydx.json",
"generated-artifacts/IDydxBridge.json",
"generated-artifacts/IERC20Bridge.json",
"generated-artifacts/IEth2Dai.json",
"generated-artifacts/IGasToken.json",
"generated-artifacts/IKyberNetworkProxy.json",
"generated-artifacts/IUniswapExchange.json",
"generated-artifacts/IUniswapExchangeFactory.json",
"generated-artifacts/IUniswapV2Router01.json",
"generated-artifacts/KyberBridge.json",
"generated-artifacts/MixinAssetProxyDispatcher.json",
"generated-artifacts/MixinAuthorizable.json",
"generated-artifacts/MixinGasToken.json",
"generated-artifacts/MultiAssetProxy.json",
"generated-artifacts/Ownable.json",
"generated-artifacts/StaticCallProxy.json",
"generated-artifacts/TestChaiBridge.json",
"generated-artifacts/TestDexForwarderBridge.json",
"generated-artifacts/TestDydxBridge.json",
"generated-artifacts/TestERC20Bridge.json",
"generated-artifacts/TestEth2DaiBridge.json",
"generated-artifacts/TestKyberBridge.json",
"generated-artifacts/TestStaticCallTarget.json",
"generated-artifacts/TestUniswapBridge.json",
"generated-artifacts/TestUniswapV2Bridge.json",
"generated-artifacts/UniswapBridge.json",
"generated-artifacts/UniswapV2Bridge.json",
"test/generated-artifacts/ChaiBridge.json",
"test/generated-artifacts/CurveBridge.json",
"test/generated-artifacts/DexForwarderBridge.json",
"test/generated-artifacts/DydxBridge.json",
"test/generated-artifacts/ERC1155Proxy.json",
"test/generated-artifacts/ERC20BridgeProxy.json",
"test/generated-artifacts/ERC20Proxy.json",
@@ -24,23 +58,35 @@
"test/generated-artifacts/IAssetProxy.json",
"test/generated-artifacts/IAssetProxyDispatcher.json",
"test/generated-artifacts/IAuthorizable.json",
"test/generated-artifacts/IChai.json",
"test/generated-artifacts/ICurve.json",
"test/generated-artifacts/IDydx.json",
"test/generated-artifacts/IDydxBridge.json",
"test/generated-artifacts/IERC20Bridge.json",
"test/generated-artifacts/IEth2Dai.json",
"test/generated-artifacts/IGasToken.json",
"test/generated-artifacts/IKyberNetworkProxy.json",
"test/generated-artifacts/IUniswapExchange.json",
"test/generated-artifacts/IUniswapExchangeFactory.json",
"test/generated-artifacts/IUniswapV2Router01.json",
"test/generated-artifacts/KyberBridge.json",
"test/generated-artifacts/MixinAssetProxyDispatcher.json",
"test/generated-artifacts/MixinAuthorizable.json",
"test/generated-artifacts/MixinGasToken.json",
"test/generated-artifacts/MultiAssetProxy.json",
"test/generated-artifacts/Ownable.json",
"test/generated-artifacts/StaticCallProxy.json",
"test/generated-artifacts/TestChaiBridge.json",
"test/generated-artifacts/TestDexForwarderBridge.json",
"test/generated-artifacts/TestDydxBridge.json",
"test/generated-artifacts/TestERC20Bridge.json",
"test/generated-artifacts/TestEth2DaiBridge.json",
"test/generated-artifacts/TestKyberBridge.json",
"test/generated-artifacts/TestStaticCallTarget.json",
"test/generated-artifacts/TestUniswapBridge.json",
"test/generated-artifacts/UniswapBridge.json"
"test/generated-artifacts/TestUniswapV2Bridge.json",
"test/generated-artifacts/UniswapBridge.json",
"test/generated-artifacts/UniswapV2Bridge.json"
],
"exclude": ["./deploy/solc/solc_bin"]
}

View File

@@ -0,0 +1,10 @@
# Blacklist all files
.*
*
# Whitelist lib
!lib/**/*
# Whitelist Solidity contracts
!contracts/src/**/*
# Blacklist tests in lib
/lib/test/*
# Package specific ignore

View File

@@ -0,0 +1,85 @@
[
{
"version": "1.1.5",
"changes": [
{
"note": "Fix broken tests.",
"pr": 2591
}
],
"timestamp": 1592969527
},
{
"timestamp": 1583220306,
"version": "1.1.4",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1582837861,
"version": "1.1.3",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1582677073,
"version": "1.1.2",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1582623685,
"version": "1.1.1",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"version": "1.1.0",
"changes": [
{
"note": "Added decoders for broker data",
"pr": 2484
}
],
"timestamp": 1581748629
},
{
"timestamp": 1581204851,
"version": "1.0.2",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1580988106,
"version": "1.0.1",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"version": "1.0.0",
"changes": [
{
"note": "Created package",
"pr": "2455"
}
]
}
]

View File

@@ -0,0 +1,42 @@
<!--
changelogUtils.file is auto-generated using the monorepo-scripts package. Don't edit directly.
Edit the package's CHANGELOG.json file only.
-->
CHANGELOG
## v1.1.5 - _June 24, 2020_
* Fix broken tests. (#2591)
## v1.1.4 - _March 3, 2020_
* Dependencies updated
## v1.1.3 - _February 27, 2020_
* Dependencies updated
## v1.1.2 - _February 26, 2020_
* Dependencies updated
## v1.1.1 - _February 25, 2020_
* Dependencies updated
## v1.1.0 - _February 15, 2020_
* Added decoders for broker data (#2484)
## v1.0.2 - _February 8, 2020_
* Dependencies updated
## v1.0.1 - _February 6, 2020_
* Dependencies updated
## v1.0.0 - _Invalid date_
* Created package (#2455)

View File

@@ -0,0 +1 @@
[]

View File

@@ -1,6 +1,18 @@
## Tests
## Broker
This package implements unit tests against 0x's smart contracts. Its primary purpose is to help avoid circular dependencies between the contract packages.
This package contains the implementation of the [`Broker` contract](https://github.com/0xProject/ZEIPs/issues/75). This contract serves as an entry-point to the 0x Exchange for the filling of property-based orders. Addresses of the deployed contracts can be found in this 0x [guide](https://0x.org/docs/guides/0x-cheat-sheet) or the [DEPLOYS](./DEPLOYS.json) file within this package.
## Installation
**Install**
```bash
npm install @0x/contracts-broker --save
```
## Bug bounty
A bug bounty for the 3.0 contracts is ongoing! Instructions can be found [here](https://0x.org/docs/guides/bug-bounty-program).
## Contributing
@@ -29,39 +41,21 @@ yarn install
To build this package and all other monorepo packages that it depends on, run the following from the monorepo root directory:
```bash
PKG=@0x/contracts-tests yarn build
PKG=@0x/contracts-broker yarn build
```
Or continuously rebuild on change:
```bash
PKG=@0x/contracts-tests yarn watch
PKG=@0x/contracts-broker yarn watch
```
If imports are rebuilt in their source packages, they do not need to be rebuilt here.
Example:
```
// contracts/tests/test/some-new/some_new_test.ts
import { SomeNewContract } from '@0x/contracts-some-new';
describe('should do its thing', () => {
const contractInstance = new SomeNewContract();
expect(contractInstance.someTruthyFunction.callAsync()).to.be.true();
})
```
Run `yarn watch` from `contracts/some-new`, and then running `yarn test` from this package should test the new changes.
### Clean
```bash
yarn clean
```
Since the purpose of this package is to test other packages, make sure you are running `yarn clean` as necessary in the imported packages as well.
### Lint
```bash
@@ -73,3 +67,7 @@ yarn lint
```bash
yarn test
```
#### Testing options
Contracts testing options like coverage, profiling, revert traces or backing node choosing - are described [here](../TESTING.md).

View File

@@ -3,8 +3,9 @@
"contractsDir": "./contracts",
"useDockerisedSolc": false,
"isOfflineMode": false,
"shouldSaveStandardInput": true,
"compilerSettings": {
"evmVersion": "constantinople",
"evmVersion": "istanbul",
"optimizer": {
"enabled": true,
"runs": 1000000,

View File

@@ -0,0 +1,314 @@
/*
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.5.9;
pragma experimental ABIEncoderV2;
import "@0x/contracts-asset-proxy/contracts/src/interfaces/IAssetData.sol";
import "@0x/contracts-erc20/contracts/src/interfaces/IEtherToken.sol";
import "@0x/contracts-erc721/contracts/src/interfaces/IERC721Token.sol";
import "@0x/contracts-exchange/contracts/src/interfaces/IExchange.sol";
import "@0x/contracts-exchange-libs/contracts/src/LibFillResults.sol";
import "@0x/contracts-exchange-libs/contracts/src/LibOrder.sol";
import "@0x/contracts-extensions/contracts/src/LibAssetDataTransfer.sol";
import "@0x/contracts-extensions/contracts/src/MixinWethUtils.sol";
import "@0x/contracts-utils/contracts/src/LibBytes.sol";
import "@0x/contracts-utils/contracts/src/LibRichErrors.sol";
import "@0x/contracts-utils/contracts/src/LibSafeMath.sol";
import "./interfaces/IBroker.sol";
import "./interfaces/IPropertyValidator.sol";
import "./libs/LibBrokerRichErrors.sol";
// solhint-disable space-after-comma, var-name-mixedcase
contract Broker is
IBroker,
MixinWethUtils
{
// Contract addresses
// Address of the 0x Exchange contract
address internal EXCHANGE;
// Address of the 0x ERC1155 Asset Proxy contract
address internal ERC1155_PROXY;
// The following storage variables are used to cache data for the duration of the transcation.
// They should always cleared at the end of the transaction.
// Token IDs specified by the taker to be used to fill property-based orders.
uint256[] internal _cachedTokenIds;
// An index to the above array keeping track of which assets have been transferred.
uint256 internal _cacheIndex;
// The address that called `brokerTrade` or `batchBrokerTrade`. Assets will be transferred to
// and from this address as the effectual taker of the orders.
address internal _sender;
using LibSafeMath for uint256;
using LibBytes for bytes;
using LibAssetDataTransfer for bytes;
/// @param exchange Address of the 0x Exchange contract.
/// @param exchange Address of the Wrapped Ether contract.
/// @param exchange Address of the 0x ERC1155 Asset Proxy contract.
constructor (
address exchange,
address weth
)
public
MixinWethUtils(
exchange,
weth
)
{
EXCHANGE = exchange;
ERC1155_PROXY = IExchange(EXCHANGE).getAssetProxy(IAssetData(address(0)).ERC1155Assets.selector);
}
/// @dev The Broker implements the ERC1155 transfer function to be compatible with the ERC1155 asset proxy
/// @param from Since the Broker serves as the taker of the order, this should equal `address(this)`
/// @param to This should be the maker of the order.
/// @param amounts Should be an array of just one `uint256`, specifying the amount of the brokered assets to transfer.
/// @param data Encodes the validator contract address and any auxiliary data it needs for property validation.
function safeBatchTransferFrom(
address from,
address to,
uint256[] calldata /* ids */,
uint256[] calldata amounts,
bytes calldata data
)
external
{
// Only the ERC1155 asset proxy contract should be calling this function.
if (msg.sender != ERC1155_PROXY) {
LibRichErrors.rrevert(LibBrokerRichErrors.OnlyERC1155ProxyError(
msg.sender
));
}
// Only `takerAssetData` should be using Broker assets
if (from != address(this)) {
LibRichErrors.rrevert(
LibBrokerRichErrors.InvalidFromAddressError(from)
);
}
// Only one asset amount should be specified.
if (amounts.length != 1) {
LibRichErrors.rrevert(
LibBrokerRichErrors.AmountsLengthMustEqualOneError(amounts.length)
);
}
uint256 cacheIndex = _cacheIndex;
uint256 remainingAmount = amounts[0];
// Verify that there are enough broker assets to transfer
if (_cachedTokenIds.length.safeSub(cacheIndex) < remainingAmount) {
LibRichErrors.rrevert(
LibBrokerRichErrors.TooFewBrokerAssetsProvidedError(_cachedTokenIds.length)
);
}
// Decode validator and params from `data`
(address tokenAddress, address validator, bytes memory propertyData) = abi.decode(
data,
(address, address, bytes)
);
while (remainingAmount != 0) {
uint256 tokenId = _cachedTokenIds[cacheIndex];
cacheIndex++;
// Validate asset properties
IPropertyValidator(validator).checkBrokerAsset(
tokenId,
propertyData
);
// Perform the transfer
IERC721Token(tokenAddress).transferFrom(
_sender,
to,
tokenId
);
remainingAmount--;
}
// Update cache index in storage
_cacheIndex = cacheIndex;
}
/// @dev Fills a single property-based order by the given amount using the given assets.
/// Pays protocol fees using either the ETH supplied by the taker to the transaction or
/// WETH acquired from the maker during settlement. The final WETH balance is sent to the taker.
/// @param brokeredTokenIds Token IDs specified by the taker to be used to fill the orders.
/// @param order The property-based order to fill. The format of a property-based order is the
/// same as that of a normal order, except the takerAssetData. Instaed of specifying a
/// specific ERC721 asset, the takerAssetData should be ERC1155 assetData where the
/// underlying tokenAddress is this contract's address and the desired properties are
/// encoded in the extra data field. Also note that takerFees must be denominated in
/// WETH (or zero).
/// @param takerAssetFillAmount The amount to fill the order by.
/// @param signature The maker's signature of the given order.
/// @param fillFunctionSelector The selector for either `fillOrder` or `fillOrKillOrder`.
/// @param ethFeeAmounts Amounts of ETH, denominated in Wei, that are paid to corresponding feeRecipients.
/// @param feeRecipients Addresses that will receive ETH when orders are filled.
/// @return fillResults Amounts filled and fees paid by the maker and taker.
function brokerTrade(
uint256[] memory brokeredTokenIds,
LibOrder.Order memory order,
uint256 takerAssetFillAmount,
bytes memory signature,
bytes4 fillFunctionSelector,
uint256[] memory ethFeeAmounts,
address payable[] memory feeRecipients
)
public
payable
returns (LibFillResults.FillResults memory fillResults)
{
// Cache the taker-supplied asset data
_cachedTokenIds = brokeredTokenIds;
// Cache the sender's address
_sender = msg.sender;
// Sanity-check the provided function selector
if (
fillFunctionSelector != IExchange(address(0)).fillOrder.selector &&
fillFunctionSelector != IExchange(address(0)).fillOrKillOrder.selector
) {
LibBrokerRichErrors.InvalidFunctionSelectorError(fillFunctionSelector);
}
// Pay ETH affiliate fees to all feeRecipient addresses
_transferEthFeesAndWrapRemaining(ethFeeAmounts, feeRecipients);
// Perform the fill
bytes memory fillCalldata = abi.encodeWithSelector(
fillFunctionSelector,
order,
takerAssetFillAmount,
signature
);
// solhint-disable-next-line avoid-call-value
(bool didSucceed, bytes memory returnData) = EXCHANGE.call(fillCalldata);
if (didSucceed) {
fillResults = abi.decode(returnData, (LibFillResults.FillResults));
} else {
// Re-throw error
LibRichErrors.rrevert(returnData);
}
// Transfer maker asset to taker
if (!order.makerAssetData.equals(WETH_ASSET_DATA)) {
order.makerAssetData.transferOut(fillResults.makerAssetFilledAmount);
}
// Refund remaining ETH to msg.sender.
_unwrapAndTransferEth(WETH.balanceOf(address(this)));
_clearStorage();
return fillResults;
}
/// @dev Fills multiple property-based orders by the given amounts using the given assets.
/// Pays protocol fees using either the ETH supplied by the taker to the transaction or
/// WETH acquired from the maker during settlement. The final WETH balance is sent to the taker.
/// @param brokeredTokenIds Token IDs specified by the taker to be used to fill the orders.
/// @param orders The property-based orders to fill. The format of a property-based order is the
/// same as that of a normal order, except the takerAssetData. Instaed of specifying a
/// specific ERC721 asset, the takerAssetData should be ERC1155 assetData where the
/// underlying tokenAddress is this contract's address and the desired properties are
/// encoded in the extra data field. Also note that takerFees must be denominated in
/// WETH (or zero).
/// @param takerAssetFillAmounts The amounts to fill the orders by.
/// @param signatures The makers' signatures for the given orders.
/// @param batchFillFunctionSelector The selector for either `batchFillOrders`,
/// `batchFillOrKillOrders`, or `batchFillOrdersNoThrow`.
/// @param ethFeeAmounts Amounts of ETH, denominated in Wei, that are paid to corresponding feeRecipients.
/// @param feeRecipients Addresses that will receive ETH when orders are filled.
/// @return fillResults Amounts filled and fees paid by the makers and taker.
function batchBrokerTrade(
uint256[] memory brokeredTokenIds,
LibOrder.Order[] memory orders,
uint256[] memory takerAssetFillAmounts,
bytes[] memory signatures,
bytes4 batchFillFunctionSelector,
uint256[] memory ethFeeAmounts,
address payable[] memory feeRecipients
)
public
payable
returns (LibFillResults.FillResults[] memory fillResults)
{
// Cache the taker-supplied asset data
_cachedTokenIds = brokeredTokenIds;
// Cache the sender's address
_sender = msg.sender;
// Sanity-check the provided function selector
if (
batchFillFunctionSelector != IExchange(address(0)).batchFillOrders.selector &&
batchFillFunctionSelector != IExchange(address(0)).batchFillOrKillOrders.selector &&
batchFillFunctionSelector != IExchange(address(0)).batchFillOrdersNoThrow.selector
) {
LibBrokerRichErrors.InvalidFunctionSelectorError(batchFillFunctionSelector);
}
// Pay ETH affiliate fees to all feeRecipient addresses
_transferEthFeesAndWrapRemaining(ethFeeAmounts, feeRecipients);
// Perform the batch fill
bytes memory batchFillCalldata = abi.encodeWithSelector(
batchFillFunctionSelector,
orders,
takerAssetFillAmounts,
signatures
);
// solhint-disable-next-line avoid-call-value
(bool didSucceed, bytes memory returnData) = EXCHANGE.call(batchFillCalldata);
if (didSucceed) {
// solhint-disable-next-line indent
fillResults = abi.decode(returnData, (LibFillResults.FillResults[]));
} else {
// Re-throw error
LibRichErrors.rrevert(returnData);
}
// Transfer maker assets to taker
for (uint256 i = 0; i < orders.length; i++) {
if (!orders[i].makerAssetData.equals(WETH_ASSET_DATA)) {
orders[i].makerAssetData.transferOut(fillResults[i].makerAssetFilledAmount);
}
}
// Refund remaining ETH to msg.sender.
_unwrapAndTransferEth(WETH.balanceOf(address(this)));
_clearStorage();
return fillResults;
}
function _clearStorage()
private
{
delete _cachedTokenIds;
_cacheIndex = 0;
_sender = address(0);
}
}

View File

@@ -0,0 +1,101 @@
/*
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.5.9;
pragma experimental ABIEncoderV2;
import "@0x/contracts-exchange-libs/contracts/src/LibFillResults.sol";
import "@0x/contracts-exchange-libs/contracts/src/LibOrder.sol";
// solhint-disable space-after-comma
interface IBroker {
/// @dev Fills a single property-based order by the given amount using the given assets.
/// Pays protocol fees using either the ETH supplied by the taker to the transaction or
/// WETH acquired from the maker during settlement. The final WETH balance is sent to the taker.
/// @param brokeredTokenIds Token IDs specified by the taker to be used to fill the orders.
/// @param order The property-based order to fill. The format of a property-based order is the
/// same as that of a normal order, except the takerAssetData. Instaed of specifying a
/// specific ERC721 asset, the takerAssetData should be ERC1155 assetData where the
/// underlying tokenAddress is this contract's address and the desired properties are
/// encoded in the extra data field. Also note that takerFees must be denominated in
/// WETH (or zero).
/// @param takerAssetFillAmount The amount to fill the order by.
/// @param signature The maker's signature of the given order.
/// @param fillFunctionSelector The selector for either `fillOrder` or `fillOrKillOrder`.
/// @param ethFeeAmounts Amounts of ETH, denominated in Wei, that are paid to corresponding feeRecipients.
/// @param feeRecipients Addresses that will receive ETH when orders are filled.
/// @return fillResults Amounts filled and fees paid by the maker and taker.
function brokerTrade(
uint256[] calldata brokeredTokenIds,
LibOrder.Order calldata order,
uint256 takerAssetFillAmount,
bytes calldata signature,
bytes4 fillFunctionSelector,
uint256[] calldata ethFeeAmounts,
address payable[] calldata feeRecipients
)
external
payable
returns (LibFillResults.FillResults memory fillResults);
/// @dev Fills multiple property-based orders by the given amounts using the given assets.
/// Pays protocol fees using either the ETH supplied by the taker to the transaction or
/// WETH acquired from the maker during settlement. The final WETH balance is sent to the taker.
/// @param brokeredTokenIds Token IDs specified by the taker to be used to fill the orders.
/// @param orders The property-based orders to fill. The format of a property-based order is the
/// same as that of a normal order, except the takerAssetData. Instaed of specifying a
/// specific ERC721 asset, the takerAssetData should be ERC1155 assetData where the
/// underlying tokenAddress is this contract's address and the desired properties are
/// encoded in the extra data field. Also note that takerFees must be denominated in
/// WETH (or zero).
/// @param takerAssetFillAmounts The amounts to fill the orders by.
/// @param signatures The makers' signatures for the given orders.
/// @param batchFillFunctionSelector The selector for either `batchFillOrders`,
/// `batchFillOrKillOrders`, or `batchFillOrdersNoThrow`.
/// @param ethFeeAmounts Amounts of ETH, denominated in Wei, that are paid to corresponding feeRecipients.
/// @param feeRecipients Addresses that will receive ETH when orders are filled.
/// @return fillResults Amounts filled and fees paid by the makers and taker.
function batchBrokerTrade(
uint256[] calldata brokeredTokenIds,
LibOrder.Order[] calldata orders,
uint256[] calldata takerAssetFillAmounts,
bytes[] calldata signatures,
bytes4 batchFillFunctionSelector,
uint256[] calldata ethFeeAmounts,
address payable[] calldata feeRecipients
)
external
payable
returns (LibFillResults.FillResults[] memory fillResults);
/// @dev The Broker implements the ERC1155 transfer function to be compatible with the ERC1155 asset proxy
/// @param from Since the Broker serves as the taker of the order, this should equal `address(this)`
/// @param to This should be the maker of the order.
/// @param amounts Should be an array of just one `uint256`, specifying the amount of the brokered assets to transfer.
/// @param data Encodes the validator contract address and any auxiliary data it needs for property validation.
function safeBatchTransferFrom(
address from,
address to,
uint256[] calldata /* ids */,
uint256[] calldata amounts,
bytes calldata data
)
external;
}

View File

@@ -0,0 +1,33 @@
/*
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.5.9;
pragma experimental ABIEncoderV2;
interface IGodsUnchained {
/// @dev Returns the proto and quality for a particular card given its token id
/// @param tokenId The id of the card to query.
/// @return proto The proto of the given card.
/// @return quality The quality of the given card
function getDetails(uint256 tokenId)
external
view
returns (uint16 proto, uint8 quality);
}

View File

@@ -0,0 +1,35 @@
/*
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.5.9;
pragma experimental ABIEncoderV2;
interface IPropertyValidator {
/// @dev Checks that the given asset data satisfies the properties encoded in `propertyData`.
/// Should revert if the asset does not satisfy the specified properties.
/// @param tokenId The ERC721 tokenId of the asset to check.
/// @param propertyData Encoded properties or auxiliary data needed to perform the check.
function checkBrokerAsset(
uint256 tokenId,
bytes calldata propertyData
)
external
view;
}

View File

@@ -0,0 +1,109 @@
/*
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.5.9;
library LibBrokerRichErrors {
// bytes4(keccak256("InvalidFromAddressError(address)"))
bytes4 internal constant INVALID_FROM_ADDRESS_ERROR_SELECTOR =
0x906bfb3c;
// bytes4(keccak256("AmountsLengthMustEqualOneError(uint256)"))
bytes4 internal constant AMOUNTS_LENGTH_MUST_EQUAL_ONE_ERROR_SELECTOR =
0xba9be200;
// bytes4(keccak256("TooFewBrokerAssetsProvidedError(uint256)"))
bytes4 internal constant TOO_FEW_BROKER_ASSETS_PROVIDED_ERROR_SELECTOR =
0x55272586;
// bytes4(keccak256("InvalidFunctionSelectorError(bytes4)"))
bytes4 internal constant INVALID_FUNCTION_SELECTOR_ERROR_SELECTOR =
0x540943f1;
// bytes4(keccak256("OnlyERC1155ProxyError(address)"))
bytes4 internal constant ONLY_ERC_1155_PROXY_ERROR_SELECTOR =
0xccc529af;
// solhint-disable func-name-mixedcase
function InvalidFromAddressError(
address from
)
internal
pure
returns (bytes memory)
{
return abi.encodeWithSelector(
INVALID_FROM_ADDRESS_ERROR_SELECTOR,
from
);
}
function AmountsLengthMustEqualOneError(
uint256 amountsLength
)
internal
pure
returns (bytes memory)
{
return abi.encodeWithSelector(
AMOUNTS_LENGTH_MUST_EQUAL_ONE_ERROR_SELECTOR,
amountsLength
);
}
function TooFewBrokerAssetsProvidedError(
uint256 numBrokeredAssets
)
internal
pure
returns (bytes memory)
{
return abi.encodeWithSelector(
TOO_FEW_BROKER_ASSETS_PROVIDED_ERROR_SELECTOR,
numBrokeredAssets
);
}
function InvalidFunctionSelectorError(
bytes4 selector
)
internal
pure
returns (bytes memory)
{
return abi.encodeWithSelector(
INVALID_FUNCTION_SELECTOR_ERROR_SELECTOR,
selector
);
}
function OnlyERC1155ProxyError(
address sender
)
internal
pure
returns (bytes memory)
{
return abi.encodeWithSelector(
ONLY_ERC_1155_PROXY_ERROR_SELECTOR,
sender
);
}
}

View File

@@ -0,0 +1,61 @@
/*
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.5.9;
pragma experimental ABIEncoderV2;
import "@0x/contracts-utils/contracts/src/LibBytes.sol";
import "../interfaces/IGodsUnchained.sol";
import "../interfaces/IPropertyValidator.sol";
contract GodsUnchainedValidator is
IPropertyValidator
{
IGodsUnchained internal GODS_UNCHAINED; // solhint-disable-line var-name-mixedcase
using LibBytes for bytes;
constructor(address _godsUnchained)
public
{
GODS_UNCHAINED = IGodsUnchained(_godsUnchained);
}
/// @dev Checks that the given card (encoded as assetData) has the proto and quality encoded in `propertyData`.
/// Reverts if the card doesn't match the specified proto and quality.
/// @param tokenId The ERC721 tokenId of the card to check.
/// @param propertyData Encoded proto and quality that the card is expected to have.
function checkBrokerAsset(
uint256 tokenId,
bytes calldata propertyData
)
external
view
{
(uint16 expectedProto, uint8 expectedQuality) = abi.decode(
propertyData,
(uint16, uint8)
);
// Validate card properties.
(uint16 proto, uint8 quality) = GODS_UNCHAINED.getDetails(tokenId);
require(proto == expectedProto, "GodsUnchainedValidator/PROTO_MISMATCH");
require(quality == expectedQuality, "GodsUnchainedValidator/QUALITY_MISMATCH");
}
}

View File

@@ -0,0 +1,55 @@
/*
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.5.9;
pragma experimental ABIEncoderV2;
import "@0x/contracts-erc721/contracts/test/DummyERC721Token.sol";
import "../src/interfaces/IGodsUnchained.sol";
contract TestGodsUnchained is
IGodsUnchained,
DummyERC721Token
{
mapping (uint256 => uint16) internal _protoByTokenId;
mapping (uint256 => uint8) internal _qualityByTokenId;
constructor (
string memory _name,
string memory _symbol
)
public
DummyERC721Token(_name, _symbol)
{} // solhint-disable-line no-empty-blocks
function setTokenProperties(uint256 tokenId, uint16 proto, uint8 quality)
external
{
_protoByTokenId[tokenId] = proto;
_qualityByTokenId[tokenId] = quality;
}
function getDetails(uint256 tokenId)
external
view
returns (uint16 proto, uint8 quality)
{
return (_protoByTokenId[tokenId], _qualityByTokenId[tokenId]);
}
}

View File

@@ -1,19 +1,19 @@
{
"name": "@0x/contracts-tests",
"private": true,
"version": "0.0.6",
"name": "@0x/contracts-broker",
"version": "1.1.5",
"engines": {
"node": ">=6.12"
},
"description": "Unit tests for 0x contracts",
"description": "Extension of 0x protocol for property-based orders",
"main": "lib/src/index.js",
"directories": {
"test": "test"
},
"scripts": {
"build": "tsc -b",
"build": "yarn build:contracts && yarn build:ts",
"build:contracts": "run-s compile contracts:gen generate_contract_wrappers contracts:copy",
"build:ts": "tsc -b",
"build:ci": "yarn build",
"pre_build": "run-s compile contracts:gen generate_contract_wrappers contracts:copy",
"test": "yarn run_mocha",
"rebuild_and_test": "run-s build test",
"test:coverage": "SOLIDITY_COVERAGE=true run-s build run_mocha coverage:report:text coverage:report:lcov",
@@ -23,9 +23,8 @@
"compile": "sol-compiler",
"watch": "sol-compiler -w",
"clean": "shx rm -rf lib test/generated-artifacts test/generated-wrappers generated-artifacts generated-wrappers",
"generate_contract_wrappers": "abi-gen --abis ${npm_package_config_abis} --output test/generated-wrappers --backend ethers",
"generate_contract_wrappers": "abi-gen --debug --abis ${npm_package_config_abis} --output test/generated-wrappers --backend ethers",
"lint": "tslint --format stylish --project . --exclude ./generated-wrappers/**/* --exclude ./test/generated-wrappers/**/* --exclude ./generated-artifacts/**/* --exclude ./test/generated-artifacts/**/* --exclude **/lib/**/* && yarn lint-contracts",
"fix": "tslint --fix --format stylish --project . --exclude ./generated-wrappers/**/* --exclude ./test/generated-wrappers/**/* --exclude ./generated-artifacts/**/* --exclude ./test/generated-artifacts/**/* --exclude **/lib/**/* && yarn lint-contracts",
"coverage:report:text": "istanbul report text",
"coverage:report:html": "istanbul report html && open coverage/index.html",
"profiler:report:html": "istanbul report html && open coverage/index.html",
@@ -34,11 +33,13 @@
"contracts:gen": "contracts-gen generate",
"contracts:copy": "contracts-gen copy",
"lint-contracts": "solhint -c ../.solhint.json contracts/**/**/**/**/*.sol",
"compile:truffle": "truffle compile"
"compile:truffle": "truffle compile",
"docs:md": "ts-doc-gen --sourceDir='$PROJECT_FILES' --output=$MD_FILE_DIR --fileExtension=mdx --tsconfig=./typedoc-tsconfig.json",
"docs:json": "typedoc --excludePrivate --excludeExternals --excludeProtected --ignoreCompilerErrors --target ES5 --tsconfig typedoc-tsconfig.json --json $JSON_FILE_PATH $PROJECT_FILES"
},
"config": {
"abis": "./generated-artifacts/@().json",
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually."
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually.",
"abis": "./test/generated-artifacts/@(Broker|GodsUnchainedValidator|IBroker|IGodsUnchained|IPropertyValidator|LibBrokerRichErrors|TestGodsUnchained).json"
},
"repository": {
"type": "git",
@@ -48,31 +49,30 @@
"bugs": {
"url": "https://github.com/0xProject/0x-monorepo/issues"
},
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/tests/README.md",
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/extensions/README.md",
"devDependencies": {
"@0x/abi-gen": "^5.0.0",
"@0x/base-contract": "^6.0.0",
"@0x/contracts-asset-proxy": "^3.0.0",
"@0x/contracts-dev-utils": "^1.0.0",
"@0x/contracts-erc1155": "^2.0.0",
"@0x/contracts-erc20": "^3.0.0",
"@0x/contracts-erc721": "^3.0.0",
"@0x/contracts-exchange": "^3.0.0",
"@0x/contracts-gen": "^2.0.0",
"@0x/contracts-test-utils": "^4.0.0",
"@0x/sol-compiler": "^4.0.0",
"@0x/abi-gen": "^5.3.0",
"@0x/contracts-asset-proxy": "^3.3.0",
"@0x/contracts-erc20": "^3.2.0",
"@0x/contracts-erc721": "^3.1.6",
"@0x/contracts-exchange": "^3.2.6",
"@0x/contracts-exchange-libs": "^4.3.6",
"@0x/contracts-gen": "^2.0.9",
"@0x/contracts-test-utils": "^5.3.3",
"@0x/contracts-utils": "^4.5.0",
"@0x/sol-compiler": "^4.1.0",
"@0x/ts-doc-gen": "^0.0.22",
"@0x/tslint-config": "^4.0.0",
"@0x/types": "^3.0.0",
"@0x/typescript-typings": "^5.0.0",
"@0x/utils": "^5.0.0",
"@0x/web3-wrapper": "^7.0.0",
"@0x/types": "^3.1.3",
"@0x/web3-wrapper": "^7.1.0",
"@types/lodash": "4.14.104",
"@types/mocha": "^5.2.7",
"@types/node": "*",
"chai": "^4.0.1",
"chai-as-promised": "^7.1.0",
"chai-bignumber": "^3.0.0",
"dirty-chai": "^2.0.1",
"ethereum-types": "^3.0.0",
"lodash": "^4.17.11",
"make-promises-safe": "^1.1.0",
"mocha": "^6.2.0",
"npm-run-all": "^4.1.2",
@@ -80,9 +80,17 @@
"solhint": "^1.4.1",
"truffle": "^5.0.32",
"tslint": "5.11.0",
"typedoc": "^0.15.0",
"typescript": "3.0.1"
},
"dependencies": {
"@0x/base-contract": "^6.2.2",
"@0x/order-utils": "^10.2.5",
"@0x/typescript-typings": "^5.1.0",
"@0x/utils": "^5.5.0",
"ethereum-types": "^3.1.1"
},
"publishConfig": {
"access": "private"
"access": "public"
}
}

View File

@@ -0,0 +1,23 @@
/*
* -----------------------------------------------------------------------------
* Warning: This file is auto-generated by contracts-gen. Don't edit manually.
* -----------------------------------------------------------------------------
*/
import { ContractArtifact } from 'ethereum-types';
import * as Broker from '../generated-artifacts/Broker.json';
import * as GodsUnchainedValidator from '../generated-artifacts/GodsUnchainedValidator.json';
import * as IBroker from '../generated-artifacts/IBroker.json';
import * as IGodsUnchained from '../generated-artifacts/IGodsUnchained.json';
import * as IPropertyValidator from '../generated-artifacts/IPropertyValidator.json';
import * as LibBrokerRichErrors from '../generated-artifacts/LibBrokerRichErrors.json';
import * as TestGodsUnchained from '../generated-artifacts/TestGodsUnchained.json';
export const artifacts = {
Broker: Broker as ContractArtifact,
IBroker: IBroker as ContractArtifact,
IGodsUnchained: IGodsUnchained as ContractArtifact,
IPropertyValidator: IPropertyValidator as ContractArtifact,
LibBrokerRichErrors: LibBrokerRichErrors as ContractArtifact,
GodsUnchainedValidator: GodsUnchainedValidator as ContractArtifact,
TestGodsUnchained: TestGodsUnchained as ContractArtifact,
};

View File

@@ -0,0 +1,59 @@
import { assetDataUtils } from '@0x/order-utils';
import { ERC1155AssetData } from '@0x/types';
import { AbiEncoder, BigNumber } from '@0x/utils';
export interface GodsUnchainedProperties {
proto: BigNumber | number;
quality: BigNumber | number;
}
const propertyDataEncoder = AbiEncoder.create([{ name: 'proto', type: 'uint16' }, { name: 'quality', type: 'uint8' }]);
const brokerDataEncoder = AbiEncoder.create([
{ name: 'godsUnchainedAddress', type: 'address' },
{ name: 'validatorAddress', type: 'address' },
{ name: 'propertyData', type: 'bytes' },
]);
/**
* Encodes the given proto and quality into the bytes format expected by the GodsUnchainedValidator.
*/
export function encodePropertyData(properties: GodsUnchainedProperties): string {
return propertyDataEncoder.encode(properties);
}
/**
* Encodes the given proto and quality into ERC1155 asset data to be used as the takerAssetData
* of a property-based GodsUnchained order. Must also provide the addresses of the Broker,
* GodsUnchained, and GodsUnchainedValidator contracts. The optional bundleSize parameter specifies
* how many cards are expected for each "unit" of the takerAssetAmount. For example, If the
* takerAssetAmount is 3 and the bundleSize is 2, the taker must provide 2, 4, or 6 cards
* with the given proto and quality to fill the order. If an odd number is provided, the fill fails.
*/
export function encodeBrokerAssetData(
brokerAddress: string,
godsUnchainedAddress: string,
validatorAddress: string,
properties: GodsUnchainedProperties,
bundleSize: number = 1,
): string {
const propertyData = propertyDataEncoder.encode(properties);
const brokerData = brokerDataEncoder.encode({ godsUnchainedAddress, validatorAddress, propertyData });
return assetDataUtils.encodeERC1155AssetData(brokerAddress, [], [new BigNumber(bundleSize)], brokerData);
}
/**
* Decodes proto and quality from the bytes format expected by the GodsUnchainedValidator.
*/
export function decodePropertyData(propertyData: string): GodsUnchainedProperties {
return propertyDataEncoder.decode(propertyData);
}
/**
* Decodes proto and quality from the ERC1155 takerAssetData of a property-based GodsUnchained order.
*/
export function decodeBrokerAssetData(brokerAssetData: string): GodsUnchainedProperties {
// tslint:disable-next-line:no-unnecessary-type-assertion
const { callbackData: brokerData } = assetDataUtils.decodeAssetDataOrThrow(brokerAssetData) as ERC1155AssetData;
const { propertyData } = brokerDataEncoder.decode(brokerData);
return decodePropertyData(propertyData);
}

View File

@@ -0,0 +1,32 @@
export { artifacts } from './artifacts';
export { BrokerContract, GodsUnchainedValidatorContract, TestGodsUnchainedContract } from './wrappers';
export * from './gods_unchained_utils';
export { BrokerRevertErrors } from '@0x/utils';
export {
ContractArtifact,
ContractChains,
CompilerOpts,
StandardContractOutput,
CompilerSettings,
ContractChainData,
ContractAbi,
DevdocOutput,
EvmOutput,
CompilerSettingsMetadata,
OptimizerSettings,
OutputField,
ParamDescription,
EvmBytecodeOutput,
AbiDefinition,
FunctionAbi,
EventAbi,
RevertErrorAbi,
EventParameter,
DataItem,
MethodAbi,
ConstructorAbi,
FallbackAbi,
ConstructorStateMutability,
TupleDataItem,
StateMutability,
} from 'ethereum-types';

View File

@@ -0,0 +1,12 @@
/*
* -----------------------------------------------------------------------------
* Warning: This file is auto-generated by contracts-gen. Don't edit manually.
* -----------------------------------------------------------------------------
*/
export * from '../generated-wrappers/broker';
export * from '../generated-wrappers/gods_unchained_validator';
export * from '../generated-wrappers/i_broker';
export * from '../generated-wrappers/i_gods_unchained';
export * from '../generated-wrappers/i_property_validator';
export * from '../generated-wrappers/lib_broker_rich_errors';
export * from '../generated-wrappers/test_gods_unchained';

View File

@@ -0,0 +1,23 @@
/*
* -----------------------------------------------------------------------------
* Warning: This file is auto-generated by contracts-gen. Don't edit manually.
* -----------------------------------------------------------------------------
*/
import { ContractArtifact } from 'ethereum-types';
import * as Broker from '../test/generated-artifacts/Broker.json';
import * as GodsUnchainedValidator from '../test/generated-artifacts/GodsUnchainedValidator.json';
import * as IBroker from '../test/generated-artifacts/IBroker.json';
import * as IGodsUnchained from '../test/generated-artifacts/IGodsUnchained.json';
import * as IPropertyValidator from '../test/generated-artifacts/IPropertyValidator.json';
import * as LibBrokerRichErrors from '../test/generated-artifacts/LibBrokerRichErrors.json';
import * as TestGodsUnchained from '../test/generated-artifacts/TestGodsUnchained.json';
export const artifacts = {
Broker: Broker as ContractArtifact,
IBroker: IBroker as ContractArtifact,
IGodsUnchained: IGodsUnchained as ContractArtifact,
IPropertyValidator: IPropertyValidator as ContractArtifact,
LibBrokerRichErrors: LibBrokerRichErrors as ContractArtifact,
GodsUnchainedValidator: GodsUnchainedValidator as ContractArtifact,
TestGodsUnchained: TestGodsUnchained as ContractArtifact,
};

View File

@@ -0,0 +1,56 @@
import { blockchainTests, constants, expect, getRandomInteger } from '@0x/contracts-test-utils';
import { BigNumber } from '@0x/utils';
import * as _ from 'lodash';
import { encodePropertyData } from '../src/gods_unchained_utils';
import { artifacts } from './artifacts';
import { GodsUnchainedValidatorContract, TestGodsUnchainedContract } from './wrappers';
blockchainTests.resets('GodsUnchainedValidator unit tests', env => {
let godsUnchained: TestGodsUnchainedContract;
let validator: GodsUnchainedValidatorContract;
before(async () => {
godsUnchained = await TestGodsUnchainedContract.deployFrom0xArtifactAsync(
artifacts.TestGodsUnchained,
env.provider,
env.txDefaults,
artifacts,
'Gods Unchained Cards',
'GU',
);
validator = await GodsUnchainedValidatorContract.deployFrom0xArtifactAsync(
artifacts.GodsUnchainedValidator,
env.provider,
env.txDefaults,
artifacts,
godsUnchained.address,
);
});
describe('checkBrokerAsset', () => {
const proto = new BigNumber(42);
const quality = new BigNumber(7);
const propertyData = encodePropertyData({ proto, quality });
it('succeeds if assetData proto and quality match propertyData', async () => {
const tokenId = getRandomInteger(0, constants.MAX_UINT256);
await godsUnchained.setTokenProperties(tokenId, proto, quality).awaitTransactionSuccessAsync();
await validator.checkBrokerAsset(tokenId, propertyData).callAsync();
});
it("reverts if assetData proto doesn't match propertyData", async () => {
const tokenId = getRandomInteger(0, constants.MAX_UINT256);
await godsUnchained.setTokenProperties(tokenId, proto.plus(1), quality).awaitTransactionSuccessAsync();
const tx = validator.checkBrokerAsset(tokenId, propertyData).callAsync();
expect(tx).to.revertWith('GodsUnchainedValidator/PROTO_MISMATCH');
});
it("reverts if assetData quality doesn't match proeprtyData", async () => {
const tokenId = getRandomInteger(0, constants.MAX_UINT256);
await godsUnchained.setTokenProperties(tokenId, proto, quality.plus(1)).awaitTransactionSuccessAsync();
const tx = validator.checkBrokerAsset(tokenId, propertyData).callAsync();
expect(tx).to.revertWith('GodsUnchainedValidator/QUALITY_MISMATCH');
});
});
});

View File

@@ -0,0 +1,12 @@
/*
* -----------------------------------------------------------------------------
* Warning: This file is auto-generated by contracts-gen. Don't edit manually.
* -----------------------------------------------------------------------------
*/
export * from '../test/generated-wrappers/broker';
export * from '../test/generated-wrappers/gods_unchained_validator';
export * from '../test/generated-wrappers/i_broker';
export * from '../test/generated-wrappers/i_gods_unchained';
export * from '../test/generated-wrappers/i_property_validator';
export * from '../test/generated-wrappers/lib_broker_rich_errors';
export * from '../test/generated-wrappers/test_gods_unchained';

View File

@@ -0,0 +1,96 @@
/**
* Use this file to configure your truffle project. It's seeded with some
* common settings for different networks and features like migrations,
* compilation and testing. Uncomment the ones you need or modify
* them to suit your project as necessary.
*
* More information about configuration can be found at:
*
* truffleframework.com/docs/advanced/configuration
*
* To deploy via Infura you'll need a wallet provider (like truffle-hdwallet-provider)
* to sign your transactions before they're sent to a remote public node. Infura accounts
* are available for free at: infura.io/register.
*
* You'll also need a mnemonic - the twelve word phrase the wallet uses to generate
* public/private key pairs. If you're publishing your code to GitHub make sure you load this
* phrase from a file you've .gitignored so it doesn't accidentally become public.
*
*/
// const HDWalletProvider = require('truffle-hdwallet-provider');
// const infuraKey = "fj4jll3k.....";
//
// const fs = require('fs');
// const mnemonic = fs.readFileSync(".secret").toString().trim();
module.exports = {
/**
* Networks define how you connect to your ethereum client and let you set the
* defaults web3 uses to send transactions. If you don't specify one truffle
* will spin up a development blockchain for you on port 9545 when you
* run `develop` or `test`. You can ask a truffle command to use a specific
* network from the command line, e.g
*
* $ truffle test --network <network-name>
*/
networks: {
// Useful for testing. The `development` name is special - truffle uses it by default
// if it's defined here and no other network is specified at the command line.
// You should run a client (like ganache-cli, geth or parity) in a separate terminal
// tab if you use this network and you must also set the `host`, `port` and `network_id`
// options below to some value.
//
// development: {
// host: "127.0.0.1", // Localhost (default: none)
// port: 8545, // Standard Ethereum port (default: none)
// network_id: "*", // Any network (default: none)
// },
// Another network with more advanced options...
// advanced: {
// port: 8777, // Custom port
// network_id: 1342, // Custom network
// gas: 8500000, // Gas sent with each transaction (default: ~6700000)
// gasPrice: 20000000000, // 20 gwei (in wei) (default: 100 gwei)
// from: <address>, // Account to send txs from (default: accounts[0])
// websockets: true // Enable EventEmitter interface for web3 (default: false)
// },
// Useful for deploying to a public network.
// NB: It's important to wrap the provider as a function.
// ropsten: {
// provider: () => new HDWalletProvider(mnemonic, `https://ropsten.infura.io/v3/YOUR-PROJECT-ID`),
// network_id: 3, // Ropsten's id
// gas: 5500000, // Ropsten has a lower block limit than mainnet
// confirmations: 2, // # of confs to wait between deployments. (default: 0)
// timeoutBlocks: 200, // # of blocks before a deployment times out (minimum/default: 50)
// skipDryRun: true // Skip dry run before migrations? (default: false for public nets )
// },
// Useful for private networks
// private: {
// provider: () => new HDWalletProvider(mnemonic, `https://network.io`),
// network_id: 2111, // This network is yours, in the cloud.
// production: true // Treats this network as if it was a public net. (default: false)
// }
},
// Set default mocha options here, use special reporters etc.
mocha: {
// timeout: 100000
},
// Configure your compilers
compilers: {
solc: {
version: '0.5.9',
settings: {
evmVersion: 'istanbul',
optimizer: {
enabled: true,
runs: 1000000,
details: { yul: true, deduplicate: true, cse: true, constantOptimizer: true },
},
},
},
},
};

View File

@@ -0,0 +1,22 @@
{
"extends": "../../tsconfig",
"compilerOptions": { "outDir": "lib", "rootDir": ".", "resolveJsonModule": true },
"include": ["./src/**/*", "./test/**/*", "./generated-wrappers/**/*"],
"files": [
"generated-artifacts/Broker.json",
"generated-artifacts/GodsUnchainedValidator.json",
"generated-artifacts/IBroker.json",
"generated-artifacts/IGodsUnchained.json",
"generated-artifacts/IPropertyValidator.json",
"generated-artifacts/LibBrokerRichErrors.json",
"generated-artifacts/TestGodsUnchained.json",
"test/generated-artifacts/Broker.json",
"test/generated-artifacts/GodsUnchainedValidator.json",
"test/generated-artifacts/IBroker.json",
"test/generated-artifacts/IGodsUnchained.json",
"test/generated-artifacts/IPropertyValidator.json",
"test/generated-artifacts/LibBrokerRichErrors.json",
"test/generated-artifacts/TestGodsUnchained.json"
],
"exclude": ["./deploy/solc/solc_bin"]
}

View File

@@ -0,0 +1,6 @@
{
"extends": ["@0x/tslint-config"],
"rules": {
"custom-no-magic-numbers": false
}
}

View File

@@ -0,0 +1,7 @@
{
"extends": "../../typedoc-tsconfig",
"compilerOptions": {
"outDir": "lib"
},
"include": ["./src/**/*", "./test/**/*"]
}

View File

@@ -1,4 +1,122 @@
[
{
"timestamp": 1592969527,
"version": "3.1.6",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1583220306,
"version": "3.1.5",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1582837861,
"version": "3.1.4",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1582677073,
"version": "3.1.3",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1582623685,
"version": "3.1.2",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1581748629,
"version": "3.1.1",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"version": "3.1.0",
"changes": [
{
"note": "Update tests.",
"pr": 2462
}
],
"timestamp": 1581204851
},
{
"timestamp": 1580988106,
"version": "3.0.6",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1580811564,
"version": "3.0.5",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1579682890,
"version": "3.0.4",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1578272714,
"version": "3.0.3",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1576540892,
"version": "3.0.2",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1575931811,
"version": "3.0.1",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"version": "3.0.0",
"changes": [

View File

@@ -5,6 +5,58 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v3.1.6 - _June 24, 2020_
* Dependencies updated
## v3.1.5 - _March 3, 2020_
* Dependencies updated
## v3.1.4 - _February 27, 2020_
* Dependencies updated
## v3.1.3 - _February 26, 2020_
* Dependencies updated
## v3.1.2 - _February 25, 2020_
* Dependencies updated
## v3.1.1 - _February 15, 2020_
* Dependencies updated
## v3.1.0 - _February 8, 2020_
* Update tests. (#2462)
## v3.0.6 - _February 6, 2020_
* Dependencies updated
## v3.0.5 - _February 4, 2020_
* Dependencies updated
## v3.0.4 - _January 22, 2020_
* Dependencies updated
## v3.0.3 - _January 6, 2020_
* Dependencies updated
## v3.0.2 - _December 17, 2019_
* Dependencies updated
## v3.0.1 - _December 9, 2019_
* Dependencies updated
## v3.0.0 - _December 2, 2019_
* Drastically reduced bundle size by adding .npmignore, only exporting specific artifacts/wrappers/utils (#2330)

View File

@@ -2,8 +2,9 @@
"artifactsDir": "./test/generated-artifacts",
"contractsDir": "./contracts",
"useDockerisedSolc": false,
"shouldSaveStandardInput": true,
"compilerSettings": {
"evmVersion": "constantinople",
"evmVersion": "istanbul",
"optimizer": {
"enabled": true,
"runs": 1000000,

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/contracts-coordinator",
"version": "3.0.0",
"version": "3.1.6",
"engines": {
"node": ">=6.12"
},
@@ -52,19 +52,19 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/extensions/README.md",
"devDependencies": {
"@0x/abi-gen": "^5.0.0",
"@0x/contracts-asset-proxy": "^3.0.0",
"@0x/contracts-dev-utils": "^1.0.0",
"@0x/contracts-erc20": "^3.0.0",
"@0x/contracts-exchange": "^3.0.0",
"@0x/contracts-gen": "^2.0.0",
"@0x/contracts-test-utils": "^4.0.0",
"@0x/dev-utils": "^3.0.0",
"@0x/order-utils": "^9.0.0",
"@0x/sol-compiler": "^4.0.0",
"@0x/abi-gen": "^5.3.0",
"@0x/contracts-asset-proxy": "^3.3.0",
"@0x/contracts-dev-utils": "^1.3.4",
"@0x/contracts-erc20": "^3.2.0",
"@0x/contracts-exchange": "^3.2.6",
"@0x/contracts-gen": "^2.0.9",
"@0x/contracts-test-utils": "^5.3.3",
"@0x/dev-utils": "^3.2.2",
"@0x/order-utils": "^10.2.5",
"@0x/sol-compiler": "^4.1.0",
"@0x/ts-doc-gen": "^0.0.22",
"@0x/tslint-config": "^4.0.0",
"@0x/web3-wrapper": "^7.0.0",
"@0x/web3-wrapper": "^7.1.0",
"@types/lodash": "4.14.104",
"@types/mocha": "^5.2.7",
"@types/node": "*",
@@ -84,15 +84,15 @@
"typescript": "3.0.1"
},
"dependencies": {
"@0x/assert": "^3.0.0",
"@0x/base-contract": "^6.0.0",
"@0x/contract-addresses": "^4.0.0",
"@0x/contracts-utils": "^4.0.0",
"@0x/json-schemas": "^5.0.0",
"@0x/types": "^3.0.0",
"@0x/typescript-typings": "^5.0.0",
"@0x/utils": "^5.0.0",
"ethereum-types": "^3.0.0",
"@0x/assert": "^3.0.8",
"@0x/base-contract": "^6.2.2",
"@0x/contract-addresses": "^4.10.0",
"@0x/contracts-utils": "^4.5.0",
"@0x/json-schemas": "^5.0.8",
"@0x/types": "^3.1.3",
"@0x/typescript-typings": "^5.1.0",
"@0x/utils": "^5.5.0",
"ethereum-types": "^3.1.1",
"http-status-codes": "^1.3.2"
},
"publishConfig": {

View File

@@ -1,5 +1,6 @@
import { hexConcat, signingUtils } from '@0x/contracts-test-utils';
import { signingUtils } from '@0x/contracts-test-utils';
import { SignatureType, SignedZeroExTransaction } from '@0x/types';
import { hexUtils } from '@0x/utils';
import { hashUtils } from './hash_utils';
import { SignedCoordinatorApproval } from './types';
@@ -13,21 +14,17 @@ export class ApprovalFactory {
this._verifyingContractAddress = verifyingContract;
}
public async newSignedApprovalAsync(
public newSignedApproval(
transaction: SignedZeroExTransaction,
txOrigin: string,
signatureType: SignatureType = SignatureType.EthSign,
): Promise<SignedCoordinatorApproval> {
const approvalHashBuff = await hashUtils.getApprovalHashBufferAsync(
transaction,
this._verifyingContractAddress,
txOrigin,
);
): SignedCoordinatorApproval {
const approvalHashBuff = hashUtils.getApprovalHashBuffer(transaction, this._verifyingContractAddress, txOrigin);
const signatureBuff = signingUtils.signMessage(approvalHashBuff, this._privateKey, signatureType);
const signedApproval = {
txOrigin,
transaction,
signature: hexConcat(signatureBuff),
signature: hexUtils.concat(signatureBuff),
};
return signedApproval;
}

View File

@@ -1,28 +1,15 @@
import { hexConcat } from '@0x/contracts-test-utils';
import { eip712Utils } from '@0x/order-utils';
import { SignedZeroExTransaction } from '@0x/types';
import { signTypedDataUtils } from '@0x/utils';
import { hexUtils, signTypedDataUtils } from '@0x/utils';
export const hashUtils = {
async getApprovalHashBufferAsync(
transaction: SignedZeroExTransaction,
verifyingContract: string,
txOrigin: string,
): Promise<Buffer> {
const typedData = await eip712Utils.createCoordinatorApprovalTypedDataAsync(
transaction,
verifyingContract,
txOrigin,
);
getApprovalHashBuffer(transaction: SignedZeroExTransaction, verifyingContract: string, txOrigin: string): Buffer {
const typedData = eip712Utils.createCoordinatorApprovalTypedData(transaction, verifyingContract, txOrigin);
const hashBuffer = signTypedDataUtils.generateTypedDataHash(typedData);
return hashBuffer;
},
async getApprovalHashHexAsync(
transaction: SignedZeroExTransaction,
verifyingContract: string,
txOrigin: string,
): Promise<string> {
const hashHex = hexConcat(await hashUtils.getApprovalHashBufferAsync(transaction, verifyingContract, txOrigin));
getApprovalHashHex(transaction: SignedZeroExTransaction, verifyingContract: string, txOrigin: string): string {
const hashHex = hexUtils.toHex(hashUtils.getApprovalHashBuffer(transaction, verifyingContract, txOrigin));
return hashHex;
},
};

View File

@@ -35,6 +35,7 @@ export {
OutputField,
ParamDescription,
EvmBytecodeOutput,
EvmBytecodeOutputLinkReferences,
AbiDefinition,
FunctionAbi,
EventAbi,

View File

@@ -44,11 +44,7 @@ blockchainTests.resets('Libs tests', env => {
transactionHash: transactionHashUtils.getTransactionHashHex(signedTx),
transactionSignature: signedTx.signature,
};
const expectedApprovalHash = await hashUtils.getApprovalHashHexAsync(
signedTx,
coordinatorContract.address,
txOrigin,
);
const expectedApprovalHash = hashUtils.getApprovalHashHex(signedTx, coordinatorContract.address, txOrigin);
const approvalHash = await coordinatorContract.getCoordinatorApprovalHash(approval).callAsync();
expect(expectedApprovalHash).to.eq(approvalHash);
});

View File

@@ -4,15 +4,13 @@ import {
constants,
ExchangeFunctionName,
expect,
hexConcat,
hexSlice,
randomAddress,
TransactionFactory,
transactionHashUtils,
} from '@0x/contracts-test-utils';
import { LibBytesRevertErrors } from '@0x/contracts-utils';
import { SignatureType, SignedOrder } from '@0x/types';
import { BigNumber, CoordinatorRevertErrors } from '@0x/utils';
import { BigNumber, CoordinatorRevertErrors, hexUtils } from '@0x/utils';
import { ApprovalFactory } from '../src/approval_factory';
@@ -89,8 +87,8 @@ blockchainTests.resets('Mixins tests', env => {
it('should revert with with the Illegal signature type', async () => {
const data = constants.NULL_BYTES;
const transaction = await transactionFactory.newSignedTransactionAsync({ data });
transaction.signature = hexConcat(
hexSlice(transaction.signature, 0, transaction.signature.length - 1),
transaction.signature = hexUtils.concat(
hexUtils.slice(transaction.signature, 0, transaction.signature.length - 1),
SignatureType.Illegal,
);
const transactionHash = transactionHashUtils.getTransactionHashHex(transaction);
@@ -105,7 +103,7 @@ blockchainTests.resets('Mixins tests', env => {
it('should revert with with the Invalid signature type', async () => {
const data = constants.NULL_BYTES;
const transaction = await transactionFactory.newSignedTransactionAsync({ data });
transaction.signature = hexConcat(SignatureType.Invalid);
transaction.signature = hexUtils.concat(SignatureType.Invalid);
const transactionHash = transactionHashUtils.getTransactionHashHex(transaction);
expect(mixins.getSignerAddress(transactionHash, transaction.signature).callAsync()).to.revertWith(
new CoordinatorRevertErrors.SignatureError(
@@ -118,8 +116,8 @@ blockchainTests.resets('Mixins tests', env => {
it('should revert with with a signature type that equals `NSignatureTypes`', async () => {
const data = constants.NULL_BYTES;
const transaction = await transactionFactory.newSignedTransactionAsync({ data });
transaction.signature = hexConcat(
hexSlice(transaction.signature, 0, transaction.signature.length - 1),
transaction.signature = hexUtils.concat(
hexUtils.slice(transaction.signature, 0, transaction.signature.length - 1),
SignatureType.NSignatureTypes,
);
const transactionHash = transactionHashUtils.getTransactionHashHex(transaction);
@@ -134,8 +132,8 @@ blockchainTests.resets('Mixins tests', env => {
it("should revert with with a signature type that isn't supported", async () => {
const data = constants.NULL_BYTES;
const transaction = await transactionFactory.newSignedTransactionAsync({ data });
transaction.signature = hexConcat(
hexSlice(transaction.signature, 0, transaction.signature.length - 1),
transaction.signature = hexUtils.concat(
hexUtils.slice(transaction.signature, 0, transaction.signature.length - 1),
SignatureType.Wallet,
);
const transactionHash = transactionHashUtils.getTransactionHashHex(transaction);
@@ -238,7 +236,7 @@ blockchainTests.resets('Mixins tests', env => {
const orders = [defaultOrder];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const transaction = await transactionFactory.newSignedTransactionAsync({ data });
const approval = await approvalFactory1.newSignedApprovalAsync(transaction, transactionSignerAddress);
const approval = approvalFactory1.newSignedApproval(transaction, transactionSignerAddress);
await mixins
.assertValidCoordinatorApprovals(transaction, transactionSignerAddress, transaction.signature, [
approval.signature,
@@ -253,7 +251,7 @@ blockchainTests.resets('Mixins tests', env => {
const orders = [order];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const transaction = await transactionFactory.newSignedTransactionAsync({ data });
const approval = await approvalFactory1.newSignedApprovalAsync(transaction, transactionSignerAddress);
const approval = approvalFactory1.newSignedApproval(transaction, transactionSignerAddress);
await mixins
.assertValidCoordinatorApprovals(transaction, transactionSignerAddress, transaction.signature, [
approval.signature,
@@ -274,7 +272,7 @@ blockchainTests.resets('Mixins tests', env => {
const orders = [defaultOrder];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const transaction = await transactionFactory.newSignedTransactionAsync({ data });
const approval = await approvalFactory1.newSignedApprovalAsync(transaction, transactionSignerAddress);
const approval = approvalFactory1.newSignedApproval(transaction, transactionSignerAddress);
await mixins
.assertValidCoordinatorApprovals(transaction, approvalSignerAddress1, transaction.signature, [
approval.signature,
@@ -295,11 +293,11 @@ blockchainTests.resets('Mixins tests', env => {
const orders = [defaultOrder];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const transaction = await transactionFactory.newSignedTransactionAsync({ data });
const approval = await approvalFactory1.newSignedApprovalAsync(transaction, transactionSignerAddress);
const signature = hexConcat(
hexSlice(approval.signature, 0, 2),
const approval = approvalFactory1.newSignedApproval(transaction, transactionSignerAddress);
const signature = hexUtils.concat(
hexUtils.slice(approval.signature, 0, 2),
'0xFFFFFFFF',
hexSlice(approval.signature, 6),
hexUtils.slice(approval.signature, 6),
);
const tx = mixins
.assertValidCoordinatorApprovals(transaction, transactionSignerAddress, transaction.signature, [
@@ -316,7 +314,7 @@ blockchainTests.resets('Mixins tests', env => {
const orders = [defaultOrder];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const transaction = await transactionFactory.newSignedTransactionAsync({ data });
const approval = await approvalFactory1.newSignedApprovalAsync(transaction, transactionSignerAddress);
const approval = approvalFactory1.newSignedApproval(transaction, transactionSignerAddress);
const tx = mixins
.assertValidCoordinatorApprovals(transaction, transactionSignerAddress, transaction.signature, [
@@ -337,7 +335,7 @@ blockchainTests.resets('Mixins tests', env => {
const orders = [defaultOrder, defaultOrder];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const transaction = await transactionFactory.newSignedTransactionAsync({ data });
const approval = await approvalFactory1.newSignedApprovalAsync(transaction, transactionSignerAddress);
const approval = approvalFactory1.newSignedApproval(transaction, transactionSignerAddress);
await mixins
.assertValidCoordinatorApprovals(transaction, transactionSignerAddress, transaction.signature, [
approval.signature,
@@ -351,7 +349,7 @@ blockchainTests.resets('Mixins tests', env => {
}));
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const transaction = await transactionFactory.newSignedTransactionAsync({ data });
const approval = await approvalFactory1.newSignedApprovalAsync(transaction, transactionSignerAddress);
const approval = approvalFactory1.newSignedApproval(transaction, transactionSignerAddress);
await mixins
.assertValidCoordinatorApprovals(transaction, transactionSignerAddress, transaction.signature, [
approval.signature,
@@ -373,7 +371,7 @@ blockchainTests.resets('Mixins tests', env => {
const orders = [defaultOrder, { ...defaultOrder, senderAddress: constants.NULL_ADDRESS }];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const transaction = await transactionFactory.newSignedTransactionAsync({ data });
const approval = await approvalFactory1.newSignedApprovalAsync(transaction, transactionSignerAddress);
const approval = approvalFactory1.newSignedApproval(transaction, transactionSignerAddress);
await mixins
.assertValidCoordinatorApprovals(transaction, transactionSignerAddress, transaction.signature, [
approval.signature,
@@ -384,8 +382,8 @@ blockchainTests.resets('Mixins tests', env => {
const orders = [defaultOrder, { ...defaultOrder, feeRecipientAddress: approvalSignerAddress2 }];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const transaction = await transactionFactory.newSignedTransactionAsync({ data });
const approval1 = await approvalFactory1.newSignedApprovalAsync(transaction, transactionSignerAddress);
const approval2 = await approvalFactory2.newSignedApprovalAsync(transaction, transactionSignerAddress);
const approval1 = approvalFactory1.newSignedApproval(transaction, transactionSignerAddress);
const approval2 = approvalFactory2.newSignedApproval(transaction, transactionSignerAddress);
await mixins
.assertValidCoordinatorApprovals(transaction, transactionSignerAddress, transaction.signature, [
approval1.signature,
@@ -405,7 +403,7 @@ blockchainTests.resets('Mixins tests', env => {
const orders = [defaultOrder, { ...defaultOrder, feeRecipientAddress: approvalSignerAddress2 }];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const transaction = await transactionFactory.newSignedTransactionAsync({ data });
const approval2 = await approvalFactory2.newSignedApprovalAsync(transaction, transactionSignerAddress);
const approval2 = approvalFactory2.newSignedApproval(transaction, transactionSignerAddress);
const tx = mixins
.assertValidCoordinatorApprovals(transaction, transactionSignerAddress, transaction.signature, [
@@ -431,11 +429,11 @@ blockchainTests.resets('Mixins tests', env => {
const orders = [defaultOrder, defaultOrder];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const transaction = await transactionFactory.newSignedTransactionAsync({ data });
const approval = await approvalFactory1.newSignedApprovalAsync(transaction, transactionSignerAddress);
const signature = hexConcat(
hexSlice(approval.signature, 0, 2),
const approval = approvalFactory1.newSignedApproval(transaction, transactionSignerAddress);
const signature = hexUtils.concat(
hexUtils.slice(approval.signature, 0, 2),
'0xFFFFFFFF',
hexSlice(approval.signature, 6),
hexUtils.slice(approval.signature, 6),
);
const tx = mixins
.assertValidCoordinatorApprovals(transaction, transactionSignerAddress, transaction.signature, [
@@ -452,12 +450,12 @@ blockchainTests.resets('Mixins tests', env => {
const orders = [defaultOrder, { ...defaultOrder, feeRecipientAddress: approvalSignerAddress2 }];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const transaction = await transactionFactory.newSignedTransactionAsync({ data });
const approval1 = await approvalFactory1.newSignedApprovalAsync(transaction, transactionSignerAddress);
const approval2 = await approvalFactory2.newSignedApprovalAsync(transaction, transactionSignerAddress);
const approvalSignature2 = hexConcat(
hexSlice(approval2.signature, 0, 2),
const approval1 = approvalFactory1.newSignedApproval(transaction, transactionSignerAddress);
const approval2 = approvalFactory2.newSignedApproval(transaction, transactionSignerAddress);
const approvalSignature2 = hexUtils.concat(
hexUtils.slice(approval2.signature, 0, 2),
'0xFFFFFFFF',
hexSlice(approval2.signature, 6),
hexUtils.slice(approval2.signature, 6),
);
const tx = mixins
.assertValidCoordinatorApprovals(transaction, transactionSignerAddress, transaction.signature, [
@@ -475,11 +473,11 @@ blockchainTests.resets('Mixins tests', env => {
const orders = [defaultOrder, { ...defaultOrder, feeRecipientAddress: approvalSignerAddress2 }];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const transaction = await transactionFactory.newSignedTransactionAsync({ data });
const approval2 = await approvalFactory2.newSignedApprovalAsync(transaction, transactionSignerAddress);
const approvalSignature2 = hexConcat(
hexSlice(approval2.signature, 0, 2),
const approval2 = approvalFactory2.newSignedApproval(transaction, transactionSignerAddress);
const approvalSignature2 = hexUtils.concat(
hexUtils.slice(approval2.signature, 0, 2),
'0xFFFFFFFF',
hexSlice(approval2.signature, 6),
hexUtils.slice(approval2.signature, 6),
);
const tx = mixins
.assertValidCoordinatorApprovals(transaction, approvalSignerAddress1, transaction.signature, [
@@ -496,7 +494,7 @@ blockchainTests.resets('Mixins tests', env => {
const orders = [defaultOrder, defaultOrder];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const transaction = await transactionFactory.newSignedTransactionAsync({ data });
const approval1 = await approvalFactory1.newSignedApprovalAsync(transaction, transactionSignerAddress);
const approval1 = approvalFactory1.newSignedApproval(transaction, transactionSignerAddress);
const tx = mixins
.assertValidCoordinatorApprovals(transaction, transactionSignerAddress, transaction.signature, [

View File

@@ -84,7 +84,7 @@ module.exports = {
solc: {
version: '0.5.9',
settings: {
evmVersion: 'constantinople',
evmVersion: 'istanbul',
optimizer: {
enabled: true,
runs: 1000000,

View File

@@ -1,4 +1,137 @@
[
{
"timestamp": 1592969527,
"version": "1.3.4",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1583220306,
"version": "1.3.3",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1582837861,
"version": "1.3.2",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1582677073,
"version": "1.3.1",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"version": "1.3.0",
"changes": [
{
"note": "Update `DevUtils` addresses in `DeploymentConstants`",
"pr": 2493
}
],
"timestamp": 1582623685
},
{
"version": "1.2.0",
"changes": [
{
"note": "Add `DydxBridge` order validation",
"pr": 2466
}
]
},
{
"timestamp": 1581748629,
"version": "1.1.1",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"version": "1.1.0",
"changes": [
{
"note": "Refactor mixins into public libraries.",
"pr": 2464
},
{
"note": "Remove `LibTransactionDecoder` export",
"pr": 2464
}
],
"timestamp": 1581204851
},
{
"timestamp": 1580988106,
"version": "1.0.6",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1580811564,
"version": "1.0.5",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1579682890,
"version": "1.0.4",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"version": "1.0.3",
"changes": [
{
"note": "Fixed ERC721 duplicate token ID bug",
"pr": 2400
}
],
"timestamp": 1578272714
},
{
"timestamp": 1576540892,
"version": "1.0.2",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1575931811,
"version": "1.0.1",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"version": "1.0.0",
"changes": [

View File

@@ -5,6 +5,63 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v1.3.4 - _June 24, 2020_
* Dependencies updated
## v1.3.3 - _March 3, 2020_
* Dependencies updated
## v1.3.2 - _February 27, 2020_
* Dependencies updated
## v1.3.1 - _February 26, 2020_
* Dependencies updated
## v1.3.0 - _February 25, 2020_
* Update `DevUtils` addresses in `DeploymentConstants` (#2493)
## v1.2.0 - _Invalid date_
* Add `DydxBridge` order validation (#2466)
## v1.1.1 - _February 15, 2020_
* Dependencies updated
## v1.1.0 - _February 8, 2020_
* Refactor mixins into public libraries. (#2464)
* Remove `LibTransactionDecoder` export (#2464)
## v1.0.6 - _February 6, 2020_
* Dependencies updated
## v1.0.5 - _February 4, 2020_
* Dependencies updated
## v1.0.4 - _January 22, 2020_
* Dependencies updated
## v1.0.3 - _January 6, 2020_
* Fixed ERC721 duplicate token ID bug (#2400)
## v1.0.2 - _December 17, 2019_
* Dependencies updated
## v1.0.1 - _December 9, 2019_
* Dependencies updated
## v1.0.0 - _December 2, 2019_
* Drastically reduced bundle size by adding .npmignore, only exporting specific artifacts/wrappers/utils (#2330)

View File

@@ -41,13 +41,13 @@ yarn install
To build this package and all other monorepo packages that it depends on, run the following from the monorepo root directory:
```bash
PKG=@0x/contracts-extensions yarn build
PKG=@0x/contracts-dev-utils yarn build
```
Or continuously rebuild on change:
```bash
PKG=@0x/contracts-extensions yarn watch
PKG=@0x/contracts-dev-utils yarn watch
```
### Clean

View File

@@ -3,11 +3,12 @@
"contractsDir": "./contracts",
"useDockerisedSolc": false,
"isOfflineMode": false,
"shouldSaveStandardInput": true,
"compilerSettings": {
"evmVersion": "constantinople",
"evmVersion": "istanbul",
"optimizer": {
"enabled": true,
"runs": 1666,
"runs": 5000,
"details": { "yul": true, "deduplicate": true, "cse": true, "constantOptimizer": true }
},
"outputSelection": {

View File

@@ -0,0 +1,54 @@
/*
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.5.16;
pragma experimental ABIEncoderV2;
import "@0x/contracts-asset-proxy/contracts/src/interfaces/IAssetData.sol";
import "@0x/contracts-exchange/contracts/src/interfaces/IExchange.sol";
import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol";
// solhint-disable no-empty-blocks
contract Addresses is
DeploymentConstants
{
address public exchangeAddress;
address public erc20ProxyAddress;
address public erc721ProxyAddress;
address public erc1155ProxyAddress;
address public staticCallProxyAddress;
address public chaiBridgeAddress;
address public dydxBridgeAddress;
constructor (
address exchange_,
address chaiBridge_,
address dydxBridge_
)
public
{
exchangeAddress = exchange_;
chaiBridgeAddress = chaiBridge_;
dydxBridgeAddress = dydxBridge_;
erc20ProxyAddress = IExchange(exchange_).getAssetProxy(IAssetData(address(0)).ERC20Token.selector);
erc721ProxyAddress = IExchange(exchange_).getAssetProxy(IAssetData(address(0)).ERC721Token.selector);
erc1155ProxyAddress = IExchange(exchange_).getAssetProxy(IAssetData(address(0)).ERC1155Assets.selector);
staticCallProxyAddress = IExchange(exchange_).getAssetProxy(IAssetData(address(0)).StaticCall.selector);
}
}

View File

@@ -0,0 +1,388 @@
/*
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.5.16;
pragma experimental ABIEncoderV2;
import "@0x/contracts-utils/contracts/src/LibBytes.sol";
import "@0x/contracts-asset-proxy/contracts/src/interfaces/IAssetData.sol";
import "@0x/contracts-asset-proxy/contracts/src/interfaces/IAssetProxy.sol";
import "@0x/contracts-erc20/contracts/src/LibERC20Token.sol";
import "@0x/contracts-erc721/contracts/src/interfaces/IERC721Token.sol";
import "@0x/contracts-erc1155/contracts/src/interfaces/IERC1155.sol";
import "@0x/contracts-asset-proxy/contracts/src/interfaces/IChai.sol";
import "@0x/contracts-exchange-libs/contracts/src/LibMath.sol";
import "./Addresses.sol";
import "./LibDydxBalance.sol";
contract AssetBalance is
Addresses
{
// 2^256 - 1
uint256 constant internal _MAX_UINT256 = uint256(-1);
using LibBytes for bytes;
/// @dev Returns the owner's balance of the assets(s) specified in
/// assetData. When the asset data contains multiple assets (eg in
/// ERC1155 or Multi-Asset), the return value indicates how many
/// complete "baskets" of those assets are owned by owner.
/// @param ownerAddress Owner of the assets specified by assetData.
/// @param assetData Details of asset, encoded per the AssetProxy contract specification.
/// @return Number of assets (or asset baskets) held by owner.
function getBalance(address ownerAddress, bytes memory assetData)
public
returns (uint256 balance)
{
// Get id of AssetProxy contract
bytes4 assetProxyId = assetData.readBytes4(0);
if (assetProxyId == IAssetData(address(0)).ERC20Token.selector) {
// Get ERC20 token address
address tokenAddress = assetData.readAddress(16);
balance = LibERC20Token.balanceOf(tokenAddress, ownerAddress);
} else if (assetProxyId == IAssetData(address(0)).ERC721Token.selector) {
// Get ERC721 token address and id
(, address tokenAddress, uint256 tokenId) = LibAssetData.decodeERC721AssetData(assetData);
// Check if id is owned by ownerAddress
bytes memory ownerOfCalldata = abi.encodeWithSelector(
IERC721Token(address(0)).ownerOf.selector,
tokenId
);
(bool success, bytes memory returnData) = tokenAddress.staticcall(ownerOfCalldata);
address currentOwnerAddress = (success && returnData.length == 32) ? returnData.readAddress(12) : address(0);
balance = currentOwnerAddress == ownerAddress ? 1 : 0;
} else if (assetProxyId == IAssetData(address(0)).ERC1155Assets.selector) {
// Get ERC1155 token address, array of ids, and array of values
(, address tokenAddress, uint256[] memory tokenIds, uint256[] memory tokenValues,) = LibAssetData.decodeERC1155AssetData(assetData);
uint256 length = tokenIds.length;
for (uint256 i = 0; i != length; i++) {
// Skip over the token if the corresponding value is 0.
if (tokenValues[i] == 0) {
continue;
}
// Encode data for `balanceOf(ownerAddress, tokenIds[i])
bytes memory balanceOfData = abi.encodeWithSelector(
IERC1155(address(0)).balanceOf.selector,
ownerAddress,
tokenIds[i]
);
// Query balance
(bool success, bytes memory returnData) = tokenAddress.staticcall(balanceOfData);
uint256 totalBalance = success && returnData.length == 32 ? returnData.readUint256(0) : 0;
// Scale total balance down by corresponding value in assetData
uint256 scaledBalance = totalBalance / tokenValues[i];
if (scaledBalance == 0) {
return 0;
}
if (scaledBalance < balance || balance == 0) {
balance = scaledBalance;
}
}
} else if (assetProxyId == IAssetData(address(0)).StaticCall.selector) {
// Encode data for `staticCallProxy.transferFrom(assetData,...)`
bytes memory transferFromData = abi.encodeWithSelector(
IAssetProxy(address(0)).transferFrom.selector,
assetData,
address(0), // `from` address is not used
address(0), // `to` address is not used
0 // `amount` is not used
);
// Check if staticcall would be successful
(bool success,) = staticCallProxyAddress.staticcall(transferFromData);
// Success means that the staticcall can be made an unlimited amount of times
balance = success ? _MAX_UINT256 : 0;
} else if (assetProxyId == IAssetData(address(0)).ERC20Bridge.selector) {
// Get address of ERC20 token and bridge contract
(, address tokenAddress, address bridgeAddress, ) = LibAssetData.decodeERC20BridgeAssetData(assetData);
if (tokenAddress == _getDaiAddress() && bridgeAddress == chaiBridgeAddress) {
uint256 chaiBalance = LibERC20Token.balanceOf(_getChaiAddress(), ownerAddress);
// Calculate Dai balance
balance = _convertChaiToDaiAmount(chaiBalance);
}
// Balance will be 0 if bridge is not supported
} else if (assetProxyId == IAssetData(address(0)).MultiAsset.selector) {
// Get array of values and array of assetDatas
(, uint256[] memory assetAmounts, bytes[] memory nestedAssetData) = LibAssetData.decodeMultiAssetData(assetData);
uint256 length = nestedAssetData.length;
for (uint256 i = 0; i != length; i++) {
// Skip over the asset if the corresponding amount is 0.
if (assetAmounts[i] == 0) {
continue;
}
// Query balance of individual assetData
uint256 totalBalance = getBalance(ownerAddress, nestedAssetData[i]);
// Scale total balance down by corresponding value in assetData
uint256 scaledBalance = totalBalance / assetAmounts[i];
if (scaledBalance == 0) {
return 0;
}
if (scaledBalance < balance || balance == 0) {
balance = scaledBalance;
}
}
}
// Balance will be 0 if assetProxyId is unknown
return balance;
}
/// @dev Calls getBalance() for each element of assetData.
/// @param ownerAddress Owner of the assets specified by assetData.
/// @param assetData Array of asset details, each encoded per the AssetProxy contract specification.
/// @return Array of asset balances from getBalance(), with each element
/// corresponding to the same-indexed element in the assetData input.
function getBatchBalances(address ownerAddress, bytes[] memory assetData)
public
returns (uint256[] memory balances)
{
uint256 length = assetData.length;
balances = new uint256[](length);
for (uint256 i = 0; i != length; i++) {
balances[i] = getBalance(ownerAddress, assetData[i]);
}
return balances;
}
/// @dev Returns the number of asset(s) (described by assetData) that
/// the corresponding AssetProxy contract is authorized to spend. When the asset data contains
/// multiple assets (eg for Multi-Asset), the return value indicates
/// how many complete "baskets" of those assets may be spent by all of the corresponding
/// AssetProxy contracts.
/// @param ownerAddress Owner of the assets specified by assetData.
/// @param assetData Details of asset, encoded per the AssetProxy contract specification.
/// @return Number of assets (or asset baskets) that the corresponding AssetProxy is authorized to spend.
function getAssetProxyAllowance(address ownerAddress, bytes memory assetData)
public
returns (uint256 allowance)
{
// Get id of AssetProxy contract
bytes4 assetProxyId = assetData.readBytes4(0);
if (assetProxyId == IAssetData(address(0)).MultiAsset.selector) {
// Get array of values and array of assetDatas
(, uint256[] memory amounts, bytes[] memory nestedAssetData) = LibAssetData.decodeMultiAssetData(assetData);
uint256 length = nestedAssetData.length;
for (uint256 i = 0; i != length; i++) {
// Skip over the asset if the corresponding amount is 0.
if (amounts[i] == 0) {
continue;
}
// Query allowance of individual assetData
uint256 totalAllowance = getAssetProxyAllowance(ownerAddress, nestedAssetData[i]);
// Scale total allowance down by corresponding value in assetData
uint256 scaledAllowance = totalAllowance / amounts[i];
if (scaledAllowance == 0) {
return 0;
}
if (scaledAllowance < allowance || allowance == 0) {
allowance = scaledAllowance;
}
}
return allowance;
}
if (assetProxyId == IAssetData(address(0)).ERC20Token.selector) {
// Get ERC20 token address
address tokenAddress = assetData.readAddress(16);
allowance = LibERC20Token.allowance(tokenAddress, ownerAddress, erc20ProxyAddress);
} else if (assetProxyId == IAssetData(address(0)).ERC721Token.selector) {
// Get ERC721 token address and id
(, address tokenAddress, uint256 tokenId) = LibAssetData.decodeERC721AssetData(assetData);
// Encode data for `isApprovedForAll(ownerAddress, erc721ProxyAddress)`
bytes memory isApprovedForAllData = abi.encodeWithSelector(
IERC721Token(address(0)).isApprovedForAll.selector,
ownerAddress,
erc721ProxyAddress
);
(bool success, bytes memory returnData) = tokenAddress.staticcall(isApprovedForAllData);
// If not approved for all, call `getApproved(tokenId)`
if (!success || returnData.length != 32 || returnData.readUint256(0) != 1) {
// Encode data for `getApproved(tokenId)`
bytes memory getApprovedData = abi.encodeWithSelector(IERC721Token(address(0)).getApproved.selector, tokenId);
(success, returnData) = tokenAddress.staticcall(getApprovedData);
// Allowance is 1 if successful and the approved address is the ERC721Proxy
allowance = success && returnData.length == 32 && returnData.readAddress(12) == erc721ProxyAddress ? 1 : 0;
} else {
// Allowance is 2^256 - 1 if `isApprovedForAll` returned true
allowance = _MAX_UINT256;
}
} else if (assetProxyId == IAssetData(address(0)).ERC1155Assets.selector) {
// Get ERC1155 token address
(, address tokenAddress, , , ) = LibAssetData.decodeERC1155AssetData(assetData);
// Encode data for `isApprovedForAll(ownerAddress, erc1155ProxyAddress)`
bytes memory isApprovedForAllData = abi.encodeWithSelector(
IERC1155(address(0)).isApprovedForAll.selector,
ownerAddress,
erc1155ProxyAddress
);
// Query allowance
(bool success, bytes memory returnData) = tokenAddress.staticcall(isApprovedForAllData);
allowance = success && returnData.length == 32 && returnData.readUint256(0) == 1 ? _MAX_UINT256 : 0;
} else if (assetProxyId == IAssetData(address(0)).StaticCall.selector) {
// The StaticCallProxy does not require any approvals
allowance = _MAX_UINT256;
} else if (assetProxyId == IAssetData(address(0)).ERC20Bridge.selector) {
// Get address of ERC20 token and bridge contract
(, address tokenAddress, address bridgeAddress,) =
LibAssetData.decodeERC20BridgeAssetData(assetData);
if (tokenAddress == _getDaiAddress() && bridgeAddress == chaiBridgeAddress) {
uint256 chaiAllowance = LibERC20Token.allowance(_getChaiAddress(), ownerAddress, chaiBridgeAddress);
// Dai allowance is unlimited if Chai allowance is unlimited
allowance = chaiAllowance == _MAX_UINT256 ? _MAX_UINT256 : _convertChaiToDaiAmount(chaiAllowance);
} else if (bridgeAddress == dydxBridgeAddress) {
allowance = LibDydxBalance.getDydxMakerAllowance(ownerAddress, bridgeAddress, _getDydxAddress());
}
// Allowance will be 0 if bridge is not supported
}
// Allowance will be 0 if the assetProxyId is unknown
return allowance;
}
/// @dev Calls getAssetProxyAllowance() for each element of assetData.
/// @param ownerAddress Owner of the assets specified by assetData.
/// @param assetData Array of asset details, each encoded per the AssetProxy contract specification.
/// @return An array of asset allowances from getAllowance(), with each
/// element corresponding to the same-indexed element in the assetData input.
function getBatchAssetProxyAllowances(address ownerAddress, bytes[] memory assetData)
public
returns (uint256[] memory allowances)
{
uint256 length = assetData.length;
allowances = new uint256[](length);
for (uint256 i = 0; i != length; i++) {
allowances[i] = getAssetProxyAllowance(ownerAddress, assetData[i]);
}
return allowances;
}
/// @dev Calls getBalance() and getAllowance() for assetData.
/// @param ownerAddress Owner of the assets specified by assetData.
/// @param assetData Details of asset, encoded per the AssetProxy contract specification.
/// @return Number of assets (or asset baskets) held by owner, and number
/// of assets (or asset baskets) that the corresponding AssetProxy is authorized to spend.
function getBalanceAndAssetProxyAllowance(
address ownerAddress,
bytes memory assetData
)
public
returns (uint256 balance, uint256 allowance)
{
balance = getBalance(ownerAddress, assetData);
allowance = getAssetProxyAllowance(ownerAddress, assetData);
return (balance, allowance);
}
/// @dev Calls getBatchBalances() and getBatchAllowances() for each element of assetData.
/// @param ownerAddress Owner of the assets specified by assetData.
/// @param assetData Array of asset details, each encoded per the AssetProxy contract specification.
/// @return An array of asset balances from getBalance(), and an array of
/// asset allowances from getAllowance(), with each element
/// corresponding to the same-indexed element in the assetData input.
function getBatchBalancesAndAssetProxyAllowances(
address ownerAddress,
bytes[] memory assetData
)
public
returns (uint256[] memory balances, uint256[] memory allowances)
{
balances = getBatchBalances(ownerAddress, assetData);
allowances = getBatchAssetProxyAllowances(ownerAddress, assetData);
return (balances, allowances);
}
/// @dev Converts an amount of Chai into its equivalent Dai amount.
/// Also accumulates Dai from DSR if called after the last time it was collected.
/// @param chaiAmount Amount of Chai to converts.
function _convertChaiToDaiAmount(uint256 chaiAmount)
internal
returns (uint256 daiAmount)
{
PotLike pot = IChai(_getChaiAddress()).pot();
// Accumulate savings if called after last time savings were collected
// solhint-disable-next-line not-rely-on-time
uint256 chiMultiplier = (now > pot.rho())
? pot.drip()
: pot.chi();
daiAmount = LibMath.getPartialAmountFloor(chiMultiplier, 10**27, chaiAmount);
return daiAmount;
}
/// @dev Returns an order MAKER's balance of the assets(s) specified in
/// makerAssetData. Unlike `getBalanceAndAssetProxyAllowance()`, this
/// can handle maker asset types that depend on taker tokens being
/// transferred to the maker first.
/// @param order The order.
/// @return balance Quantity of assets transferrable from maker to taker.
function _getConvertibleMakerBalanceAndAssetProxyAllowance(
LibOrder.Order memory order
)
internal
returns (uint256 balance, uint256 allowance)
{
if (order.makerAssetData.length < 4) {
return (0, 0);
}
bytes4 assetProxyId = order.makerAssetData.readBytes4(0);
// Handle dydx bridge assets.
if (assetProxyId == IAssetData(address(0)).ERC20Bridge.selector) {
(, , address bridgeAddress, ) = LibAssetData.decodeERC20BridgeAssetData(order.makerAssetData);
if (bridgeAddress == dydxBridgeAddress) {
return (
LibDydxBalance.getDydxMakerBalance(order, _getDydxAddress()),
getAssetProxyAllowance(order.makerAddress, order.makerAssetData)
);
}
}
return (
getBalance(order.makerAddress, order.makerAssetData),
getAssetProxyAllowance(order.makerAddress, order.makerAssetData)
);
}
}

View File

@@ -16,7 +16,7 @@
*/
pragma solidity ^0.5.5;
pragma solidity ^0.5.16;
pragma experimental ABIEncoderV2;
import "@0x/contracts-exchange-libs/contracts/src/LibEIP712ExchangeDomain.sol";
@@ -24,28 +24,39 @@ import "@0x/contracts-exchange-libs/contracts/src/LibOrder.sol";
import "@0x/contracts-exchange-libs/contracts/src/LibZeroExTransaction.sol";
import "@0x/contracts-utils/contracts/src/LibEIP712.sol";
import "@0x/contracts-utils/contracts/src/LibBytes.sol";
import "./Addresses.sol";
import "./OrderValidationUtils.sol";
import "./OrderTransferSimulationUtils.sol";
import "./LibTransactionDecoder.sol";
import "./EthBalanceChecker.sol";
import "./ExternalFunctions.sol";
// solhint-disable no-empty-blocks
contract DevUtils is
Addresses,
OrderValidationUtils,
LibTransactionDecoder,
LibEIP712ExchangeDomain,
EthBalanceChecker,
OrderTransferSimulationUtils
ExternalFunctions
{
constructor (address _exchange)
constructor (
address exchange_,
address chaiBridge_,
address dydxBridge_
)
public
OrderValidationUtils(_exchange)
OrderTransferSimulationUtils(_exchange)
Addresses(
exchange_,
chaiBridge_,
dydxBridge_
)
LibEIP712ExchangeDomain(uint256(0), address(0)) // null args because because we only use constants
{}
function getOrderHash(LibOrder.Order memory order, uint256 chainId, address exchange)
function getOrderHash(
LibOrder.Order memory order,
uint256 chainId,
address exchange
)
public
pure
returns (bytes32 orderHash)

View File

@@ -16,7 +16,7 @@
*/
pragma solidity ^0.5.5;
pragma solidity ^0.5.16;
contract EthBalanceChecker {

View File

@@ -0,0 +1,322 @@
/*
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.5.16;
pragma experimental ABIEncoderV2;
import "./Addresses.sol";
import "./LibAssetData.sol";
import "./LibTransactionDecoder.sol";
import "./LibOrderTransferSimulation.sol";
contract ExternalFunctions is
Addresses
{
/// @dev Decodes the call data for an Exchange contract method call.
/// @param transactionData ABI-encoded calldata for an Exchange
/// contract method call.
/// @return The name of the function called, and the parameters it was
/// given. For single-order fills and cancels, the arrays will have
/// just one element.
function decodeZeroExTransactionData(bytes memory transactionData)
public
pure
returns(
string memory functionName,
LibOrder.Order[] memory orders,
uint256[] memory takerAssetFillAmounts,
bytes[] memory signatures
)
{
return LibTransactionDecoder.decodeZeroExTransactionData(transactionData);
}
/// @dev Decode AssetProxy identifier
/// @param assetData AssetProxy-compliant asset data describing an ERC-20, ERC-721, ERC1155, or MultiAsset asset.
/// @return The AssetProxy identifier
function decodeAssetProxyId(bytes memory assetData)
public
pure
returns (
bytes4 assetProxyId
)
{
return LibAssetData.decodeAssetProxyId(assetData);
}
/// @dev Encode ERC-20 asset data into the format described in the AssetProxy contract specification.
/// @param tokenAddress The address of the ERC-20 contract hosting the asset to be traded.
/// @return AssetProxy-compliant data describing the asset.
function encodeERC20AssetData(address tokenAddress)
public
pure
returns (bytes memory assetData)
{
return LibAssetData.encodeERC20AssetData(tokenAddress);
}
/// @dev Decode ERC-20 asset data from the format described in the AssetProxy contract specification.
/// @param assetData AssetProxy-compliant asset data describing an ERC-20 asset.
/// @return The AssetProxy identifier, and the address of the ERC-20
/// contract hosting this asset.
function decodeERC20AssetData(bytes memory assetData)
public
pure
returns (
bytes4 assetProxyId,
address tokenAddress
)
{
return LibAssetData.decodeERC20AssetData(assetData);
}
/// @dev Encode ERC-721 asset data into the format described in the AssetProxy specification.
/// @param tokenAddress The address of the ERC-721 contract hosting the asset to be traded.
/// @param tokenId The identifier of the specific asset to be traded.
/// @return AssetProxy-compliant asset data describing the asset.
function encodeERC721AssetData(address tokenAddress, uint256 tokenId)
public
pure
returns (bytes memory assetData)
{
return LibAssetData.encodeERC721AssetData(tokenAddress, tokenId);
}
/// @dev Decode ERC-721 asset data from the format described in the AssetProxy contract specification.
/// @param assetData AssetProxy-compliant asset data describing an ERC-721 asset.
/// @return The ERC-721 AssetProxy identifier, the address of the ERC-721
/// contract hosting this asset, and the identifier of the specific
/// asset to be traded.
function decodeERC721AssetData(bytes memory assetData)
public
pure
returns (
bytes4 assetProxyId,
address tokenAddress,
uint256 tokenId
)
{
return LibAssetData.decodeERC721AssetData(assetData);
}
/// @dev Encode ERC-1155 asset data into the format described in the AssetProxy contract specification.
/// @param tokenAddress The address of the ERC-1155 contract hosting the asset(s) to be traded.
/// @param tokenIds The identifiers of the specific assets to be traded.
/// @param tokenValues The amounts of each asset to be traded.
/// @param callbackData Data to be passed to receiving contracts when a transfer is performed.
/// @return AssetProxy-compliant asset data describing the set of assets.
function encodeERC1155AssetData(
address tokenAddress,
uint256[] memory tokenIds,
uint256[] memory tokenValues,
bytes memory callbackData
)
public
pure
returns (bytes memory assetData)
{
return LibAssetData.encodeERC1155AssetData(
tokenAddress,
tokenIds,
tokenValues,
callbackData
);
}
/// @dev Decode ERC-1155 asset data from the format described in the AssetProxy contract specification.
/// @param assetData AssetProxy-compliant asset data describing an ERC-1155 set of assets.
/// @return The ERC-1155 AssetProxy identifier, the address of the ERC-1155
/// contract hosting the assets, an array of the identifiers of the
/// assets to be traded, an array of asset amounts to be traded, and
/// callback data. Each element of the arrays corresponds to the
/// same-indexed element of the other array. Return values specified as
/// `memory` are returned as pointers to locations within the memory of
/// the input parameter `assetData`.
function decodeERC1155AssetData(bytes memory assetData)
public
pure
returns (
bytes4 assetProxyId,
address tokenAddress,
uint256[] memory tokenIds,
uint256[] memory tokenValues,
bytes memory callbackData
)
{
return LibAssetData.decodeERC1155AssetData(assetData);
}
/// @dev Encode data for multiple assets, per the AssetProxy contract specification.
/// @param amounts The amounts of each asset to be traded.
/// @param nestedAssetData AssetProxy-compliant data describing each asset to be traded.
/// @return AssetProxy-compliant data describing the set of assets.
function encodeMultiAssetData(uint256[] memory amounts, bytes[] memory nestedAssetData)
public
pure
returns (bytes memory assetData)
{
return LibAssetData.encodeMultiAssetData(amounts, nestedAssetData);
}
/// @dev Decode multi-asset data from the format described in the AssetProxy contract specification.
/// @param assetData AssetProxy-compliant data describing a multi-asset basket.
/// @return The Multi-Asset AssetProxy identifier, an array of the amounts
/// of the assets to be traded, and an array of the
/// AssetProxy-compliant data describing each asset to be traded. Each
/// element of the arrays corresponds to the same-indexed element of the other array.
function decodeMultiAssetData(bytes memory assetData)
public
pure
returns (
bytes4 assetProxyId,
uint256[] memory amounts,
bytes[] memory nestedAssetData
)
{
return LibAssetData.decodeMultiAssetData(assetData);
}
/// @dev Encode StaticCall asset data into the format described in the AssetProxy contract specification.
/// @param staticCallTargetAddress Target address of StaticCall.
/// @param staticCallData Data that will be passed to staticCallTargetAddress in the StaticCall.
/// @param expectedReturnDataHash Expected Keccak-256 hash of the StaticCall return data.
/// @return AssetProxy-compliant asset data describing the set of assets.
function encodeStaticCallAssetData(
address staticCallTargetAddress,
bytes memory staticCallData,
bytes32 expectedReturnDataHash
)
public
pure
returns (bytes memory assetData)
{
return LibAssetData.encodeStaticCallAssetData(
staticCallTargetAddress,
staticCallData,
expectedReturnDataHash
);
}
/// @dev Decode StaticCall asset data from the format described in the AssetProxy contract specification.
/// @param assetData AssetProxy-compliant asset data describing a StaticCall asset
/// @return The StaticCall AssetProxy identifier, the target address of the StaticCAll, the data to be
/// passed to the target address, and the expected Keccak-256 hash of the static call return data.
function decodeStaticCallAssetData(bytes memory assetData)
public
pure
returns (
bytes4 assetProxyId,
address staticCallTargetAddress,
bytes memory staticCallData,
bytes32 expectedReturnDataHash
)
{
return LibAssetData.decodeStaticCallAssetData(assetData);
}
/// @dev Decode ERC20Bridge asset data from the format described in the AssetProxy contract specification.
/// @param assetData AssetProxy-compliant asset data describing an ERC20Bridge asset
/// @return The ERC20BridgeProxy identifier, the address of the ERC20 token to transfer, the address
/// of the bridge contract, and extra data to be passed to the bridge contract.
function decodeERC20BridgeAssetData(bytes memory assetData)
public
pure
returns (
bytes4 assetProxyId,
address tokenAddress,
address bridgeAddress,
bytes memory bridgeData
)
{
return LibAssetData.decodeERC20BridgeAssetData(assetData);
}
/// @dev Reverts if assetData is not of a valid format for its given proxy id.
/// @param assetData AssetProxy compliant asset data.
function revertIfInvalidAssetData(bytes memory assetData)
public
pure
{
return LibAssetData.revertIfInvalidAssetData(assetData);
}
/// @dev Simulates the maker transfers within an order and returns the index of the first failed transfer.
/// @param order The order to simulate transfers for.
/// @param takerAddress The address of the taker that will fill the order.
/// @param takerAssetFillAmount The amount of takerAsset that the taker wished to fill.
/// @return The index of the first failed transfer (or 4 if all transfers are successful).
function getSimulatedOrderMakerTransferResults(
LibOrder.Order memory order,
address takerAddress,
uint256 takerAssetFillAmount
)
public
returns (LibOrderTransferSimulation.OrderTransferResults orderTransferResults)
{
return LibOrderTransferSimulation.getSimulatedOrderMakerTransferResults(
exchangeAddress,
order,
takerAddress,
takerAssetFillAmount
);
}
/// @dev Simulates all of the transfers within an order and returns the index of the first failed transfer.
/// @param order The order to simulate transfers for.
/// @param takerAddress The address of the taker that will fill the order.
/// @param takerAssetFillAmount The amount of takerAsset that the taker wished to fill.
/// @return The index of the first failed transfer (or 4 if all transfers are successful).
function getSimulatedOrderTransferResults(
LibOrder.Order memory order,
address takerAddress,
uint256 takerAssetFillAmount
)
public
returns (LibOrderTransferSimulation.OrderTransferResults orderTransferResults)
{
return LibOrderTransferSimulation.getSimulatedOrderTransferResults(
exchangeAddress,
order,
takerAddress,
takerAssetFillAmount
);
}
/// @dev Simulates all of the transfers for each given order and returns the indices of each first failed transfer.
/// @param orders Array of orders to individually simulate transfers for.
/// @param takerAddresses Array of addresses of takers that will fill each order.
/// @param takerAssetFillAmounts Array of amounts of takerAsset that will be filled for each order.
/// @return The indices of the first failed transfer (or 4 if all transfers are successful) for each order.
function getSimulatedOrdersTransferResults(
LibOrder.Order[] memory orders,
address[] memory takerAddresses,
uint256[] memory takerAssetFillAmounts
)
public
returns (LibOrderTransferSimulation.OrderTransferResults[] memory orderTransferResults)
{
return LibOrderTransferSimulation.getSimulatedOrdersTransferResults(
exchangeAddress,
orders,
takerAddresses,
takerAssetFillAmounts
);
}
}

View File

@@ -16,307 +16,18 @@
*/
pragma solidity ^0.5.5;
pragma solidity ^0.5.16;
pragma experimental ABIEncoderV2;
import "@0x/contracts-utils/contracts/src/LibBytes.sol";
import "@0x/contracts-exchange/contracts/src/interfaces/IExchange.sol";
import "@0x/contracts-asset-proxy/contracts/src/interfaces/IAssetData.sol";
import "@0x/contracts-asset-proxy/contracts/src/interfaces/IAssetProxy.sol";
import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol";
import "@0x/contracts-erc721/contracts/src/interfaces/IERC721Token.sol";
import "@0x/contracts-erc1155/contracts/src/interfaces/IERC1155.sol";
contract LibAssetData {
// 2^256 - 1
uint256 constant internal _MAX_UINT256 = uint256(-1);
library LibAssetData {
using LibBytes for bytes;
// solhint-disable var-name-mixedcase
IExchange internal _EXCHANGE;
address internal _ERC20_PROXY_ADDRESS;
address internal _ERC721_PROXY_ADDRESS;
address internal _ERC1155_PROXY_ADDRESS;
address internal _STATIC_CALL_PROXY_ADDRESS;
// solhint-enable var-name-mixedcase
constructor (address _exchange)
public
{
_EXCHANGE = IExchange(_exchange);
_ERC20_PROXY_ADDRESS = _EXCHANGE.getAssetProxy(IAssetData(address(0)).ERC20Token.selector);
_ERC721_PROXY_ADDRESS = _EXCHANGE.getAssetProxy(IAssetData(address(0)).ERC721Token.selector);
_ERC1155_PROXY_ADDRESS = _EXCHANGE.getAssetProxy(IAssetData(address(0)).ERC1155Assets.selector);
_STATIC_CALL_PROXY_ADDRESS = _EXCHANGE.getAssetProxy(IAssetData(address(0)).StaticCall.selector);
}
/// @dev Returns the owner's balance of the assets(s) specified in
/// assetData. When the asset data contains multiple assets (eg in
/// ERC1155 or Multi-Asset), the return value indicates how many
/// complete "baskets" of those assets are owned by owner.
/// @param ownerAddress Owner of the assets specified by assetData.
/// @param assetData Details of asset, encoded per the AssetProxy contract specification.
/// @return Number of assets (or asset baskets) held by owner.
function getBalance(address ownerAddress, bytes memory assetData)
public
view
returns (uint256 balance)
{
// Get id of AssetProxy contract
bytes4 assetProxyId = assetData.readBytes4(0);
if (assetProxyId == IAssetData(address(0)).ERC20Token.selector) {
// Get ERC20 token address
address tokenAddress = assetData.readAddress(16);
// Encode data for `balanceOf(ownerAddress)`
bytes memory balanceOfData = abi.encodeWithSelector(
IERC20Token(address(0)).balanceOf.selector,
ownerAddress
);
// Query balance
(bool success, bytes memory returnData) = tokenAddress.staticcall(balanceOfData);
balance = success && returnData.length == 32 ? returnData.readUint256(0) : 0;
} else if (assetProxyId == IAssetData(address(0)).ERC721Token.selector) {
// Get ERC721 token address and id
(, address tokenAddress, uint256 tokenId) = decodeERC721AssetData(assetData);
// Check if id is owned by ownerAddress
bytes memory ownerOfCalldata = abi.encodeWithSelector(
IERC721Token(address(0)).ownerOf.selector,
tokenId
);
(bool success, bytes memory returnData) = tokenAddress.staticcall(ownerOfCalldata);
address currentOwnerAddress = (success && returnData.length == 32) ? returnData.readAddress(12) : address(0);
balance = currentOwnerAddress == ownerAddress ? 1 : 0;
} else if (assetProxyId == IAssetData(address(0)).ERC1155Assets.selector) {
// Get ERC1155 token address, array of ids, and array of values
(, address tokenAddress, uint256[] memory tokenIds, uint256[] memory tokenValues,) = decodeERC1155AssetData(assetData);
uint256 length = tokenIds.length;
for (uint256 i = 0; i != length; i++) {
// Encode data for `balanceOf(ownerAddress, tokenIds[i])
bytes memory balanceOfData = abi.encodeWithSelector(
IERC1155(address(0)).balanceOf.selector,
ownerAddress,
tokenIds[i]
);
// Query balance
(bool success, bytes memory returnData) = tokenAddress.staticcall(balanceOfData);
uint256 totalBalance = success && returnData.length == 32 ? returnData.readUint256(0) : 0;
// Scale total balance down by corresponding value in assetData
uint256 scaledBalance = totalBalance / tokenValues[i];
if (scaledBalance < balance || balance == 0) {
balance = scaledBalance;
}
}
} else if (assetProxyId == IAssetData(address(0)).StaticCall.selector) {
// Encode data for `staticCallProxy.transferFrom(assetData,...)`
bytes memory transferFromData = abi.encodeWithSelector(
IAssetProxy(address(0)).transferFrom.selector,
assetData,
address(0), // `from` address is not used
address(0), // `to` address is not used
0 // `amount` is not used
);
// Check if staticcall would be successful
(bool success,) = _STATIC_CALL_PROXY_ADDRESS.staticcall(transferFromData);
// Success means that the staticcall can be made an unlimited amount of times
balance = success ? _MAX_UINT256 : 0;
} else if (assetProxyId == IAssetData(address(0)).MultiAsset.selector) {
// Get array of values and array of assetDatas
(, uint256[] memory assetAmounts, bytes[] memory nestedAssetData) = decodeMultiAssetData(assetData);
uint256 length = nestedAssetData.length;
for (uint256 i = 0; i != length; i++) {
// Query balance of individual assetData
uint256 totalBalance = getBalance(ownerAddress, nestedAssetData[i]);
// Scale total balance down by corresponding value in assetData
uint256 scaledBalance = totalBalance / assetAmounts[i];
if (scaledBalance < balance || balance == 0) {
balance = scaledBalance;
}
}
}
// Balance will be 0 if assetProxyId is unknown
return balance;
}
/// @dev Calls getBalance() for each element of assetData.
/// @param ownerAddress Owner of the assets specified by assetData.
/// @param assetData Array of asset details, each encoded per the AssetProxy contract specification.
/// @return Array of asset balances from getBalance(), with each element
/// corresponding to the same-indexed element in the assetData input.
function getBatchBalances(address ownerAddress, bytes[] memory assetData)
public
view
returns (uint256[] memory balances)
{
uint256 length = assetData.length;
balances = new uint256[](length);
for (uint256 i = 0; i != length; i++) {
balances[i] = getBalance(ownerAddress, assetData[i]);
}
return balances;
}
/// @dev Returns the number of asset(s) (described by assetData) that
/// the corresponding AssetProxy contract is authorized to spend. When the asset data contains
/// multiple assets (eg for Multi-Asset), the return value indicates
/// how many complete "baskets" of those assets may be spent by all of the corresponding
/// AssetProxy contracts.
/// @param ownerAddress Owner of the assets specified by assetData.
/// @param assetData Details of asset, encoded per the AssetProxy contract specification.
/// @return Number of assets (or asset baskets) that the corresponding AssetProxy is authorized to spend.
function getAssetProxyAllowance(address ownerAddress, bytes memory assetData)
public
view
returns (uint256 allowance)
{
// Get id of AssetProxy contract
bytes4 assetProxyId = assetData.readBytes4(0);
if (assetProxyId == IAssetData(address(0)).MultiAsset.selector) {
// Get array of values and array of assetDatas
(, uint256[] memory amounts, bytes[] memory nestedAssetData) = decodeMultiAssetData(assetData);
uint256 length = nestedAssetData.length;
for (uint256 i = 0; i != length; i++) {
// Query allowance of individual assetData
uint256 totalAllowance = getAssetProxyAllowance(ownerAddress, nestedAssetData[i]);
// Scale total allowance down by corresponding value in assetData
uint256 scaledAllowance = totalAllowance / amounts[i];
if (scaledAllowance < allowance || allowance == 0) {
allowance = scaledAllowance;
}
}
return allowance;
}
if (assetProxyId == IAssetData(address(0)).ERC20Token.selector) {
// Get ERC20 token address
address tokenAddress = assetData.readAddress(16);
// Encode data for `allowance(ownerAddress, _ERC20_PROXY_ADDRESS)`
bytes memory allowanceData = abi.encodeWithSelector(
IERC20Token(address(0)).allowance.selector,
ownerAddress,
_ERC20_PROXY_ADDRESS
);
// Query allowance
(bool success, bytes memory returnData) = tokenAddress.staticcall(allowanceData);
allowance = success && returnData.length == 32 ? returnData.readUint256(0) : 0;
} else if (assetProxyId == IAssetData(address(0)).ERC721Token.selector) {
// Get ERC721 token address and id
(, address tokenAddress, uint256 tokenId) = decodeERC721AssetData(assetData);
// Encode data for `isApprovedForAll(ownerAddress, _ERC721_PROXY_ADDRESS)`
bytes memory isApprovedForAllData = abi.encodeWithSelector(
IERC721Token(address(0)).isApprovedForAll.selector,
ownerAddress,
_ERC721_PROXY_ADDRESS
);
(bool success, bytes memory returnData) = tokenAddress.staticcall(isApprovedForAllData);
// If not approved for all, call `getApproved(tokenId)`
if (!success || returnData.length != 32 || returnData.readUint256(0) != 1) {
// Encode data for `getApproved(tokenId)`
bytes memory getApprovedData = abi.encodeWithSelector(IERC721Token(address(0)).getApproved.selector, tokenId);
(success, returnData) = tokenAddress.staticcall(getApprovedData);
// Allowance is 1 if successful and the approved address is the ERC721Proxy
allowance = success && returnData.length == 32 && returnData.readAddress(12) == _ERC721_PROXY_ADDRESS ? 1 : 0;
} else {
// Allowance is 2^256 - 1 if `isApprovedForAll` returned true
allowance = _MAX_UINT256;
}
} else if (assetProxyId == IAssetData(address(0)).ERC1155Assets.selector) {
// Get ERC1155 token address
(, address tokenAddress, , , ) = decodeERC1155AssetData(assetData);
// Encode data for `isApprovedForAll(ownerAddress, _ERC1155_PROXY_ADDRESS)`
bytes memory isApprovedForAllData = abi.encodeWithSelector(
IERC1155(address(0)).isApprovedForAll.selector,
ownerAddress,
_ERC1155_PROXY_ADDRESS
);
// Query allowance
(bool success, bytes memory returnData) = tokenAddress.staticcall(isApprovedForAllData);
allowance = success && returnData.length == 32 && returnData.readUint256(0) == 1 ? _MAX_UINT256 : 0;
} else if (assetProxyId == IAssetData(address(0)).StaticCall.selector) {
// The StaticCallProxy does not require any approvals
allowance = _MAX_UINT256;
}
// Allowance will be 0 if the assetProxyId is unknown
return allowance;
}
/// @dev Calls getAssetProxyAllowance() for each element of assetData.
/// @param ownerAddress Owner of the assets specified by assetData.
/// @param assetData Array of asset details, each encoded per the AssetProxy contract specification.
/// @return An array of asset allowances from getAllowance(), with each
/// element corresponding to the same-indexed element in the assetData input.
function getBatchAssetProxyAllowances(address ownerAddress, bytes[] memory assetData)
public
view
returns (uint256[] memory allowances)
{
uint256 length = assetData.length;
allowances = new uint256[](length);
for (uint256 i = 0; i != length; i++) {
allowances[i] = getAssetProxyAllowance(ownerAddress, assetData[i]);
}
return allowances;
}
/// @dev Calls getBalance() and getAllowance() for assetData.
/// @param ownerAddress Owner of the assets specified by assetData.
/// @param assetData Details of asset, encoded per the AssetProxy contract specification.
/// @return Number of assets (or asset baskets) held by owner, and number
/// of assets (or asset baskets) that the corresponding AssetProxy is authorized to spend.
function getBalanceAndAssetProxyAllowance(address ownerAddress, bytes memory assetData)
public
view
returns (uint256 balance, uint256 allowance)
{
balance = getBalance(ownerAddress, assetData);
allowance = getAssetProxyAllowance(ownerAddress, assetData);
return (balance, allowance);
}
/// @dev Calls getBatchBalances() and getBatchAllowances() for each element of assetData.
/// @param ownerAddress Owner of the assets specified by assetData.
/// @param assetData Array of asset details, each encoded per the AssetProxy contract specification.
/// @return An array of asset balances from getBalance(), and an array of
/// asset allowances from getAllowance(), with each element
/// corresponding to the same-indexed element in the assetData input.
function getBatchBalancesAndAssetProxyAllowances(address ownerAddress, bytes[] memory assetData)
public
view
returns (uint256[] memory balances, uint256[] memory allowances)
{
balances = getBatchBalances(ownerAddress, assetData);
allowances = getBatchAssetProxyAllowances(ownerAddress, assetData);
return (balances, allowances);
}
/// @dev Decode AssetProxy identifier
/// @dev Decode AssetProxy identifier
/// @param assetData AssetProxy-compliant asset data describing an ERC-20, ERC-721, ERC1155, or MultiAsset asset.
/// @return The AssetProxy identifier
function decodeAssetProxyId(bytes memory assetData)
@@ -353,7 +64,7 @@ contract LibAssetData {
/// @dev Decode ERC-20 asset data from the format described in the AssetProxy contract specification.
/// @param assetData AssetProxy-compliant asset data describing an ERC-20 asset.
/// @return The AssetProxy identifier, and the address of the ERC-20
/// @return The AssetProxy identifier, and the address of the ERC-20
/// contract hosting this asset.
function decodeERC20AssetData(bytes memory assetData)
public
@@ -589,9 +300,38 @@ contract LibAssetData {
);
}
/// @dev Decode ERC20Bridge asset data from the format described in the AssetProxy contract specification.
/// @param assetData AssetProxy-compliant asset data describing an ERC20Bridge asset
/// @return The ERC20BridgeProxy identifier, the address of the ERC20 token to transfer, the address
/// of the bridge contract, and extra data to be passed to the bridge contract.
function decodeERC20BridgeAssetData(bytes memory assetData)
public
pure
returns (
bytes4 assetProxyId,
address tokenAddress,
address bridgeAddress,
bytes memory bridgeData
)
{
assetProxyId = assetData.readBytes4(0);
require(
assetProxyId == IAssetData(address(0)).ERC20Bridge.selector,
"WRONG_PROXY_ID"
);
(tokenAddress, bridgeAddress, bridgeData) = abi.decode(
assetData.slice(4, assetData.length),
(address, address, bytes)
);
}
/// @dev Reverts if assetData is not of a valid format for its given proxy id.
/// @param assetData AssetProxy compliant asset data.
function revertIfInvalidAssetData(bytes memory assetData)
public
pure
pure
{
bytes4 assetProxyId = assetData.readBytes4(0);
@@ -605,6 +345,8 @@ contract LibAssetData {
decodeMultiAssetData(assetData);
} else if (assetProxyId == IAssetData(address(0)).StaticCall.selector) {
decodeStaticCallAssetData(assetData);
} else if (assetProxyId == IAssetData(address(0)).ERC20Bridge.selector) {
decodeERC20BridgeAssetData(assetData);
} else {
revert("WRONG_PROXY_ID");
}

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