Compare commits

..

6 Commits

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

View File

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

View File

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

View File

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

View File

@@ -1,103 +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.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,18 +75,14 @@ contract DexForwarderBridge is
freesGasTokensFromCollector freesGasTokensFromCollector
returns (bytes4 success) returns (bytes4 success)
{ {
require( require(msg.sender == _getERC20BridgeProxyAddress(), "DexForwarderBridge/SENDER_NOT_AUTHORIZED");
msg.sender == _getERC20BridgeProxyAddress(),
"DexForwarderBridge/SENDER_NOT_AUTHORIZED"
);
TransferFromState memory state; TransferFromState memory state;
( (
state.inputToken, state.inputToken,
state.calls state.calls
) = abi.decode(bridgeData, (address, BridgeCall[])); ) = abi.decode(bridgeData, (address, BridgeCall[]));
state.initialInputTokenBalance = state.initialInputTokenBalance = IERC20Token(state.inputToken).balanceOf(address(this));
IERC20Token(state.inputToken).balanceOf(address(this));
for (uint256 i = 0; i < state.calls.length; ++i) { for (uint256 i = 0; i < state.calls.length; ++i) {
// Stop if the we've sold all our input tokens. // Stop if the we've sold all our input tokens.
@@ -126,6 +122,11 @@ 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. // Always succeed.
return BRIDGE_SUCCESS; return BRIDGE_SUCCESS;
} }

View File

@@ -1,39 +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.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", "name": "@0x/contracts-asset-proxy",
"version": "3.4.0", "version": "3.3.0",
"engines": { "engines": {
"node": ">=6.12" "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" "docs:json": "typedoc --excludePrivate --excludeExternals --excludeProtected --ignoreCompilerErrors --target ES5 --tsconfig typedoc-tsconfig.json --json $JSON_FILE_PATH $PROJECT_FILES"
}, },
"config": { "config": {
"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": "./test/generated-artifacts/@(ChaiBridge|CurveBridge|DexForwarderBridge|DydxBridge|ERC1155Proxy|ERC20BridgeProxy|ERC20Proxy|ERC721Proxy|Eth2DaiBridge|IAssetData|IAssetProxy|IAssetProxyDispatcher|IAuthorizable|IChai|ICurve|IDydx|IDydxBridge|IERC20Bridge|IEth2Dai|IGasToken|IKyberNetworkProxy|IUniswapExchange|IUniswapExchangeFactory|IUniswapV2Router01|KyberBridge|MixinAssetProxyDispatcher|MixinAuthorizable|MixinGasToken|MultiAssetProxy|Ownable|StaticCallProxy|TestChaiBridge|TestDexForwarderBridge|TestDydxBridge|TestERC20Bridge|TestEth2DaiBridge|TestKyberBridge|TestStaticCallTarget|TestUniswapBridge|TestUniswapV2Bridge|UniswapBridge|UniswapV2Bridge).json",
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually." "abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually."
}, },
"repository": { "repository": {
@@ -51,15 +51,15 @@
}, },
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/protocol/README.md", "homepage": "https://github.com/0xProject/0x-monorepo/contracts/protocol/README.md",
"devDependencies": { "devDependencies": {
"@0x/abi-gen": "^5.3.1", "@0x/abi-gen": "^5.3.0",
"@0x/contract-wrappers": "^13.8.0", "@0x/contract-wrappers": "^13.7.0",
"@0x/contracts-gen": "^2.0.10", "@0x/contracts-gen": "^2.0.9",
"@0x/contracts-test-utils": "^5.3.4", "@0x/contracts-test-utils": "^5.3.3",
"@0x/contracts-utils": "^4.5.1", "@0x/contracts-utils": "^4.5.0",
"@0x/dev-utils": "^3.3.0", "@0x/dev-utils": "^3.2.2",
"@0x/sol-compiler": "^4.1.1", "@0x/sol-compiler": "^4.1.0",
"@0x/ts-doc-gen": "^0.0.22", "@0x/ts-doc-gen": "^0.0.22",
"@0x/tslint-config": "^4.1.0", "@0x/tslint-config": "^4.0.0",
"@types/lodash": "4.14.104", "@types/lodash": "4.14.104",
"@types/mocha": "^5.2.7", "@types/mocha": "^5.2.7",
"@types/node": "*", "@types/node": "*",
@@ -79,21 +79,20 @@
"typescript": "3.0.1" "typescript": "3.0.1"
}, },
"dependencies": { "dependencies": {
"@0x/base-contract": "^6.2.3", "@0x/base-contract": "^6.2.2",
"@0x/contracts-erc1155": "^2.1.7", "@0x/contracts-erc1155": "^2.1.6",
"@0x/contracts-erc20": "^3.2.1", "@0x/contracts-erc20": "^3.2.0",
"@0x/contracts-erc721": "^3.1.7", "@0x/contracts-erc721": "^3.1.6",
"@0x/contracts-exchange-libs": "^4.3.7", "@0x/contracts-exchange-libs": "^4.3.6",
"@0x/order-utils": "^10.3.0", "@0x/order-utils": "^10.2.5",
"@0x/types": "^3.2.0", "@0x/types": "^3.1.3",
"@0x/typescript-typings": "^5.1.1", "@0x/typescript-typings": "^5.1.0",
"@0x/utils": "^5.5.1", "@0x/utils": "^5.5.0",
"@0x/web3-wrapper": "^7.2.0", "@0x/web3-wrapper": "^7.1.0",
"ethereum-types": "^3.2.0", "ethereum-types": "^3.1.1",
"lodash": "^4.17.11" "lodash": "^4.17.11"
}, },
"publishConfig": { "publishConfig": {
"access": "public" "access": "public"
}, }
"gitHead": "4f91bfd907996b2f4dd383778b50c479c2602b56"
} }

View File

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

View File

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

View File

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

View File

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

View File

@@ -30,6 +30,7 @@ blockchainTests.resets('DexForwarderBridge unit tests', env => {
const BRIDGE_SUCCESS = '0xdc1600f3'; const BRIDGE_SUCCESS = '0xdc1600f3';
const BRIDGE_FAILURE = '0xffffffff'; const BRIDGE_FAILURE = '0xffffffff';
const BRIDGE_REVERT_ERROR = 'oopsie'; const BRIDGE_REVERT_ERROR = 'oopsie';
const INCOMPLETE_FILL_REVERT = 'DexForwarderBridge/INCOMPLETE_FILL';
const NOT_AUTHORIZED_REVERT = 'DexForwarderBridge/SENDER_NOT_AUTHORIZED'; const NOT_AUTHORIZED_REVERT = 'DexForwarderBridge/SENDER_NOT_AUTHORIZED';
const DEFAULTS = { const DEFAULTS = {
toAddress: randomAddress(), toAddress: randomAddress(),
@@ -164,26 +165,27 @@ blockchainTests.resets('DexForwarderBridge unit tests', env => {
await callBridgeTransferFromAsync({ bridgeData, sellAmount: ZERO_AMOUNT }); await callBridgeTransferFromAsync({ bridgeData, sellAmount: ZERO_AMOUNT });
}); });
it('succeeds with no bridge calls and an input balance', async () => { it('fails with no bridge calls and an input balance', async () => {
const bridgeData = dexForwarderBridgeDataEncoder.encode({ const bridgeData = dexForwarderBridgeDataEncoder.encode({
inputToken, inputToken,
calls: [], calls: [],
}); });
await callBridgeTransferFromAsync({ return expect(callBridgeTransferFromAsync({ bridgeData, sellAmount: new BigNumber(1) })).to.revertWith(
bridgeData, INCOMPLETE_FILL_REVERT,
sellAmount: new BigNumber(1), );
});
}); });
it('succeeds if entire input token balance is not consumed', async () => { it('fails if entire input token balance is not consumed', async () => {
const bridgeData = dexForwarderBridgeDataEncoder.encode({ const bridgeData = dexForwarderBridgeDataEncoder.encode({
inputToken, inputToken,
calls: allBridgeCalls, calls: allBridgeCalls,
}); });
await callBridgeTransferFromAsync({ return expect(
callBridgeTransferFromAsync({
bridgeData, bridgeData,
sellAmount: totalFillableInputAmount.plus(1), sellAmount: totalFillableInputAmount.plus(1),
}); }),
).to.revertWith(INCOMPLETE_FILL_REVERT);
}); });
it('fails if not authorized', async () => { it('fails if not authorized', async () => {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,18 +1,4 @@
[ [
{
"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", "version": "1.6.0",
"changes": [ "changes": [

View File

@@ -5,11 +5,6 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG 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_ ## v1.6.0 - _June 24, 2020_
* Pass in `DevUtils` address as a constructor parameter (#2531) * Pass in `DevUtils` address as a constructor parameter (#2531)

View File

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

View File

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

View File

@@ -1,52 +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.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 2020 ZeroEx Intl. Copyright 2019 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@@ -18,20 +18,16 @@
pragma solidity ^0.5.9; pragma solidity ^0.5.9;
import "./IKyberStorage.sol";
import "./IKyberHintHandler.sol";
interface IKyberNetwork { interface IKyberNetwork {
function getContracts() function searchBestRate(
address fromToken,
address toToken,
uint256 fromAmount,
bool usePermissionless
)
external external
view view
returns ( returns (address reserve, uint256 expectedRate);
address kyberFeeHandlerAddress,
address kyberDaoAddress,
IKyberHintHandler kyberMatchingEngineAddress,
IKyberStorage kyberStorageAddress,
address gasHelperAddress,
address[] memory kyberProxyAddresses);
} }

View File

@@ -1,6 +1,6 @@
/* /*
Copyright 2020 ZeroEx Intl. Copyright 2019 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with 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 { interface IKyberNetworkProxy {
function kyberNetwork() external view returns (address); function kyberNetworkContract() external view returns (address);
function kyberHintHandler() external view returns (address);
function getExpectedRateAfterFee( function getExpectedRate(
address src, address fromToken,
address dest, address toToken,
uint256 srcQty, uint256 fromAmount
uint256 platformFeeBps, )
bytes calldata hint external
) external view returns (uint256 expectedRate); view
returns (uint256 expectedRate, uint256 slippageRate);
} }

View File

@@ -1,37 +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.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,17 +244,15 @@ contract TestERC20BridgeSamplerUniswapV2Router01 is
} }
// solhint-disable space-after-comma
contract TestERC20BridgeSamplerKyberNetwork is contract TestERC20BridgeSamplerKyberNetwork is
IKyberNetwork,
DeploymentConstants, DeploymentConstants,
FailTrigger FailTrigger
{ {
bytes32 constant private SALT = 0x0ff3ca9d46195c39f9a12afb74207b4970349fb3cfb1e459bbf170298d326bc7; bytes32 constant private SALT = 0x0ff3ca9d46195c39f9a12afb74207b4970349fb3cfb1e459bbf170298d326bc7;
address constant public ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; address constant public ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
enum TradeType {BestOfAll, MaskIn, MaskOut, Split} function kyberNetworkContract()
function kyberNetwork()
external external
view view
returns (address) returns (address)
@@ -262,91 +260,19 @@ contract TestERC20BridgeSamplerKyberNetwork is
return address(this); return address(this);
} }
// IKyberNetwork // IKyberNetwork not exposed via IKyberNetworkProxy
function getContracts() function searchBestRate(
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 (bytes32[] memory reserveIds)
{
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 fromToken,
address toToken, address toToken,
uint256 /* srcQty */, uint256 fromAmount,
uint256 /* fee */, bool // usePermissionless
bytes calldata /* hint */
) )
external external
view view
returns returns (address reserve, uint256 expectedRate)
(uint256 expectedRate)
{ {
_revertIfShouldFail(); (expectedRate, ) = this.getExpectedRate(fromToken, toToken, fromAmount);
fromToken = fromToken == ETH_ADDRESS ? _getWethAddress() : fromToken; return (address(this), expectedRate);
toToken = toToken == ETH_ADDRESS ? _getWethAddress() : toToken;
expectedRate = LibDeterministicQuotes.getDeterministicRate(
SALT,
fromToken,
toToken
);
} }
// Deterministic `IKyberNetworkProxy.getExpectedRate()`. // Deterministic `IKyberNetworkProxy.getExpectedRate()`.
@@ -368,14 +294,6 @@ contract TestERC20BridgeSamplerKyberNetwork is
toToken toToken
); );
} }
function _getKyberNetworkProxyAddress()
internal
view
returns (address)
{
return address(this);
}
} }
@@ -463,7 +381,7 @@ contract TestERC20BridgeSampler is
uint8 private constant MAX_ORDER_STATUS = uint8(LibOrder.OrderStatus.CANCELLED) + 1; uint8 private constant MAX_ORDER_STATUS = uint8(LibOrder.OrderStatus.CANCELLED) + 1;
constructor() public ERC20BridgeSampler() { constructor() public ERC20BridgeSampler(address(this)) {
uniswap = new TestERC20BridgeSamplerUniswapExchangeFactory(); uniswap = new TestERC20BridgeSamplerUniswapExchangeFactory();
uniswapV2Router = new TestERC20BridgeSamplerUniswapV2Router01(); uniswapV2Router = new TestERC20BridgeSamplerUniswapV2Router01();
eth2Dai = new TestERC20BridgeSamplerEth2Dai(); eth2Dai = new TestERC20BridgeSamplerEth2Dai();

View File

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

View File

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

View File

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

View File

@@ -10,10 +10,8 @@ export * from '../test/generated-wrappers/i_curve';
export * from '../test/generated-wrappers/i_dev_utils'; export * from '../test/generated-wrappers/i_dev_utils';
export * from '../test/generated-wrappers/i_erc20_bridge_sampler'; export * from '../test/generated-wrappers/i_erc20_bridge_sampler';
export * from '../test/generated-wrappers/i_eth2_dai'; 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';
export * from '../test/generated-wrappers/i_kyber_network_proxy'; 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';
export * from '../test/generated-wrappers/i_liquidity_provider_registry'; export * from '../test/generated-wrappers/i_liquidity_provider_registry';
export * from '../test/generated-wrappers/i_multi_bridge'; export * from '../test/generated-wrappers/i_multi_bridge';

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,103 +0,0 @@
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,13 +1,4 @@
[ [
{
"timestamp": 1594788383,
"version": "4.1.7",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{ {
"timestamp": 1592969527, "timestamp": 1592969527,
"version": "4.1.6", "version": "4.1.6",

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,22 +1,4 @@
[ [
{
"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, "timestamp": 1592969527,
"version": "0.1.1", "version": "0.1.1",

View File

@@ -5,12 +5,6 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG 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_ ## v0.1.1 - _June 24, 2020_
* Dependencies updated * Dependencies updated

View File

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

View File

@@ -1,174 +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;
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

@@ -1,52 +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;
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

@@ -1,127 +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-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

@@ -1,63 +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;
/// @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. /// @dev Deploy a new flash wallet instance and replace the current one with it.
/// Useful if we somehow break the current wallet instance. /// Useful if we somehow break the current wallet instance.
/// Only callable by the owner. /// Anyone can call this.
/// @return wallet The new wallet instance. /// @return wallet The new wallet instance.
function createTransformWallet() function createTransformWallet()
external external

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

View File

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

View File

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

View File

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

View File

@@ -23,17 +23,13 @@ import "@0x/contracts-utils/contracts/src/v06/errors/LibRichErrorsV06.sol";
import "../errors/LibCommonRichErrors.sol"; import "../errors/LibCommonRichErrors.sol";
import "../errors/LibOwnableRichErrors.sol"; import "../errors/LibOwnableRichErrors.sol";
import "../features/IOwnable.sol"; import "../features/IOwnable.sol";
import "../features/ISimpleFunctionRegistry.sol";
/// @dev Common feature utilities. /// @dev Common feature utilities.
abstract contract FixinCommon { contract FixinCommon {
using LibRichErrorsV06 for bytes; using LibRichErrorsV06 for bytes;
/// @dev The implementation address of this feature.
address internal immutable _implementation;
/// @dev The caller must be this contract. /// @dev The caller must be this contract.
modifier onlySelf() virtual { modifier onlySelf() virtual {
if (msg.sender != address(this)) { if (msg.sender != address(this)) {
@@ -56,21 +52,6 @@ abstract 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`. /// @dev Encode a feature version as a `uint256`.
/// @param major The major version number of the feature. /// @param major The major version number of the feature.
/// @param minor The minor version number of the feature. /// @param minor The minor version number of the feature.

View File

@@ -1,69 +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 "../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

@@ -1,46 +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;
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,8 +23,6 @@ import "../ZeroEx.sol";
import "../features/IOwnable.sol"; import "../features/IOwnable.sol";
import "../features/TokenSpender.sol"; import "../features/TokenSpender.sol";
import "../features/TransformERC20.sol"; import "../features/TransformERC20.sol";
import "../features/SignatureValidator.sol";
import "../features/MetaTransactions.sol";
import "../external/AllowanceTarget.sol"; import "../external/AllowanceTarget.sol";
import "./InitialMigration.sol"; import "./InitialMigration.sol";
@@ -40,8 +38,6 @@ contract FullMigration {
Ownable ownable; Ownable ownable;
TokenSpender tokenSpender; TokenSpender tokenSpender;
TransformERC20 transformERC20; TransformERC20 transformERC20;
SignatureValidator signatureValidator;
MetaTransactions metaTransactions;
} }
/// @dev Parameters needed to initialize features. /// @dev Parameters needed to initialize features.
@@ -49,56 +45,42 @@ contract FullMigration {
address transformerDeployer; address transformerDeployer;
} }
/// @dev The allowed caller of `initializeZeroEx()`. /// @dev The allowed caller of `deploy()`.
address public immutable initializeCaller; address public immutable deployer;
/// @dev The initial migration contract. /// @dev The initial migration contract.
InitialMigration private _initialMigration; InitialMigration private _initialMigration;
/// @dev Instantiate this contract and set the allowed caller of `initializeZeroEx()` /// @dev Instantiate this contract and set the allowed caller of `deploy()`
/// to `initializeCaller`. /// to `deployer`.
/// @param initializeCaller_ The allowed caller of `initializeZeroEx()`. /// @param deployer_ The allowed caller of `deploy()`.
constructor(address payable initializeCaller_) constructor(address payable deployer_)
public public
{ {
initializeCaller = initializeCaller_; deployer = deployer_;
// Create an initial migration contract with this contract set to the // Create an initial migration contract with this contract set to the
// allowed `initializeCaller`. // allowed deployer.
_initialMigration = new InitialMigration(address(this)); _initialMigration = new InitialMigration(address(this));
} }
/// @dev Retrieve the bootstrapper address to use when constructing `ZeroEx`. /// @dev Deploy the `ZeroEx` contract with the full feature set,
/// @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. /// transfer ownership to `owner`, then self-destruct.
/// @param owner The owner of the contract. /// @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. /// @param features Features to add to the proxy.
/// @return _zeroEx The configured ZeroEx contract. Same as the `zeroEx` parameter. /// @return zeroEx The deployed and configured `ZeroEx` contract.
/// @param migrateOpts Parameters needed to initialize features. /// @param migrateOpts Parameters needed to initialize features.
function initializeZeroEx( function deploy(
address payable owner, address payable owner,
ZeroEx zeroEx,
Features memory features, Features memory features,
MigrateOpts memory migrateOpts MigrateOpts memory migrateOpts
) )
public public
returns (ZeroEx _zeroEx) returns (ZeroEx zeroEx)
{ {
require(msg.sender == initializeCaller, "FullMigration/INVALID_SENDER"); require(msg.sender == deployer, "FullMigration/INVALID_SENDER");
// Perform the initial migration with the owner set to this contract. // Perform the initial migration with the owner set to this contract.
_initialMigration.initializeZeroEx( zeroEx = _initialMigration.deploy(
address(uint160(address(this))), address(uint160(address(this))),
zeroEx,
InitialMigration.BootstrapFeatures({ InitialMigration.BootstrapFeatures({
registry: features.registry, registry: features.registry,
ownable: features.ownable ownable: features.ownable
@@ -113,11 +95,9 @@ contract FullMigration {
// Self-destruct. // Self-destruct.
this.die(owner); this.die(owner);
return zeroEx;
} }
/// @dev Destroy this contract. Only callable from ourselves (from `initializeZeroEx()`). /// @dev Destroy this contract. Only callable from ourselves (from `deploy()`).
/// @param ethRecipient Receiver of any ETH in this contract. /// @param ethRecipient Receiver of any ETH in this contract.
function die(address payable ethRecipient) function die(address payable ethRecipient)
external external
@@ -173,27 +153,5 @@ contract FullMigration {
address(this) 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,39 +35,36 @@ contract InitialMigration {
Ownable ownable; Ownable ownable;
} }
/// @dev The allowed caller of `initializeZeroEx()`. In production, this would be /// @dev The allowed caller of `deploy()`. In production, this would be
/// the governor. /// the governor.
address public immutable initializeCaller; address public immutable deployer;
/// @dev The real address of this contract. /// @dev The real address of this contract.
address private immutable _implementation; address private immutable _implementation;
/// @dev Instantiate this contract and set the allowed caller of `initializeZeroEx()` /// @dev Instantiate this contract and set the allowed caller of `deploy()`
/// to `initializeCaller_`. /// to `deployer_`.
/// @param initializeCaller_ The allowed caller of `initializeZeroEx()`. /// @param deployer_ The allowed caller of `deploy()`.
constructor(address initializeCaller_) public { constructor(address deployer_) public {
initializeCaller = initializeCaller_; deployer = deployer_;
_implementation = address(this); _implementation = address(this);
} }
/// @dev Initialize the `ZeroEx` contract with the minimum feature set, /// @dev Deploy the `ZeroEx` contract with the minimum feature set,
/// transfers ownership to `owner`, then self-destructs. /// transfers ownership to `owner`, then self-destructs.
/// Only callable by `initializeCaller` set in the contstructor. /// Only callable by `deployer` set in the contstructor.
/// @param owner The owner of the contract. /// @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. /// @param features Features to bootstrap into the proxy.
/// @return _zeroEx The configured ZeroEx contract. Same as the `zeroEx` parameter. /// @return zeroEx The deployed and configured `ZeroEx` contract.
function initializeZeroEx( function deploy(address payable owner, BootstrapFeatures memory features)
address payable owner,
ZeroEx zeroEx,
BootstrapFeatures memory features
)
public public
virtual virtual
returns (ZeroEx _zeroEx) returns (ZeroEx zeroEx)
{ {
// Must be called by the allowed initializeCaller. // Must be called by the allowed deployer.
require(msg.sender == initializeCaller, "InitialMigration/INVALID_SENDER"); require(msg.sender == deployer, "InitialMigration/INVALID_SENDER");
// Deploy the ZeroEx contract, setting ourselves as the bootstrapper.
zeroEx = new ZeroEx();
// Bootstrap the initial feature set. // Bootstrap the initial feature set.
IBootstrap(address(zeroEx)).bootstrap( IBootstrap(address(zeroEx)).bootstrap(
@@ -78,8 +75,6 @@ contract InitialMigration {
// Self-destruct. This contract should not hold any funds but we send // Self-destruct. This contract should not hold any funds but we send
// them to the owner just in case. // them to the owner just in case.
this.die(owner); this.die(owner);
return zeroEx;
} }
/// @dev Sets up the initial state of the `ZeroEx` contract. /// @dev Sets up the initial state of the `ZeroEx` contract.

View File

@@ -1,44 +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 "./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,8 +34,7 @@ library LibStorage {
SimpleFunctionRegistry, SimpleFunctionRegistry,
Ownable, Ownable,
TokenSpender, TokenSpender,
TransformERC20, TransformERC20
MetaTransactions
} }
/// @dev Get the storage slot given a storage ID. We assign unique, well-spaced /// @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"; import "../external/IFlashWallet.sol";
/// @dev Storage helpers for the `TransformERC20` feature. /// @dev Storage helpers for the `TokenSpender` feature.
library LibTransformERC20Storage { library LibTransformERC20Storage {
/// @dev Storage bucket for this feature. /// @dev Storage bucket for this feature.

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