Compare commits

..

79 Commits

Author SHA1 Message Date
xianny
b5eb1c9ee8 Publish
- @0x/contracts-asset-proxy@3.4.0
 - @0x/contracts-broker@1.1.6
 - @0x/contracts-coordinator@3.1.7
 - @0x/contracts-dev-utils@1.3.5
 - @0x/contracts-erc1155@2.1.7
 - @0x/contracts-erc20-bridge-sampler@1.7.0
 - @0x/contracts-erc20@3.2.1
 - @0x/contracts-erc721@3.1.7
 - @0x/contracts-exchange-forwarder@4.2.7
 - @0x/contracts-exchange-libs@4.3.7
 - @0x/contracts-exchange@3.2.7
 - @0x/contracts-extensions@6.2.1
 - @0x/contracts-integrations@2.6.0
 - @0x/contracts-multisig@4.1.7
 - @0x/contracts-staking@2.0.14
 - @0x/contracts-test-utils@5.3.4
 - @0x/contracts-utils@4.5.1
 - @0x/contracts-zero-ex@0.2.0
 - 0x.js@9.2.0
 - @0x/abi-gen@5.3.1
 - @0x/assert@3.0.9
 - @0x/asset-swapper@4.6.0
 - @0x/base-contract@6.2.3
 - @0x/connect@6.0.9
 - @0x/contract-addresses@4.11.0
 - @0x/contract-artifacts@3.7.1
 - @0x/contract-wrappers-test@12.2.16
 - @0x/contract-wrappers@13.8.0
 - @0x/contracts-gen@2.0.10
 - @0x/dev-utils@3.3.0
 - ethereum-types@3.2.0
 - @0x/instant@1.0.53
 - @0x/json-schemas@5.1.0
 - @0x/migrations@6.4.0
 - @0x/monorepo-scripts@1.0.54
 - @0x/order-utils@10.3.0
 - @0x/orderbook@2.2.7
 - @0x/sol-compiler@4.1.1
 - @0x/sol-coverage@4.0.10
 - @0x/sol-doc@3.1.8
 - @0x/sol-profiler@4.1.0
 - @0x/sol-resolver@3.1.0
 - @0x/sol-trace@3.0.10
 - @0x/sol-tracing-utils@7.1.0
 - @0x/sra-spec@3.0.9
 - @0x/subproviders@6.1.1
 - @0x/tslint-config@4.1.0
 - @0x/types@3.2.0
 - @0x/typescript-typings@5.1.1
 - @0x/utils@5.5.1
 - @0x/web3-wrapper@7.2.0
2020-07-14 21:48:14 -07:00
xianny
9d3755db36 Updated CHANGELOGS & MD docs 2020-07-14 21:47:59 -07:00
Jacob Evans
762e0aec2d fix: Update to use KNP getExpectedRateAfterFee (#2629)
* Update to use KNP getExpectedRateAfterFee

* hack: use overrides instead of forking in ganache

* fix: added some tests using overrides

* override sampler

* Overrides in bridge_sampler_mainnet_test

* use getContracts to fake out tests

* chore: supply devUtils address

* feat: specify the call override by default

* CHANGELOGs

* export SamplerOverrides

* fix package.json

* fix: after rebase
2020-07-15 14:05:57 +10:00
mzhu25
ff9c9241d8 BalancerBridge (#2613)
* Add BalancerBridge and Sampler functions

* Update sampler artifacts/wrappers

* Add Balancer support to AssetSwapper + related refactoring

* Make use of GraphQL instead of sampler

* "fix" build and add mainnet BalancerBridge tests

* address some comments

* add balancer cache and fix DexSampler tests

* lint

* wip: tests for balancer sampler ops

* Fix market operation utils test

* balancer unit tests

* Return a buy quote of 0 if the buy amount exceeds the Balancer pool's balance

* Dynamic fee estimation

* Update contract addresses, export BalancerBridge wrapper

* Update changelogs

* Fix bugs discovered via simbot

* Fix issues in balancer_utils

* override `BigNumber.config` in configured_bignumber.ts

* Special case Balancer subops in  too

* Address some more comments

* Address Balancer performance issue

* Performance improvements

* Address comment

* Fix tests

Co-authored-by: xianny <xianny@gmail.com>
2020-07-14 19:18:50 -07:00
Lawrence Forman
18bc701e8b Merge pull request #2610 from 0xProject/feat/zero-ex/meta-transactions
EP: MetaTransactions
2020-07-10 11:12:58 -04:00
Lawrence Forman
a47795fd3f @0x/contract-wrappers-test: Increase test timeout. 2020-07-10 03:05:56 -04:00
Lawrence Forman
a55e8b268c @0x/contracts-zero-ex: Fix linter errors. 2020-07-10 02:36:25 -04:00
Lawrence Forman
e8106f04b5 @0x/contracts-zero-ex: Address review feedback. 2020-07-10 02:36:25 -04:00
Lawrence Forman
bdc1dbf08a @0x/order-utils: Address review feedback. 2020-07-10 02:36:25 -04:00
Lawrence Forman
06eeb2088b @0x/types: Address review feedback. 2020-07-10 02:36:25 -04:00
Lawrence Forman
7da9ec2c75 @0x/contract-addresses: Update ganache snapshot addresses for the Exchange Proxy. 2020-07-10 02:36:24 -04:00
Lawrence Forman
297ff10c14 @0x/contracts-zero-ex: add SignatureValidator and MetaTransactions features. 2020-07-10 02:36:00 -04:00
Lawrence Forman
1305f4314d @0x/0x.js: Export ExchangeProxyMetaTransaction and SignedExchangeProxyMetaTransaction 2020-07-10 02:36:00 -04:00
Lawrence Forman
55474c0599 @0x/types: Add ExchangeProxyMetaTransactionHash(). 2020-07-10 02:36:00 -04:00
Lawrence Forman
687c79ae81 @0x/utils: Add more revert errors to ZeroExRevertErrors 2020-07-10 02:36:00 -04:00
Lawrence Forman
829a353b14 @0x/order-utils: Add getOrderHash(), getExchangeTransactionHash(), getExchangeProxyTransactionHash() 2020-07-10 02:36:00 -04:00
Lawrence Forman
aced474dc5 Merge pull request #2628 from 0xProject/fix/dfb-redeploy-kovan-07-10-20
Redeploy DFB on kovan.
2020-07-10 02:35:37 -04:00
Lawrence Forman
7c08d5f198 etheereum-types: Touch this package to fix publish. 2020-07-10 01:53:02 -04:00
Lawrence Forman
c546787994 @0x/contract-addresses: Redeploy DFB on kovan.
`@0x/contracts-utils`: Reorganize `DeploymentConstants` addresses.
2020-07-10 01:29:28 -04:00
Lawrence Forman
7967a8416c Merge pull request #2625 from 0xProject/feat/deploy-new-fqt-2608
Deploy FQT from #2608
2020-07-07 16:05:04 -04:00
Lawrence Forman
9164cff234 @0x/contract-addresses: Deploy FQT from PR 2608 2020-07-07 01:10:16 -04:00
Lawrence Forman
017f98e87e Merge pull request #2616 from 0xProject/fix/dfb-revert
Fix DFB instability
2020-07-07 01:08:51 -04:00
Lawrence Forman
f33d8670aa @0x/contract-addresses: Update DFB addresses. 2020-07-07 01:07:44 -04:00
Lawrence Forman
845a42e73a @0x/asset-proxy: Fix DFB instability 2020-07-07 01:06:46 -04:00
Jacob Evans
406d2cefc5 feat: ExchangeProxy FillQuoteTransformer bridge direct (#2608)
* Detect Bridge orders and fill direct

* Mark as external for try/catch

* Initial tests

* discuss: Continue if protocol fee insufficient

* Emit ProtocolFeeUnfunded

* put the clamps on taker balance

* feat: GST free and optimize

* fix: low level GST free call

* fix: review feedback

* remove unused return struct
2020-07-07 07:37:26 +10:00
Lawrence Forman
41cdbc0ec4 Merge pull request #2622 from 0xProject/migration/exchange-proxy/affiliate-fee-transformer-initial
Deploy AffiliateFeeTransformer
2020-07-02 23:40:35 -04:00
Lawrence Forman
c6ec261c5c @0x/asset-swapper: Fix failing test. 2020-07-02 21:45:39 -04:00
Lawrence Forman
a2db1a3275 @0x/migrations: Add affiliateFeeTransformer and exchangeProxyFlashWallet to ganache snapshot migration. 2020-07-02 21:45:39 -04:00
Lawrence Forman
1e8f2f0e83 @0x/contract-addresses: Add affiliateFeeTransformer and exchangeProxyFlashWallet addresses. 2020-07-02 16:04:33 -04:00
Lawrence Forman
8491abe142 @0x/contracts-zero-ex: Export AffiliateFeeTransformer. 2020-07-02 16:04:33 -04:00
Lawrence Forman
d4302538bf Merge pull request #2620 from 0xProject/feat/contract-wrappers/geth-call-support
geth eth_call support.
2020-07-02 11:48:35 -04:00
Lawrence Forman
c34e3765ef @0x/dev-utils: Export GethCallOverrides type 2020-07-02 01:57:01 -04:00
Lawrence Forman
1f86bc06ef @0x/web3-wrapper: Export GethCallOverrides and GethCallOverridesRPC. 2020-07-02 01:56:33 -04:00
Lawrence Forman
7e892fac2d @0x/asset-swapper: Increase test timeout for slow CI 2020-07-02 00:33:23 -04:00
Lawrence Forman
23789b0692 @0x/contract-wrappers: Export GethCallOverrides. 2020-07-01 22:33:52 -04:00
Lawrence Forman
89adbe4127 0x.js: Export GethCallOverrides. 2020-07-01 21:08:25 -04:00
Lawrence Forman
11940fb98e @0x/json-schemas: Rename CallData.value -> CallData.balance and make it `wholeNumberSchema type.'
`@0x/web3-wrapper`: Only supply overrides to eth_call RPC if provided.
2020-07-01 20:43:33 -04:00
Lawrence Forman
13ae335811 0x/ethereum-types: Add geth eth_call types.
`0x/json-schemas`: Add geth eth_call properties to `CallData`.
`@0x/web3-wrapper`: Add geth geth eth_call support.
2020-07-01 15:54:49 -04:00
Lawrence Forman
b2dc6ad2fa @0x/asset-swapper: "Fix" forwarder buys of low decimal tokens. (#2618)
Co-authored-by: Lawrence Forman <me@merklejerk.com>
2020-07-01 20:30:12 +10:00
Jacob Evans
85ca926fd0 feat: asset-swapper singleton gas price oracle (#2619) 2020-07-01 18:43:47 +10:00
Jacob Evans
676698a59b fix: asset-swapper ethgasstation url option (#2617)
* fix: asset-swapper order-utils version

* fix: asset-swapper specify ethgasstation url as option

* default to real EGS

* fix: bad package.json
2020-07-01 13:47:34 +10:00
Lawrence Forman
22408ecd58 @0x/asset-swapper: Fix best/worst case asset amount calculations. (#2615)
Co-authored-by: Lawrence Forman <me@merklejerk.com>
Co-authored-by: Jacob Evans <jacob@dekz.net>
2020-06-30 17:58:06 +10:00
Jacob Evans
d36acc7ec7 fix: asset-swapper EthGasStation proxy url (#2614) 2020-06-30 17:41:52 +10:00
Lawrence Forman
a5a68acfec Add Exchange Proxy to Ganache snapshot (#2612)
* `@0x/contracts-zero-ex`: Expose migration tools.

* `@0x/contract-addresses`: Update ganache snapshot Exchange Proxy addresses

* `@0x/migrations`: Add Exchange Proxy migration
2020-06-25 13:52:01 +10:00
Jacob Evans
7431651666 fix: package.json from publish (#2611) 2020-06-24 15:44:42 +10:00
Jacob Evans
4f91bfd907 Updated CHANGELOGS & MD docs 2020-06-24 14:12:56 +10:00
mzhu25
8d2086870b Merge pull request #2607 from 0xProject/fix/sol-profiler-returns
Fix sol-profiler bugs
2020-06-22 14:35:52 -07:00
Daniel Pyrathon
1511ef1a98 Merge pull request #2609 from 0xProject/feature/quote-requestor-strings
Quote Requestor Fix:  BigNumbers to Strings
2020-06-19 15:40:58 -07:00
Daniel Pyrathon
4e030ce1e8 remove legacy taker request 2020-06-19 15:07:39 -07:00
Steve Klebanoff
2507ad274b remove BigNumbers from expectedParams 2020-06-19 14:42:45 -07:00
Steve Klebanoff
fb1c149eb9 another comment 2020-06-19 13:43:27 -07:00
Steve Klebanoff
d4662f428a change BNs to strings 2020-06-19 13:29:19 -07:00
F. Eugene Aumson
73c779c13a Merge pull request #2582 from 0xProject/feat/asset-swapper/use-quote-server
asset-swapper: Use @0x/quote-server, not local typedefs; and adapt to renamed taker request parameters
2020-06-19 13:05:10 -04:00
F. Eugene Aumson
b8cc164af1 asset-s: rm refs to quoteExpiry for RFQT tests
Addresses review comment https://github.com/0xProject/0x-monorepo/pull/2582#discussion_r441836846
2020-06-17 17:29:35 -04:00
Michael Zhu
64a391b5f8 Update changelogs 2020-06-17 12:23:49 -07:00
Michael Zhu
21a202dd16 Fix sol-profiler bugs 2020-06-17 12:08:29 -07:00
F. Eugene Aumson
187dd2fdc3 asset-swapper: Prune dead code 2020-06-17 14:56:39 -04:00
F. Eugene Aumson
c18f3f0b33 asset-s: use RFQT-specific types in MarketOpUtils 2020-06-17 14:56:04 -04:00
F. Eugene Aumson
7162935028 asset-s: use RFQT-specific types in MarketOpUtils 2020-06-17 10:39:48 -04:00
Lawrence Forman
9215a73b6c Merge pull request #2604 from 0xProject/feat/order-utils/transformer-encoders
order-utils: ERC20 Transformer utils
2020-06-17 09:32:43 -04:00
Lawrence Forman
edd840794c @0x/asset-swapper: Fix linter errors. 2020-06-17 02:12:32 -04:00
Lawrence Forman
c30a6eb1aa @0x/contracts-zero-ex: Fix linter errors. 2020-06-17 01:23:08 -04:00
Lawrence Forman
233642af29 @0x/asset-swapper: Remove dependency on contracts-zero-ex. 2020-06-17 01:23:08 -04:00
Lawrence Forman
7dffd0a03e @0x/contracts-zero-ex: Use transformer utils from order-utils. 2020-06-17 01:23:08 -04:00
Lawrence Forman
f7bc3ff49d @0x/order-utils: Add ERC20 Transformer utils and export useful constants. 2020-06-17 01:23:08 -04:00
Lawrence Forman
53aabe3cdb Merge pull request #2605 from 0xProject/feat/zero-ex/transform-erc20-make-creatTransformWallet-onlyOwner
Flip `TransformERC20.createTransformWallet()` to `onlyOwner`
2020-06-17 01:17:43 -04:00
Lawrence Forman
09b8d7cfc9 @0x/contracts-zero-ex: Flip TransformERC20.createTransformWallet() to onlyOwner. 2020-06-16 18:07:03 -04:00
F. Eugene Aumson
1512afc7e6 CI: persist test-publish npm logs as Artifacts 2020-06-16 17:33:30 -04:00
F. Eugene Aumson
dde0c76112 Merge branch 'development' into feat/asset-swapper/use-quote-server 2020-06-16 10:26:56 -04:00
F. Eugene Aumson
ad868af96e asset-swapper: use RFQT-specific response types
@0x/quote-server was recently updated to offer RFQT- and RFQM-specific
types, in addition to abstracted types.  Since everything here is RFQT
specific, usage has been changed to use those specific types.

Addresses review comments
https://github.com/0xProject/0x-monorepo/pull/2582#discussion_r437623138
and
https://github.com/0xProject/0x-monorepo/pull/2582#discussion_r437625305
2020-06-11 15:57:49 -04:00
F. Eugene Aumson
f7cd7110ea asset-s: Remove erroneous addition of API key
It was added due to the introduction of the use of the TakerRequest type
from @0x/quote-server, as it's included in that structure.  However,
that structure is primarily used within the quote server as the output
of parameter parsing, and that parsing routine transforms the API key
HEADER from the request into the TakerRequest type.  In short, the API
key is input as a header, not a parameter.

Addresses review comment
https://github.com/0xProject/0x-monorepo/pull/2582#discussion_r437624647
2020-06-11 14:17:45 -04:00
F. Eugene Aumson
d5d07dd34e Merge branch 'development' into feat/asset-swapper/use-quote-server 2020-06-08 19:15:07 -04:00
F. Eugene Aumson
b91cc3781d asset-swapper: Use newer @0x/quote-server 2020-06-08 18:07:59 -04:00
F. Eugene Aumson
1b8b9186a8 asset-swapper: Fix test-publish 2020-05-26 18:46:19 -04:00
F. Eugene Aumson
a8cfcfb371 Fix test-publish CI failure 2020-05-26 15:24:43 -04:00
F. Eugene Aumson
f7a414bc29 asset-s/RFQ: adapt to renamed TakerRequest fields 2020-05-26 15:24:42 -04:00
F. Eugene Aumson
e05cd1d66b asset-s/QuoteRequestor: use TakerRequest type 2020-05-26 15:24:38 -04:00
F. Eugene Aumson
b9984b6df4 asset-swapper: fix bug: bad maker response throws
Formerly, a maker sending back a non-JSON was causing an exception to be
thrown.
2020-05-15 01:20:30 -04:00
F. Eugene Aumson
9c11835fee asset-s: use @0x/quote-server, not local typedefs 2020-05-15 01:20:29 -04:00
294 changed files with 8920 additions and 4026 deletions

View File

@@ -91,6 +91,8 @@ jobs:
- run:
command: yarn test:publish:circleci
no_output_timeout: 1800
- store_artifacts:
path: ~/.npm/_logs
test-doc-generation:
docker:
- image: nikolaik/python-nodejs:python3.7-nodejs8

View File

@@ -1,4 +1,18 @@
[
{
"version": "3.4.0",
"changes": [
{
"note": "Fix instability with DFB.",
"pr": 2616
},
{
"note": "Add `BalancerBridge`",
"pr": 2613
}
],
"timestamp": 1594788383
},
{
"version": "3.3.0",
"changes": [

View File

@@ -5,6 +5,11 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v3.4.0 - _July 15, 2020_
* Fix instability with DFB. (#2616)
* Add `BalancerBridge` (#2613)
## v3.3.0 - _June 24, 2020_
* Use `LibERC20Token.approveIfBelow()` in DEX bridges for for approvals. (#2512)

View File

@@ -0,0 +1,103 @@
/*
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-utils/contracts/src/DeploymentConstants.sol";
import "../interfaces/IERC20Bridge.sol";
import "../interfaces/IBalancerPool.sol";
contract BalancerBridge is
IERC20Bridge,
IWallet,
DeploymentConstants
{
/// @dev Callback for `IERC20Bridge`. Tries to buy `amount` of
/// `toTokenAddress` tokens by selling the entirety of the `fromTokenAddress`
/// token encoded in the bridge data, then transfers the bought
/// tokens to `to`.
/// @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 addresses of the "from" token and Balancer pool.
/// @return success The magic bytes if successful.
function bridgeTransferFrom(
address toTokenAddress,
address from,
address to,
uint256 amount,
bytes calldata bridgeData
)
external
returns (bytes4 success)
{
// Decode the bridge data.
(address fromTokenAddress, address poolAddress) = abi.decode(
bridgeData,
(address, address)
);
require(toTokenAddress != fromTokenAddress, "BalancerBridge/INVALID_PAIR");
uint256 fromTokenBalance = IERC20Token(fromTokenAddress).balanceOf(address(this));
// Grant an allowance to the exchange to spend `fromTokenAddress` token.
LibERC20Token.approveIfBelow(fromTokenAddress, poolAddress, fromTokenBalance);
// Sell all of this contract's `fromTokenAddress` token balance.
(uint256 boughtAmount,) = IBalancerPool(poolAddress).swapExactAmountIn(
fromTokenAddress, // tokenIn
fromTokenBalance, // tokenAmountIn
toTokenAddress, // tokenOut
amount, // minAmountOut
uint256(-1) // maxPrice
);
// Transfer the converted `toToken`s to `to`.
LibERC20Token.transfer(toTokenAddress, to, boughtAmount);
emit ERC20BridgeTransfer(
fromTokenAddress,
toTokenAddress,
fromTokenBalance,
boughtAmount,
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

@@ -75,14 +75,18 @@ contract DexForwarderBridge is
freesGasTokensFromCollector
returns (bytes4 success)
{
require(msg.sender == _getERC20BridgeProxyAddress(), "DexForwarderBridge/SENDER_NOT_AUTHORIZED");
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));
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.
@@ -122,11 +126,6 @@ contract DexForwarderBridge is
);
}
}
// 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;
}

View File

@@ -0,0 +1,39 @@
/*
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 IBalancerPool {
/// @dev Sell `tokenAmountIn` of `tokenIn` and receive `tokenOut`.
/// @param tokenIn The token being sold
/// @param tokenAmountIn The amount of `tokenIn` to sell.
/// @param tokenOut The token being bought.
/// @param minAmountOut The minimum amount of `tokenOut` to buy.
/// @param maxPrice The maximum value for `spotPriceAfter`.
/// @return tokenAmountOut The amount of `tokenOut` bought.
/// @return spotPriceAfter The new marginal spot price of the given
/// token pair for this pool.
function swapExactAmountIn(
address tokenIn,
uint tokenAmountIn,
address tokenOut,
uint minAmountOut,
uint maxPrice
) external returns (uint tokenAmountOut, uint spotPriceAfter);
}

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/contracts-asset-proxy",
"version": "3.3.0",
"version": "3.4.0",
"engines": {
"node": ">=6.12"
},
@@ -38,7 +38,7 @@
"docs:json": "typedoc --excludePrivate --excludeExternals --excludeProtected --ignoreCompilerErrors --target ES5 --tsconfig typedoc-tsconfig.json --json $JSON_FILE_PATH $PROJECT_FILES"
},
"config": {
"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": "./test/generated-artifacts/@(BalancerBridge|ChaiBridge|CurveBridge|DexForwarderBridge|DydxBridge|ERC1155Proxy|ERC20BridgeProxy|ERC20Proxy|ERC721Proxy|Eth2DaiBridge|IAssetData|IAssetProxy|IAssetProxyDispatcher|IAuthorizable|IBalancerPool|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": {
@@ -51,15 +51,15 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/protocol/README.md",
"devDependencies": {
"@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/abi-gen": "^5.3.1",
"@0x/contract-wrappers": "^13.8.0",
"@0x/contracts-gen": "^2.0.10",
"@0x/contracts-test-utils": "^5.3.4",
"@0x/contracts-utils": "^4.5.1",
"@0x/dev-utils": "^3.3.0",
"@0x/sol-compiler": "^4.1.1",
"@0x/ts-doc-gen": "^0.0.22",
"@0x/tslint-config": "^4.0.0",
"@0x/tslint-config": "^4.1.0",
"@types/lodash": "4.14.104",
"@types/mocha": "^5.2.7",
"@types/node": "*",
@@ -79,20 +79,21 @@
"typescript": "3.0.1"
},
"dependencies": {
"@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",
"@0x/base-contract": "^6.2.3",
"@0x/contracts-erc1155": "^2.1.7",
"@0x/contracts-erc20": "^3.2.1",
"@0x/contracts-erc721": "^3.1.7",
"@0x/contracts-exchange-libs": "^4.3.7",
"@0x/order-utils": "^10.3.0",
"@0x/types": "^3.2.0",
"@0x/typescript-typings": "^5.1.1",
"@0x/utils": "^5.5.1",
"@0x/web3-wrapper": "^7.2.0",
"ethereum-types": "^3.2.0",
"lodash": "^4.17.11"
},
"publishConfig": {
"access": "public"
}
},
"gitHead": "4f91bfd907996b2f4dd383778b50c479c2602b56"
}

View File

@@ -5,6 +5,7 @@
*/
import { ContractArtifact } from 'ethereum-types';
import * as BalancerBridge from '../generated-artifacts/BalancerBridge.json';
import * as ChaiBridge from '../generated-artifacts/ChaiBridge.json';
import * as CurveBridge from '../generated-artifacts/CurveBridge.json';
import * as DexForwarderBridge from '../generated-artifacts/DexForwarderBridge.json';
@@ -18,6 +19,7 @@ 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 IBalancerPool from '../generated-artifacts/IBalancerPool.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';
@@ -57,6 +59,7 @@ export const artifacts = {
ERC721Proxy: ERC721Proxy as ContractArtifact,
MultiAssetProxy: MultiAssetProxy as ContractArtifact,
StaticCallProxy: StaticCallProxy as ContractArtifact,
BalancerBridge: BalancerBridge as ContractArtifact,
ChaiBridge: ChaiBridge as ContractArtifact,
CurveBridge: CurveBridge as ContractArtifact,
DexForwarderBridge: DexForwarderBridge as ContractArtifact,
@@ -70,6 +73,7 @@ export const artifacts = {
IAssetProxy: IAssetProxy as ContractArtifact,
IAssetProxyDispatcher: IAssetProxyDispatcher as ContractArtifact,
IAuthorizable: IAuthorizable as ContractArtifact,
IBalancerPool: IBalancerPool as ContractArtifact,
IChai: IChai as ContractArtifact,
ICurve: ICurve as ContractArtifact,
IDydx: IDydx as ContractArtifact,

View File

@@ -1,5 +1,6 @@
export { artifacts } from './artifacts';
export {
BalancerBridgeContract,
ChaiBridgeContract,
ERC1155ProxyContract,
ERC20BridgeProxyContract,

View File

@@ -3,6 +3,7 @@
* Warning: This file is auto-generated by contracts-gen. Don't edit manually.
* -----------------------------------------------------------------------------
*/
export * from '../generated-wrappers/balancer_bridge';
export * from '../generated-wrappers/chai_bridge';
export * from '../generated-wrappers/curve_bridge';
export * from '../generated-wrappers/dex_forwarder_bridge';
@@ -16,6 +17,7 @@ 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_balancer_pool';
export * from '../generated-wrappers/i_chai';
export * from '../generated-wrappers/i_curve';
export * from '../generated-wrappers/i_dydx';

View File

@@ -5,6 +5,7 @@
*/
import { ContractArtifact } from 'ethereum-types';
import * as BalancerBridge from '../test/generated-artifacts/BalancerBridge.json';
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';
@@ -18,6 +19,7 @@ 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 IBalancerPool from '../test/generated-artifacts/IBalancerPool.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';
@@ -57,6 +59,7 @@ export const artifacts = {
ERC721Proxy: ERC721Proxy as ContractArtifact,
MultiAssetProxy: MultiAssetProxy as ContractArtifact,
StaticCallProxy: StaticCallProxy as ContractArtifact,
BalancerBridge: BalancerBridge as ContractArtifact,
ChaiBridge: ChaiBridge as ContractArtifact,
CurveBridge: CurveBridge as ContractArtifact,
DexForwarderBridge: DexForwarderBridge as ContractArtifact,
@@ -70,6 +73,7 @@ export const artifacts = {
IAssetProxy: IAssetProxy as ContractArtifact,
IAssetProxyDispatcher: IAssetProxyDispatcher as ContractArtifact,
IAuthorizable: IAuthorizable as ContractArtifact,
IBalancerPool: IBalancerPool as ContractArtifact,
IChai: IChai as ContractArtifact,
ICurve: ICurve as ContractArtifact,
IDydx: IDydx as ContractArtifact,

View File

@@ -30,7 +30,6 @@ blockchainTests.resets('DexForwarderBridge unit tests', env => {
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(),
@@ -165,27 +164,26 @@ blockchainTests.resets('DexForwarderBridge unit tests', env => {
await callBridgeTransferFromAsync({ bridgeData, sellAmount: ZERO_AMOUNT });
});
it('fails with no bridge calls and an input balance', async () => {
it('succeeds 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,
);
await callBridgeTransferFromAsync({
bridgeData,
sellAmount: new BigNumber(1),
});
});
it('fails if entire input token balance is not consumed', async () => {
it('succeeds 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);
await callBridgeTransferFromAsync({
bridgeData,
sellAmount: totalFillableInputAmount.plus(1),
});
});
it('fails if not authorized', async () => {

View File

@@ -3,6 +3,7 @@
* Warning: This file is auto-generated by contracts-gen. Don't edit manually.
* -----------------------------------------------------------------------------
*/
export * from '../test/generated-wrappers/balancer_bridge';
export * from '../test/generated-wrappers/chai_bridge';
export * from '../test/generated-wrappers/curve_bridge';
export * from '../test/generated-wrappers/dex_forwarder_bridge';
@@ -16,6 +17,7 @@ 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_balancer_pool';
export * from '../test/generated-wrappers/i_chai';
export * from '../test/generated-wrappers/i_curve';
export * from '../test/generated-wrappers/i_dydx';

View File

@@ -3,6 +3,7 @@
"compilerOptions": { "outDir": "lib", "rootDir": ".", "resolveJsonModule": true },
"include": ["./src/**/*", "./test/**/*", "./generated-wrappers/**/*"],
"files": [
"generated-artifacts/BalancerBridge.json",
"generated-artifacts/ChaiBridge.json",
"generated-artifacts/CurveBridge.json",
"generated-artifacts/DexForwarderBridge.json",
@@ -16,6 +17,7 @@
"generated-artifacts/IAssetProxy.json",
"generated-artifacts/IAssetProxyDispatcher.json",
"generated-artifacts/IAuthorizable.json",
"generated-artifacts/IBalancerPool.json",
"generated-artifacts/IChai.json",
"generated-artifacts/ICurve.json",
"generated-artifacts/IDydx.json",
@@ -45,6 +47,7 @@
"generated-artifacts/TestUniswapV2Bridge.json",
"generated-artifacts/UniswapBridge.json",
"generated-artifacts/UniswapV2Bridge.json",
"test/generated-artifacts/BalancerBridge.json",
"test/generated-artifacts/ChaiBridge.json",
"test/generated-artifacts/CurveBridge.json",
"test/generated-artifacts/DexForwarderBridge.json",
@@ -58,6 +61,7 @@
"test/generated-artifacts/IAssetProxy.json",
"test/generated-artifacts/IAssetProxyDispatcher.json",
"test/generated-artifacts/IAuthorizable.json",
"test/generated-artifacts/IBalancerPool.json",
"test/generated-artifacts/IChai.json",
"test/generated-artifacts/ICurve.json",
"test/generated-artifacts/IDydx.json",

View File

@@ -1,4 +1,13 @@
[
{
"timestamp": 1594788383,
"version": "1.1.6",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"version": "1.1.5",
"changes": [

View File

@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v1.1.6 - _July 15, 2020_
* Dependencies updated
## v1.1.5 - _June 24, 2020_
* Fix broken tests. (#2591)

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/contracts-broker",
"version": "1.1.5",
"version": "1.1.6",
"engines": {
"node": ">=6.12"
},
@@ -51,20 +51,20 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/extensions/README.md",
"devDependencies": {
"@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/abi-gen": "^5.3.1",
"@0x/contracts-asset-proxy": "^3.4.0",
"@0x/contracts-erc20": "^3.2.1",
"@0x/contracts-erc721": "^3.1.7",
"@0x/contracts-exchange": "^3.2.7",
"@0x/contracts-exchange-libs": "^4.3.7",
"@0x/contracts-gen": "^2.0.10",
"@0x/contracts-test-utils": "^5.3.4",
"@0x/contracts-utils": "^4.5.1",
"@0x/sol-compiler": "^4.1.1",
"@0x/ts-doc-gen": "^0.0.22",
"@0x/tslint-config": "^4.0.0",
"@0x/types": "^3.1.3",
"@0x/web3-wrapper": "^7.1.0",
"@0x/tslint-config": "^4.1.0",
"@0x/types": "^3.2.0",
"@0x/web3-wrapper": "^7.2.0",
"@types/lodash": "4.14.104",
"@types/mocha": "^5.2.7",
"@types/node": "*",
@@ -84,13 +84,14 @@
"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"
"@0x/base-contract": "^6.2.3",
"@0x/order-utils": "^10.3.0",
"@0x/typescript-typings": "^5.1.1",
"@0x/utils": "^5.5.1",
"ethereum-types": "^3.2.0"
},
"publishConfig": {
"access": "public"
}
},
"gitHead": "4f91bfd907996b2f4dd383778b50c479c2602b56"
}

View File

@@ -1,4 +1,13 @@
[
{
"timestamp": 1594788383,
"version": "3.1.7",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1592969527,
"version": "3.1.6",

View File

@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v3.1.7 - _July 15, 2020_
* Dependencies updated
## v3.1.6 - _June 24, 2020_
* Dependencies updated

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/contracts-coordinator",
"version": "3.1.6",
"version": "3.1.7",
"engines": {
"node": ">=6.12"
},
@@ -52,19 +52,19 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/extensions/README.md",
"devDependencies": {
"@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/abi-gen": "^5.3.1",
"@0x/contracts-asset-proxy": "^3.4.0",
"@0x/contracts-dev-utils": "^1.3.5",
"@0x/contracts-erc20": "^3.2.1",
"@0x/contracts-exchange": "^3.2.7",
"@0x/contracts-gen": "^2.0.10",
"@0x/contracts-test-utils": "^5.3.4",
"@0x/dev-utils": "^3.3.0",
"@0x/order-utils": "^10.3.0",
"@0x/sol-compiler": "^4.1.1",
"@0x/ts-doc-gen": "^0.0.22",
"@0x/tslint-config": "^4.0.0",
"@0x/web3-wrapper": "^7.1.0",
"@0x/tslint-config": "^4.1.0",
"@0x/web3-wrapper": "^7.2.0",
"@types/lodash": "4.14.104",
"@types/mocha": "^5.2.7",
"@types/node": "*",
@@ -84,18 +84,19 @@
"typescript": "3.0.1"
},
"dependencies": {
"@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",
"@0x/assert": "^3.0.9",
"@0x/base-contract": "^6.2.3",
"@0x/contract-addresses": "^4.11.0",
"@0x/contracts-utils": "^4.5.1",
"@0x/json-schemas": "^5.1.0",
"@0x/types": "^3.2.0",
"@0x/typescript-typings": "^5.1.1",
"@0x/utils": "^5.5.1",
"ethereum-types": "^3.2.0",
"http-status-codes": "^1.3.2"
},
"publishConfig": {
"access": "public"
}
},
"gitHead": "4f91bfd907996b2f4dd383778b50c479c2602b56"
}

View File

@@ -1,4 +1,13 @@
[
{
"timestamp": 1594788383,
"version": "1.3.5",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1592969527,
"version": "1.3.4",

View File

@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v1.3.5 - _July 15, 2020_
* Dependencies updated
## v1.3.4 - _June 24, 2020_
* Dependencies updated

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/contracts-dev-utils",
"version": "1.3.4",
"version": "1.3.5",
"engines": {
"node": ">=6.12"
},
@@ -41,19 +41,19 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/dev-utils/README.md",
"devDependencies": {
"@0x/abi-gen": "^5.3.0",
"@0x/assert": "^3.0.8",
"@0x/contracts-asset-proxy": "^3.3.0",
"@0x/contracts-erc20": "^3.2.0",
"@0x/contracts-gen": "^2.0.9",
"@0x/contracts-test-utils": "^5.3.3",
"@0x/sol-compiler": "^4.1.0",
"@0x/abi-gen": "^5.3.1",
"@0x/assert": "^3.0.9",
"@0x/contracts-asset-proxy": "^3.4.0",
"@0x/contracts-erc20": "^3.2.1",
"@0x/contracts-gen": "^2.0.10",
"@0x/contracts-test-utils": "^5.3.4",
"@0x/sol-compiler": "^4.1.1",
"@0x/ts-doc-gen": "^0.0.22",
"@0x/tslint-config": "^4.0.0",
"@0x/types": "^3.1.3",
"@0x/utils": "^5.5.0",
"@0x/tslint-config": "^4.1.0",
"@0x/types": "^3.2.0",
"@0x/utils": "^5.5.1",
"@types/node": "*",
"ethereum-types": "^3.1.1",
"ethereum-types": "^3.2.0",
"ethers": "~4.0.4",
"npm-run-all": "^4.1.2",
"shx": "^0.2.2",
@@ -64,9 +64,10 @@
"typescript": "3.0.1"
},
"dependencies": {
"@0x/base-contract": "^6.2.2"
"@0x/base-contract": "^6.2.3"
},
"publishConfig": {
"access": "public"
}
},
"gitHead": "4f91bfd907996b2f4dd383778b50c479c2602b56"
}

View File

@@ -1,4 +1,13 @@
[
{
"timestamp": 1594788383,
"version": "2.1.7",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1592969527,
"version": "2.1.6",

View File

@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v2.1.7 - _July 15, 2020_
* Dependencies updated
## v2.1.6 - _June 24, 2020_
* Dependencies updated

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/contracts-erc1155",
"version": "2.1.6",
"version": "2.1.7",
"engines": {
"node": ">=6.12"
},
@@ -52,15 +52,15 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/tokens/README.md",
"devDependencies": {
"@0x/abi-gen": "^5.3.0",
"@0x/contracts-gen": "^2.0.9",
"@0x/contracts-utils": "^4.5.0",
"@0x/dev-utils": "^3.2.2",
"@0x/sol-compiler": "^4.1.0",
"@0x/abi-gen": "^5.3.1",
"@0x/contracts-gen": "^2.0.10",
"@0x/contracts-utils": "^4.5.1",
"@0x/dev-utils": "^3.3.0",
"@0x/sol-compiler": "^4.1.1",
"@0x/ts-doc-gen": "^0.0.22",
"@0x/tslint-config": "^4.0.0",
"@0x/types": "^3.1.3",
"@0x/typescript-typings": "^5.1.0",
"@0x/tslint-config": "^4.1.0",
"@0x/types": "^3.2.0",
"@0x/typescript-typings": "^5.1.1",
"@types/lodash": "4.14.104",
"@types/mocha": "^5.2.7",
"@types/node": "*",
@@ -68,7 +68,7 @@
"chai-as-promised": "^7.1.0",
"chai-bignumber": "^3.0.0",
"dirty-chai": "^2.0.1",
"ethereum-types": "^3.1.1",
"ethereum-types": "^3.2.0",
"make-promises-safe": "^1.1.0",
"mocha": "^6.2.0",
"npm-run-all": "^4.1.2",
@@ -80,13 +80,14 @@
"typescript": "3.0.1"
},
"dependencies": {
"@0x/base-contract": "^6.2.2",
"@0x/contracts-test-utils": "^5.3.3",
"@0x/utils": "^5.5.0",
"@0x/web3-wrapper": "^7.1.0",
"@0x/base-contract": "^6.2.3",
"@0x/contracts-test-utils": "^5.3.4",
"@0x/utils": "^5.5.1",
"@0x/web3-wrapper": "^7.2.0",
"lodash": "^4.17.11"
},
"publishConfig": {
"access": "public"
}
},
"gitHead": "4f91bfd907996b2f4dd383778b50c479c2602b56"
}

View File

@@ -1,4 +1,18 @@
[
{
"version": "1.7.0",
"changes": [
{
"note": "Pass in `DevUtils` address to required functions",
"pr": 2629
},
{
"note": "Use new Kyber Katalyst functions",
"pr": 2629
}
],
"timestamp": 1594788383
},
{
"version": "1.6.0",
"changes": [

View File

@@ -5,6 +5,11 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v1.7.0 - _July 15, 2020_
* Pass in `DevUtils` address to required functions (#2629)
* Use new Kyber Katalyst functions (#2629)
## v1.6.0 - _June 24, 2020_
* Pass in `DevUtils` address as a constructor parameter (#2531)

View File

@@ -30,6 +30,8 @@ import "./IERC20BridgeSampler.sol";
import "./IEth2Dai.sol";
import "./IKyberNetwork.sol";
import "./IKyberNetworkProxy.sol";
import "./IKyberStorage.sol";
import "./IKyberHintHandler.sol";
import "./IUniswapExchangeQuotes.sol";
import "./ICurve.sol";
import "./ILiquidityProvider.sol";
@@ -58,16 +60,12 @@ contract ERC20BridgeSampler is
/// @dev Default gas limit for liquidity provider calls.
uint256 constant internal DEFAULT_CALL_GAS = 400e3; // 400k
/// @dev The Kyber Uniswap Reserve address
address constant internal KYBER_UNIWAP_RESERVE = 0x31E085Afd48a1d6e51Cc193153d625e8f0514C7F;
address constant internal KYBER_UNISWAP_RESERVE = 0x31E085Afd48a1d6e51Cc193153d625e8f0514C7F;
/// @dev The Kyber Uniswap V2 Reserve address
address constant internal KYBER_UNISWAPV2_RESERVE = 0x10908C875D865C66f271F5d3949848971c9595C9;
/// @dev The Kyber Eth2Dai Reserve address
address constant internal KYBER_ETH2DAI_RESERVE = 0x1E158c0e93c30d24e918Ef83d1e0bE23595C3c0f;
address private _devUtilsAddress;
constructor(address devUtilsAddress) public {
_devUtilsAddress = devUtilsAddress;
}
/// @dev Call multiple public functions on this contract in a single transaction.
/// @param callDatas ABI-encoded call data for each function call.
/// @return callResults ABI-encoded results data for each call.
@@ -91,18 +89,19 @@ contract ERC20BridgeSampler is
/// maker/taker asset amounts (returning 0).
/// @param orders Native orders to query.
/// @param orderSignatures Signatures for each respective order in `orders`.
/// @param devUtilsAddress Address to the DevUtils contract.
/// @return orderFillableTakerAssetAmounts How much taker asset can be filled
/// by each order in `orders`.
function getOrderFillableTakerAssetAmounts(
LibOrder.Order[] memory orders,
bytes[] memory orderSignatures
bytes[] memory orderSignatures,
address devUtilsAddress
)
public
view
returns (uint256[] memory orderFillableTakerAssetAmounts)
{
orderFillableTakerAssetAmounts = new uint256[](orders.length);
address devUtilsAddress = _devUtilsAddress;
for (uint256 i = 0; i != orders.length; i++) {
// Ignore orders with no signature or empty maker/taker amounts.
if (orderSignatures[i].length == 0 ||
@@ -149,11 +148,13 @@ contract ERC20BridgeSampler is
/// Effectively ignores orders that have empty signatures or
/// @param orders Native orders to query.
/// @param orderSignatures Signatures for each respective order in `orders`.
/// @param devUtilsAddress Address to the DevUtils contract.
/// @return orderFillableMakerAssetAmounts How much maker asset can be filled
/// by each order in `orders`.
function getOrderFillableMakerAssetAmounts(
LibOrder.Order[] memory orders,
bytes[] memory orderSignatures
bytes[] memory orderSignatures,
address devUtilsAddress
)
public
view
@@ -161,7 +162,8 @@ contract ERC20BridgeSampler is
{
orderFillableMakerAssetAmounts = getOrderFillableTakerAssetAmounts(
orders,
orderSignatures
orderSignatures,
devUtilsAddress
);
// `orderFillableMakerAssetAmounts` now holds taker asset amounts, so
// convert them to maker asset amounts.
@@ -196,26 +198,15 @@ contract ERC20BridgeSampler is
makerTokenAmounts = new uint256[](numSamples);
address wethAddress = _getWethAddress();
uint256 value;
address reserve;
for (uint256 i = 0; i < numSamples; i++) {
if (takerToken == wethAddress || makerToken == wethAddress) {
// Direct ETH based trade
(value, reserve) = _sampleSellFromKyberNetwork(takerToken, makerToken, takerTokenAmounts[i]);
// If this fills on an on-chain reserve we remove it as that can introduce collisions
if (reserve == KYBER_UNIWAP_RESERVE || reserve == KYBER_ETH2DAI_RESERVE) {
value = 0;
}
value = _sampleSellFromKyberNetwork(takerToken, makerToken, takerTokenAmounts[i]);
} else {
// Hop to ETH
(value, reserve) = _sampleSellFromKyberNetwork(takerToken, wethAddress, takerTokenAmounts[i]);
value = _sampleSellFromKyberNetwork(takerToken, wethAddress, takerTokenAmounts[i]);
if (value != 0) {
address otherReserve;
(value, otherReserve) = _sampleSellFromKyberNetwork(wethAddress, makerToken, value);
// If this fills on Eth2Dai it is ok as we queried a different market
// If this fills on Uniswap on both legs then this is a hard collision
if (reserve == KYBER_UNIWAP_RESERVE && reserve == otherReserve) {
value = 0;
}
value = _sampleSellFromKyberNetwork(wethAddress, makerToken, value);
}
}
makerTokenAmounts[i] = value;
@@ -960,6 +951,25 @@ contract ERC20BridgeSampler is
}
}
function _appendToList(bytes32[] memory list, bytes32 item) private view returns (bytes32[] memory appendedList)
{
appendedList = new bytes32[](list.length + 1);
for (uint256 i = 0; i < list.length; i++) {
appendedList[i] = list[i];
}
appendedList[appendedList.length - 1] = item;
}
function _getKyberAddresses()
private
view
returns (IKyberHintHandler kyberHint, IKyberStorage kyberStorage)
{
(, , kyberHint, kyberStorage, ,) = IKyberNetwork(
IKyberNetworkProxy(_getKyberNetworkProxyAddress()).kyberNetwork()).getContracts();
return (IKyberHintHandler(kyberHint), IKyberStorage(kyberStorage));
}
function _sampleSellFromKyberNetwork(
address takerToken,
address makerToken,
@@ -967,43 +977,67 @@ contract ERC20BridgeSampler is
)
private
view
returns (uint256 makerTokenAmount, address reserve)
returns (uint256 makerTokenAmount)
{
address _takerToken = takerToken == _getWethAddress() ? KYBER_ETH_ADDRESS : takerToken;
address _makerToken = makerToken == _getWethAddress() ? KYBER_ETH_ADDRESS : makerToken;
uint256 takerTokenDecimals = _getTokenDecimals(takerToken);
uint256 makerTokenDecimals = _getTokenDecimals(makerToken);
(bool didSucceed, bytes memory resultData) = _getKyberNetworkProxyAddress().staticcall.gas(DEFAULT_CALL_GAS)(
abi.encodeWithSelector(
IKyberNetworkProxy(0).kyberNetworkContract.selector
));
if (!didSucceed) {
return (0, address(0));
(IKyberHintHandler kyberHint, IKyberStorage kyberStorage) = _getKyberAddresses();
// Ban reserves which can clash with our internal aggregation
bytes32[] memory reserveIds = kyberStorage.getReserveIdsPerTokenSrc(
takerToken == _getWethAddress() ? makerToken : takerToken
);
bytes32[] memory bannedReserveIds = new bytes32[](0);
// Poor mans resize and append
for (uint256 i = 0; i < reserveIds.length; i++) {
if (
reserveIds[i] == kyberStorage.getReserveId(KYBER_UNISWAP_RESERVE) ||
reserveIds[i] == kyberStorage.getReserveId(KYBER_UNISWAPV2_RESERVE) ||
reserveIds[i] == kyberStorage.getReserveId(KYBER_ETH2DAI_RESERVE)
) {
bannedReserveIds = _appendToList(bannedReserveIds, reserveIds[i]);
}
}
address kyberNetworkContract = abi.decode(resultData, (address));
(didSucceed, resultData) =
kyberNetworkContract.staticcall.gas(KYBER_CALL_GAS)(
// Sampler either detects X->ETH/ETH->X
// or subsamples as X->ETH-Y. So token->token here is not possible
bytes memory hint;
if (takerToken == _getWethAddress()) {
// ETH -> X
hint = kyberHint.buildEthToTokenHint(
makerToken,
IKyberHintHandler.TradeType.MaskOut,
bannedReserveIds,
new uint256[](0));
} else {
// X->ETH
hint = kyberHint.buildEthToTokenHint(
takerToken,
IKyberHintHandler.TradeType.MaskOut,
bannedReserveIds,
new uint256[](0));
}
(bool didSucceed, bytes memory resultData) =
_getKyberNetworkProxyAddress().staticcall.gas(KYBER_CALL_GAS)(
abi.encodeWithSelector(
IKyberNetwork(0).searchBestRate.selector,
_takerToken,
_makerToken,
IKyberNetworkProxy(0).getExpectedRateAfterFee.selector,
takerToken == _getWethAddress() ? KYBER_ETH_ADDRESS : takerToken,
makerToken == _getWethAddress() ? KYBER_ETH_ADDRESS : makerToken,
takerTokenAmount,
false // usePermissionless
0, // fee
hint
));
uint256 rate = 0;
address reserve;
if (didSucceed) {
(reserve, rate) = abi.decode(resultData, (address, uint256));
(rate) = abi.decode(resultData, (uint256));
} else {
return (0, address(0));
return 0;
}
uint256 makerTokenDecimals = _getTokenDecimals(makerToken);
uint256 takerTokenDecimals = _getTokenDecimals(takerToken);
makerTokenAmount =
rate *
takerTokenAmount *
10 ** makerTokenDecimals /
10 ** takerTokenDecimals /
10 ** 18;
return (makerTokenAmount, reserve);
return makerTokenAmount;
}
}

View File

@@ -40,11 +40,13 @@ interface IERC20BridgeSampler {
/// @dev Queries the fillable taker asset amounts of native orders.
/// @param orders Native orders to query.
/// @param orderSignatures Signatures for each respective order in `orders`.
/// @param devUtilsAddress Address to the DevUtils contract.
/// @return orderFillableTakerAssetAmounts How much taker asset can be filled
/// by each order in `orders`.
function getOrderFillableTakerAssetAmounts(
LibOrder.Order[] calldata orders,
bytes[] calldata orderSignatures
bytes[] calldata orderSignatures,
address devUtilsAddress
)
external
view
@@ -53,11 +55,13 @@ interface IERC20BridgeSampler {
/// @dev Queries the fillable maker asset amounts of native orders.
/// @param orders Native orders to query.
/// @param orderSignatures Signatures for each respective order in `orders`.
/// @param devUtilsAddress Address to the DevUtils contract.
/// @return orderFillableMakerAssetAmounts How much maker asset can be filled
/// by each order in `orders`.
function getOrderFillableMakerAssetAmounts(
LibOrder.Order[] calldata orders,
bytes[] calldata orderSignatures
bytes[] calldata orderSignatures,
address devUtilsAddress
)
external
view

View File

@@ -0,0 +1,52 @@
/*
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 IKyberHintHandler {
function kyberStorage() external returns (address);
enum TradeType {BestOfAll, MaskIn, MaskOut, Split}
function buildTokenToEthHint(
address tokenSrc,
TradeType tokenToEthType,
bytes32[] calldata tokenToEthReserveIds,
uint256[] calldata tokenToEthSplits
) external view returns (bytes memory hint);
function buildEthToTokenHint(
address tokenDest,
TradeType ethToTokenType,
bytes32[] calldata ethToTokenReserveIds,
uint256[] calldata ethToTokenSplits
) external view returns (bytes memory hint);
function buildTokenToTokenHint(
address tokenSrc,
TradeType tokenToEthType,
bytes32[] calldata tokenToEthReserveIds,
uint256[] calldata tokenToEthSplits,
address tokenDest,
TradeType ethToTokenType,
bytes32[] calldata ethToTokenReserveIds,
uint256[] calldata ethToTokenSplits
) external view returns (bytes memory hint);
}

View File

@@ -1,6 +1,6 @@
/*
Copyright 2019 ZeroEx Intl.
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.
@@ -18,16 +18,20 @@
pragma solidity ^0.5.9;
import "./IKyberStorage.sol";
import "./IKyberHintHandler.sol";
interface IKyberNetwork {
function searchBestRate(
address fromToken,
address toToken,
uint256 fromAmount,
bool usePermissionless
)
function getContracts()
external
view
returns (address reserve, uint256 expectedRate);
returns (
address kyberFeeHandlerAddress,
address kyberDaoAddress,
IKyberHintHandler kyberMatchingEngineAddress,
IKyberStorage kyberStorageAddress,
address gasHelperAddress,
address[] memory kyberProxyAddresses);
}

View File

@@ -1,6 +1,6 @@
/*
Copyright 2019 ZeroEx Intl.
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.
@@ -21,14 +21,14 @@ pragma solidity ^0.5.9;
interface IKyberNetworkProxy {
function kyberNetworkContract() external view returns (address);
function kyberNetwork() external view returns (address);
function kyberHintHandler() external view returns (address);
function getExpectedRate(
address fromToken,
address toToken,
uint256 fromAmount
)
external
view
returns (uint256 expectedRate, uint256 slippageRate);
function getExpectedRateAfterFee(
address src,
address dest,
uint256 srcQty,
uint256 platformFeeBps,
bytes calldata hint
) external view returns (uint256 expectedRate);
}

View File

@@ -0,0 +1,37 @@
/*
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 IKyberStorage {
function getReserveId(
address reserve
)
external
view
returns (bytes32 reserveId);
function getReserveIdsPerTokenSrc(
address token
)
external
view
returns (bytes32[] memory reserveIds);
}

View File

@@ -244,15 +244,17 @@ contract TestERC20BridgeSamplerUniswapV2Router01 is
}
// solhint-disable space-after-comma
contract TestERC20BridgeSamplerKyberNetwork is
IKyberNetwork,
DeploymentConstants,
FailTrigger
{
bytes32 constant private SALT = 0x0ff3ca9d46195c39f9a12afb74207b4970349fb3cfb1e459bbf170298d326bc7;
address constant public ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
function kyberNetworkContract()
enum TradeType {BestOfAll, MaskIn, MaskOut, Split}
function kyberNetwork()
external
view
returns (address)
@@ -260,19 +262,91 @@ contract TestERC20BridgeSamplerKyberNetwork is
return address(this);
}
// IKyberNetwork not exposed via IKyberNetworkProxy
function searchBestRate(
address fromToken,
address toToken,
uint256 fromAmount,
bool // usePermissionless
// IKyberNetwork
function getContracts()
external
view
returns (
address kyberFeeHandlerAddress,
address kyberDaoAddress,
address kyberMatchingEngineAddress,
address kyberStorageAddress,
address gasHelperAddress,
address[] memory kyberProxyAddresses
)
{
return (kyberFeeHandlerAddress,
kyberDaoAddress,
address(this),
address(this),
gasHelperAddress,
kyberProxyAddresses
);
}
// IKyberStorage
function getReserveIdsPerTokenSrc(
address /* token */
)
external
view
returns (address reserve, uint256 expectedRate)
returns (bytes32[] memory reserveIds)
{
(expectedRate, ) = this.getExpectedRate(fromToken, toToken, fromAmount);
return (address(this), expectedRate);
return reserveIds;
}
function getReserveId(
address /* reserve */
)
external
view
returns (bytes32 reserveId)
{
return reserveId;
}
// IKyberHintHandler
function buildTokenToEthHint(
address /* tokenSrc */,
TradeType /* tokenToEthType */,
bytes32[] calldata /* tokenToEthReserveIds */,
uint256[] calldata /* tokenToEthSplits */
) external view returns (bytes memory hint)
{
return hint;
}
function buildEthToTokenHint(
address /* tokenDest */,
TradeType /* ethToTokenType */,
bytes32[] calldata /* ethToTokenReserveIds */,
uint256[] calldata /* ethToTokenSplits */
) external view returns (bytes memory hint)
{
return hint;
}
// Deterministic `IKyberNetworkProxy.getExpectedRateAfterFee()`.
function getExpectedRateAfterFee(
address fromToken,
address toToken,
uint256 /* srcQty */,
uint256 /* fee */,
bytes calldata /* hint */
)
external
view
returns
(uint256 expectedRate)
{
_revertIfShouldFail();
fromToken = fromToken == ETH_ADDRESS ? _getWethAddress() : fromToken;
toToken = toToken == ETH_ADDRESS ? _getWethAddress() : toToken;
expectedRate = LibDeterministicQuotes.getDeterministicRate(
SALT,
fromToken,
toToken
);
}
// Deterministic `IKyberNetworkProxy.getExpectedRate()`.
@@ -294,6 +368,14 @@ contract TestERC20BridgeSamplerKyberNetwork is
toToken
);
}
function _getKyberNetworkProxyAddress()
internal
view
returns (address)
{
return address(this);
}
}
@@ -381,7 +463,7 @@ contract TestERC20BridgeSampler is
uint8 private constant MAX_ORDER_STATUS = uint8(LibOrder.OrderStatus.CANCELLED) + 1;
constructor() public ERC20BridgeSampler(address(this)) {
constructor() public ERC20BridgeSampler() {
uniswap = new TestERC20BridgeSamplerUniswapExchangeFactory();
uniswapV2Router = new TestERC20BridgeSamplerUniswapV2Router01();
eth2Dai = new TestERC20BridgeSamplerEth2Dai();

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/contracts-erc20-bridge-sampler",
"version": "1.6.0",
"version": "1.7.0",
"engines": {
"node": ">=6.12"
},
@@ -38,7 +38,7 @@
"config": {
"publicInterfaceContracts": "ERC20BridgeSampler,IERC20BridgeSampler,ILiquidityProvider,ILiquidityProviderRegistry,DummyLiquidityProviderRegistry,DummyLiquidityProvider",
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually.",
"abis": "./test/generated-artifacts/@(DummyLiquidityProvider|DummyLiquidityProviderRegistry|ERC20BridgeSampler|ICurve|IDevUtils|IERC20BridgeSampler|IEth2Dai|IKyberNetwork|IKyberNetworkProxy|ILiquidityProvider|ILiquidityProviderRegistry|IMultiBridge|IUniswapExchangeQuotes|IUniswapV2Router01|TestERC20BridgeSampler).json"
"abis": "./test/generated-artifacts/@(DummyLiquidityProvider|DummyLiquidityProviderRegistry|ERC20BridgeSampler|ICurve|IDevUtils|IERC20BridgeSampler|IEth2Dai|IKyberHintHandler|IKyberNetwork|IKyberNetworkProxy|IKyberStorage|ILiquidityProvider|ILiquidityProviderRegistry|IMultiBridge|IUniswapExchangeQuotes|IUniswapV2Router01|TestERC20BridgeSampler).json"
},
"repository": {
"type": "git",
@@ -50,18 +50,18 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/protocol/README.md",
"devDependencies": {
"@0x/abi-gen": "^5.3.0",
"@0x/contracts-asset-proxy": "^3.3.0",
"@0x/contracts-erc20": "^3.2.0",
"@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/dev-utils": "^3.2.2",
"@0x/sol-compiler": "^4.1.0",
"@0x/tslint-config": "^4.0.0",
"@0x/web3-wrapper": "^7.1.0",
"@0x/abi-gen": "^5.3.1",
"@0x/contracts-asset-proxy": "^3.4.0",
"@0x/contracts-erc20": "^3.2.1",
"@0x/contracts-exchange": "^3.2.7",
"@0x/contracts-exchange-libs": "^4.3.7",
"@0x/contracts-gen": "^2.0.10",
"@0x/contracts-test-utils": "^5.3.4",
"@0x/contracts-utils": "^4.5.1",
"@0x/dev-utils": "^3.3.0",
"@0x/sol-compiler": "^4.1.1",
"@0x/tslint-config": "^4.1.0",
"@0x/web3-wrapper": "^7.2.0",
"@types/lodash": "4.14.104",
"@types/mocha": "^5.2.7",
"@types/node": "*",
@@ -79,14 +79,15 @@
"typescript": "3.0.1"
},
"dependencies": {
"@0x/base-contract": "^6.2.2",
"@0x/types": "^3.1.3",
"@0x/typescript-typings": "^5.1.0",
"@0x/utils": "^5.5.0",
"ethereum-types": "^3.1.1",
"@0x/base-contract": "^6.2.3",
"@0x/types": "^3.2.0",
"@0x/typescript-typings": "^5.1.1",
"@0x/utils": "^5.5.1",
"ethereum-types": "^3.2.0",
"lodash": "^4.17.11"
},
"publishConfig": {
"access": "public"
}
},
"gitHead": "4f91bfd907996b2f4dd383778b50c479c2602b56"
}

View File

@@ -12,8 +12,10 @@ import * as ICurve from '../test/generated-artifacts/ICurve.json';
import * as IDevUtils from '../test/generated-artifacts/IDevUtils.json';
import * as IERC20BridgeSampler from '../test/generated-artifacts/IERC20BridgeSampler.json';
import * as IEth2Dai from '../test/generated-artifacts/IEth2Dai.json';
import * as IKyberHintHandler from '../test/generated-artifacts/IKyberHintHandler.json';
import * as IKyberNetwork from '../test/generated-artifacts/IKyberNetwork.json';
import * as IKyberNetworkProxy from '../test/generated-artifacts/IKyberNetworkProxy.json';
import * as IKyberStorage from '../test/generated-artifacts/IKyberStorage.json';
import * as ILiquidityProvider from '../test/generated-artifacts/ILiquidityProvider.json';
import * as ILiquidityProviderRegistry from '../test/generated-artifacts/ILiquidityProviderRegistry.json';
import * as IMultiBridge from '../test/generated-artifacts/IMultiBridge.json';
@@ -28,8 +30,10 @@ export const artifacts = {
IDevUtils: IDevUtils as ContractArtifact,
IERC20BridgeSampler: IERC20BridgeSampler as ContractArtifact,
IEth2Dai: IEth2Dai as ContractArtifact,
IKyberHintHandler: IKyberHintHandler as ContractArtifact,
IKyberNetwork: IKyberNetwork as ContractArtifact,
IKyberNetworkProxy: IKyberNetworkProxy as ContractArtifact,
IKyberStorage: IKyberStorage as ContractArtifact,
ILiquidityProvider: ILiquidityProvider as ContractArtifact,
ILiquidityProviderRegistry: ILiquidityProviderRegistry as ContractArtifact,
IMultiBridge: IMultiBridge as ContractArtifact,

View File

@@ -33,6 +33,7 @@ blockchainTests('erc20-bridge-sampler', env => {
const INVALID_TOKEN_PAIR_ERROR = 'ERC20BridgeSampler/INVALID_TOKEN_PAIR';
const MAKER_TOKEN = randomAddress();
const TAKER_TOKEN = randomAddress();
let devUtilsAddress: string;
const FAKE_BUY_OPTS = {
targetSlippageBps: new BigNumber(5),
maxIterations: new BigNumber(5),
@@ -45,6 +46,8 @@ blockchainTests('erc20-bridge-sampler', env => {
env.txDefaults,
{},
);
// TestERC20BridgeSampler stubs DevUtils
devUtilsAddress = testContract.address;
});
function getPackedHash(...args: string[]): string {
@@ -272,12 +275,14 @@ blockchainTests('erc20-bridge-sampler', env => {
const orders = createOrders(MAKER_TOKEN, TAKER_TOKEN);
const signatures: string[] = _.times(orders.length, i => hexUtils.random());
const expected = orders.map(getDeterministicFillableTakerAssetAmount);
const actual = await testContract.getOrderFillableTakerAssetAmounts(orders, signatures).callAsync();
const actual = await testContract
.getOrderFillableTakerAssetAmounts(orders, signatures, devUtilsAddress)
.callAsync();
expect(actual).to.deep.eq(expected);
});
it('returns empty for no orders', async () => {
const actual = await testContract.getOrderFillableTakerAssetAmounts([], []).callAsync();
const actual = await testContract.getOrderFillableTakerAssetAmounts([], [], devUtilsAddress).callAsync();
expect(actual).to.deep.eq([]);
});
@@ -285,7 +290,9 @@ blockchainTests('erc20-bridge-sampler', env => {
const orders = createOrders(MAKER_TOKEN, TAKER_TOKEN, 1);
orders[0].makerAssetAmount = constants.ZERO_AMOUNT;
const signatures: string[] = _.times(orders.length, i => hexUtils.random());
const actual = await testContract.getOrderFillableTakerAssetAmounts(orders, signatures).callAsync();
const actual = await testContract
.getOrderFillableTakerAssetAmounts(orders, signatures, devUtilsAddress)
.callAsync();
expect(actual).to.deep.eq([constants.ZERO_AMOUNT]);
});
@@ -293,14 +300,18 @@ blockchainTests('erc20-bridge-sampler', env => {
const orders = createOrders(MAKER_TOKEN, TAKER_TOKEN, 1);
orders[0].takerAssetAmount = constants.ZERO_AMOUNT;
const signatures: string[] = _.times(orders.length, i => hexUtils.random());
const actual = await testContract.getOrderFillableTakerAssetAmounts(orders, signatures).callAsync();
const actual = await testContract
.getOrderFillableTakerAssetAmounts(orders, signatures, devUtilsAddress)
.callAsync();
expect(actual).to.deep.eq([constants.ZERO_AMOUNT]);
});
it('returns zero for an order with an empty signature', async () => {
const orders = createOrders(MAKER_TOKEN, TAKER_TOKEN, 1);
const signatures: string[] = _.times(orders.length, () => constants.NULL_BYTES);
const actual = await testContract.getOrderFillableTakerAssetAmounts(orders, signatures).callAsync();
const actual = await testContract
.getOrderFillableTakerAssetAmounts(orders, signatures, devUtilsAddress)
.callAsync();
expect(actual).to.deep.eq([constants.ZERO_AMOUNT]);
});
});
@@ -310,12 +321,14 @@ blockchainTests('erc20-bridge-sampler', env => {
const orders = createOrders(MAKER_TOKEN, TAKER_TOKEN);
const signatures: string[] = _.times(orders.length, i => hexUtils.random());
const expected = orders.map(getDeterministicFillableMakerAssetAmount);
const actual = await testContract.getOrderFillableMakerAssetAmounts(orders, signatures).callAsync();
const actual = await testContract
.getOrderFillableMakerAssetAmounts(orders, signatures, devUtilsAddress)
.callAsync();
expect(actual).to.deep.eq(expected);
});
it('returns empty for no orders', async () => {
const actual = await testContract.getOrderFillableMakerAssetAmounts([], []).callAsync();
const actual = await testContract.getOrderFillableMakerAssetAmounts([], [], devUtilsAddress).callAsync();
expect(actual).to.deep.eq([]);
});
@@ -323,7 +336,9 @@ blockchainTests('erc20-bridge-sampler', env => {
const orders = createOrders(MAKER_TOKEN, TAKER_TOKEN, 1);
orders[0].makerAssetAmount = constants.ZERO_AMOUNT;
const signatures: string[] = _.times(orders.length, i => hexUtils.random());
const actual = await testContract.getOrderFillableMakerAssetAmounts(orders, signatures).callAsync();
const actual = await testContract
.getOrderFillableMakerAssetAmounts(orders, signatures, devUtilsAddress)
.callAsync();
expect(actual).to.deep.eq([constants.ZERO_AMOUNT]);
});
@@ -331,14 +346,18 @@ blockchainTests('erc20-bridge-sampler', env => {
const orders = createOrders(MAKER_TOKEN, TAKER_TOKEN, 1);
orders[0].takerAssetAmount = constants.ZERO_AMOUNT;
const signatures: string[] = _.times(orders.length, i => hexUtils.random());
const actual = await testContract.getOrderFillableMakerAssetAmounts(orders, signatures).callAsync();
const actual = await testContract
.getOrderFillableMakerAssetAmounts(orders, signatures, devUtilsAddress)
.callAsync();
expect(actual).to.deep.eq([constants.ZERO_AMOUNT]);
});
it('returns zero for an order with an empty signature', async () => {
const orders = createOrders(MAKER_TOKEN, TAKER_TOKEN, 1);
const signatures: string[] = _.times(orders.length, () => constants.NULL_BYTES);
const actual = await testContract.getOrderFillableMakerAssetAmounts(orders, signatures).callAsync();
const actual = await testContract
.getOrderFillableMakerAssetAmounts(orders, signatures, devUtilsAddress)
.callAsync();
expect(actual).to.deep.eq([constants.ZERO_AMOUNT]);
});
});
@@ -1029,7 +1048,9 @@ blockchainTests('erc20-bridge-sampler', env => {
const signatures: string[] = _.times(orders.length, i => hexUtils.random());
const expected = orders.map(getDeterministicFillableTakerAssetAmount);
const calls = [
testContract.getOrderFillableTakerAssetAmounts(orders, signatures).getABIEncodedTransactionData(),
testContract
.getOrderFillableTakerAssetAmounts(orders, signatures, devUtilsAddress)
.getABIEncodedTransactionData(),
];
const r = await testContract.batchCall(calls).callAsync();
expect(r).to.be.length(1);
@@ -1046,8 +1067,12 @@ blockchainTests('erc20-bridge-sampler', env => {
orders[1].map(getDeterministicFillableMakerAssetAmount),
];
const calls = [
testContract.getOrderFillableTakerAssetAmounts(orders[0], signatures).getABIEncodedTransactionData(),
testContract.getOrderFillableMakerAssetAmounts(orders[1], signatures).getABIEncodedTransactionData(),
testContract
.getOrderFillableTakerAssetAmounts(orders[0], signatures, devUtilsAddress)
.getABIEncodedTransactionData(),
testContract
.getOrderFillableMakerAssetAmounts(orders[1], signatures, devUtilsAddress)
.getABIEncodedTransactionData(),
];
const r = await testContract.batchCall(calls).callAsync();
expect(r).to.be.length(2);
@@ -1069,7 +1094,7 @@ blockchainTests('erc20-bridge-sampler', env => {
testContract
.batchCall([
testContract
.getOrderFillableTakerAssetAmounts(orders, signatures)
.getOrderFillableTakerAssetAmounts(orders, signatures, devUtilsAddress)
.getABIEncodedTransactionData(),
])
.getABIEncodedTransactionData(),

View File

@@ -10,8 +10,10 @@ export * from '../test/generated-wrappers/i_curve';
export * from '../test/generated-wrappers/i_dev_utils';
export * from '../test/generated-wrappers/i_erc20_bridge_sampler';
export * from '../test/generated-wrappers/i_eth2_dai';
export * from '../test/generated-wrappers/i_kyber_hint_handler';
export * from '../test/generated-wrappers/i_kyber_network';
export * from '../test/generated-wrappers/i_kyber_network_proxy';
export * from '../test/generated-wrappers/i_kyber_storage';
export * from '../test/generated-wrappers/i_liquidity_provider';
export * from '../test/generated-wrappers/i_liquidity_provider_registry';
export * from '../test/generated-wrappers/i_multi_bridge';

View File

@@ -16,8 +16,10 @@
"test/generated-artifacts/IDevUtils.json",
"test/generated-artifacts/IERC20BridgeSampler.json",
"test/generated-artifacts/IEth2Dai.json",
"test/generated-artifacts/IKyberHintHandler.json",
"test/generated-artifacts/IKyberNetwork.json",
"test/generated-artifacts/IKyberNetworkProxy.json",
"test/generated-artifacts/IKyberStorage.json",
"test/generated-artifacts/ILiquidityProvider.json",
"test/generated-artifacts/ILiquidityProviderRegistry.json",
"test/generated-artifacts/IMultiBridge.json",

View File

@@ -1,4 +1,13 @@
[
{
"timestamp": 1594788383,
"version": "3.2.1",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"version": "3.2.0",
"changes": [

View File

@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v3.2.1 - _July 15, 2020_
* Dependencies updated
## v3.2.0 - _June 24, 2020_
* Add `LibERC20Token.approveIfBelow()` (#2512)

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/contracts-erc20",
"version": "3.2.0",
"version": "3.2.1",
"engines": {
"node": ">=6.12"
},
@@ -51,18 +51,18 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/tokens/README.md",
"devDependencies": {
"@0x/abi-gen": "^5.3.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/abi-gen": "^5.3.1",
"@0x/contracts-gen": "^2.0.10",
"@0x/contracts-test-utils": "^5.3.4",
"@0x/contracts-utils": "^4.5.1",
"@0x/dev-utils": "^3.3.0",
"@0x/sol-compiler": "^4.1.1",
"@0x/ts-doc-gen": "^0.0.22",
"@0x/tslint-config": "^4.0.0",
"@0x/types": "^3.1.3",
"@0x/typescript-typings": "^5.1.0",
"@0x/utils": "^5.5.0",
"@0x/web3-wrapper": "^7.1.0",
"@0x/tslint-config": "^4.1.0",
"@0x/types": "^3.2.0",
"@0x/typescript-typings": "^5.1.1",
"@0x/utils": "^5.5.1",
"@0x/web3-wrapper": "^7.2.0",
"@types/lodash": "4.14.104",
"@types/mocha": "^5.2.7",
"@types/node": "*",
@@ -70,7 +70,7 @@
"chai-as-promised": "^7.1.0",
"chai-bignumber": "^3.0.0",
"dirty-chai": "^2.0.1",
"ethereum-types": "^3.1.1",
"ethereum-types": "^3.2.0",
"lodash": "^4.17.11",
"make-promises-safe": "^1.1.0",
"mocha": "^6.2.0",
@@ -82,9 +82,10 @@
"typescript": "3.0.1"
},
"dependencies": {
"@0x/base-contract": "^6.2.2"
"@0x/base-contract": "^6.2.3"
},
"publishConfig": {
"access": "public"
}
},
"gitHead": "4f91bfd907996b2f4dd383778b50c479c2602b56"
}

View File

@@ -1,4 +1,13 @@
[
{
"timestamp": 1594788383,
"version": "3.1.7",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1592969527,
"version": "3.1.6",

View File

@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v3.1.7 - _July 15, 2020_
* Dependencies updated
## v3.1.6 - _June 24, 2020_
* Dependencies updated

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/contracts-erc721",
"version": "3.1.6",
"version": "3.1.7",
"engines": {
"node": ">=6.12"
},
@@ -52,18 +52,18 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/tokens/README.md",
"devDependencies": {
"@0x/abi-gen": "^5.3.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/abi-gen": "^5.3.1",
"@0x/contracts-gen": "^2.0.10",
"@0x/contracts-test-utils": "^5.3.4",
"@0x/contracts-utils": "^4.5.1",
"@0x/dev-utils": "^3.3.0",
"@0x/sol-compiler": "^4.1.1",
"@0x/ts-doc-gen": "^0.0.22",
"@0x/tslint-config": "^4.0.0",
"@0x/types": "^3.1.3",
"@0x/typescript-typings": "^5.1.0",
"@0x/utils": "^5.5.0",
"@0x/web3-wrapper": "^7.1.0",
"@0x/tslint-config": "^4.1.0",
"@0x/types": "^3.2.0",
"@0x/typescript-typings": "^5.1.1",
"@0x/utils": "^5.5.1",
"@0x/web3-wrapper": "^7.2.0",
"@types/lodash": "4.14.104",
"@types/mocha": "^5.2.7",
"@types/node": "*",
@@ -71,7 +71,7 @@
"chai-as-promised": "^7.1.0",
"chai-bignumber": "^3.0.0",
"dirty-chai": "^2.0.1",
"ethereum-types": "^3.1.1",
"ethereum-types": "^3.2.0",
"lodash": "^4.17.11",
"make-promises-safe": "^1.1.0",
"mocha": "^6.2.0",
@@ -84,9 +84,10 @@
"typescript": "3.0.1"
},
"dependencies": {
"@0x/base-contract": "^6.2.2"
"@0x/base-contract": "^6.2.3"
},
"publishConfig": {
"access": "public"
}
},
"gitHead": "4f91bfd907996b2f4dd383778b50c479c2602b56"
}

View File

@@ -1,4 +1,13 @@
[
{
"timestamp": 1594788383,
"version": "4.2.7",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1592969527,
"version": "4.2.6",

View File

@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v4.2.7 - _July 15, 2020_
* Dependencies updated
## v4.2.6 - _June 24, 2020_
* Dependencies updated

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/contracts-exchange-forwarder",
"version": "4.2.6",
"version": "4.2.7",
"engines": {
"node": ">=6.12"
},
@@ -52,25 +52,25 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/extensions/README.md",
"devDependencies": {
"@0x/abi-gen": "^5.3.0",
"@0x/contracts-asset-proxy": "^3.3.0",
"@0x/contracts-dev-utils": "^1.3.4",
"@0x/contracts-erc1155": "^2.1.6",
"@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/dev-utils": "^3.2.2",
"@0x/order-utils": "^10.2.5",
"@0x/sol-compiler": "^4.1.0",
"@0x/abi-gen": "^5.3.1",
"@0x/contracts-asset-proxy": "^3.4.0",
"@0x/contracts-dev-utils": "^1.3.5",
"@0x/contracts-erc1155": "^2.1.7",
"@0x/contracts-erc20": "^3.2.1",
"@0x/contracts-erc721": "^3.1.7",
"@0x/contracts-exchange": "^3.2.7",
"@0x/contracts-exchange-libs": "^4.3.7",
"@0x/contracts-gen": "^2.0.10",
"@0x/contracts-test-utils": "^5.3.4",
"@0x/contracts-utils": "^4.5.1",
"@0x/dev-utils": "^3.3.0",
"@0x/order-utils": "^10.3.0",
"@0x/sol-compiler": "^4.1.1",
"@0x/ts-doc-gen": "^0.0.22",
"@0x/tslint-config": "^4.0.0",
"@0x/types": "^3.1.3",
"@0x/utils": "^5.5.0",
"@0x/web3-wrapper": "^7.1.0",
"@0x/tslint-config": "^4.1.0",
"@0x/types": "^3.2.0",
"@0x/utils": "^5.5.1",
"@0x/web3-wrapper": "^7.2.0",
"@types/lodash": "4.14.104",
"@types/mocha": "^5.2.7",
"@types/node": "*",
@@ -90,11 +90,12 @@
"typescript": "3.0.1"
},
"dependencies": {
"@0x/base-contract": "^6.2.2",
"@0x/typescript-typings": "^5.1.0",
"ethereum-types": "^3.1.1"
"@0x/base-contract": "^6.2.3",
"@0x/typescript-typings": "^5.1.1",
"ethereum-types": "^3.2.0"
},
"publishConfig": {
"access": "public"
}
},
"gitHead": "4f91bfd907996b2f4dd383778b50c479c2602b56"
}

View File

@@ -1,4 +1,13 @@
[
{
"timestamp": 1594788383,
"version": "4.3.7",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1592969527,
"version": "4.3.6",

View File

@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v4.3.7 - _July 15, 2020_
* Dependencies updated
## v4.3.6 - _June 24, 2020_
* Dependencies updated

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/contracts-exchange-libs",
"version": "4.3.6",
"version": "4.3.7",
"engines": {
"node": ">=6.12"
},
@@ -52,14 +52,14 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/libs/README.md",
"devDependencies": {
"@0x/abi-gen": "^5.3.0",
"@0x/contracts-gen": "^2.0.9",
"@0x/dev-utils": "^3.2.2",
"@0x/sol-compiler": "^4.1.0",
"@0x/subproviders": "^6.1.0",
"@0x/abi-gen": "^5.3.1",
"@0x/contracts-gen": "^2.0.10",
"@0x/dev-utils": "^3.3.0",
"@0x/sol-compiler": "^4.1.1",
"@0x/subproviders": "^6.1.1",
"@0x/ts-doc-gen": "^0.0.22",
"@0x/tslint-config": "^4.0.0",
"@0x/web3-wrapper": "^7.1.0",
"@0x/tslint-config": "^4.1.0",
"@0x/web3-wrapper": "^7.2.0",
"@types/lodash": "4.14.104",
"@types/mocha": "^5.2.7",
"@types/node": "*",
@@ -80,16 +80,17 @@
"typescript": "3.0.1"
},
"dependencies": {
"@0x/base-contract": "^6.2.2",
"@0x/contracts-test-utils": "^5.3.3",
"@0x/contracts-utils": "^4.5.0",
"@0x/order-utils": "^10.2.5",
"@0x/types": "^3.1.3",
"@0x/typescript-typings": "^5.1.0",
"@0x/utils": "^5.5.0",
"ethereum-types": "^3.1.1"
"@0x/base-contract": "^6.2.3",
"@0x/contracts-test-utils": "^5.3.4",
"@0x/contracts-utils": "^4.5.1",
"@0x/order-utils": "^10.3.0",
"@0x/types": "^3.2.0",
"@0x/typescript-typings": "^5.1.1",
"@0x/utils": "^5.5.1",
"ethereum-types": "^3.2.0"
},
"publishConfig": {
"access": "public"
}
},
"gitHead": "4f91bfd907996b2f4dd383778b50c479c2602b56"
}

View File

@@ -1,4 +1,13 @@
[
{
"timestamp": 1594788383,
"version": "3.2.7",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1592969527,
"version": "3.2.6",

View File

@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v3.2.7 - _July 15, 2020_
* Dependencies updated
## v3.2.6 - _June 24, 2020_
* Dependencies updated

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/contracts-exchange",
"version": "3.2.6",
"version": "3.2.7",
"engines": {
"node": ">=6.12"
},
@@ -52,21 +52,21 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/protocol/README.md",
"devDependencies": {
"@0x/abi-gen": "^5.3.0",
"@0x/contracts-asset-proxy": "^3.3.0",
"@0x/contracts-exchange-libs": "^4.3.6",
"@0x/contracts-gen": "^2.0.9",
"@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/dev-utils": "^3.2.2",
"@0x/sol-compiler": "^4.1.0",
"@0x/abi-gen": "^5.3.1",
"@0x/contracts-asset-proxy": "^3.4.0",
"@0x/contracts-exchange-libs": "^4.3.7",
"@0x/contracts-gen": "^2.0.10",
"@0x/contracts-multisig": "^4.1.7",
"@0x/contracts-staking": "^2.0.14",
"@0x/contracts-test-utils": "^5.3.4",
"@0x/contracts-utils": "^4.5.1",
"@0x/dev-utils": "^3.3.0",
"@0x/sol-compiler": "^4.1.1",
"@0x/ts-doc-gen": "^0.0.22",
"@0x/tslint-config": "^4.0.0",
"@0x/types": "^3.1.3",
"@0x/typescript-typings": "^5.1.0",
"@0x/web3-wrapper": "^7.1.0",
"@0x/tslint-config": "^4.1.0",
"@0x/types": "^3.2.0",
"@0x/typescript-typings": "^5.1.1",
"@0x/web3-wrapper": "^7.2.0",
"@types/lodash": "4.14.104",
"@types/mocha": "^5.2.7",
"@types/node": "*",
@@ -74,7 +74,7 @@
"chai-as-promised": "^7.1.0",
"chai-bignumber": "^3.0.0",
"dirty-chai": "^2.0.1",
"ethereum-types": "^3.1.1",
"ethereum-types": "^3.2.0",
"ethereumjs-util": "^5.1.1",
"js-combinatorics": "^0.5.3",
"make-promises-safe": "^1.1.0",
@@ -88,16 +88,17 @@
"typescript": "3.0.1"
},
"dependencies": {
"@0x/base-contract": "^6.2.2",
"@0x/contracts-dev-utils": "^1.3.4",
"@0x/contracts-erc1155": "^2.1.6",
"@0x/contracts-erc20": "^3.2.0",
"@0x/contracts-erc721": "^3.1.6",
"@0x/order-utils": "^10.2.5",
"@0x/utils": "^5.5.0",
"@0x/base-contract": "^6.2.3",
"@0x/contracts-dev-utils": "^1.3.5",
"@0x/contracts-erc1155": "^2.1.7",
"@0x/contracts-erc20": "^3.2.1",
"@0x/contracts-erc721": "^3.1.7",
"@0x/order-utils": "^10.3.0",
"@0x/utils": "^5.5.1",
"lodash": "^4.17.11"
},
"publishConfig": {
"access": "public"
}
},
"gitHead": "4f91bfd907996b2f4dd383778b50c479c2602b56"
}

View File

@@ -1,4 +1,13 @@
[
{
"timestamp": 1594788383,
"version": "6.2.1",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"version": "6.2.0",
"changes": [

View File

@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v6.2.1 - _July 15, 2020_
* Dependencies updated
## v6.2.0 - _June 24, 2020_
* Add MaximumGasPrice contract, tooling, and unit tests (#2511)

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/contracts-extensions",
"version": "6.2.0",
"version": "6.2.1",
"engines": {
"node": ">=6.12"
},
@@ -51,24 +51,24 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/extensions/README.md",
"devDependencies": {
"@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-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/dev-utils": "^3.2.2",
"@0x/order-utils": "^10.2.5",
"@0x/sol-compiler": "^4.1.0",
"@0x/abi-gen": "^5.3.1",
"@0x/contracts-asset-proxy": "^3.4.0",
"@0x/contracts-dev-utils": "^1.3.5",
"@0x/contracts-erc20": "^3.2.1",
"@0x/contracts-erc721": "^3.1.7",
"@0x/contracts-exchange": "^3.2.7",
"@0x/contracts-exchange-libs": "^4.3.7",
"@0x/contracts-gen": "^2.0.10",
"@0x/contracts-test-utils": "^5.3.4",
"@0x/contracts-utils": "^4.5.1",
"@0x/dev-utils": "^3.3.0",
"@0x/order-utils": "^10.3.0",
"@0x/sol-compiler": "^4.1.1",
"@0x/ts-doc-gen": "^0.0.22",
"@0x/tslint-config": "^4.0.0",
"@0x/types": "^3.1.3",
"@0x/utils": "^5.5.0",
"@0x/web3-wrapper": "^7.1.0",
"@0x/tslint-config": "^4.1.0",
"@0x/types": "^3.2.0",
"@0x/utils": "^5.5.1",
"@0x/web3-wrapper": "^7.2.0",
"@types/lodash": "4.14.104",
"@types/mocha": "^5.2.7",
"@types/node": "*",
@@ -90,11 +90,12 @@
"typescript": "3.0.1"
},
"dependencies": {
"@0x/base-contract": "^6.2.2",
"@0x/typescript-typings": "^5.1.0",
"ethereum-types": "^3.1.1"
"@0x/base-contract": "^6.2.3",
"@0x/typescript-typings": "^5.1.1",
"ethereum-types": "^3.2.0"
},
"publishConfig": {
"access": "public"
}
},
"gitHead": "4f91bfd907996b2f4dd383778b50c479c2602b56"
}

View File

@@ -1,4 +1,14 @@
[
{
"version": "2.6.0",
"changes": [
{
"note": "Add `BalancerBridge` mainnet tests",
"pr": 2613
}
],
"timestamp": 1594788383
},
{
"version": "2.5.2",
"changes": [

View File

@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v2.6.0 - _July 15, 2020_
* Add `BalancerBridge` mainnet tests (#2613)
## v2.5.2 - _June 24, 2020_
* Update `ERC20BridgeSampler` tests (#2531)

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/contracts-integrations",
"version": "2.5.2",
"version": "2.6.0",
"engines": {
"node": ">=6.12"
},
@@ -51,25 +51,25 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/extensions/README.md",
"devDependencies": {
"@0x/abi-gen": "^5.3.0",
"@0x/contract-addresses": "^4.10.0",
"@0x/contract-wrappers": "^13.7.0",
"@0x/contracts-broker": "^1.1.5",
"@0x/contracts-coordinator": "^3.1.6",
"@0x/contracts-dev-utils": "^1.3.4",
"@0x/contracts-erc20-bridge-sampler": "^1.6.0",
"@0x/contracts-exchange-forwarder": "^4.2.6",
"@0x/contracts-exchange-libs": "^4.3.6",
"@0x/contracts-extensions": "^6.2.0",
"@0x/contracts-gen": "^2.0.9",
"@0x/contracts-utils": "^4.5.0",
"@0x/abi-gen": "^5.3.1",
"@0x/contract-addresses": "^4.11.0",
"@0x/contract-wrappers": "^13.8.0",
"@0x/contracts-broker": "^1.1.6",
"@0x/contracts-coordinator": "^3.1.7",
"@0x/contracts-dev-utils": "^1.3.5",
"@0x/contracts-erc20-bridge-sampler": "^1.7.0",
"@0x/contracts-exchange-forwarder": "^4.2.7",
"@0x/contracts-exchange-libs": "^4.3.7",
"@0x/contracts-extensions": "^6.2.1",
"@0x/contracts-gen": "^2.0.10",
"@0x/contracts-utils": "^4.5.1",
"@0x/coordinator-server": "^1.0.5",
"@0x/dev-utils": "^3.2.2",
"@0x/migrations": "^6.3.0",
"@0x/order-utils": "^10.2.5",
"@0x/sol-compiler": "^4.1.0",
"@0x/tslint-config": "^4.0.0",
"@0x/web3-wrapper": "^7.1.0",
"@0x/dev-utils": "^3.3.0",
"@0x/migrations": "^6.4.0",
"@0x/order-utils": "^10.3.0",
"@0x/sol-compiler": "^4.1.1",
"@0x/tslint-config": "^4.1.0",
"@0x/web3-wrapper": "^7.2.0",
"@azure/core-asynciterator-polyfill": "^1.0.0",
"@types/lodash": "4.14.104",
"@types/mocha": "^5.2.7",
@@ -92,24 +92,25 @@
"typescript": "3.0.1"
},
"dependencies": {
"@0x/asset-swapper": "^4.5.0",
"@0x/base-contract": "^6.2.2",
"@0x/contracts-asset-proxy": "^3.3.0",
"@0x/contracts-erc1155": "^2.1.6",
"@0x/contracts-erc20": "^3.2.0",
"@0x/contracts-erc721": "^3.1.6",
"@0x/contracts-exchange": "^3.2.6",
"@0x/contracts-multisig": "^4.1.6",
"@0x/contracts-staking": "^2.0.13",
"@0x/contracts-test-utils": "^5.3.3",
"@0x/types": "^3.1.3",
"@0x/typescript-typings": "^5.1.0",
"@0x/utils": "^5.5.0",
"ethereum-types": "^3.1.1",
"@0x/asset-swapper": "^4.6.0",
"@0x/base-contract": "^6.2.3",
"@0x/contracts-asset-proxy": "^3.4.0",
"@0x/contracts-erc1155": "^2.1.7",
"@0x/contracts-erc20": "^3.2.1",
"@0x/contracts-erc721": "^3.1.7",
"@0x/contracts-exchange": "^3.2.7",
"@0x/contracts-multisig": "^4.1.7",
"@0x/contracts-staking": "^2.0.14",
"@0x/contracts-test-utils": "^5.3.4",
"@0x/types": "^3.2.0",
"@0x/typescript-typings": "^5.1.1",
"@0x/utils": "^5.5.1",
"ethereum-types": "^3.2.0",
"ethereumjs-util": "^6.2.0",
"lodash": "^4.17.11"
},
"publishConfig": {
"access": "public"
}
},
"gitHead": "4f91bfd907996b2f4dd383778b50c479c2602b56"
}

View File

@@ -1,6 +1,7 @@
import { artifacts, ERC20BridgeSamplerContract } from '@0x/contracts-erc20-bridge-sampler';
import { blockchainTests, constants, describe, expect, toBaseUnitAmount } from '@0x/contracts-test-utils';
import { BigNumber } from '@0x/utils';
import { blockchainTests, describe, expect, toBaseUnitAmount, Web3ProviderEngine } from '@0x/contracts-test-utils';
import { RPCSubprovider } from '@0x/dev-utils/node_modules/@0x/subproviders';
import { BigNumber, providerUtils } from '@0x/utils';
export const VB = '0x6cc5f688a315f3dc28a7781717a9a798a59fda7b';
blockchainTests.configure({
@@ -11,14 +12,21 @@ blockchainTests.configure({
blockchainTests.fork.resets('Mainnet Sampler Tests', env => {
let testContract: ERC20BridgeSamplerContract;
const fakeSamplerAddress = '0x1111111111111111111111111111111111111111';
const overrides = {
[fakeSamplerAddress]: {
code: artifacts.ERC20BridgeSampler.compilerOutput.evm.deployedBytecode.object,
},
};
before(async () => {
testContract = await ERC20BridgeSamplerContract.deployFrom0xArtifactAsync(
artifacts.ERC20BridgeSampler,
env.provider,
{ ...env.txDefaults, from: VB },
{},
constants.NULL_ADDRESS,
);
const provider = new Web3ProviderEngine();
// tslint:disable-next-line:no-non-null-assertion
provider.addProvider(new RPCSubprovider(process.env.FORK_RPC_URL!));
providerUtils.startProviderEngine(provider);
testContract = new ERC20BridgeSamplerContract(fakeSamplerAddress, provider, {
...env.txDefaults,
from: VB,
});
});
describe('Curve', () => {
const CURVE_ADDRESS = '0xa2b47e3d5c44877cca798226b7b8118f9bfb7a56';
@@ -29,7 +37,7 @@ blockchainTests.fork.resets('Mainnet Sampler Tests', env => {
it('samples sells from Curve DAI->USDC', async () => {
const samples = await testContract
.sampleSellsFromCurve(CURVE_ADDRESS, DAI_TOKEN_INDEX, USDC_TOKEN_INDEX, [toBaseUnitAmount(1)])
.callAsync();
.callAsync({ overrides });
expect(samples.length).to.be.bignumber.greaterThan(0);
expect(samples[0]).to.be.bignumber.greaterThan(0);
});
@@ -37,7 +45,7 @@ blockchainTests.fork.resets('Mainnet Sampler Tests', env => {
it('samples sells from Curve USDC->DAI', async () => {
const samples = await testContract
.sampleSellsFromCurve(CURVE_ADDRESS, USDC_TOKEN_INDEX, DAI_TOKEN_INDEX, [toBaseUnitAmount(1, 6)])
.callAsync();
.callAsync({ overrides });
expect(samples.length).to.be.bignumber.greaterThan(0);
expect(samples[0]).to.be.bignumber.greaterThan(0);
});
@@ -49,7 +57,7 @@ blockchainTests.fork.resets('Mainnet Sampler Tests', env => {
// I want to buy 1 USDC
const samples = await testContract
.sampleBuysFromCurve(CURVE_ADDRESS, DAI_TOKEN_INDEX, USDC_TOKEN_INDEX, [toBaseUnitAmount(1, 6)])
.callAsync();
.callAsync({ overrides });
expect(samples.length).to.be.bignumber.greaterThan(0);
expect(samples[0]).to.be.bignumber.greaterThan(0);
});
@@ -59,7 +67,7 @@ blockchainTests.fork.resets('Mainnet Sampler Tests', env => {
// I want to buy 1 DAI
const samples = await testContract
.sampleBuysFromCurve(CURVE_ADDRESS, USDC_TOKEN_INDEX, DAI_TOKEN_INDEX, [toBaseUnitAmount(1)])
.callAsync();
.callAsync({ overrides });
expect(samples.length).to.be.bignumber.greaterThan(0);
expect(samples[0]).to.be.bignumber.greaterThan(0);
});
@@ -70,16 +78,40 @@ blockchainTests.fork.resets('Mainnet Sampler Tests', env => {
targetSlippageBps: new BigNumber(5),
maxIterations: new BigNumber(5),
};
const DAI_ADDRESS = '0x6B175474E89094C44Da98b954EedeAC495271d0F';
const WETH_ADDRESS = '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2';
const WETH = '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2';
const DAI = '0x6b175474e89094c44da98b954eedeac495271d0f';
const USDC = '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48';
describe('sampleSellsFromKyberNetwork()', () => {
it('samples sells from Kyber DAI->WETH', async () => {
const samples = await testContract
.sampleSellsFromKyberNetwork(DAI, WETH, [toBaseUnitAmount(1)])
.callAsync({ overrides });
expect(samples.length).to.be.bignumber.greaterThan(0);
expect(samples[0]).to.be.bignumber.greaterThan(0);
});
it('samples sells from Kyber WETH->DAI', async () => {
const samples = await testContract
.sampleSellsFromKyberNetwork(WETH, DAI, [toBaseUnitAmount(1)])
.callAsync({ overrides });
expect(samples.length).to.be.bignumber.greaterThan(0);
expect(samples[0]).to.be.bignumber.greaterThan(0);
});
it('samples sells from Kyber DAI->USDC', async () => {
const samples = await testContract
.sampleSellsFromKyberNetwork(DAI, USDC, [toBaseUnitAmount(1)])
.callAsync({ overrides });
expect(samples.length).to.be.bignumber.greaterThan(0);
expect(samples[0]).to.be.bignumber.greaterThan(0);
});
});
describe('sampleBuysFromKyber()', () => {
it('samples buys from Kyber WETH->DAI', async () => {
// From ETH to DAI
// I want to buy 1 DAI
const samples = await testContract
.sampleBuysFromKyberNetwork(WETH_ADDRESS, DAI_ADDRESS, [toBaseUnitAmount(1)], FAKE_BUY_OPTS)
.callAsync();
.sampleBuysFromKyberNetwork(WETH, DAI, [toBaseUnitAmount(1)], FAKE_BUY_OPTS)
.callAsync({ overrides });
expect(samples.length).to.be.bignumber.greaterThan(0);
expect(samples[0]).to.be.bignumber.greaterThan(0);
});
@@ -88,8 +120,8 @@ blockchainTests.fork.resets('Mainnet Sampler Tests', env => {
// From USDC to DAI
// I want to buy 1 WETH
const samples = await testContract
.sampleBuysFromKyberNetwork(DAI_ADDRESS, WETH_ADDRESS, [toBaseUnitAmount(1)], FAKE_BUY_OPTS)
.callAsync();
.sampleBuysFromKyberNetwork(DAI, WETH, [toBaseUnitAmount(1)], FAKE_BUY_OPTS)
.callAsync({ overrides });
expect(samples.length).to.be.bignumber.greaterThan(0);
expect(samples[0]).to.be.bignumber.greaterThan(0);
});

View File

@@ -0,0 +1,103 @@
import { artifacts as assetProxyArtifacts } from '@0x/contracts-asset-proxy';
import { BalancerBridgeContract } from '@0x/contracts-asset-proxy/lib/src/wrappers';
import { ERC20TokenContract } from '@0x/contracts-erc20';
import { blockchainTests, constants, expect, toBaseUnitAmount } from '@0x/contracts-test-utils';
import { AbiEncoder } from '@0x/utils';
const CHONKY_DAI_WALLET = '0x1e0447b19bb6ecfdae1e4ae1694b0c3659614e4e'; // dydx solo margin
const CHONKY_WETH_WALLET = '0x2f0b23f53734252bda2277357e97e1517d6b042a'; // MCD wETH vault
const CHONKY_USDC_WALLET = '0x39aa39c021dfbae8fac545936693ac917d5e7563'; // Compound
blockchainTests.configure({
fork: {
unlockedAccounts: [CHONKY_USDC_WALLET, CHONKY_WETH_WALLET, CHONKY_DAI_WALLET],
},
});
blockchainTests.fork('Mainnet Balancer bridge tests', env => {
let testContract: BalancerBridgeContract;
let weth: ERC20TokenContract;
let usdc: ERC20TokenContract;
const receiver = '0x986ccf5234d9cfbb25246f1a5bfa51f4ccfcb308';
const usdcAddress = '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48';
const wethAddress = '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2';
const wethUsdcBalancerAddress = '0x2471de1547296aadb02cc1af84afe369b6f67c87';
const wethUsdcDaiBalancerAddress = '0x9b208194acc0a8ccb2a8dcafeacfbb7dcc093f81';
const bridgeDataEncoder = AbiEncoder.create([
{ name: 'takerToken', type: 'address' },
{ name: 'poolAddress', type: 'address' },
]);
before(async () => {
testContract = await BalancerBridgeContract.deployFrom0xArtifactAsync(
assetProxyArtifacts.BalancerBridge,
env.provider,
{ ...env.txDefaults, from: CHONKY_DAI_WALLET, gasPrice: 0 },
{},
);
weth = new ERC20TokenContract(wethAddress, env.provider, env.txDefaults);
usdc = new ERC20TokenContract(usdcAddress, env.provider, env.txDefaults);
});
blockchainTests.resets('Can trade with two-asset pool', () => {
it('successfully exchanges WETH for USDC', async () => {
const bridgeData = bridgeDataEncoder.encode([wethAddress, wethUsdcBalancerAddress]);
// Fund the Bridge
await weth
.transfer(testContract.address, toBaseUnitAmount(1))
.awaitTransactionSuccessAsync({ from: CHONKY_WETH_WALLET, gasPrice: 0 }, { shouldValidate: false });
const usdcBalanceBefore = await usdc.balanceOf(receiver).callAsync();
// Exchange via Balancer
await testContract
.bridgeTransferFrom(usdcAddress, constants.NULL_ADDRESS, receiver, constants.ZERO_AMOUNT, bridgeData)
.awaitTransactionSuccessAsync({ from: CHONKY_WETH_WALLET, gasPrice: 0 }, { shouldValidate: false });
// Check that USDC balance increased
const usdcBalanceAfter = await usdc.balanceOf(receiver).callAsync();
expect(usdcBalanceAfter).to.be.bignumber.greaterThan(usdcBalanceBefore);
});
it('successfully exchanges USDC for WETH', async () => {
const bridgeData = bridgeDataEncoder.encode([usdcAddress, wethUsdcBalancerAddress]);
// Fund the Bridge
await usdc
.transfer(testContract.address, toBaseUnitAmount(1, 6))
.awaitTransactionSuccessAsync({ from: CHONKY_USDC_WALLET, gasPrice: 0 }, { shouldValidate: false });
const wethBalanceBefore = await weth.balanceOf(receiver).callAsync();
// Exchange via Balancer
await testContract
.bridgeTransferFrom(wethAddress, constants.NULL_ADDRESS, receiver, constants.ZERO_AMOUNT, bridgeData)
.awaitTransactionSuccessAsync({ from: CHONKY_USDC_WALLET, gasPrice: 0 }, { shouldValidate: false });
const wethBalanceAfter = await weth.balanceOf(receiver).callAsync();
expect(wethBalanceAfter).to.be.bignumber.greaterThan(wethBalanceBefore);
});
});
blockchainTests.resets('Can trade with three-asset pool', () => {
it('successfully exchanges WETH for USDC', async () => {
const bridgeData = bridgeDataEncoder.encode([wethAddress, wethUsdcDaiBalancerAddress]);
// Fund the Bridge
await weth
.transfer(testContract.address, toBaseUnitAmount(1))
.awaitTransactionSuccessAsync({ from: CHONKY_WETH_WALLET, gasPrice: 0 }, { shouldValidate: false });
const usdcBalanceBefore = await usdc.balanceOf(receiver).callAsync();
// Exchange via Balancer
await testContract
.bridgeTransferFrom(usdcAddress, constants.NULL_ADDRESS, receiver, constants.ZERO_AMOUNT, bridgeData)
.awaitTransactionSuccessAsync({ from: CHONKY_WETH_WALLET, gasPrice: 0 }, { shouldValidate: false });
// Check that USDC balance increased
const usdcBalanceAfter = await usdc.balanceOf(receiver).callAsync();
expect(usdcBalanceAfter).to.be.bignumber.greaterThan(usdcBalanceBefore);
});
it('successfully exchanges USDC for WETH', async () => {
const bridgeData = bridgeDataEncoder.encode([usdcAddress, wethUsdcDaiBalancerAddress]);
// Fund the Bridge
await usdc
.transfer(testContract.address, toBaseUnitAmount(1, 6))
.awaitTransactionSuccessAsync({ from: CHONKY_USDC_WALLET, gasPrice: 0 }, { shouldValidate: false });
const wethBalanceBefore = await weth.balanceOf(receiver).callAsync();
// Exchange via Balancer
await testContract
.bridgeTransferFrom(wethAddress, constants.NULL_ADDRESS, receiver, constants.ZERO_AMOUNT, bridgeData)
.awaitTransactionSuccessAsync({ from: CHONKY_USDC_WALLET, gasPrice: 0 }, { shouldValidate: false });
const wethBalanceAfter = await weth.balanceOf(receiver).callAsync();
expect(wethBalanceAfter).to.be.bignumber.greaterThan(wethBalanceBefore);
});
});
});

View File

@@ -1,4 +1,13 @@
[
{
"timestamp": 1594788383,
"version": "4.1.7",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1592969527,
"version": "4.1.6",

View File

@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v4.1.7 - _July 15, 2020_
* Dependencies updated
## v4.1.6 - _June 24, 2020_
* Dependencies updated

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/contracts-multisig",
"version": "4.1.6",
"version": "4.1.7",
"engines": {
"node": ">=6.12"
},
@@ -49,18 +49,18 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/multisig/README.md",
"devDependencies": {
"@0x/abi-gen": "^5.3.0",
"@0x/contracts-asset-proxy": "^3.3.0",
"@0x/contracts-erc20": "^3.2.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/tslint-config": "^4.0.0",
"@0x/types": "^3.1.3",
"@0x/utils": "^5.5.0",
"@0x/web3-wrapper": "^7.1.0",
"@0x/abi-gen": "^5.3.1",
"@0x/contracts-asset-proxy": "^3.4.0",
"@0x/contracts-erc20": "^3.2.1",
"@0x/contracts-gen": "^2.0.10",
"@0x/contracts-test-utils": "^5.3.4",
"@0x/contracts-utils": "^4.5.1",
"@0x/dev-utils": "^3.3.0",
"@0x/sol-compiler": "^4.1.1",
"@0x/tslint-config": "^4.1.0",
"@0x/types": "^3.2.0",
"@0x/utils": "^5.5.1",
"@0x/web3-wrapper": "^7.2.0",
"@types/lodash": "4.14.104",
"@types/mocha": "^5.2.7",
"@types/node": "*",
@@ -78,11 +78,12 @@
"typescript": "3.0.1"
},
"dependencies": {
"@0x/base-contract": "^6.2.2",
"@0x/typescript-typings": "^5.1.0",
"ethereum-types": "^3.1.1"
"@0x/base-contract": "^6.2.3",
"@0x/typescript-typings": "^5.1.1",
"ethereum-types": "^3.2.0"
},
"publishConfig": {
"access": "public"
}
},
"gitHead": "4f91bfd907996b2f4dd383778b50c479c2602b56"
}

View File

@@ -1,4 +1,13 @@
[
{
"timestamp": 1594788383,
"version": "2.0.14",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1592969527,
"version": "2.0.13",

View File

@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v2.0.14 - _July 15, 2020_
* Dependencies updated
## v2.0.13 - _June 24, 2020_
* Dependencies updated

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/contracts-staking",
"version": "2.0.13",
"version": "2.0.14",
"engines": {
"node": ">=6.12"
},
@@ -53,20 +53,20 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/tokens/README.md",
"devDependencies": {
"@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-libs": "^4.3.6",
"@0x/contracts-gen": "^2.0.9",
"@0x/contracts-utils": "^4.5.0",
"@0x/dev-utils": "^3.2.2",
"@0x/order-utils": "^10.2.5",
"@0x/sol-compiler": "^4.1.0",
"@0x/abi-gen": "^5.3.1",
"@0x/contracts-asset-proxy": "^3.4.0",
"@0x/contracts-dev-utils": "^1.3.5",
"@0x/contracts-erc20": "^3.2.1",
"@0x/contracts-exchange-libs": "^4.3.7",
"@0x/contracts-gen": "^2.0.10",
"@0x/contracts-utils": "^4.5.1",
"@0x/dev-utils": "^3.3.0",
"@0x/order-utils": "^10.3.0",
"@0x/sol-compiler": "^4.1.1",
"@0x/ts-doc-gen": "^0.0.22",
"@0x/tslint-config": "^4.0.0",
"@0x/types": "^3.1.3",
"@0x/web3-wrapper": "^7.1.0",
"@0x/tslint-config": "^4.1.0",
"@0x/types": "^3.2.0",
"@0x/web3-wrapper": "^7.2.0",
"@types/lodash": "4.14.104",
"@types/node": "*",
"chai": "^4.0.1",
@@ -87,14 +87,15 @@
"typescript": "3.0.1"
},
"dependencies": {
"@0x/base-contract": "^6.2.2",
"@0x/contracts-test-utils": "^5.3.3",
"@0x/typescript-typings": "^5.1.0",
"@0x/utils": "^5.5.0",
"ethereum-types": "^3.1.1",
"@0x/base-contract": "^6.2.3",
"@0x/contracts-test-utils": "^5.3.4",
"@0x/typescript-typings": "^5.1.1",
"@0x/utils": "^5.5.1",
"ethereum-types": "^3.2.0",
"ethereumjs-util": "^5.1.1"
},
"publishConfig": {
"access": "public"
}
},
"gitHead": "4f91bfd907996b2f4dd383778b50c479c2602b56"
}

View File

@@ -1,4 +1,13 @@
[
{
"timestamp": 1594788383,
"version": "5.3.4",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"version": "5.3.3",
"changes": [

View File

@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v5.3.4 - _July 15, 2020_
* Dependencies updated
## v5.3.3 - _June 24, 2020_
* Add `msg` param to `assertIntegerRoughlyEquals` (#2576)

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/contracts-test-utils",
"version": "5.3.3",
"version": "5.3.4",
"engines": {
"node": ">=6.12"
},
@@ -34,28 +34,28 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/test-utils/README.md",
"devDependencies": {
"@0x/sol-compiler": "^4.1.0",
"@0x/tslint-config": "^4.0.0",
"@0x/sol-compiler": "^4.1.1",
"@0x/tslint-config": "^4.1.0",
"npm-run-all": "^4.1.2",
"shx": "^0.2.2",
"tslint": "5.11.0",
"typescript": "3.0.1"
},
"dependencies": {
"@0x/assert": "^3.0.8",
"@0x/base-contract": "^6.2.2",
"@0x/contract-addresses": "^4.10.0",
"@0x/dev-utils": "^3.2.2",
"@0x/json-schemas": "^5.0.8",
"@0x/order-utils": "^10.2.5",
"@0x/sol-coverage": "^4.0.9",
"@0x/sol-profiler": "^4.0.9",
"@0x/sol-trace": "^3.0.9",
"@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",
"@0x/assert": "^3.0.9",
"@0x/base-contract": "^6.2.3",
"@0x/contract-addresses": "^4.11.0",
"@0x/dev-utils": "^3.3.0",
"@0x/json-schemas": "^5.1.0",
"@0x/order-utils": "^10.3.0",
"@0x/sol-coverage": "^4.0.10",
"@0x/sol-profiler": "^4.1.0",
"@0x/sol-trace": "^3.0.10",
"@0x/subproviders": "^6.1.1",
"@0x/types": "^3.2.0",
"@0x/typescript-typings": "^5.1.1",
"@0x/utils": "^5.5.1",
"@0x/web3-wrapper": "^7.2.0",
"@types/bn.js": "^4.11.0",
"@types/js-combinatorics": "^0.5.29",
"@types/lodash": "4.14.104",
@@ -67,7 +67,7 @@
"chai-bignumber": "^3.0.0",
"decimal.js": "^10.2.0",
"dirty-chai": "^2.0.1",
"ethereum-types": "^3.1.1",
"ethereum-types": "^3.2.0",
"ethereumjs-util": "^5.1.1",
"ethers": "~4.0.4",
"js-combinatorics": "^0.5.3",
@@ -77,5 +77,6 @@
},
"publishConfig": {
"access": "public"
}
},
"gitHead": "4f91bfd907996b2f4dd383778b50c479c2602b56"
}

View File

@@ -1,4 +1,14 @@
[
{
"version": "4.5.1",
"changes": [
{
"note": "Reorganize `DeploymentConstants` addresses",
"pr": 2628
}
],
"timestamp": 1594788383
},
{
"version": "4.5.0",
"changes": [

View File

@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v4.5.1 - _July 15, 2020_
* Reorganize `DeploymentConstants` addresses (#2628)
## v4.5.0 - _June 24, 2020_
* Added `GST_ADDRESS` and `GST_COLLECTOR_ADDRESS` (#2523)

View File

@@ -20,40 +20,28 @@ pragma solidity ^0.5.9;
contract DeploymentConstants {
// solhint-disable separate-by-one-line-in-contract
// Mainnet addresses ///////////////////////////////////////////////////////
/// @dev Mainnet address of the WETH contract.
address constant private WETH_ADDRESS = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
// /// @dev Kovan address of the WETH contract.
// address constant private WETH_ADDRESS = 0xd0A1E359811322d97991E03f863a0C30C2cF029C;
/// @dev Mainnet address of the KyberNetworkProxy contract.
address constant private KYBER_NETWORK_PROXY_ADDRESS = 0x818E6FECD516Ecc3849DAf6845e3EC868087B755;
// /// @dev Kovan address of the KyberNetworkProxy contract.
// address constant private KYBER_NETWORK_PROXY_ADDRESS = 0x692f391bCc85cefCe8C237C01e1f636BbD70EA4D;
address constant private KYBER_NETWORK_PROXY_ADDRESS = 0x9AAb3f75489902f3a48495025729a0AF77d4b11e;
/// @dev Mainnet address of the `UniswapExchangeFactory` contract.
address constant private UNISWAP_EXCHANGE_FACTORY_ADDRESS = 0xc0a47dFe034B400B47bDaD5FecDa2621de6c4d95;
// /// @dev Kovan address of the `UniswapExchangeFactory` contract.
// address constant private UNISWAP_EXCHANGE_FACTORY_ADDRESS = 0xD3E51Ef092B2845f10401a0159B2B96e8B6c3D30;
/// @dev Mainnet address of the `UniswapV2Router01` contract.
address constant private UNISWAP_V2_ROUTER_01_ADDRESS = 0xf164fC0Ec4E93095b804a4795bBe1e041497b92a;
// /// @dev Kovan address of the `UniswapV2Router01` contract.
// address constant private UNISWAP_V2_ROUTER_01_ADDRESS = 0xf164fC0Ec4E93095b804a4795bBe1e041497b92a;
/// @dev Mainnet address of the Eth2Dai `MatchingMarket` contract.
address constant private ETH2DAI_ADDRESS = 0x794e6e91555438aFc3ccF1c5076A74F42133d08D;
// /// @dev Kovan address of the Eth2Dai `MatchingMarket` contract.
// address constant private ETH2DAI_ADDRESS = 0xe325acB9765b02b8b418199bf9650972299235F4;
/// @dev Mainnet address of the `ERC20BridgeProxy` contract
address constant private ERC20_BRIDGE_PROXY_ADDRESS = 0x8ED95d1746bf1E4dAb58d8ED4724f1Ef95B20Db0;
// /// @dev Kovan address of the `ERC20BridgeProxy` contract
// address constant private ERC20_BRIDGE_PROXY_ADDRESS = 0xFb2DD2A1366dE37f7241C83d47DA58fd503E2C64;
///@dev Mainnet address of the `Dai` (multi-collateral) contract
address constant private DAI_ADDRESS = 0x6B175474E89094C44Da98b954EedeAC495271d0F;
// ///@dev Kovan address of the `Dai` (multi-collateral) contract
// address constant private DAI_ADDRESS = 0x4F96Fe3b7A6Cf9725f59d353F723c1bDb64CA6Aa;
/// @dev Mainnet address of the `Chai` contract
address constant private CHAI_ADDRESS = 0x06AF07097C9Eeb7fD685c692751D5C66dB49c215;
/// @dev Mainnet address of the 0x DevUtils contract.
address constant private DEV_UTILS_ADDRESS = 0x74134CF88b21383713E096a5ecF59e297dc7f547;
// /// @dev Kovan address of the 0x DevUtils contract.
// address constant private DEV_UTILS_ADDRESS = 0x9402639A828BdF4E9e4103ac3B69E1a6E522eB59;
/// @dev Kyber ETH pseudo-address.
address constant internal KYBER_ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
/// @dev Mainnet address of the dYdX contract.
@@ -62,6 +50,30 @@ contract DeploymentConstants {
address constant private GST_ADDRESS = 0x0000000000b3F879cb30FE243b4Dfee438691c04;
/// @dev Mainnet address of the GST Collector
address constant private GST_COLLECTOR_ADDRESS = 0x000000D3b08566BE75A6DB803C03C85C0c1c5B96;
// Kovan addresses /////////////////////////////////////////////////////////
// /// @dev Kovan address of the WETH contract.
// address constant private WETH_ADDRESS = 0xd0A1E359811322d97991E03f863a0C30C2cF029C;
// /// @dev Kovan address of the KyberNetworkProxy contract.
// address constant private KYBER_NETWORK_PROXY_ADDRESS = 0x692f391bCc85cefCe8C237C01e1f636BbD70EA4D;
// /// @dev Kovan address of the `UniswapExchangeFactory` contract.
// address constant private UNISWAP_EXCHANGE_FACTORY_ADDRESS = 0xD3E51Ef092B2845f10401a0159B2B96e8B6c3D30;
// /// @dev Kovan address of the `UniswapV2Router01` contract.
// address constant private UNISWAP_V2_ROUTER_01_ADDRESS = 0xf164fC0Ec4E93095b804a4795bBe1e041497b92a;
// /// @dev Kovan address of the Eth2Dai `MatchingMarket` contract.
// address constant private ETH2DAI_ADDRESS = 0xe325acB9765b02b8b418199bf9650972299235F4;
// /// @dev Kovan address of the `ERC20BridgeProxy` contract
// address constant private ERC20_BRIDGE_PROXY_ADDRESS = 0xFb2DD2A1366dE37f7241C83d47DA58fd503E2C64;
// /// @dev Kovan address of the `Chai` contract
// address constant private CHAI_ADDRESS = address(0);
// /// @dev Kovan address of the `Dai` (multi-collateral) contract
// address constant private DAI_ADDRESS = 0x4F96Fe3b7A6Cf9725f59d353F723c1bDb64CA6Aa;
// /// @dev Kovan address of the 0x DevUtils contract.
// address constant private DEV_UTILS_ADDRESS = 0x9402639A828BdF4E9e4103ac3B69E1a6E522eB59;
// /// @dev Kyber ETH pseudo-address.
// address constant internal KYBER_ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
// /// @dev Kovan address of the dYdX contract.
// address constant private DYDX_ADDRESS = address(0);
// /// @dev Kovan address of the GST2 contract
// address constant private GST_ADDRESS = address(0);
// /// @dev Kovan address of the GST Collector

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/contracts-utils",
"version": "4.5.0",
"version": "4.5.1",
"engines": {
"node": ">=6.12"
},
@@ -50,15 +50,15 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/utils/README.md",
"devDependencies": {
"@0x/abi-gen": "^5.3.0",
"@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/tslint-config": "^4.0.0",
"@0x/types": "^3.1.3",
"@0x/web3-wrapper": "^7.1.0",
"@0x/abi-gen": "^5.3.1",
"@0x/contracts-gen": "^2.0.10",
"@0x/contracts-test-utils": "^5.3.4",
"@0x/dev-utils": "^3.3.0",
"@0x/order-utils": "^10.3.0",
"@0x/sol-compiler": "^4.1.1",
"@0x/tslint-config": "^4.1.0",
"@0x/types": "^3.2.0",
"@0x/web3-wrapper": "^7.2.0",
"@types/bn.js": "^4.11.0",
"@types/lodash": "4.14.104",
"@types/mocha": "^5.2.7",
@@ -79,13 +79,14 @@
"typescript": "3.0.1"
},
"dependencies": {
"@0x/base-contract": "^6.2.2",
"@0x/typescript-typings": "^5.1.0",
"@0x/utils": "^5.5.0",
"@0x/base-contract": "^6.2.3",
"@0x/typescript-typings": "^5.1.1",
"@0x/utils": "^5.5.1",
"bn.js": "^4.11.8",
"ethereum-types": "^3.1.1"
"ethereum-types": "^3.2.0"
},
"publishConfig": {
"access": "public"
}
},
"gitHead": "4f91bfd907996b2f4dd383778b50c479c2602b56"
}

View File

@@ -1,4 +1,22 @@
[
{
"version": "0.2.0",
"changes": [
{
"note": "Export migration tools",
"pr": 2612
},
{
"note": "Export `AffiliateFeeTransformerContract`",
"pr": 2622
},
{
"note": "Add `MetaTransactions` and `SignatureValidator` features",
"pr": 2610
}
],
"timestamp": 1594788383
},
{
"timestamp": 1592969527,
"version": "0.1.1",

View File

@@ -5,6 +5,12 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v0.2.0 - _July 15, 2020_
* Export migration tools (#2612)
* Export `AffiliateFeeTransformerContract` (#2622)
* Add `MetaTransactions` and `SignatureValidator` features (#2610)
## v0.1.1 - _June 24, 2020_
* Dependencies updated

View File

@@ -34,11 +34,12 @@ contract ZeroEx {
/// @dev Construct this contract and register the `Bootstrap` feature.
/// After constructing this contract, `bootstrap()` should be called
/// to seed the initial feature set.
constructor() public {
/// by `bootstrap()` to seed the initial feature set.
/// @param bootstrapper Who can call `bootstrap()`.
constructor(address bootstrapper) public {
// Temporarily create and register the bootstrap feature.
// It will deregister itself after `bootstrap()` has been called.
Bootstrap bootstrap = new Bootstrap(msg.sender);
Bootstrap bootstrap = new Bootstrap(bootstrapper);
LibProxyStorage.getStorage().impls[bootstrap.bootstrap.selector] =
address(bootstrap);
}

View File

@@ -0,0 +1,174 @@
/*
Copyright 2020 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.6.5;
library LibMetaTransactionsRichErrors {
// solhint-disable func-name-mixedcase
function InvalidMetaTransactionsArrayLengthsError(
uint256 mtxCount,
uint256 signatureCount
)
internal
pure
returns (bytes memory)
{
return abi.encodeWithSelector(
bytes4(keccak256("InvalidMetaTransactionsArrayLengthsError(uint256,uint256)")),
mtxCount,
signatureCount
);
}
function MetaTransactionUnsupportedFunctionError(
bytes32 mtxHash,
bytes4 selector
)
internal
pure
returns (bytes memory)
{
return abi.encodeWithSelector(
bytes4(keccak256("MetaTransactionUnsupportedFunctionError(bytes32,bytes4)")),
mtxHash,
selector
);
}
function MetaTransactionWrongSenderError(
bytes32 mtxHash,
address sender,
address expectedSender
)
internal
pure
returns (bytes memory)
{
return abi.encodeWithSelector(
bytes4(keccak256("MetaTransactionWrongSenderError(bytes32,address,address)")),
mtxHash,
sender,
expectedSender
);
}
function MetaTransactionExpiredError(
bytes32 mtxHash,
uint256 time,
uint256 expirationTime
)
internal
pure
returns (bytes memory)
{
return abi.encodeWithSelector(
bytes4(keccak256("MetaTransactionExpiredError(bytes32,uint256,uint256)")),
mtxHash,
time,
expirationTime
);
}
function MetaTransactionGasPriceError(
bytes32 mtxHash,
uint256 gasPrice,
uint256 minGasPrice,
uint256 maxGasPrice
)
internal
pure
returns (bytes memory)
{
return abi.encodeWithSelector(
bytes4(keccak256("MetaTransactionGasPriceError(bytes32,uint256,uint256,uint256)")),
mtxHash,
gasPrice,
minGasPrice,
maxGasPrice
);
}
function MetaTransactionInsufficientEthError(
bytes32 mtxHash,
uint256 ethBalance,
uint256 ethRequired
)
internal
pure
returns (bytes memory)
{
return abi.encodeWithSelector(
bytes4(keccak256("MetaTransactionInsufficientEthError(bytes32,uint256,uint256)")),
mtxHash,
ethBalance,
ethRequired
);
}
function MetaTransactionInvalidSignatureError(
bytes32 mtxHash,
bytes memory signature,
bytes memory errData
)
internal
pure
returns (bytes memory)
{
return abi.encodeWithSelector(
bytes4(keccak256("MetaTransactionInvalidSignatureError(bytes32,bytes,bytes)")),
mtxHash,
signature,
errData
);
}
function MetaTransactionAlreadyExecutedError(
bytes32 mtxHash,
uint256 executedBlockNumber
)
internal
pure
returns (bytes memory)
{
return abi.encodeWithSelector(
bytes4(keccak256("MetaTransactionAlreadyExecutedError(bytes32,uint256)")),
mtxHash,
executedBlockNumber
);
}
function MetaTransactionCallFailedError(
bytes32 mtxHash,
bytes memory callData,
bytes memory returnData
)
internal
pure
returns (bytes memory)
{
return abi.encodeWithSelector(
bytes4(keccak256("MetaTransactionCallFailedError(bytes32,bytes,bytes)")),
mtxHash,
callData,
returnData
);
}
}

View File

@@ -0,0 +1,52 @@
/*
Copyright 2020 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.6.5;
library LibSignatureRichErrors {
enum SignatureValidationErrorCodes {
ALWAYS_INVALID,
INVALID_LENGTH,
UNSUPPORTED,
ILLEGAL,
WRONG_SIGNER
}
// solhint-disable func-name-mixedcase
function SignatureValidationError(
SignatureValidationErrorCodes code,
bytes32 hash,
address signerAddress,
bytes memory signature
)
internal
pure
returns (bytes memory)
{
return abi.encodeWithSelector(
bytes4(keccak256("SignatureValidationError(uint8,bytes32,address,bytes)")),
code,
hash,
signerAddress,
signature
);
}
}

View File

@@ -0,0 +1,127 @@
/*
Copyright 2020 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.6.5;
pragma experimental ABIEncoderV2;
import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
/// @dev Meta-transactions feature.
interface IMetaTransactions {
/// @dev Describes an exchange proxy meta transaction.
struct MetaTransactionData {
// Signer of meta-transaction. On whose behalf to execute the MTX.
address signer;
// Required sender, or NULL for anyone.
address sender;
// Minimum gas price.
uint256 minGasPrice;
// Maximum gas price.
uint256 maxGasPrice;
// MTX is invalid after this time.
uint256 expirationTimeSeconds;
// Nonce to make this MTX unique.
uint256 salt;
// Encoded call data to a function on the exchange proxy.
bytes callData;
// Amount of ETH to attach to the call.
uint256 value;
// ERC20 fee `signer` pays `sender`.
IERC20TokenV06 feeToken;
// ERC20 fee amount.
uint256 feeAmount;
}
/// @dev Emitted whenever a meta-transaction is executed via
/// `executeMetaTransaction()` or `executeMetaTransactions()`.
/// @param hash The meta-transaction hash.
/// @param selector The selector of the function being executed.
/// @param signer Who to execute the meta-transaction on behalf of.
/// @param sender Who executed the meta-transaction.
event MetaTransactionExecuted(
bytes32 hash,
bytes4 indexed selector,
address signer,
address sender
);
/// @dev Execute a single meta-transaction.
/// @param mtx The meta-transaction.
/// @param signature The signature by `mtx.signer`.
/// @return returnResult The ABI-encoded result of the underlying call.
function executeMetaTransaction(
MetaTransactionData calldata mtx,
bytes calldata signature
)
external
payable
returns (bytes memory returnResult);
/// @dev Execute multiple meta-transactions.
/// @param mtxs The meta-transactions.
/// @param signatures The signature by each respective `mtx.signer`.
/// @return returnResults The ABI-encoded results of the underlying calls.
function batchExecuteMetaTransactions(
MetaTransactionData[] calldata mtxs,
bytes[] calldata signatures
)
external
payable
returns (bytes[] memory returnResults);
/// @dev Execute a meta-transaction via `sender`. Privileged variant.
/// Only callable from within.
/// @param sender Who is executing the meta-transaction..
/// @param mtx The meta-transaction.
/// @param signature The signature by `mtx.signer`.
/// @return returnResult The ABI-encoded result of the underlying call.
function _executeMetaTransaction(
address sender,
MetaTransactionData calldata mtx,
bytes calldata signature
)
external
payable
returns (bytes memory returnResult);
/// @dev Get the block at which a meta-transaction has been executed.
/// @param mtx The meta-transaction.
/// @return blockNumber The block height when the meta-transactioin was executed.
function getMetaTransactionExecutedBlock(MetaTransactionData calldata mtx)
external
view
returns (uint256 blockNumber);
/// @dev Get the block at which a meta-transaction hash has been executed.
/// @param mtxHash The meta-transaction hash.
/// @return blockNumber The block height when the meta-transactioin was executed.
function getMetaTransactionHashExecutedBlock(bytes32 mtxHash)
external
view
returns (uint256 blockNumber);
/// @dev Get the EIP712 hash of a meta-transaction.
/// @param mtx The meta-transaction.
/// @return mtxHash The EIP712 hash of `mtx`.
function getMetaTransactionHash(MetaTransactionData calldata mtx)
external
view
returns (bytes32 mtxHash);
}

View File

@@ -0,0 +1,63 @@
/*
Copyright 2020 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.6.5;
pragma experimental ABIEncoderV2;
/// @dev Feature for validating signatures.
interface ISignatureValidator {
/// @dev Allowed signature types.
enum SignatureType {
Illegal, // 0x00, default value
Invalid, // 0x01
EIP712, // 0x02
EthSign, // 0x03
NSignatureTypes // 0x04, number of signature types. Always leave at end.
}
/// @dev Validate that `hash` was signed by `signer` given `signature`.
/// Reverts otherwise.
/// @param hash The hash that was signed.
/// @param signer The signer of the hash.
/// @param signature The signature. The last byte of this signature should
/// be a member of the `SignatureType` enum.
function validateHashSignature(
bytes32 hash,
address signer,
bytes calldata signature
)
external
view;
/// @dev Check that `hash` was signed by `signer` given `signature`.
/// @param hash The hash that was signed.
/// @param signer The signer of the hash.
/// @param signature The signature. The last byte of this signature should
/// be a member of the `SignatureType` enum.
/// @return isValid `true` on success.
function isValidHashSignature(
bytes32 hash,
address signer,
bytes calldata signature
)
external
view
returns (bool isValid);
}

View File

@@ -65,7 +65,7 @@ interface ITransformERC20 {
/// @dev Deploy a new flash wallet instance and replace the current one with it.
/// Useful if we somehow break the current wallet instance.
/// Anyone can call this.
/// Only callable by the owner.
/// @return wallet The new wallet instance.
function createTransformWallet()
external

View File

@@ -0,0 +1,436 @@
/*
Copyright 2020 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.6.5;
pragma experimental ABIEncoderV2;
import "@0x/contracts-utils/contracts/src/v06/errors/LibRichErrorsV06.sol";
import "@0x/contracts-utils/contracts/src/v06/LibBytesV06.sol";
import "../errors/LibMetaTransactionsRichErrors.sol";
import "../fixins/FixinCommon.sol";
import "../fixins/FixinEIP712.sol";
import "../migrations/LibMigrate.sol";
import "../storage/LibMetaTransactionsStorage.sol";
import "./IMetaTransactions.sol";
import "./ITransformERC20.sol";
import "./ISignatureValidator.sol";
import "./ITokenSpender.sol";
import "./IFeature.sol";
/// @dev MetaTransactions feature.
contract MetaTransactions is
IFeature,
IMetaTransactions,
FixinCommon,
FixinEIP712
{
using LibBytesV06 for bytes;
using LibRichErrorsV06 for bytes;
/// @dev Intermediate state vars to avoid stack overflows.
struct ExecuteState {
address sender;
bytes32 hash;
MetaTransactionData mtx;
bytes signature;
bytes4 selector;
uint256 selfBalance;
uint256 executedBlockNumber;
}
struct TransformERC20Args {
IERC20TokenV06 inputToken;
IERC20TokenV06 outputToken;
uint256 inputTokenAmount;
uint256 minOutputTokenAmount;
ITransformERC20.Transformation[] transformations;
}
/// @dev Name of this feature.
string public constant override FEATURE_NAME = "MetaTransactions";
/// @dev Version of this feature.
uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 0, 0);
/// @dev EIP712 typehash of the `MetaTransactionData` struct.
bytes32 public immutable MTX_EIP712_TYPEHASH = keccak256(
"MetaTransactionData("
"address signer,"
"address sender,"
"uint256 minGasPrice,"
"uint256 maxGasPrice,"
"uint256 expirationTimeSeconds,"
"uint256 salt,"
"bytes callData,"
"uint256 value,"
"address feeToken,"
"uint256 feeAmount"
")"
);
constructor(address zeroExAddress)
public
FixinCommon()
FixinEIP712(zeroExAddress)
{
// solhint-disable-next-line no-empty-blocks
}
/// @dev Initialize and register this feature.
/// Should be delegatecalled by `Migrate.migrate()`.
/// @return success `LibMigrate.SUCCESS` on success.
function migrate()
external
returns (bytes4 success)
{
_registerFeatureFunction(this.executeMetaTransaction.selector);
_registerFeatureFunction(this.batchExecuteMetaTransactions.selector);
_registerFeatureFunction(this._executeMetaTransaction.selector);
_registerFeatureFunction(this.getMetaTransactionExecutedBlock.selector);
_registerFeatureFunction(this.getMetaTransactionHashExecutedBlock.selector);
_registerFeatureFunction(this.getMetaTransactionHash.selector);
return LibMigrate.MIGRATE_SUCCESS;
}
/// @dev Execute a single meta-transaction.
/// @param mtx The meta-transaction.
/// @param signature The signature by `mtx.signer`.
/// @return returnResult The ABI-encoded result of the underlying call.
function executeMetaTransaction(
MetaTransactionData memory mtx,
bytes memory signature
)
public
payable
override
returns (bytes memory returnResult)
{
return _executeMetaTransactionPrivate(
msg.sender,
mtx,
signature
);
}
/// @dev Execute multiple meta-transactions.
/// @param mtxs The meta-transactions.
/// @param signatures The signature by each respective `mtx.signer`.
/// @return returnResults The ABI-encoded results of the underlying calls.
function batchExecuteMetaTransactions(
MetaTransactionData[] memory mtxs,
bytes[] memory signatures
)
public
payable
override
returns (bytes[] memory returnResults)
{
if (mtxs.length != signatures.length) {
LibMetaTransactionsRichErrors.InvalidMetaTransactionsArrayLengthsError(
mtxs.length,
signatures.length
).rrevert();
}
returnResults = new bytes[](mtxs.length);
for (uint256 i = 0; i < mtxs.length; ++i) {
returnResults[i] = _executeMetaTransactionPrivate(
msg.sender,
mtxs[i],
signatures[i]
);
}
}
/// @dev Execute a meta-transaction via `sender`. Privileged variant.
/// Only callable from within.
/// @param sender Who is executing the meta-transaction..
/// @param mtx The meta-transaction.
/// @param signature The signature by `mtx.signer`.
/// @return returnResult The ABI-encoded result of the underlying call.
function _executeMetaTransaction(
address sender,
MetaTransactionData memory mtx,
bytes memory signature
)
public
payable
override
onlySelf
returns (bytes memory returnResult)
{
return _executeMetaTransactionPrivate(sender, mtx, signature);
}
/// @dev Get the block at which a meta-transaction has been executed.
/// @param mtx The meta-transaction.
/// @return blockNumber The block height when the meta-transactioin was executed.
function getMetaTransactionExecutedBlock(MetaTransactionData memory mtx)
public
override
view
returns (uint256 blockNumber)
{
return getMetaTransactionHashExecutedBlock(getMetaTransactionHash(mtx));
}
/// @dev Get the block at which a meta-transaction hash has been executed.
/// @param mtxHash The meta-transaction hash.
/// @return blockNumber The block height when the meta-transactioin was executed.
function getMetaTransactionHashExecutedBlock(bytes32 mtxHash)
public
override
view
returns (uint256 blockNumber)
{
return LibMetaTransactionsStorage.getStorage().mtxHashToExecutedBlockNumber[mtxHash];
}
/// @dev Get the EIP712 hash of a meta-transaction.
/// @param mtx The meta-transaction.
/// @return mtxHash The EIP712 hash of `mtx`.
function getMetaTransactionHash(MetaTransactionData memory mtx)
public
override
view
returns (bytes32 mtxHash)
{
return _getEIP712Hash(keccak256(abi.encode(
MTX_EIP712_TYPEHASH,
mtx.signer,
mtx.sender,
mtx.minGasPrice,
mtx.maxGasPrice,
mtx.expirationTimeSeconds,
mtx.salt,
keccak256(mtx.callData),
mtx.value,
mtx.feeToken,
mtx.feeAmount
)));
}
/// @dev Execute a meta-transaction by `sender`. Low-level, hidden variant.
/// @param sender Who is executing the meta-transaction..
/// @param mtx The meta-transaction.
/// @param signature The signature by `mtx.signer`.
/// @return returnResult The ABI-encoded result of the underlying call.
function _executeMetaTransactionPrivate(
address sender,
MetaTransactionData memory mtx,
bytes memory signature
)
private
returns (bytes memory returnResult)
{
ExecuteState memory state;
state.sender = sender;
state.hash = getMetaTransactionHash(mtx);
state.mtx = mtx;
state.signature = signature;
_validateMetaTransaction(state);
// Mark the transaction executed.
assert(block.number > 0);
LibMetaTransactionsStorage.getStorage()
.mtxHashToExecutedBlockNumber[state.hash] = block.number;
// Execute the call based on the selector.
state.selector = mtx.callData.readBytes4(0);
if (state.selector == ITransformERC20.transformERC20.selector) {
returnResult = _executeTransformERC20Call(state);
} else {
LibMetaTransactionsRichErrors
.MetaTransactionUnsupportedFunctionError(state.hash, state.selector)
.rrevert();
}
// Pay the fee to the sender.
if (mtx.feeAmount > 0) {
ITokenSpender(address(this))._spendERC20Tokens(
mtx.feeToken,
mtx.signer, // From the signer.
sender, // To the sender.
mtx.feeAmount
);
}
emit MetaTransactionExecuted(
state.hash,
state.selector,
mtx.signer,
mtx.sender
);
}
/// @dev Validate that a meta-transaction is executable.
function _validateMetaTransaction(ExecuteState memory state)
private
view
{
// Must be from the required sender, if set.
if (state.mtx.sender != address(0) && state.mtx.sender != state.sender) {
LibMetaTransactionsRichErrors
.MetaTransactionWrongSenderError(
state.hash,
state.sender,
state.mtx.sender
).rrevert();
}
// Must not be expired.
if (state.mtx.expirationTimeSeconds <= block.timestamp) {
LibMetaTransactionsRichErrors
.MetaTransactionExpiredError(
state.hash,
block.timestamp,
state.mtx.expirationTimeSeconds
).rrevert();
}
// Must have a valid gas price.
if (state.mtx.minGasPrice > tx.gasprice || state.mtx.maxGasPrice < tx.gasprice) {
LibMetaTransactionsRichErrors
.MetaTransactionGasPriceError(
state.hash,
tx.gasprice,
state.mtx.minGasPrice,
state.mtx.maxGasPrice
).rrevert();
}
// Must have enough ETH.
state.selfBalance = address(this).balance;
if (state.mtx.value > state.selfBalance) {
LibMetaTransactionsRichErrors
.MetaTransactionInsufficientEthError(
state.hash,
state.selfBalance,
state.mtx.value
).rrevert();
}
// Must be signed by signer.
try
ISignatureValidator(address(this))
.validateHashSignature(state.hash, state.mtx.signer, state.signature)
{}
catch (bytes memory err) {
LibMetaTransactionsRichErrors
.MetaTransactionInvalidSignatureError(
state.hash,
state.signature,
err
).rrevert();
}
// Transaction must not have been already executed.
state.executedBlockNumber = LibMetaTransactionsStorage
.getStorage().mtxHashToExecutedBlockNumber[state.hash];
if (state.executedBlockNumber != 0) {
LibMetaTransactionsRichErrors
.MetaTransactionAlreadyExecutedError(
state.hash,
state.executedBlockNumber
).rrevert();
}
}
/// @dev Execute a `ITransformERC20.transformERC20()` meta-transaction call
/// by decoding the call args and translating the call to the internal
/// `ITransformERC20._transformERC20()` variant, where we can override
/// the taker address.
function _executeTransformERC20Call(ExecuteState memory state)
private
returns (bytes memory returnResult)
{
// HACK(dorothy-zbornak): `abi.decode()` with the individual args
// will cause a stack overflow. But we can prefix the call data with an
// offset to transform it into the encoding for the equivalent single struct arg,
// since decoding a single struct arg consumes far less stack space than
// decoding multiple struct args.
// Where the encoding for multiple args (with the seleector ommitted)
// would typically look like:
// | argument | offset |
// |--------------------------|---------|
// | inputToken | 0 |
// | outputToken | 32 |
// | inputTokenAmount | 64 |
// | minOutputTokenAmount | 96 |
// | transformations (offset) | 128 | = 32
// | transformations (data) | 160 |
// We will ABI-decode a single struct arg copy with the layout:
// | argument | offset |
// |--------------------------|---------|
// | (arg 1 offset) | 0 | = 32
// | inputToken | 32 |
// | outputToken | 64 |
// | inputTokenAmount | 96 |
// | minOutputTokenAmount | 128 |
// | transformations (offset) | 160 | = 32
// | transformations (data) | 192 |
TransformERC20Args memory args;
{
bytes memory encodedStructArgs = new bytes(state.mtx.callData.length - 4 + 32);
// Copy the args data from the original, after the new struct offset prefix.
bytes memory fromCallData = state.mtx.callData;
assert(fromCallData.length >= 4);
uint256 fromMem;
uint256 toMem;
assembly {
// Prefix the original calldata with a struct offset,
// which is just one word over.
mstore(add(encodedStructArgs, 32), 32)
// Copy everything after the selector.
fromMem := add(fromCallData, 36)
// Start copying after the struct offset.
toMem := add(encodedStructArgs, 64)
}
LibBytesV06.memCopy(toMem, fromMem, fromCallData.length - 4);
// Decode call args for `ITransformERC20.transformERC20()` as a struct.
args = abi.decode(encodedStructArgs, (TransformERC20Args));
}
// Call `ITransformERC20._transformERC20()` (internal variant).
return _callSelf(
state.hash,
abi.encodeWithSelector(
ITransformERC20._transformERC20.selector,
keccak256(state.mtx.callData),
state.mtx.signer, // taker is mtx signer
args.inputToken,
args.outputToken,
args.inputTokenAmount,
args.minOutputTokenAmount,
args.transformations
),
state.mtx.value
);
}
/// @dev Make an arbitrary internal, meta-transaction call.
/// Warning: Do not let unadulerated `callData` into this function.
function _callSelf(bytes32 hash, bytes memory callData, uint256 value)
private
returns (bytes memory returnResult)
{
bool success;
(success, returnResult) = address(this).call{value: value}(callData);
if (!success) {
LibMetaTransactionsRichErrors.MetaTransactionCallFailedError(
hash,
callData,
returnResult
).rrevert();
}
}
}

View File

@@ -37,19 +37,15 @@ contract Ownable is
FixinCommon
{
// solhint-disable
/// @dev Name of this feature.
string public constant override FEATURE_NAME = "Ownable";
/// @dev Version of this feature.
uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 0, 0);
/// @dev The deployed address of this contract.
address immutable private _implementation;
// solhint-enable
using LibRichErrorsV06 for bytes;
constructor() public {
_implementation = address(this);
constructor() public FixinCommon() {
// solhint-disable-next-line no-empty-blocks
}
/// @dev Initializes this feature. The intial owner will be set to this (ZeroEx)

View File

@@ -0,0 +1,260 @@
/*
Copyright 2020 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.6.5;
pragma experimental ABIEncoderV2;
import "@0x/contracts-utils/contracts/src/v06/errors/LibRichErrorsV06.sol";
import "@0x/contracts-utils/contracts/src/v06/LibBytesV06.sol";
import "../errors/LibSignatureRichErrors.sol";
import "../fixins/FixinCommon.sol";
import "../migrations/LibMigrate.sol";
import "./ISignatureValidator.sol";
import "./IFeature.sol";
/// @dev Feature for validating signatures.
contract SignatureValidator is
IFeature,
ISignatureValidator,
FixinCommon
{
using LibBytesV06 for bytes;
using LibRichErrorsV06 for bytes;
/// @dev Name of this feature.
string public constant override FEATURE_NAME = "SignatureValidator";
/// @dev Version of this feature.
uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 0, 0);
constructor() public FixinCommon() {
// solhint-disable-next-line no-empty-blocks
}
/// @dev Initialize and register this feature.
/// Should be delegatecalled by `Migrate.migrate()`.
/// @return success `LibMigrate.SUCCESS` on success.
function migrate()
external
returns (bytes4 success)
{
_registerFeatureFunction(this.validateHashSignature.selector);
_registerFeatureFunction(this.isValidHashSignature.selector);
return LibMigrate.MIGRATE_SUCCESS;
}
/// @dev Validate that `hash` was signed by `signer` given `signature`.
/// Reverts otherwise.
/// @param hash The hash that was signed.
/// @param signer The signer of the hash.
/// @param signature The signature. The last byte of this signature should
/// be a member of the `SignatureType` enum.
function validateHashSignature(
bytes32 hash,
address signer,
bytes memory signature
)
public
override
view
{
SignatureType signatureType = _readValidSignatureType(
hash,
signer,
signature
);
// TODO: When we support non-hash signature types, assert that
// `signatureType` is only `EIP712` or `EthSign` here.
_validateHashSignatureTypes(
signatureType,
hash,
signer,
signature
);
}
/// @dev Check that `hash` was signed by `signer` given `signature`.
/// @param hash The hash that was signed.
/// @param signer The signer of the hash.
/// @param signature The signature. The last byte of this signature should
/// be a member of the `SignatureType` enum.
/// @return isValid `true` on success.
function isValidHashSignature(
bytes32 hash,
address signer,
bytes calldata signature
)
external
view
override
returns (bool isValid)
{
try this.validateHashSignature(hash, signer, signature) {
isValid = true;
} catch (bytes memory) {
isValid = false;
}
}
/// @dev Validates a hash-only signature type. Low-level, hidden variant.
/// @param signatureType The type of signature to check.
/// @param hash The hash that was signed.
/// @param signer The signer of the hash.
/// @param signature The signature. The last byte of this signature should
/// be a member of the `SignatureType` enum.
function _validateHashSignatureTypes(
SignatureType signatureType,
bytes32 hash,
address signer,
bytes memory signature
)
private
pure
{
address recovered = address(0);
if (signatureType == SignatureType.Invalid) {
// Always invalid signature.
// Like Illegal, this is always implicitly available and therefore
// offered explicitly. It can be implicitly created by providing
// a correctly formatted but incorrect signature.
LibSignatureRichErrors.SignatureValidationError(
LibSignatureRichErrors.SignatureValidationErrorCodes.ALWAYS_INVALID,
hash,
signer,
signature
).rrevert();
} else if (signatureType == SignatureType.EIP712) {
// Signature using EIP712
if (signature.length != 66) {
LibSignatureRichErrors.SignatureValidationError(
LibSignatureRichErrors.SignatureValidationErrorCodes.INVALID_LENGTH,
hash,
signer,
signature
).rrevert();
}
uint8 v = uint8(signature[0]);
bytes32 r = signature.readBytes32(1);
bytes32 s = signature.readBytes32(33);
recovered = ecrecover(
hash,
v,
r,
s
);
} else if (signatureType == SignatureType.EthSign) {
// Signed using `eth_sign`
if (signature.length != 66) {
LibSignatureRichErrors.SignatureValidationError(
LibSignatureRichErrors.SignatureValidationErrorCodes.INVALID_LENGTH,
hash,
signer,
signature
).rrevert();
}
uint8 v = uint8(signature[0]);
bytes32 r = signature.readBytes32(1);
bytes32 s = signature.readBytes32(33);
recovered = ecrecover(
keccak256(abi.encodePacked(
"\x19Ethereum Signed Message:\n32",
hash
)),
v,
r,
s
);
} else {
// This should never happen.
revert('SignatureValidator/ILLEGAL_CODE_PATH');
}
if (recovered == address(0) || signer != recovered) {
LibSignatureRichErrors.SignatureValidationError(
LibSignatureRichErrors.SignatureValidationErrorCodes.WRONG_SIGNER,
hash,
signer,
signature
).rrevert();
}
}
/// @dev Reads the `SignatureType` from the end of a signature and validates it.
function _readValidSignatureType(
bytes32 hash,
address signer,
bytes memory signature
)
private
pure
returns (SignatureType signatureType)
{
// Read the signatureType from the signature
signatureType = _readSignatureType(
hash,
signer,
signature
);
// Ensure signature is supported
if (uint8(signatureType) >= uint8(SignatureType.NSignatureTypes)) {
LibSignatureRichErrors.SignatureValidationError(
LibSignatureRichErrors.SignatureValidationErrorCodes.UNSUPPORTED,
hash,
signer,
signature
).rrevert();
}
// Always illegal signature.
// This is always an implicit option since a signer can create a
// signature array with invalid type or length. We may as well make
// it an explicit option. This aids testing and analysis. It is
// also the initialization value for the enum type.
if (signatureType == SignatureType.Illegal) {
LibSignatureRichErrors.SignatureValidationError(
LibSignatureRichErrors.SignatureValidationErrorCodes.ILLEGAL,
hash,
signer,
signature
).rrevert();
}
}
/// @dev Reads the `SignatureType` from the end of a signature.
function _readSignatureType(
bytes32 hash,
address signer,
bytes memory signature
)
private
pure
returns (SignatureType sigType)
{
if (signature.length == 0) {
LibSignatureRichErrors.SignatureValidationError(
LibSignatureRichErrors.SignatureValidationErrorCodes.INVALID_LENGTH,
hash,
signer,
signature
).rrevert();
}
return SignatureType(uint8(signature[signature.length - 1]));
}
}

View File

@@ -35,19 +35,15 @@ contract SimpleFunctionRegistry is
ISimpleFunctionRegistry,
FixinCommon
{
// solhint-disable
/// @dev Name of this feature.
string public constant override FEATURE_NAME = "SimpleFunctionRegistry";
/// @dev Version of this feature.
uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 0, 0);
/// @dev The deployed address of this contract.
address private immutable _implementation;
// solhint-enable
using LibRichErrorsV06 for bytes;
constructor() public {
_implementation = address(this);
constructor() public FixinCommon() {
// solhint-disable-next-line no-empty-blocks
}
/// @dev Initializes this feature, registering its own functions.

View File

@@ -44,14 +44,12 @@ contract TokenSpender is
string public constant override FEATURE_NAME = "TokenSpender";
/// @dev Version of this feature.
uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 0, 0);
/// @dev The implementation address of this feature.
address private immutable _implementation;
// solhint-enable
using LibRichErrorsV06 for bytes;
constructor() public {
_implementation = address(this);
constructor() public FixinCommon() {
// solhint-disable-next-line no-empty-blocks
}
/// @dev Initialize and register this feature. Should be delegatecalled
@@ -59,14 +57,14 @@ contract TokenSpender is
/// @param allowanceTarget An `allowanceTarget` instance, configured to have
/// the ZeroeEx contract as an authority.
/// @return success `MIGRATE_SUCCESS` on success.
function migrate(IAllowanceTarget allowanceTarget) external returns (bytes4 success) {
function migrate(IAllowanceTarget allowanceTarget)
external
returns (bytes4 success)
{
LibTokenSpenderStorage.getStorage().allowanceTarget = allowanceTarget;
ISimpleFunctionRegistry(address(this))
.extend(this.getAllowanceTarget.selector, _implementation);
ISimpleFunctionRegistry(address(this))
.extend(this._spendERC20Tokens.selector, _implementation);
ISimpleFunctionRegistry(address(this))
.extend(this.getSpendableERC20BalanceOf.selector, _implementation);
_registerFeatureFunction(this.getAllowanceTarget.selector);
_registerFeatureFunction(this._spendERC20Tokens.selector);
_registerFeatureFunction(this.getSpendableERC20BalanceOf.selector);
return LibMigrate.MIGRATE_SUCCESS;
}

View File

@@ -52,40 +52,33 @@ contract TransformERC20 is
uint256 takerOutputTokenBalanceAfter;
}
// solhint-disable
/// @dev Name of this feature.
string public constant override FEATURE_NAME = "TransformERC20";
/// @dev Version of this feature.
uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 0, 0);
/// @dev The implementation address of this feature.
address private immutable _implementation;
// solhint-enable
uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 1, 0);
using LibSafeMathV06 for uint256;
using LibRichErrorsV06 for bytes;
constructor() public {
_implementation = address(this);
constructor() public FixinCommon() {
// solhint-disable-next-line no-empty-blocks
}
/// @dev Initialize and register this feature.
/// Should be delegatecalled by `Migrate.migrate()`.
/// @param transformerDeployer The trusted deployer for transformers.
/// @return success `LibMigrate.SUCCESS` on success.
function migrate(address transformerDeployer) external returns (bytes4 success) {
ISimpleFunctionRegistry(address(this))
.extend(this.getTransformerDeployer.selector, _implementation);
ISimpleFunctionRegistry(address(this))
.extend(this.createTransformWallet.selector, _implementation);
ISimpleFunctionRegistry(address(this))
.extend(this.getTransformWallet.selector, _implementation);
ISimpleFunctionRegistry(address(this))
.extend(this.setTransformerDeployer.selector, _implementation);
ISimpleFunctionRegistry(address(this))
.extend(this.transformERC20.selector, _implementation);
ISimpleFunctionRegistry(address(this))
.extend(this._transformERC20.selector, _implementation);
createTransformWallet();
function migrate(address transformerDeployer)
external
returns (bytes4 success)
{
_registerFeatureFunction(this.getTransformerDeployer.selector);
_registerFeatureFunction(this.createTransformWallet.selector);
_registerFeatureFunction(this.getTransformWallet.selector);
_registerFeatureFunction(this.setTransformerDeployer.selector);
_registerFeatureFunction(this.transformERC20.selector);
_registerFeatureFunction(this._transformERC20.selector);
this.createTransformWallet();
LibTransformERC20Storage.getStorage().transformerDeployer = transformerDeployer;
return LibMigrate.MIGRATE_SUCCESS;
}
@@ -115,11 +108,12 @@ contract TransformERC20 is
/// @dev Deploy a new wallet instance and replace the current one with it.
/// Useful if we somehow break the current wallet instance.
/// Anyone can call this.
/// Only callable by the owner.
/// @return wallet The new wallet instance.
function createTransformWallet()
public
override
onlyOwner
returns (IFlashWallet wallet)
{
wallet = new FlashWallet();
@@ -190,6 +184,7 @@ contract TransformERC20 is
Transformation[] memory transformations
)
public
virtual
override
payable
onlySelf

View File

@@ -23,13 +23,17 @@ import "@0x/contracts-utils/contracts/src/v06/errors/LibRichErrorsV06.sol";
import "../errors/LibCommonRichErrors.sol";
import "../errors/LibOwnableRichErrors.sol";
import "../features/IOwnable.sol";
import "../features/ISimpleFunctionRegistry.sol";
/// @dev Common feature utilities.
contract FixinCommon {
abstract contract FixinCommon {
using LibRichErrorsV06 for bytes;
/// @dev The implementation address of this feature.
address internal immutable _implementation;
/// @dev The caller must be this contract.
modifier onlySelf() virtual {
if (msg.sender != address(this)) {
@@ -52,6 +56,21 @@ contract FixinCommon {
_;
}
constructor() internal {
// Remember this feature's original address.
_implementation = address(this);
}
/// @dev Registers a function implemented by this feature at `_implementation`.
/// Can and should only be called within a `migrate()`.
/// @param selector The selector of the function whose implementation
/// is at `_implementation`.
function _registerFeatureFunction(bytes4 selector)
internal
{
ISimpleFunctionRegistry(address(this)).extend(selector, _implementation);
}
/// @dev Encode a feature version as a `uint256`.
/// @param major The major version number of the feature.
/// @param minor The minor version number of the feature.

View File

@@ -0,0 +1,69 @@
/*
Copyright 2020 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.6.5;
pragma experimental ABIEncoderV2;
import "@0x/contracts-utils/contracts/src/v06/errors/LibRichErrorsV06.sol";
import "../errors/LibCommonRichErrors.sol";
import "../errors/LibOwnableRichErrors.sol";
import "../features/IOwnable.sol";
/// @dev EIP712 helpers for features.
abstract contract FixinEIP712 {
/// @dev The domain hash separator for the entire exchange proxy.
bytes32 public immutable EIP712_DOMAIN_SEPARATOR;
constructor(address zeroExAddress) internal {
// Compute `EIP712_DOMAIN_SEPARATOR`
{
uint256 chainId;
assembly { chainId := chainid() }
EIP712_DOMAIN_SEPARATOR = keccak256(
abi.encode(
keccak256(
"EIP712Domain("
"string name,"
"string version,"
"uint256 chainId,"
"address verifyingContract"
")"
),
keccak256("ZeroEx"),
keccak256("1.0.0"),
chainId,
zeroExAddress
)
);
}
}
function _getEIP712Hash(bytes32 structHash)
internal
view
returns (bytes32 eip712Hash)
{
return keccak256(abi.encodePacked(
hex"1901",
EIP712_DOMAIN_SEPARATOR,
structHash
));
}
}

View File

@@ -0,0 +1,46 @@
/*
Copyright 2020 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.6.5;
import "../vendor/v3/IGasToken.sol";
contract FixinGasToken
{
/// @dev Mainnet address of the GST2 contract
address constant private GST_ADDRESS = 0x0000000000b3F879cb30FE243b4Dfee438691c04;
/// @dev Mainnet address of the GST Collector
address constant private GST_COLLECTOR_ADDRESS = 0x000000D3b08566BE75A6DB803C03C85C0c1c5B96;
/// @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();
_;
// (gasUsed + FREE_BASE) / (2 * REIMBURSE - FREE_TOKEN)
// 14154 24000 6870
uint256 value = (gasBefore - gasleft() + 14154) / 41130;
GST_ADDRESS.call(
abi.encodeWithSelector(
IGasToken(address(0)).freeFromUpTo.selector,
GST_COLLECTOR_ADDRESS,
value
)
);
}
}

View File

@@ -23,6 +23,8 @@ import "../ZeroEx.sol";
import "../features/IOwnable.sol";
import "../features/TokenSpender.sol";
import "../features/TransformERC20.sol";
import "../features/SignatureValidator.sol";
import "../features/MetaTransactions.sol";
import "../external/AllowanceTarget.sol";
import "./InitialMigration.sol";
@@ -38,6 +40,8 @@ contract FullMigration {
Ownable ownable;
TokenSpender tokenSpender;
TransformERC20 transformERC20;
SignatureValidator signatureValidator;
MetaTransactions metaTransactions;
}
/// @dev Parameters needed to initialize features.
@@ -45,42 +49,56 @@ contract FullMigration {
address transformerDeployer;
}
/// @dev The allowed caller of `deploy()`.
address public immutable deployer;
/// @dev The allowed caller of `initializeZeroEx()`.
address public immutable initializeCaller;
/// @dev The initial migration contract.
InitialMigration private _initialMigration;
/// @dev Instantiate this contract and set the allowed caller of `deploy()`
/// to `deployer`.
/// @param deployer_ The allowed caller of `deploy()`.
constructor(address payable deployer_)
/// @dev Instantiate this contract and set the allowed caller of `initializeZeroEx()`
/// to `initializeCaller`.
/// @param initializeCaller_ The allowed caller of `initializeZeroEx()`.
constructor(address payable initializeCaller_)
public
{
deployer = deployer_;
initializeCaller = initializeCaller_;
// Create an initial migration contract with this contract set to the
// allowed deployer.
// allowed `initializeCaller`.
_initialMigration = new InitialMigration(address(this));
}
/// @dev Deploy the `ZeroEx` contract with the full feature set,
/// @dev Retrieve the bootstrapper address to use when constructing `ZeroEx`.
/// @return bootstrapper The bootstrapper address.
function getBootstrapper()
external
view
returns (address bootstrapper)
{
return address(_initialMigration);
}
/// @dev Initialize the `ZeroEx` contract with the full feature set,
/// transfer ownership to `owner`, then self-destruct.
/// @param owner The owner of the contract.
/// @param zeroEx The instance of the ZeroEx contract. ZeroEx should
/// been constructed with this contract as the bootstrapper.
/// @param features Features to add to the proxy.
/// @return zeroEx The deployed and configured `ZeroEx` contract.
/// @return _zeroEx The configured ZeroEx contract. Same as the `zeroEx` parameter.
/// @param migrateOpts Parameters needed to initialize features.
function deploy(
function initializeZeroEx(
address payable owner,
ZeroEx zeroEx,
Features memory features,
MigrateOpts memory migrateOpts
)
public
returns (ZeroEx zeroEx)
returns (ZeroEx _zeroEx)
{
require(msg.sender == deployer, "FullMigration/INVALID_SENDER");
require(msg.sender == initializeCaller, "FullMigration/INVALID_SENDER");
// Perform the initial migration with the owner set to this contract.
zeroEx = _initialMigration.deploy(
_initialMigration.initializeZeroEx(
address(uint160(address(this))),
zeroEx,
InitialMigration.BootstrapFeatures({
registry: features.registry,
ownable: features.ownable
@@ -95,9 +113,11 @@ contract FullMigration {
// Self-destruct.
this.die(owner);
return zeroEx;
}
/// @dev Destroy this contract. Only callable from ourselves (from `deploy()`).
/// @dev Destroy this contract. Only callable from ourselves (from `initializeZeroEx()`).
/// @param ethRecipient Receiver of any ETH in this contract.
function die(address payable ethRecipient)
external
@@ -153,5 +173,27 @@ contract FullMigration {
address(this)
);
}
// SignatureValidator
{
// Register the feature.
ownable.migrate(
address(features.signatureValidator),
abi.encodeWithSelector(
SignatureValidator.migrate.selector
),
address(this)
);
}
// MetaTransactions
{
// Register the feature.
ownable.migrate(
address(features.metaTransactions),
abi.encodeWithSelector(
MetaTransactions.migrate.selector
),
address(this)
);
}
}
}

View File

@@ -35,36 +35,39 @@ contract InitialMigration {
Ownable ownable;
}
/// @dev The allowed caller of `deploy()`. In production, this would be
/// @dev The allowed caller of `initializeZeroEx()`. In production, this would be
/// the governor.
address public immutable deployer;
address public immutable initializeCaller;
/// @dev The real address of this contract.
address private immutable _implementation;
/// @dev Instantiate this contract and set the allowed caller of `deploy()`
/// to `deployer_`.
/// @param deployer_ The allowed caller of `deploy()`.
constructor(address deployer_) public {
deployer = deployer_;
/// @dev Instantiate this contract and set the allowed caller of `initializeZeroEx()`
/// to `initializeCaller_`.
/// @param initializeCaller_ The allowed caller of `initializeZeroEx()`.
constructor(address initializeCaller_) public {
initializeCaller = initializeCaller_;
_implementation = address(this);
}
/// @dev Deploy the `ZeroEx` contract with the minimum feature set,
/// @dev Initialize the `ZeroEx` contract with the minimum feature set,
/// transfers ownership to `owner`, then self-destructs.
/// Only callable by `deployer` set in the contstructor.
/// Only callable by `initializeCaller` set in the contstructor.
/// @param owner The owner of the contract.
/// @param zeroEx The instance of the ZeroEx contract. ZeroEx should
/// been constructed with this contract as the bootstrapper.
/// @param features Features to bootstrap into the proxy.
/// @return zeroEx The deployed and configured `ZeroEx` contract.
function deploy(address payable owner, BootstrapFeatures memory features)
/// @return _zeroEx The configured ZeroEx contract. Same as the `zeroEx` parameter.
function initializeZeroEx(
address payable owner,
ZeroEx zeroEx,
BootstrapFeatures memory features
)
public
virtual
returns (ZeroEx zeroEx)
returns (ZeroEx _zeroEx)
{
// Must be called by the allowed deployer.
require(msg.sender == deployer, "InitialMigration/INVALID_SENDER");
// Deploy the ZeroEx contract, setting ourselves as the bootstrapper.
zeroEx = new ZeroEx();
// Must be called by the allowed initializeCaller.
require(msg.sender == initializeCaller, "InitialMigration/INVALID_SENDER");
// Bootstrap the initial feature set.
IBootstrap(address(zeroEx)).bootstrap(
@@ -75,6 +78,8 @@ contract InitialMigration {
// Self-destruct. This contract should not hold any funds but we send
// them to the owner just in case.
this.die(owner);
return zeroEx;
}
/// @dev Sets up the initial state of the `ZeroEx` contract.

View File

@@ -0,0 +1,44 @@
/*
Copyright 2020 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.6.5;
pragma experimental ABIEncoderV2;
import "./LibStorage.sol";
/// @dev Storage helpers for the `MetaTransactions` feature.
library LibMetaTransactionsStorage {
/// @dev Storage bucket for this feature.
struct Storage {
// The block number when a hash was executed.
mapping (bytes32 => uint256) mtxHashToExecutedBlockNumber;
}
/// @dev Get the storage bucket for this contract.
function getStorage() internal pure returns (Storage storage stor) {
uint256 storageSlot = LibStorage.getStorageSlot(
LibStorage.StorageId.MetaTransactions
);
// Dip into assembly to change the slot pointed to by the local
// variable `stor`.
// See https://solidity.readthedocs.io/en/v0.6.8/assembly.html?highlight=slot#access-to-external-variables-functions-and-libraries
assembly { stor_slot := storageSlot }
}
}

View File

@@ -34,7 +34,8 @@ library LibStorage {
SimpleFunctionRegistry,
Ownable,
TokenSpender,
TransformERC20
TransformERC20,
MetaTransactions
}
/// @dev Get the storage slot given a storage ID. We assign unique, well-spaced

View File

@@ -23,7 +23,7 @@ import "./LibStorage.sol";
import "../external/IFlashWallet.sol";
/// @dev Storage helpers for the `TokenSpender` feature.
/// @dev Storage helpers for the `TransformERC20` feature.
library LibTransformERC20Storage {
/// @dev Storage bucket for this feature.

View File

@@ -1,436 +0,0 @@
/*
Copyright 2020 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.6.5;
pragma experimental ABIEncoderV2;
import "@0x/contracts-utils/contracts/src/v06/errors/LibRichErrorsV06.sol";
import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
import "@0x/contracts-utils/contracts/src/v06/LibBytesV06.sol";
import "@0x/contracts-erc20/contracts/src/v06/LibERC20TokenV06.sol";
import "@0x/contracts-utils/contracts/src/v06/LibSafeMathV06.sol";
import "@0x/contracts-utils/contracts/src/v06/LibMathV06.sol";
import "../errors/LibTransformERC20RichErrors.sol";
import "../vendor/v3/IExchange.sol";
import "./Transformer.sol";
import "./LibERC20Transformer.sol";
/// @dev A transformer that fills an ERC20 market sell/buy quote.
contract FillOrdersTransformer is
Transformer
{
using LibERC20TokenV06 for IERC20TokenV06;
using LibERC20Transformer for IERC20TokenV06;
using LibSafeMathV06 for uint256;
using LibRichErrorsV06 for bytes;
/// @dev Whether we are performing a market sell or buy.
enum Side {
Sell,
Buy
}
/// @dev Transform data to ABI-encode and pass into `transform()`.
struct TransformData {
// Whether we aer performing a market sell or buy.
Side side;
// The token being sold.
// This should be an actual token, not the ETH pseudo-token.
IERC20TokenV06 sellToken;
// The token being bought.
// This should be an actual token, not the ETH pseudo-token.
IERC20TokenV06 buyToken;
// The orders to fill.
IExchange.Order[] orders;
// Signatures for each respective order in `orders`.
bytes[] signatures;
// Maximum fill amount for each order. This may be shorter than the
// number of orders, where missing entries will be treated as `uint256(-1)`.
// For sells, this will be the maximum sell amount (taker asset).
// For buys, this will be the maximum buy amount (maker asset).
uint256[] maxOrderFillAmounts;
// Amount of `sellToken` to sell or `buyToken` to buy.
// For sells, this may be `uint256(-1)` to sell the entire balance of
// `sellToken`.
uint256 fillAmount;
}
/// @dev Results of a call to `_fillOrder()`.
struct FillOrderResults {
// The amount of taker tokens sold, according to balance checks.
uint256 takerTokenSoldAmount;
// The amount of maker tokens sold, according to balance checks.
uint256 makerTokenBoughtAmount;
// The amount of protocol fee paid.
uint256 protocolFeePaid;
}
/// @dev The Exchange ERC20Proxy ID.
bytes4 private constant ERC20_ASSET_PROXY_ID = 0xf47261b0;
/// @dev Maximum uint256 value.
uint256 private constant MAX_UINT256 = uint256(-1);
/// @dev The Exchange contract.
IExchange public immutable exchange;
/// @dev The ERC20Proxy address.
address public immutable erc20Proxy;
/// @dev Create this contract.
/// @param exchange_ The Exchange V3 instance.
constructor(IExchange exchange_)
public
Transformer()
{
exchange = exchange_;
erc20Proxy = exchange_.getAssetProxy(ERC20_ASSET_PROXY_ID);
}
/// @dev Sell this contract's entire balance of of `sellToken` in exchange
/// for `buyToken` by filling `orders`. Protocol fees should be attached
/// to this call. `buyToken` and excess ETH will be transferred back to the caller.
/// @param data_ ABI-encoded `TransformData`.
/// @return success The success bytes (`LibERC20Transformer.TRANSFORMER_SUCCESS`).
function transform(
bytes32, // callDataHash,
address payable, // taker,
bytes calldata data_
)
external
override
returns (bytes4 success)
{
TransformData memory data = abi.decode(data_, (TransformData));
// Validate data fields.
if (data.sellToken.isTokenETH() || data.buyToken.isTokenETH()) {
LibTransformERC20RichErrors.InvalidTransformDataError(
LibTransformERC20RichErrors.InvalidTransformDataErrorCode.INVALID_TOKENS,
data_
).rrevert();
}
if (data.orders.length != data.signatures.length) {
LibTransformERC20RichErrors.InvalidTransformDataError(
LibTransformERC20RichErrors.InvalidTransformDataErrorCode.INVALID_ARRAY_LENGTH,
data_
).rrevert();
}
if (data.side == Side.Sell && data.fillAmount == MAX_UINT256) {
// If `sellAmount == -1 then we are selling
// the entire balance of `sellToken`. This is useful in cases where
// the exact sell amount is not exactly known in advance, like when
// unwrapping Chai/cUSDC/cDAI.
data.fillAmount = data.sellToken.getTokenBalanceOf(address(this));
}
// Approve the ERC20 proxy to spend `sellToken`.
data.sellToken.approveIfBelow(erc20Proxy, data.fillAmount);
// Fill the orders.
uint256 singleProtocolFee = exchange.protocolFeeMultiplier().safeMul(tx.gasprice);
uint256 ethRemaining = address(this).balance;
uint256 boughtAmount = 0;
uint256 soldAmount = 0;
for (uint256 i = 0; i < data.orders.length; ++i) {
// Check if we've hit our targets.
if (data.side == Side.Sell) {
// Market sell check.
if (soldAmount >= data.fillAmount) {
break;
}
} else {
// Market buy check.
if (boughtAmount >= data.fillAmount) {
break;
}
}
// Ensure we have enough ETH to cover the protocol fee.
if (ethRemaining < singleProtocolFee) {
LibTransformERC20RichErrors
.InsufficientProtocolFeeError(ethRemaining, singleProtocolFee)
.rrevert();
}
// Fill the order.
FillOrderResults memory results;
if (data.side == Side.Sell) {
// Market sell.
results = _sellToOrder(
data.buyToken,
data.sellToken,
data.orders[i],
data.signatures[i],
data.fillAmount.safeSub(soldAmount).min256(
data.maxOrderFillAmounts.length > i
? data.maxOrderFillAmounts[i]
: MAX_UINT256
),
singleProtocolFee
);
} else {
// Market buy.
results = _buyFromOrder(
data.buyToken,
data.sellToken,
data.orders[i],
data.signatures[i],
data.fillAmount.safeSub(boughtAmount).min256(
data.maxOrderFillAmounts.length > i
? data.maxOrderFillAmounts[i]
: MAX_UINT256
),
singleProtocolFee
);
}
// Accumulate totals.
soldAmount = soldAmount.safeAdd(results.takerTokenSoldAmount);
boughtAmount = boughtAmount.safeAdd(results.makerTokenBoughtAmount);
ethRemaining = ethRemaining.safeSub(results.protocolFeePaid);
}
// Ensure we hit our targets.
if (data.side == Side.Sell) {
// Market sell check.
if (soldAmount < data.fillAmount) {
LibTransformERC20RichErrors
.IncompleteFillSellQuoteError(
address(data.sellToken),
soldAmount,
data.fillAmount
).rrevert();
}
} else {
// Market buy check.
if (boughtAmount < data.fillAmount) {
LibTransformERC20RichErrors
.IncompleteFillBuyQuoteError(
address(data.buyToken),
boughtAmount,
data.fillAmount
).rrevert();
}
}
return LibERC20Transformer.TRANSFORMER_SUCCESS;
}
/// @dev Try to sell up to `sellAmount` from an order.
/// @param makerToken The maker/buy token.
/// @param takerToken The taker/sell token.
/// @param order The order to fill.
/// @param signature The signature for `order`.
/// @param sellAmount Amount of taker token to sell.
/// @param protocolFee The protocol fee needed to fill `order`.
function _sellToOrder(
IERC20TokenV06 makerToken,
IERC20TokenV06 takerToken,
IExchange.Order memory order,
bytes memory signature,
uint256 sellAmount,
uint256 protocolFee
)
private
returns (FillOrderResults memory results)
{
IERC20TokenV06 takerFeeToken =
_getTokenFromERC20AssetData(order.takerFeeAssetData);
uint256 takerTokenFillAmount = sellAmount;
if (order.takerFee != 0) {
if (takerFeeToken == makerToken) {
// Taker fee is payable in the maker token, so we need to
// approve the proxy to spend the maker token.
// It isn't worth computing the actual taker fee
// since `approveIfBelow()` will set the allowance to infinite. We
// just need a reasonable upper bound to avoid unnecessarily re-approving.
takerFeeToken.approveIfBelow(erc20Proxy, order.takerFee);
} else if (takerFeeToken == takerToken){
// Taker fee is payable in the taker token, so we need to
// reduce the fill amount to cover the fee.
// takerTokenFillAmount' =
// (takerTokenFillAmount * order.takerAssetAmount) /
// (order.takerAssetAmount + order.takerFee)
takerTokenFillAmount = LibMathV06.getPartialAmountCeil(
order.takerAssetAmount,
order.takerAssetAmount.safeAdd(order.takerFee),
sellAmount
);
} else {
// Only support taker or maker asset denominated taker fees.
LibTransformERC20RichErrors.InvalidTakerFeeTokenError(
address(takerFeeToken)
).rrevert();
}
}
// Clamp fill amount to order size.
takerTokenFillAmount = LibSafeMathV06.min256(
takerTokenFillAmount,
order.takerAssetAmount
);
// Perform the fill.
return _fillOrder(
order,
signature,
takerTokenFillAmount,
protocolFee,
makerToken,
takerFeeToken == takerToken
);
}
/// @dev Try to buy up to `buyAmount` from an order.
/// @param makerToken The maker/buy token.
/// @param takerToken The taker/sell token.
/// @param order The order to fill.
/// @param signature The signature for `order`.
/// @param buyAmount Amount of maker token to buy.
/// @param protocolFee The protocol fee needed to fill `order`.
function _buyFromOrder(
IERC20TokenV06 makerToken,
IERC20TokenV06 takerToken,
IExchange.Order memory order,
bytes memory signature,
uint256 buyAmount,
uint256 protocolFee
)
private
returns (FillOrderResults memory results)
{
IERC20TokenV06 takerFeeToken =
_getTokenFromERC20AssetData(order.takerFeeAssetData);
// Compute the default taker token fill amount.
uint256 takerTokenFillAmount = LibMathV06.getPartialAmountCeil(
buyAmount,
order.makerAssetAmount,
order.takerAssetAmount
);
if (order.takerFee != 0) {
if (takerFeeToken == makerToken) {
// Taker fee is payable in the maker token.
// Adjust the taker token fill amount to account for maker
// tokens being lost to the taker fee.
// takerTokenFillAmount' =
// (order.takerAssetAmount * buyAmount) /
// (order.makerAssetAmount - order.takerFee)
takerTokenFillAmount = LibMathV06.getPartialAmountCeil(
buyAmount,
order.makerAssetAmount.safeSub(order.takerFee),
order.takerAssetAmount
);
// Approve the proxy to spend the maker token.
// It isn't worth computing the actual taker fee
// since `approveIfBelow()` will set the allowance to infinite. We
// just need a reasonable upper bound to avoid unnecessarily re-approving.
takerFeeToken.approveIfBelow(erc20Proxy, order.takerFee);
} else if (takerFeeToken != takerToken) {
// Only support taker or maker asset denominated taker fees.
LibTransformERC20RichErrors.InvalidTakerFeeTokenError(
address(takerFeeToken)
).rrevert();
}
}
// Clamp to order size.
takerTokenFillAmount = LibSafeMathV06.min256(
order.takerAssetAmount,
takerTokenFillAmount
);
// Perform the fill.
return _fillOrder(
order,
signature,
takerTokenFillAmount,
protocolFee,
makerToken,
takerFeeToken == takerToken
);
}
/// @dev Attempt to fill an order. If the fill reverts, the revert will be
/// swallowed and `results` will be zeroed out.
/// @param order The order to fill.
/// @param signature The order signature.
/// @param takerAssetFillAmount How much taker asset to fill.
/// @param protocolFee The protocol fee needed to fill this order.
/// @param makerToken The maker token.
/// @param isTakerFeeInTakerToken Whether the taker fee token is the same as the
/// taker token.
function _fillOrder(
IExchange.Order memory order,
bytes memory signature,
uint256 takerAssetFillAmount,
uint256 protocolFee,
IERC20TokenV06 makerToken,
bool isTakerFeeInTakerToken
)
private
returns (FillOrderResults memory results)
{
// Track changes in the maker token balance.
uint256 initialMakerTokenBalance = makerToken.balanceOf(address(this));
try
exchange.fillOrder
{value: protocolFee}
(order, takerAssetFillAmount, signature)
returns (IExchange.FillResults memory fillResults)
{
// Update maker quantity based on changes in token balances.
results.makerTokenBoughtAmount = makerToken.balanceOf(address(this))
.safeSub(initialMakerTokenBalance);
// We can trust the other fill result quantities.
results.protocolFeePaid = fillResults.protocolFeePaid;
results.takerTokenSoldAmount = fillResults.takerAssetFilledAmount;
// If the taker fee is payable in the taker asset, include the
// taker fee in the total amount sold.
if (isTakerFeeInTakerToken) {
results.takerTokenSoldAmount =
results.takerTokenSoldAmount.safeAdd(fillResults.takerFeePaid);
}
} catch (bytes memory) {
// Swallow failures, leaving all results as zero.
}
}
/// @dev Extract the token from plain ERC20 asset data.
/// If the asset-data is empty, a zero token address will be returned.
/// @param assetData The order asset data.
function _getTokenFromERC20AssetData(bytes memory assetData)
private
pure
returns (IERC20TokenV06 token)
{
if (assetData.length == 0) {
return IERC20TokenV06(address(0));
}
if (assetData.length != 36 ||
LibBytesV06.readBytes4(assetData, 0) != ERC20_ASSET_PROXY_ID)
{
LibTransformERC20RichErrors
.InvalidERC20AssetDataError(assetData)
.rrevert();
}
return IERC20TokenV06(LibBytesV06.readAddress(assetData, 16));
}
}

View File

@@ -30,12 +30,14 @@ import "../vendor/v3/IExchange.sol";
import "../vendor/v3/IERC20Bridge.sol";
import "./Transformer.sol";
import "./LibERC20Transformer.sol";
import "../fixins/FixinGasToken.sol";
/// @dev A transformer that fills an ERC20 market sell/buy quote.
/// This transformer shortcuts bridge orders and fills them directly
contract FillQuoteTransformer is
Transformer
Transformer,
FixinGasToken
{
using LibERC20TokenV06 for IERC20TokenV06;
using LibERC20Transformer for IERC20TokenV06;
@@ -84,6 +86,25 @@ contract FillQuoteTransformer is
uint256 protocolFeePaid;
}
/// @dev Intermediate state variables to get around stack limits.
struct FillState {
uint256 ethRemaining;
uint256 boughtAmount;
uint256 soldAmount;
uint256 protocolFee;
uint256 takerTokenBalanceRemaining;
}
/// @dev Emitted when a trade is skipped due to a lack of funds
/// to pay the 0x Protocol fee.
/// @param ethBalance The current eth balance.
/// @param ethNeeded The current eth balance required to pay
/// the protocol fee.
event ProtocolFeeUnfunded(
uint256 ethBalance,
uint256 ethNeeded
);
/// @dev The Exchange ERC20Proxy ID.
bytes4 private constant ERC20_ASSET_PROXY_ID = 0xf47261b0;
/// @dev The Exchange ERC20BridgeProxy ID.
@@ -95,8 +116,6 @@ contract FillQuoteTransformer is
IExchange public immutable exchange;
/// @dev The ERC20Proxy address.
address public immutable erc20Proxy;
/// @dev The Transformer implementation (self) address.
address public immutable implementation;
/// @dev Create this contract.
/// @param exchange_ The Exchange V3 instance.
@@ -106,7 +125,6 @@ contract FillQuoteTransformer is
{
exchange = exchange_;
erc20Proxy = exchange_.getAssetProxy(ERC20_ASSET_PROXY_ID);
implementation = address(this);
}
/// @dev Sell this contract's entire balance of of `sellToken` in exchange
@@ -121,9 +139,11 @@ contract FillQuoteTransformer is
)
external
override
freesGasTokensFromCollector
returns (bytes4 success)
{
TransformData memory data = abi.decode(data_, (TransformData));
FillState memory state;
// Validate data fields.
if (data.sellToken.isTokenETH() || data.buyToken.isTokenETH()) {
@@ -139,31 +159,31 @@ contract FillQuoteTransformer is
).rrevert();
}
state.takerTokenBalanceRemaining = data.sellToken.getTokenBalanceOf(address(this));
if (data.side == Side.Sell && data.fillAmount == MAX_UINT256) {
// If `sellAmount == -1 then we are selling
// the entire balance of `sellToken`. This is useful in cases where
// the exact sell amount is not exactly known in advance, like when
// unwrapping Chai/cUSDC/cDAI.
data.fillAmount = data.sellToken.getTokenBalanceOf(address(this));
data.fillAmount = state.takerTokenBalanceRemaining;
}
// Approve the ERC20 proxy to spend `sellToken`.
data.sellToken.approveIfBelow(erc20Proxy, data.fillAmount);
// Fill the orders.
uint256 singleProtocolFee = exchange.protocolFeeMultiplier().safeMul(tx.gasprice);
uint256 boughtAmount = 0;
uint256 soldAmount = 0;
state.protocolFee = exchange.protocolFeeMultiplier().safeMul(tx.gasprice);
state.ethRemaining = address(this).balance;
for (uint256 i = 0; i < data.orders.length; ++i) {
// Check if we've hit our targets.
if (data.side == Side.Sell) {
// Market sell check.
if (soldAmount >= data.fillAmount) {
if (state.soldAmount >= data.fillAmount) {
break;
}
} else {
// Market buy check.
if (boughtAmount >= data.fillAmount) {
if (state.boughtAmount >= data.fillAmount) {
break;
}
}
@@ -177,12 +197,12 @@ contract FillQuoteTransformer is
data.sellToken,
data.orders[i],
data.signatures[i],
data.fillAmount.safeSub(soldAmount).min256(
data.fillAmount.safeSub(state.soldAmount).min256(
data.maxOrderFillAmounts.length > i
? data.maxOrderFillAmounts[i]
: MAX_UINT256
),
singleProtocolFee
state
);
} else {
// Market buy.
@@ -191,38 +211,40 @@ contract FillQuoteTransformer is
data.sellToken,
data.orders[i],
data.signatures[i],
data.fillAmount.safeSub(boughtAmount).min256(
data.fillAmount.safeSub(state.boughtAmount).min256(
data.maxOrderFillAmounts.length > i
? data.maxOrderFillAmounts[i]
: MAX_UINT256
),
singleProtocolFee
state
);
}
// Accumulate totals.
soldAmount = soldAmount.safeAdd(results.takerTokenSoldAmount);
boughtAmount = boughtAmount.safeAdd(results.makerTokenBoughtAmount);
state.soldAmount = state.soldAmount.safeAdd(results.takerTokenSoldAmount);
state.boughtAmount = state.boughtAmount.safeAdd(results.makerTokenBoughtAmount);
state.ethRemaining = state.ethRemaining.safeSub(results.protocolFeePaid);
state.takerTokenBalanceRemaining = state.takerTokenBalanceRemaining.safeSub(results.takerTokenSoldAmount);
}
// Ensure we hit our targets.
if (data.side == Side.Sell) {
// Market sell check.
if (soldAmount < data.fillAmount) {
if (state.soldAmount < data.fillAmount) {
LibTransformERC20RichErrors
.IncompleteFillSellQuoteError(
address(data.sellToken),
soldAmount,
state.soldAmount,
data.fillAmount
).rrevert();
}
} else {
// Market buy check.
if (boughtAmount < data.fillAmount) {
if (state.boughtAmount < data.fillAmount) {
LibTransformERC20RichErrors
.IncompleteFillBuyQuoteError(
address(data.buyToken),
boughtAmount,
state.boughtAmount,
data.fillAmount
).rrevert();
}
@@ -236,14 +258,14 @@ contract FillQuoteTransformer is
/// @param order The order to fill.
/// @param signature The signature for `order`.
/// @param sellAmount Amount of taker token to sell.
/// @param protocolFee The protocol fee needed to fill `order`.
/// @param state Intermediate state variables to get around stack limits.
function _sellToOrder(
IERC20TokenV06 makerToken,
IERC20TokenV06 takerToken,
IExchange.Order memory order,
bytes memory signature,
uint256 sellAmount,
uint256 protocolFee
FillState memory state
)
private
returns (FillOrderResults memory results)
@@ -280,18 +302,12 @@ contract FillQuoteTransformer is
}
}
// Clamp fill amount to order size.
takerTokenFillAmount = LibSafeMathV06.min256(
takerTokenFillAmount,
order.takerAssetAmount
);
// Perform the fill.
return _fillOrder(
order,
signature,
takerTokenFillAmount,
protocolFee,
state,
makerToken,
takerFeeToken == takerToken
);
@@ -303,14 +319,14 @@ contract FillQuoteTransformer is
/// @param order The order to fill.
/// @param signature The signature for `order`.
/// @param buyAmount Amount of maker token to buy.
/// @param protocolFee The protocol fee needed to fill `order`.
/// @param state Intermediate state variables to get around stack limits.
function _buyFromOrder(
IERC20TokenV06 makerToken,
IERC20TokenV06 takerToken,
IExchange.Order memory order,
bytes memory signature,
uint256 buyAmount,
uint256 protocolFee
FillState memory state
)
private
returns (FillOrderResults memory results)
@@ -350,18 +366,12 @@ contract FillQuoteTransformer is
}
}
// Clamp to order size.
takerTokenFillAmount = LibSafeMathV06.min256(
order.takerAssetAmount,
takerTokenFillAmount
);
// Perform the fill.
return _fillOrder(
order,
signature,
takerTokenFillAmount,
protocolFee,
state,
makerToken,
takerFeeToken == takerToken
);
@@ -372,7 +382,7 @@ contract FillQuoteTransformer is
/// @param order The order to fill.
/// @param signature The order signature.
/// @param takerAssetFillAmount How much taker asset to fill.
/// @param protocolFee The protocol fee needed to fill this order.
/// @param state Intermediate state variables to get around stack limits.
/// @param makerToken The maker token.
/// @param isTakerFeeInTakerToken Whether the taker fee token is the same as the
/// taker token.
@@ -380,54 +390,64 @@ contract FillQuoteTransformer is
IExchange.Order memory order,
bytes memory signature,
uint256 takerAssetFillAmount,
uint256 protocolFee,
FillState memory state,
IERC20TokenV06 makerToken,
bool isTakerFeeInTakerToken
)
private
returns (FillOrderResults memory results)
{
bytes4 makerAssetProxyId = order.makerAssetData.readBytes4(0);
// Clamp to remaining taker asset amount or order size.
uint256 availableTakerAssetFillAmount =
takerAssetFillAmount.min256(order.takerAssetAmount);
availableTakerAssetFillAmount =
availableTakerAssetFillAmount.min256(state.takerTokenBalanceRemaining);
// If it is a Bridge order we fill this directly
// rather than filling via 0x Exchange
if (makerAssetProxyId == ERC20_BRIDGE_PROXY_ID) {
if (order.makerAssetData.readBytes4(0) == ERC20_BRIDGE_PROXY_ID) {
// Calculate the amount (in maker token) we expect to receive
// from the bridge
uint256 outputTokenAmount = LibMathV06.getPartialAmountFloor(
takerAssetFillAmount,
availableTakerAssetFillAmount,
order.takerAssetAmount,
order.makerAssetAmount
);
(bool success, bytes memory data) = address(implementation).delegatecall(
(bool success, bytes memory data) = address(_implementation).delegatecall(
abi.encodeWithSelector(
this.fillBridgeOrder.selector,
order,
takerAssetFillAmount,
outputTokenAmount,
makerToken
order.makerAddress,
order.makerAssetData,
order.takerAssetData,
availableTakerAssetFillAmount,
outputTokenAmount
)
);
if (success) {
results = abi.decode(data, (FillOrderResults));
}
// Swallow failures, leaving all results as zero.
// TransformERC20 asserts the overall price is as expected. It is possible
// a subsequent fill can net out at the expected price so we do not assert
// the trade balance
if (success) {
results.makerTokenBoughtAmount = makerToken
.balanceOf(address(this))
.safeSub(state.boughtAmount);
results.takerTokenSoldAmount = availableTakerAssetFillAmount;
// protocol fee paid remains 0
}
} else {
// Ensure we have enough ETH to cover the protocol fee.
if (address(this).balance < protocolFee) {
// Emit an event if we do not have sufficient ETH to cover the protocol fee.
if (state.ethRemaining < state.protocolFee) {
emit ProtocolFeeUnfunded(state.ethRemaining, state.protocolFee);
return results;
}
// Track changes in the maker token balance.
uint256 initialMakerTokenBalance = makerToken.balanceOf(address(this));
try
exchange.fillOrder
{value: protocolFee}
(order, takerAssetFillAmount, signature)
{value: state.protocolFee}
(order, availableTakerAssetFillAmount, signature)
returns (IExchange.FillResults memory fillResults)
{
// Update maker quantity based on changes in token balances.
results.makerTokenBoughtAmount = makerToken.balanceOf(address(this))
.safeSub(initialMakerTokenBalance);
// We can trust the other fill result quantities.
results.protocolFeePaid = fillResults.protocolFeePaid;
results.makerTokenBoughtAmount = fillResults.makerAssetFilledAmount;
results.takerTokenSoldAmount = fillResults.takerAssetFilledAmount;
results.protocolFeePaid = fillResults.protocolFeePaid;
// If the taker fee is payable in the taker asset, include the
// taker fee in the total amount sold.
if (isTakerFeeInTakerToken) {
@@ -442,51 +462,42 @@ contract FillQuoteTransformer is
/// @dev Attempt to fill an ERC20 Bridge order. If the fill reverts,
/// or the amount filled was not sufficient this reverts.
/// @param order The bridge order to fill.
/// @param inputTokenAmount How much taker asset to fill.
/// @param makerAddress The address of the maker.
/// @param makerAssetData The encoded ERC20BridgeProxy asset data.
/// @param takerAssetData The encoded ERC20 asset data.
/// @param inputTokenAmount How much taker asset to fill clamped to the available balance.
/// @param outputTokenAmount How much maker asset to receive.
/// @param makerToken The maker token.
function fillBridgeOrder(
IExchange.Order calldata order,
address makerAddress,
bytes calldata makerAssetData,
bytes calldata takerAssetData,
uint256 inputTokenAmount,
uint256 outputTokenAmount,
IERC20TokenV06 makerToken
uint256 outputTokenAmount
)
external
returns (FillOrderResults memory results)
{
// Track changes in the maker token balance.
uint256 initialMakerTokenBalance = makerToken.balanceOf(address(this));
(
address tokenAddress,
address bridgeAddress,
bytes memory bridgeData
) = abi.decode(
order.makerAssetData.sliceDestructive(4, order.makerAssetData.length),
makerAssetData.sliceDestructive(4, makerAssetData.length),
(address, address, bytes)
);
require(bridgeAddress != address(this), "INVALID_BRIDGE_ADDRESS");
// Transfer the tokens to the bridge to perform the work
_getTokenFromERC20AssetData(order.takerAssetData).compatTransfer(
_getTokenFromERC20AssetData(takerAssetData).compatTransfer(
bridgeAddress,
inputTokenAmount
);
IERC20Bridge(bridgeAddress).bridgeTransferFrom(
tokenAddress,
order.makerAddress,
makerAddress,
address(this),
outputTokenAmount, // amount to transfer back from the bridge
bridgeData
);
uint256 afterMakerTokenBalance = makerToken.balanceOf(address(this));
// Ensure that the maker token balance has increased by the expected amount
require(
afterMakerTokenBalance >= initialMakerTokenBalance.safeAdd(outputTokenAmount),
"BRIDGE_UNDERPAY"
);
results.makerTokenBoughtAmount = afterMakerTokenBalance.safeSub(initialMakerTokenBalance);
results.takerTokenSoldAmount = inputTokenAmount;
// protocol fee paid remains 0
}
/// @dev Extract the token from plain ERC20 asset data.

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