Compare commits
6 Commits
@0x/contra
...
@0x/dev-ut
Author | SHA1 | Date | |
---|---|---|---|
|
7bf710f153 | ||
|
e50fd77973 | ||
|
71cdc8a28f | ||
|
549f7bc6ee | ||
|
92ec1d6923 | ||
|
56529180e9 |
@@ -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
|
||||
|
@@ -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": [
|
||||
|
@@ -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)
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
@@ -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;
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
@@ -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"
|
||||
}
|
||||
}
|
||||
|
@@ -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,
|
||||
|
@@ -1,6 +1,5 @@
|
||||
export { artifacts } from './artifacts';
|
||||
export {
|
||||
BalancerBridgeContract,
|
||||
ChaiBridgeContract,
|
||||
ERC1155ProxyContract,
|
||||
ERC20BridgeProxyContract,
|
||||
|
@@ -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';
|
||||
|
@@ -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,
|
||||
|
@@ -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 () => {
|
||||
|
@@ -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';
|
||||
|
@@ -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",
|
||||
|
@@ -1,13 +1,4 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1594788383,
|
||||
"version": "1.1.6",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "1.1.5",
|
||||
"changes": [
|
||||
|
@@ -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)
|
||||
|
@@ -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"
|
||||
}
|
||||
}
|
||||
|
@@ -1,13 +1,4 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1594788383,
|
||||
"version": "3.1.7",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1592969527,
|
||||
"version": "3.1.6",
|
||||
|
@@ -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
|
||||
|
@@ -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"
|
||||
}
|
||||
}
|
||||
|
@@ -1,13 +1,4 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1594788383,
|
||||
"version": "1.3.5",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1592969527,
|
||||
"version": "1.3.4",
|
||||
|
@@ -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
|
||||
|
@@ -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"
|
||||
}
|
||||
}
|
||||
|
@@ -1,13 +1,4 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1594788383,
|
||||
"version": "2.1.7",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1592969527,
|
||||
"version": "2.1.6",
|
||||
|
@@ -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
|
||||
|
@@ -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"
|
||||
}
|
||||
}
|
||||
|
@@ -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": [
|
||||
|
@@ -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)
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
}
|
@@ -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);
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
@@ -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();
|
||||
|
@@ -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"
|
||||
}
|
||||
}
|
||||
|
@@ -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,
|
||||
|
@@ -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(),
|
||||
|
@@ -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';
|
||||
|
@@ -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",
|
||||
|
@@ -1,13 +1,4 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1594788383,
|
||||
"version": "3.2.1",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "3.2.0",
|
||||
"changes": [
|
||||
|
@@ -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)
|
||||
|
@@ -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"
|
||||
}
|
||||
}
|
||||
|
@@ -1,13 +1,4 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1594788383,
|
||||
"version": "3.1.7",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1592969527,
|
||||
"version": "3.1.6",
|
||||
|
@@ -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
|
||||
|
@@ -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"
|
||||
}
|
||||
}
|
||||
|
@@ -1,13 +1,4 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1594788383,
|
||||
"version": "4.2.7",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1592969527,
|
||||
"version": "4.2.6",
|
||||
|
@@ -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
|
||||
|
@@ -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"
|
||||
}
|
||||
}
|
||||
|
@@ -1,13 +1,4 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1594788383,
|
||||
"version": "4.3.7",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1592969527,
|
||||
"version": "4.3.6",
|
||||
|
@@ -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
|
||||
|
@@ -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"
|
||||
}
|
||||
}
|
||||
|
@@ -1,13 +1,4 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1594788383,
|
||||
"version": "3.2.7",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1592969527,
|
||||
"version": "3.2.6",
|
||||
|
@@ -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
|
||||
|
@@ -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"
|
||||
}
|
||||
}
|
||||
|
@@ -1,13 +1,4 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1594788383,
|
||||
"version": "6.2.1",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "6.2.0",
|
||||
"changes": [
|
||||
|
@@ -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)
|
||||
|
@@ -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"
|
||||
}
|
||||
}
|
||||
|
@@ -1,14 +1,4 @@
|
||||
[
|
||||
{
|
||||
"version": "2.6.0",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Add `BalancerBridge` mainnet tests",
|
||||
"pr": 2613
|
||||
}
|
||||
],
|
||||
"timestamp": 1594788383
|
||||
},
|
||||
{
|
||||
"version": "2.5.2",
|
||||
"changes": [
|
||||
|
@@ -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)
|
||||
|
@@ -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"
|
||||
}
|
||||
}
|
||||
|
@@ -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);
|
||||
});
|
||||
|
@@ -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);
|
||||
});
|
||||
});
|
||||
});
|
@@ -1,13 +1,4 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1594788383,
|
||||
"version": "4.1.7",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1592969527,
|
||||
"version": "4.1.6",
|
||||
|
@@ -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
|
||||
|
@@ -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"
|
||||
}
|
||||
}
|
||||
|
@@ -1,13 +1,4 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1594788383,
|
||||
"version": "2.0.14",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1592969527,
|
||||
"version": "2.0.13",
|
||||
|
@@ -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
|
||||
|
@@ -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"
|
||||
}
|
||||
}
|
||||
|
@@ -1,13 +1,4 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1594788383,
|
||||
"version": "5.3.4",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "5.3.3",
|
||||
"changes": [
|
||||
|
@@ -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)
|
||||
|
@@ -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"
|
||||
}
|
||||
}
|
||||
|
@@ -1,14 +1,4 @@
|
||||
[
|
||||
{
|
||||
"version": "4.5.1",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Reorganize `DeploymentConstants` addresses",
|
||||
"pr": 2628
|
||||
}
|
||||
],
|
||||
"timestamp": 1594788383
|
||||
},
|
||||
{
|
||||
"version": "4.5.0",
|
||||
"changes": [
|
||||
|
@@ -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)
|
||||
|
@@ -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
|
||||
|
@@ -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"
|
||||
}
|
||||
}
|
||||
|
@@ -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",
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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
|
||||
);
|
||||
}
|
||||
}
|
@@ -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
|
||||
);
|
||||
}
|
||||
}
|
@@ -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);
|
||||
}
|
@@ -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);
|
||||
}
|
@@ -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
|
||||
|
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
@@ -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)
|
||||
|
@@ -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]));
|
||||
}
|
||||
}
|
@@ -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.
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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.
|
||||
|
@@ -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
|
||||
));
|
||||
}
|
||||
}
|
@@ -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
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
@@ -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)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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.
|
||||
|
@@ -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 }
|
||||
}
|
||||
}
|
@@ -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
|
||||
|
@@ -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.
|
||||
|
@@ -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));
|
||||
}
|
||||
}
|
@@ -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
Reference in New Issue
Block a user