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:
command: yarn test:publish:circleci
no_output_timeout: 1800
- store_artifacts:
path: ~/.npm/_logs
test-doc-generation:
docker:
- image: nikolaik/python-nodejs:python3.7-nodejs8

View File

@@ -1,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",
"changes": [

View File

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

View File

@@ -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
returns (bytes4 success)
{
require(
msg.sender == _getERC20BridgeProxyAddress(),
"DexForwarderBridge/SENDER_NOT_AUTHORIZED"
);
require(msg.sender == _getERC20BridgeProxyAddress(), "DexForwarderBridge/SENDER_NOT_AUTHORIZED");
TransferFromState memory state;
(
state.inputToken,
state.calls
) = abi.decode(bridgeData, (address, BridgeCall[]));
state.initialInputTokenBalance =
IERC20Token(state.inputToken).balanceOf(address(this));
state.initialInputTokenBalance = IERC20Token(state.inputToken).balanceOf(address(this));
for (uint256 i = 0; i < state.calls.length; ++i) {
// Stop if the we've sold all our input tokens.
@@ -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.
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",
"version": "3.4.0",
"version": "3.3.0",
"engines": {
"node": ">=6.12"
},
@@ -38,7 +38,7 @@
"docs:json": "typedoc --excludePrivate --excludeExternals --excludeProtected --ignoreCompilerErrors --target ES5 --tsconfig typedoc-tsconfig.json --json $JSON_FILE_PATH $PROJECT_FILES"
},
"config": {
"abis": "./test/generated-artifacts/@(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."
},
"repository": {
@@ -51,15 +51,15 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/protocol/README.md",
"devDependencies": {
"@0x/abi-gen": "^5.3.1",
"@0x/contract-wrappers": "^13.8.0",
"@0x/contracts-gen": "^2.0.10",
"@0x/contracts-test-utils": "^5.3.4",
"@0x/contracts-utils": "^4.5.1",
"@0x/dev-utils": "^3.3.0",
"@0x/sol-compiler": "^4.1.1",
"@0x/abi-gen": "^5.3.0",
"@0x/contract-wrappers": "^13.7.0",
"@0x/contracts-gen": "^2.0.9",
"@0x/contracts-test-utils": "^5.3.3",
"@0x/contracts-utils": "^4.5.0",
"@0x/dev-utils": "^3.2.2",
"@0x/sol-compiler": "^4.1.0",
"@0x/ts-doc-gen": "^0.0.22",
"@0x/tslint-config": "^4.1.0",
"@0x/tslint-config": "^4.0.0",
"@types/lodash": "4.14.104",
"@types/mocha": "^5.2.7",
"@types/node": "*",
@@ -79,21 +79,20 @@
"typescript": "3.0.1"
},
"dependencies": {
"@0x/base-contract": "^6.2.3",
"@0x/contracts-erc1155": "^2.1.7",
"@0x/contracts-erc20": "^3.2.1",
"@0x/contracts-erc721": "^3.1.7",
"@0x/contracts-exchange-libs": "^4.3.7",
"@0x/order-utils": "^10.3.0",
"@0x/types": "^3.2.0",
"@0x/typescript-typings": "^5.1.1",
"@0x/utils": "^5.5.1",
"@0x/web3-wrapper": "^7.2.0",
"ethereum-types": "^3.2.0",
"@0x/base-contract": "^6.2.2",
"@0x/contracts-erc1155": "^2.1.6",
"@0x/contracts-erc20": "^3.2.0",
"@0x/contracts-erc721": "^3.1.6",
"@0x/contracts-exchange-libs": "^4.3.6",
"@0x/order-utils": "^10.2.5",
"@0x/types": "^3.1.3",
"@0x/typescript-typings": "^5.1.0",
"@0x/utils": "^5.5.0",
"@0x/web3-wrapper": "^7.1.0",
"ethereum-types": "^3.1.1",
"lodash": "^4.17.11"
},
"publishConfig": {
"access": "public"
},
"gitHead": "4f91bfd907996b2f4dd383778b50c479c2602b56"
}
}

View File

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

View File

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

View File

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

View File

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

View File

@@ -30,6 +30,7 @@ blockchainTests.resets('DexForwarderBridge unit tests', env => {
const BRIDGE_SUCCESS = '0xdc1600f3';
const BRIDGE_FAILURE = '0xffffffff';
const BRIDGE_REVERT_ERROR = 'oopsie';
const INCOMPLETE_FILL_REVERT = 'DexForwarderBridge/INCOMPLETE_FILL';
const NOT_AUTHORIZED_REVERT = 'DexForwarderBridge/SENDER_NOT_AUTHORIZED';
const DEFAULTS = {
toAddress: randomAddress(),
@@ -164,26 +165,27 @@ blockchainTests.resets('DexForwarderBridge unit tests', env => {
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({
inputToken,
calls: [],
});
await callBridgeTransferFromAsync({
bridgeData,
sellAmount: new BigNumber(1),
});
return expect(callBridgeTransferFromAsync({ bridgeData, sellAmount: new BigNumber(1) })).to.revertWith(
INCOMPLETE_FILL_REVERT,
);
});
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({
inputToken,
calls: allBridgeCalls,
});
await callBridgeTransferFromAsync({
bridgeData,
sellAmount: totalFillableInputAmount.plus(1),
});
return expect(
callBridgeTransferFromAsync({
bridgeData,
sellAmount: totalFillableInputAmount.plus(1),
}),
).to.revertWith(INCOMPLETE_FILL_REVERT);
});
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.
* -----------------------------------------------------------------------------
*/
export * from '../test/generated-wrappers/balancer_bridge';
export * from '../test/generated-wrappers/chai_bridge';
export * from '../test/generated-wrappers/curve_bridge';
export * from '../test/generated-wrappers/dex_forwarder_bridge';
@@ -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_dispatcher';
export * from '../test/generated-wrappers/i_authorizable';
export * from '../test/generated-wrappers/i_balancer_pool';
export * from '../test/generated-wrappers/i_chai';
export * from '../test/generated-wrappers/i_curve';
export * from '../test/generated-wrappers/i_dydx';

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,6 +1,6 @@
/*
Copyright 2020 ZeroEx Intl.
Copyright 2019 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -21,14 +21,14 @@ pragma solidity ^0.5.9;
interface IKyberNetworkProxy {
function kyberNetwork() external view returns (address);
function kyberHintHandler() external view returns (address);
function kyberNetworkContract() external view returns (address);
function getExpectedRateAfterFee(
address src,
address dest,
uint256 srcQty,
uint256 platformFeeBps,
bytes calldata hint
) external view returns (uint256 expectedRate);
function getExpectedRate(
address fromToken,
address toToken,
uint256 fromAmount
)
external
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
IKyberNetwork,
DeploymentConstants,
FailTrigger
{
bytes32 constant private SALT = 0x0ff3ca9d46195c39f9a12afb74207b4970349fb3cfb1e459bbf170298d326bc7;
address constant public ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
enum TradeType {BestOfAll, MaskIn, MaskOut, Split}
function kyberNetwork()
function kyberNetworkContract()
external
view
returns (address)
@@ -262,91 +260,19 @@ contract TestERC20BridgeSamplerKyberNetwork is
return address(this);
}
// IKyberNetwork
function getContracts()
external
view
returns (
address kyberFeeHandlerAddress,
address kyberDaoAddress,
address kyberMatchingEngineAddress,
address kyberStorageAddress,
address gasHelperAddress,
address[] memory kyberProxyAddresses
)
{
return (kyberFeeHandlerAddress,
kyberDaoAddress,
address(this),
address(this),
gasHelperAddress,
kyberProxyAddresses
);
}
// IKyberStorage
function getReserveIdsPerTokenSrc(
address /* token */
)
external
view
returns (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(
// IKyberNetwork not exposed via IKyberNetworkProxy
function searchBestRate(
address fromToken,
address toToken,
uint256 /* srcQty */,
uint256 /* fee */,
bytes calldata /* hint */
uint256 fromAmount,
bool // usePermissionless
)
external
view
returns
(uint256 expectedRate)
returns (address reserve, uint256 expectedRate)
{
_revertIfShouldFail();
fromToken = fromToken == ETH_ADDRESS ? _getWethAddress() : fromToken;
toToken = toToken == ETH_ADDRESS ? _getWethAddress() : toToken;
expectedRate = LibDeterministicQuotes.getDeterministicRate(
SALT,
fromToken,
toToken
);
(expectedRate, ) = this.getExpectedRate(fromToken, toToken, fromAmount);
return (address(this), expectedRate);
}
// Deterministic `IKyberNetworkProxy.getExpectedRate()`.
@@ -368,14 +294,6 @@ contract TestERC20BridgeSamplerKyberNetwork is
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;
constructor() public ERC20BridgeSampler() {
constructor() public ERC20BridgeSampler(address(this)) {
uniswap = new TestERC20BridgeSamplerUniswapExchangeFactory();
uniswapV2Router = new TestERC20BridgeSamplerUniswapV2Router01();
eth2Dai = new TestERC20BridgeSamplerEth2Dai();

View File

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

View File

@@ -33,7 +33,6 @@ blockchainTests('erc20-bridge-sampler', env => {
const INVALID_TOKEN_PAIR_ERROR = 'ERC20BridgeSampler/INVALID_TOKEN_PAIR';
const MAKER_TOKEN = randomAddress();
const TAKER_TOKEN = randomAddress();
let devUtilsAddress: string;
const FAKE_BUY_OPTS = {
targetSlippageBps: new BigNumber(5),
maxIterations: new BigNumber(5),
@@ -46,8 +45,6 @@ blockchainTests('erc20-bridge-sampler', env => {
env.txDefaults,
{},
);
// TestERC20BridgeSampler stubs DevUtils
devUtilsAddress = testContract.address;
});
function getPackedHash(...args: string[]): string {
@@ -275,14 +272,12 @@ blockchainTests('erc20-bridge-sampler', env => {
const orders = createOrders(MAKER_TOKEN, TAKER_TOKEN);
const signatures: string[] = _.times(orders.length, i => hexUtils.random());
const expected = orders.map(getDeterministicFillableTakerAssetAmount);
const actual = await testContract
.getOrderFillableTakerAssetAmounts(orders, signatures, devUtilsAddress)
.callAsync();
const actual = await testContract.getOrderFillableTakerAssetAmounts(orders, signatures).callAsync();
expect(actual).to.deep.eq(expected);
});
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([]);
});
@@ -290,9 +285,7 @@ blockchainTests('erc20-bridge-sampler', env => {
const orders = createOrders(MAKER_TOKEN, TAKER_TOKEN, 1);
orders[0].makerAssetAmount = constants.ZERO_AMOUNT;
const signatures: string[] = _.times(orders.length, i => hexUtils.random());
const actual = await testContract
.getOrderFillableTakerAssetAmounts(orders, signatures, devUtilsAddress)
.callAsync();
const actual = await testContract.getOrderFillableTakerAssetAmounts(orders, signatures).callAsync();
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);
orders[0].takerAssetAmount = constants.ZERO_AMOUNT;
const signatures: string[] = _.times(orders.length, i => hexUtils.random());
const actual = await testContract
.getOrderFillableTakerAssetAmounts(orders, signatures, devUtilsAddress)
.callAsync();
const actual = await testContract.getOrderFillableTakerAssetAmounts(orders, signatures).callAsync();
expect(actual).to.deep.eq([constants.ZERO_AMOUNT]);
});
it('returns zero for an order with an empty signature', async () => {
const orders = createOrders(MAKER_TOKEN, TAKER_TOKEN, 1);
const signatures: string[] = _.times(orders.length, () => constants.NULL_BYTES);
const actual = await testContract
.getOrderFillableTakerAssetAmounts(orders, signatures, devUtilsAddress)
.callAsync();
const actual = await testContract.getOrderFillableTakerAssetAmounts(orders, signatures).callAsync();
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 signatures: string[] = _.times(orders.length, i => hexUtils.random());
const expected = orders.map(getDeterministicFillableMakerAssetAmount);
const actual = await testContract
.getOrderFillableMakerAssetAmounts(orders, signatures, devUtilsAddress)
.callAsync();
const actual = await testContract.getOrderFillableMakerAssetAmounts(orders, signatures).callAsync();
expect(actual).to.deep.eq(expected);
});
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([]);
});
@@ -336,9 +323,7 @@ blockchainTests('erc20-bridge-sampler', env => {
const orders = createOrders(MAKER_TOKEN, TAKER_TOKEN, 1);
orders[0].makerAssetAmount = constants.ZERO_AMOUNT;
const signatures: string[] = _.times(orders.length, i => hexUtils.random());
const actual = await testContract
.getOrderFillableMakerAssetAmounts(orders, signatures, devUtilsAddress)
.callAsync();
const actual = await testContract.getOrderFillableMakerAssetAmounts(orders, signatures).callAsync();
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);
orders[0].takerAssetAmount = constants.ZERO_AMOUNT;
const signatures: string[] = _.times(orders.length, i => hexUtils.random());
const actual = await testContract
.getOrderFillableMakerAssetAmounts(orders, signatures, devUtilsAddress)
.callAsync();
const actual = await testContract.getOrderFillableMakerAssetAmounts(orders, signatures).callAsync();
expect(actual).to.deep.eq([constants.ZERO_AMOUNT]);
});
it('returns zero for an order with an empty signature', async () => {
const orders = createOrders(MAKER_TOKEN, TAKER_TOKEN, 1);
const signatures: string[] = _.times(orders.length, () => constants.NULL_BYTES);
const actual = await testContract
.getOrderFillableMakerAssetAmounts(orders, signatures, devUtilsAddress)
.callAsync();
const actual = await testContract.getOrderFillableMakerAssetAmounts(orders, signatures).callAsync();
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 expected = orders.map(getDeterministicFillableTakerAssetAmount);
const calls = [
testContract
.getOrderFillableTakerAssetAmounts(orders, signatures, devUtilsAddress)
.getABIEncodedTransactionData(),
testContract.getOrderFillableTakerAssetAmounts(orders, signatures).getABIEncodedTransactionData(),
];
const r = await testContract.batchCall(calls).callAsync();
expect(r).to.be.length(1);
@@ -1067,12 +1046,8 @@ blockchainTests('erc20-bridge-sampler', env => {
orders[1].map(getDeterministicFillableMakerAssetAmount),
];
const calls = [
testContract
.getOrderFillableTakerAssetAmounts(orders[0], signatures, devUtilsAddress)
.getABIEncodedTransactionData(),
testContract
.getOrderFillableMakerAssetAmounts(orders[1], signatures, devUtilsAddress)
.getABIEncodedTransactionData(),
testContract.getOrderFillableTakerAssetAmounts(orders[0], signatures).getABIEncodedTransactionData(),
testContract.getOrderFillableMakerAssetAmounts(orders[1], signatures).getABIEncodedTransactionData(),
];
const r = await testContract.batchCall(calls).callAsync();
expect(r).to.be.length(2);
@@ -1094,7 +1069,7 @@ blockchainTests('erc20-bridge-sampler', env => {
testContract
.batchCall([
testContract
.getOrderFillableTakerAssetAmounts(orders, signatures, devUtilsAddress)
.getOrderFillableTakerAssetAmounts(orders, signatures)
.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_erc20_bridge_sampler';
export * from '../test/generated-wrappers/i_eth2_dai';
export * from '../test/generated-wrappers/i_kyber_hint_handler';
export * from '../test/generated-wrappers/i_kyber_network';
export * from '../test/generated-wrappers/i_kyber_network_proxy';
export * from '../test/generated-wrappers/i_kyber_storage';
export * from '../test/generated-wrappers/i_liquidity_provider';
export * from '../test/generated-wrappers/i_liquidity_provider_registry';
export * from '../test/generated-wrappers/i_multi_bridge';

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -34,12 +34,11 @@ contract ZeroEx {
/// @dev Construct this contract and register the `Bootstrap` feature.
/// After constructing this contract, `bootstrap()` should be called
/// by `bootstrap()` to seed the initial feature set.
/// @param bootstrapper Who can call `bootstrap()`.
constructor(address bootstrapper) public {
/// to seed the initial feature set.
constructor() public {
// Temporarily create and register the bootstrap feature.
// 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] =
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.
/// Useful if we somehow break the current wallet instance.
/// Only callable by the owner.
/// Anyone can call this.
/// @return wallet The new wallet instance.
function createTransformWallet()
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
{
// solhint-disable
/// @dev Name of this feature.
string public constant override FEATURE_NAME = "Ownable";
/// @dev Version of this feature.
uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 0, 0);
/// @dev The deployed address of this contract.
address immutable private _implementation;
// solhint-enable
using LibRichErrorsV06 for bytes;
constructor() public FixinCommon() {
// solhint-disable-next-line no-empty-blocks
constructor() public {
_implementation = address(this);
}
/// @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,
FixinCommon
{
// solhint-disable
/// @dev Name of this feature.
string public constant override FEATURE_NAME = "SimpleFunctionRegistry";
/// @dev Version of this feature.
uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 0, 0);
/// @dev The deployed address of this contract.
address private immutable _implementation;
// solhint-enable
using LibRichErrorsV06 for bytes;
constructor() public FixinCommon() {
// solhint-disable-next-line no-empty-blocks
constructor() public {
_implementation = address(this);
}
/// @dev Initializes this feature, registering its own functions.

View File

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

View File

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

View File

@@ -23,17 +23,13 @@ import "@0x/contracts-utils/contracts/src/v06/errors/LibRichErrorsV06.sol";
import "../errors/LibCommonRichErrors.sol";
import "../errors/LibOwnableRichErrors.sol";
import "../features/IOwnable.sol";
import "../features/ISimpleFunctionRegistry.sol";
/// @dev Common feature utilities.
abstract contract FixinCommon {
contract FixinCommon {
using LibRichErrorsV06 for bytes;
/// @dev The implementation address of this feature.
address internal immutable _implementation;
/// @dev The caller must be this contract.
modifier onlySelf() virtual {
if (msg.sender != address(this)) {
@@ -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`.
/// @param major The major 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/TokenSpender.sol";
import "../features/TransformERC20.sol";
import "../features/SignatureValidator.sol";
import "../features/MetaTransactions.sol";
import "../external/AllowanceTarget.sol";
import "./InitialMigration.sol";
@@ -40,8 +38,6 @@ contract FullMigration {
Ownable ownable;
TokenSpender tokenSpender;
TransformERC20 transformERC20;
SignatureValidator signatureValidator;
MetaTransactions metaTransactions;
}
/// @dev Parameters needed to initialize features.
@@ -49,56 +45,42 @@ contract FullMigration {
address transformerDeployer;
}
/// @dev The allowed caller of `initializeZeroEx()`.
address public immutable initializeCaller;
/// @dev The allowed caller of `deploy()`.
address public immutable deployer;
/// @dev The initial migration contract.
InitialMigration private _initialMigration;
/// @dev Instantiate this contract and set the allowed caller of `initializeZeroEx()`
/// to `initializeCaller`.
/// @param initializeCaller_ The allowed caller of `initializeZeroEx()`.
constructor(address payable initializeCaller_)
/// @dev Instantiate this contract and set the allowed caller of `deploy()`
/// to `deployer`.
/// @param deployer_ The allowed caller of `deploy()`.
constructor(address payable deployer_)
public
{
initializeCaller = initializeCaller_;
deployer = deployer_;
// Create an initial migration contract with this contract set to the
// allowed `initializeCaller`.
// allowed deployer.
_initialMigration = new InitialMigration(address(this));
}
/// @dev Retrieve the bootstrapper address to use when constructing `ZeroEx`.
/// @return bootstrapper The bootstrapper address.
function getBootstrapper()
external
view
returns (address bootstrapper)
{
return address(_initialMigration);
}
/// @dev Initialize the `ZeroEx` contract with the full feature set,
/// @dev Deploy the `ZeroEx` contract with the full feature set,
/// transfer ownership to `owner`, then self-destruct.
/// @param owner The owner of the contract.
/// @param zeroEx The instance of the ZeroEx contract. ZeroEx should
/// been constructed with this contract as the bootstrapper.
/// @param features Features to add to the proxy.
/// @return _zeroEx The configured ZeroEx contract. Same as the `zeroEx` parameter.
/// @return zeroEx The deployed and configured `ZeroEx` contract.
/// @param migrateOpts Parameters needed to initialize features.
function initializeZeroEx(
function deploy(
address payable owner,
ZeroEx zeroEx,
Features memory features,
MigrateOpts memory migrateOpts
)
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.
_initialMigration.initializeZeroEx(
zeroEx = _initialMigration.deploy(
address(uint160(address(this))),
zeroEx,
InitialMigration.BootstrapFeatures({
registry: features.registry,
ownable: features.ownable
@@ -113,11 +95,9 @@ contract FullMigration {
// Self-destruct.
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.
function die(address payable ethRecipient)
external
@@ -173,27 +153,5 @@ contract FullMigration {
address(this)
);
}
// SignatureValidator
{
// Register the feature.
ownable.migrate(
address(features.signatureValidator),
abi.encodeWithSelector(
SignatureValidator.migrate.selector
),
address(this)
);
}
// MetaTransactions
{
// Register the feature.
ownable.migrate(
address(features.metaTransactions),
abi.encodeWithSelector(
MetaTransactions.migrate.selector
),
address(this)
);
}
}
}

View File

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

View File

@@ -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,
Ownable,
TokenSpender,
TransformERC20,
MetaTransactions
TransformERC20
}
/// @dev Get the storage slot given a storage ID. We assign unique, well-spaced

View File

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

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