Compare commits
33 Commits
@0x/sol-tr
...
@0x/contra
Author | SHA1 | Date | |
---|---|---|---|
|
4a133ca36f | ||
|
f7252f919a | ||
|
e05a03a842 | ||
|
dcce8276b8 | ||
|
fd47947e55 | ||
|
ae151df2eb | ||
|
79de188683 | ||
|
6e5c788e13 | ||
|
f53606007d | ||
|
a4ac418bc9 | ||
|
a8c09d0bdb | ||
|
871105a48a | ||
|
3b61129ade | ||
|
f471c79b59 | ||
|
dfd9443f74 | ||
|
a36ff9e365 | ||
|
12e65bbf26 | ||
|
ab9841e60b | ||
|
7a52f12e57 | ||
|
11fd4506ac | ||
|
0c9c68030e | ||
|
55d6eddbb2 | ||
|
8341e60edb | ||
|
6273a1ca73 | ||
|
1b83ebdf89 | ||
|
fef7f0506f | ||
|
f44eb4e383 | ||
|
05df485c4a | ||
|
44857c526b | ||
|
b8ad5d5d32 | ||
|
e3e0d00e21 | ||
|
a9b1ea9690 | ||
|
8e5dd0f8d9 |
@@ -1,4 +1,13 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"timestamp": 1581748629,
|
||||||
|
"version": "3.2.1",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Dependencies updated"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"version": "3.2.0",
|
"version": "3.2.0",
|
||||||
"changes": [
|
"changes": [
|
||||||
|
@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
|
|||||||
|
|
||||||
CHANGELOG
|
CHANGELOG
|
||||||
|
|
||||||
|
## v3.2.1 - _February 15, 2020_
|
||||||
|
|
||||||
|
* Dependencies updated
|
||||||
|
|
||||||
## v3.2.0 - _February 8, 2020_
|
## v3.2.0 - _February 8, 2020_
|
||||||
|
|
||||||
* Fix broken tests. (#2462)
|
* Fix broken tests. (#2462)
|
||||||
|
108
contracts/asset-proxy/contracts/src/bridges/CurveBridge.sol
Normal file
108
contracts/asset-proxy/contracts/src/bridges/CurveBridge.sol
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
Copyright 2019 ZeroEx Intl.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
pragma solidity ^0.5.9;
|
||||||
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
|
import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol";
|
||||||
|
import "@0x/contracts-erc20/contracts/src/LibERC20Token.sol";
|
||||||
|
import "@0x/contracts-exchange-libs/contracts/src/IWallet.sol";
|
||||||
|
import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol";
|
||||||
|
import "../interfaces/IERC20Bridge.sol";
|
||||||
|
import "../interfaces/ICurve.sol";
|
||||||
|
|
||||||
|
|
||||||
|
// solhint-disable not-rely-on-time
|
||||||
|
// solhint-disable space-after-comma
|
||||||
|
contract CurveBridge is
|
||||||
|
IERC20Bridge,
|
||||||
|
IWallet,
|
||||||
|
DeploymentConstants
|
||||||
|
{
|
||||||
|
/// @dev Callback for `ICurve`. Tries to buy `amount` of
|
||||||
|
/// `toTokenAddress` tokens by selling the entirety of the opposing asset
|
||||||
|
/// (DAI, USDC) to the Curve contract, then transfers the bought
|
||||||
|
/// tokens to `to`.
|
||||||
|
/// @param toTokenAddress The token to give to `to` (i.e DAI, USDC, USDT).
|
||||||
|
/// @param to The recipient of the bought tokens.
|
||||||
|
/// @param amount Minimum amount of `toTokenAddress` tokens to buy.
|
||||||
|
/// @param bridgeData The abi-encoeded "from" token address.
|
||||||
|
/// @return success The magic bytes if successful.
|
||||||
|
function bridgeTransferFrom(
|
||||||
|
address toTokenAddress,
|
||||||
|
address /* from */,
|
||||||
|
address to,
|
||||||
|
uint256 amount,
|
||||||
|
bytes calldata bridgeData
|
||||||
|
)
|
||||||
|
external
|
||||||
|
returns (bytes4 success)
|
||||||
|
{
|
||||||
|
// Decode the bridge data to get the Curve metadata.
|
||||||
|
(address curveAddress, int128 fromCoinIdx, int128 toCoinIdx, int128 version) = abi.decode(bridgeData, (address, int128, int128, int128));
|
||||||
|
ICurve exchange = ICurve(curveAddress);
|
||||||
|
|
||||||
|
address fromTokenAddress = exchange.underlying_coins(fromCoinIdx);
|
||||||
|
require(toTokenAddress != fromTokenAddress, "CurveBridge/INVALID_PAIR");
|
||||||
|
// Grant an allowance to the exchange to spend `fromTokenAddress` token.
|
||||||
|
LibERC20Token.approve(fromTokenAddress, address(exchange), uint256(-1));
|
||||||
|
|
||||||
|
// Try to sell all of this contract's `fromTokenAddress` token balance.
|
||||||
|
if (version == 0) {
|
||||||
|
exchange.exchange_underlying(
|
||||||
|
fromCoinIdx,
|
||||||
|
toCoinIdx,
|
||||||
|
// dx
|
||||||
|
IERC20Token(fromTokenAddress).balanceOf(address(this)),
|
||||||
|
// min dy
|
||||||
|
amount,
|
||||||
|
// expires
|
||||||
|
block.timestamp + 1
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
exchange.exchange_underlying(
|
||||||
|
fromCoinIdx,
|
||||||
|
toCoinIdx,
|
||||||
|
// dx
|
||||||
|
IERC20Token(fromTokenAddress).balanceOf(address(this)),
|
||||||
|
// min dy
|
||||||
|
amount
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint256 toTokenBalance = IERC20Token(toTokenAddress).balanceOf(address(this));
|
||||||
|
// Transfer the converted `toToken`s to `to`.
|
||||||
|
LibERC20Token.transfer(toTokenAddress, to, toTokenBalance);
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
87
contracts/asset-proxy/contracts/src/interfaces/ICurve.sol
Normal file
87
contracts/asset-proxy/contracts/src/interfaces/ICurve.sol
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright 2019 ZeroEx Intl.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
pragma solidity ^0.5.9;
|
||||||
|
|
||||||
|
|
||||||
|
// solhint-disable func-name-mixedcase
|
||||||
|
interface ICurve {
|
||||||
|
|
||||||
|
/// @dev Sell `sellAmount` of `fromToken` token and receive `toToken` token.
|
||||||
|
/// This function exists on early versions of Curve (USDC/DAI)
|
||||||
|
/// @param i The token index being sold.
|
||||||
|
/// @param j The token index being bought.
|
||||||
|
/// @param sellAmount The amount of token being bought.
|
||||||
|
/// @param minBuyAmount The minimum buy amount of the token being bought.
|
||||||
|
/// @param deadline The time in seconds when this operation should expire.
|
||||||
|
function exchange_underlying(
|
||||||
|
int128 i,
|
||||||
|
int128 j,
|
||||||
|
uint256 sellAmount,
|
||||||
|
uint256 minBuyAmount,
|
||||||
|
uint256 deadline
|
||||||
|
)
|
||||||
|
external;
|
||||||
|
|
||||||
|
/// @dev Sell `sellAmount` of `fromToken` token and receive `toToken` token.
|
||||||
|
/// This function exists on later versions of Curve (USDC/DAI/USDT)
|
||||||
|
/// @param i The token index being sold.
|
||||||
|
/// @param j The token index being bought.
|
||||||
|
/// @param sellAmount The amount of token being bought.
|
||||||
|
/// @param minBuyAmount The minimum buy amount of the token being bought.
|
||||||
|
function exchange_underlying(
|
||||||
|
int128 i,
|
||||||
|
int128 j,
|
||||||
|
uint256 sellAmount,
|
||||||
|
uint256 minBuyAmount
|
||||||
|
)
|
||||||
|
external;
|
||||||
|
|
||||||
|
/// @dev Get the amount of `toToken` by selling `sellAmount` of `fromToken`
|
||||||
|
/// @param i The token index being sold.
|
||||||
|
/// @param j The token index being bought.
|
||||||
|
/// @param sellAmount The amount of token being bought.
|
||||||
|
function get_dy_underlying(
|
||||||
|
int128 i,
|
||||||
|
int128 j,
|
||||||
|
uint256 sellAmount
|
||||||
|
)
|
||||||
|
external
|
||||||
|
returns (uint256 dy);
|
||||||
|
|
||||||
|
/// @dev Get the amount of `fromToken` by buying `buyAmount` of `toToken`
|
||||||
|
/// This function exists on later versions of Curve (USDC/DAI/USDT)
|
||||||
|
/// @param i The token index being sold.
|
||||||
|
/// @param j The token index being bought.
|
||||||
|
/// @param buyAmount The amount of token being bought.
|
||||||
|
function get_dx_underlying(
|
||||||
|
int128 i,
|
||||||
|
int128 j,
|
||||||
|
uint256 buyAmount
|
||||||
|
)
|
||||||
|
external
|
||||||
|
returns (uint256 dx);
|
||||||
|
|
||||||
|
/// @dev Get the underlying token address from the token index
|
||||||
|
/// @param i The token index.
|
||||||
|
function underlying_coins(
|
||||||
|
int128 i
|
||||||
|
)
|
||||||
|
external
|
||||||
|
returns (address tokenAddress);
|
||||||
|
}
|
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@0x/contracts-asset-proxy",
|
"name": "@0x/contracts-asset-proxy",
|
||||||
"version": "3.2.0",
|
"version": "3.2.1",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.12"
|
"node": ">=6.12"
|
||||||
},
|
},
|
||||||
@@ -38,7 +38,7 @@
|
|||||||
"docs:json": "typedoc --excludePrivate --excludeExternals --excludeProtected --ignoreCompilerErrors --target ES5 --tsconfig typedoc-tsconfig.json --json $JSON_FILE_PATH $PROJECT_FILES"
|
"docs:json": "typedoc --excludePrivate --excludeExternals --excludeProtected --ignoreCompilerErrors --target ES5 --tsconfig typedoc-tsconfig.json --json $JSON_FILE_PATH $PROJECT_FILES"
|
||||||
},
|
},
|
||||||
"config": {
|
"config": {
|
||||||
"abis": "./test/generated-artifacts/@(ChaiBridge|DydxBridge|ERC1155Proxy|ERC20BridgeProxy|ERC20Proxy|ERC721Proxy|Eth2DaiBridge|IAssetData|IAssetProxy|IAssetProxyDispatcher|IAuthorizable|IChai|IDydx|IDydxBridge|IERC20Bridge|IEth2Dai|IKyberNetworkProxy|IUniswapExchange|IUniswapExchangeFactory|KyberBridge|MixinAssetProxyDispatcher|MixinAuthorizable|MultiAssetProxy|Ownable|StaticCallProxy|TestChaiBridge|TestDydxBridge|TestERC20Bridge|TestEth2DaiBridge|TestKyberBridge|TestStaticCallTarget|TestUniswapBridge|UniswapBridge).json",
|
"abis": "./test/generated-artifacts/@(ChaiBridge|CurveBridge|DydxBridge|ERC1155Proxy|ERC20BridgeProxy|ERC20Proxy|ERC721Proxy|Eth2DaiBridge|IAssetData|IAssetProxy|IAssetProxyDispatcher|IAuthorizable|IChai|ICurve|IDydx|IDydxBridge|IERC20Bridge|IEth2Dai|IKyberNetworkProxy|IUniswapExchange|IUniswapExchangeFactory|KyberBridge|MixinAssetProxyDispatcher|MixinAuthorizable|MultiAssetProxy|Ownable|StaticCallProxy|TestChaiBridge|TestDydxBridge|TestERC20Bridge|TestEth2DaiBridge|TestKyberBridge|TestStaticCallTarget|TestUniswapBridge|UniswapBridge).json",
|
||||||
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually."
|
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually."
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
@@ -53,8 +53,8 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@0x/abi-gen": "^5.2.0",
|
"@0x/abi-gen": "^5.2.0",
|
||||||
"@0x/contracts-gen": "^2.0.7",
|
"@0x/contracts-gen": "^2.0.7",
|
||||||
"@0x/contracts-test-utils": "^5.1.4",
|
"@0x/contracts-test-utils": "^5.1.5",
|
||||||
"@0x/contracts-utils": "^4.3.0",
|
"@0x/contracts-utils": "^4.3.1",
|
||||||
"@0x/dev-utils": "^3.2.0",
|
"@0x/dev-utils": "^3.2.0",
|
||||||
"@0x/sol-compiler": "^4.0.7",
|
"@0x/sol-compiler": "^4.0.7",
|
||||||
"@0x/ts-doc-gen": "^0.0.22",
|
"@0x/ts-doc-gen": "^0.0.22",
|
||||||
@@ -79,11 +79,11 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@0x/base-contract": "^6.2.0",
|
"@0x/base-contract": "^6.2.0",
|
||||||
"@0x/contracts-erc1155": "^2.1.0",
|
"@0x/contracts-erc1155": "^2.1.1",
|
||||||
"@0x/contracts-erc20": "^3.1.0",
|
"@0x/contracts-erc20": "^3.1.1",
|
||||||
"@0x/contracts-erc721": "^3.1.0",
|
"@0x/contracts-erc721": "^3.1.1",
|
||||||
"@0x/contracts-exchange-libs": "^4.3.0",
|
"@0x/contracts-exchange-libs": "^4.3.1",
|
||||||
"@0x/order-utils": "^10.2.0",
|
"@0x/order-utils": "^10.2.1",
|
||||||
"@0x/types": "^3.1.2",
|
"@0x/types": "^3.1.2",
|
||||||
"@0x/typescript-typings": "^5.0.2",
|
"@0x/typescript-typings": "^5.0.2",
|
||||||
"@0x/utils": "^5.4.0",
|
"@0x/utils": "^5.4.0",
|
||||||
|
@@ -6,6 +6,7 @@
|
|||||||
import { ContractArtifact } from 'ethereum-types';
|
import { ContractArtifact } from 'ethereum-types';
|
||||||
|
|
||||||
import * as ChaiBridge from '../generated-artifacts/ChaiBridge.json';
|
import * as ChaiBridge from '../generated-artifacts/ChaiBridge.json';
|
||||||
|
import * as CurveBridge from '../generated-artifacts/CurveBridge.json';
|
||||||
import * as DydxBridge from '../generated-artifacts/DydxBridge.json';
|
import * as DydxBridge from '../generated-artifacts/DydxBridge.json';
|
||||||
import * as ERC1155Proxy from '../generated-artifacts/ERC1155Proxy.json';
|
import * as ERC1155Proxy from '../generated-artifacts/ERC1155Proxy.json';
|
||||||
import * as ERC20BridgeProxy from '../generated-artifacts/ERC20BridgeProxy.json';
|
import * as ERC20BridgeProxy from '../generated-artifacts/ERC20BridgeProxy.json';
|
||||||
@@ -17,6 +18,7 @@ import * as IAssetProxy from '../generated-artifacts/IAssetProxy.json';
|
|||||||
import * as IAssetProxyDispatcher from '../generated-artifacts/IAssetProxyDispatcher.json';
|
import * as IAssetProxyDispatcher from '../generated-artifacts/IAssetProxyDispatcher.json';
|
||||||
import * as IAuthorizable from '../generated-artifacts/IAuthorizable.json';
|
import * as IAuthorizable from '../generated-artifacts/IAuthorizable.json';
|
||||||
import * as IChai from '../generated-artifacts/IChai.json';
|
import * as IChai from '../generated-artifacts/IChai.json';
|
||||||
|
import * as ICurve from '../generated-artifacts/ICurve.json';
|
||||||
import * as IDydx from '../generated-artifacts/IDydx.json';
|
import * as IDydx from '../generated-artifacts/IDydx.json';
|
||||||
import * as IDydxBridge from '../generated-artifacts/IDydxBridge.json';
|
import * as IDydxBridge from '../generated-artifacts/IDydxBridge.json';
|
||||||
import * as IERC20Bridge from '../generated-artifacts/IERC20Bridge.json';
|
import * as IERC20Bridge from '../generated-artifacts/IERC20Bridge.json';
|
||||||
@@ -49,6 +51,7 @@ export const artifacts = {
|
|||||||
MultiAssetProxy: MultiAssetProxy as ContractArtifact,
|
MultiAssetProxy: MultiAssetProxy as ContractArtifact,
|
||||||
StaticCallProxy: StaticCallProxy as ContractArtifact,
|
StaticCallProxy: StaticCallProxy as ContractArtifact,
|
||||||
ChaiBridge: ChaiBridge as ContractArtifact,
|
ChaiBridge: ChaiBridge as ContractArtifact,
|
||||||
|
CurveBridge: CurveBridge as ContractArtifact,
|
||||||
DydxBridge: DydxBridge as ContractArtifact,
|
DydxBridge: DydxBridge as ContractArtifact,
|
||||||
Eth2DaiBridge: Eth2DaiBridge as ContractArtifact,
|
Eth2DaiBridge: Eth2DaiBridge as ContractArtifact,
|
||||||
KyberBridge: KyberBridge as ContractArtifact,
|
KyberBridge: KyberBridge as ContractArtifact,
|
||||||
@@ -58,6 +61,7 @@ export const artifacts = {
|
|||||||
IAssetProxyDispatcher: IAssetProxyDispatcher as ContractArtifact,
|
IAssetProxyDispatcher: IAssetProxyDispatcher as ContractArtifact,
|
||||||
IAuthorizable: IAuthorizable as ContractArtifact,
|
IAuthorizable: IAuthorizable as ContractArtifact,
|
||||||
IChai: IChai as ContractArtifact,
|
IChai: IChai as ContractArtifact,
|
||||||
|
ICurve: ICurve as ContractArtifact,
|
||||||
IDydx: IDydx as ContractArtifact,
|
IDydx: IDydx as ContractArtifact,
|
||||||
IDydxBridge: IDydxBridge as ContractArtifact,
|
IDydxBridge: IDydxBridge as ContractArtifact,
|
||||||
IERC20Bridge: IERC20Bridge as ContractArtifact,
|
IERC20Bridge: IERC20Bridge as ContractArtifact,
|
||||||
|
@@ -4,6 +4,7 @@
|
|||||||
* -----------------------------------------------------------------------------
|
* -----------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
export * from '../generated-wrappers/chai_bridge';
|
export * from '../generated-wrappers/chai_bridge';
|
||||||
|
export * from '../generated-wrappers/curve_bridge';
|
||||||
export * from '../generated-wrappers/dydx_bridge';
|
export * from '../generated-wrappers/dydx_bridge';
|
||||||
export * from '../generated-wrappers/erc1155_proxy';
|
export * from '../generated-wrappers/erc1155_proxy';
|
||||||
export * from '../generated-wrappers/erc20_bridge_proxy';
|
export * from '../generated-wrappers/erc20_bridge_proxy';
|
||||||
@@ -15,6 +16,7 @@ export * from '../generated-wrappers/i_asset_proxy';
|
|||||||
export * from '../generated-wrappers/i_asset_proxy_dispatcher';
|
export * from '../generated-wrappers/i_asset_proxy_dispatcher';
|
||||||
export * from '../generated-wrappers/i_authorizable';
|
export * from '../generated-wrappers/i_authorizable';
|
||||||
export * from '../generated-wrappers/i_chai';
|
export * from '../generated-wrappers/i_chai';
|
||||||
|
export * from '../generated-wrappers/i_curve';
|
||||||
export * from '../generated-wrappers/i_dydx';
|
export * from '../generated-wrappers/i_dydx';
|
||||||
export * from '../generated-wrappers/i_dydx_bridge';
|
export * from '../generated-wrappers/i_dydx_bridge';
|
||||||
export * from '../generated-wrappers/i_erc20_bridge';
|
export * from '../generated-wrappers/i_erc20_bridge';
|
||||||
|
@@ -6,6 +6,7 @@
|
|||||||
import { ContractArtifact } from 'ethereum-types';
|
import { ContractArtifact } from 'ethereum-types';
|
||||||
|
|
||||||
import * as ChaiBridge from '../test/generated-artifacts/ChaiBridge.json';
|
import * as ChaiBridge from '../test/generated-artifacts/ChaiBridge.json';
|
||||||
|
import * as CurveBridge from '../test/generated-artifacts/CurveBridge.json';
|
||||||
import * as DydxBridge from '../test/generated-artifacts/DydxBridge.json';
|
import * as DydxBridge from '../test/generated-artifacts/DydxBridge.json';
|
||||||
import * as ERC1155Proxy from '../test/generated-artifacts/ERC1155Proxy.json';
|
import * as ERC1155Proxy from '../test/generated-artifacts/ERC1155Proxy.json';
|
||||||
import * as ERC20BridgeProxy from '../test/generated-artifacts/ERC20BridgeProxy.json';
|
import * as ERC20BridgeProxy from '../test/generated-artifacts/ERC20BridgeProxy.json';
|
||||||
@@ -17,6 +18,7 @@ import * as IAssetProxy from '../test/generated-artifacts/IAssetProxy.json';
|
|||||||
import * as IAssetProxyDispatcher from '../test/generated-artifacts/IAssetProxyDispatcher.json';
|
import * as IAssetProxyDispatcher from '../test/generated-artifacts/IAssetProxyDispatcher.json';
|
||||||
import * as IAuthorizable from '../test/generated-artifacts/IAuthorizable.json';
|
import * as IAuthorizable from '../test/generated-artifacts/IAuthorizable.json';
|
||||||
import * as IChai from '../test/generated-artifacts/IChai.json';
|
import * as IChai from '../test/generated-artifacts/IChai.json';
|
||||||
|
import * as ICurve from '../test/generated-artifacts/ICurve.json';
|
||||||
import * as IDydx from '../test/generated-artifacts/IDydx.json';
|
import * as IDydx from '../test/generated-artifacts/IDydx.json';
|
||||||
import * as IDydxBridge from '../test/generated-artifacts/IDydxBridge.json';
|
import * as IDydxBridge from '../test/generated-artifacts/IDydxBridge.json';
|
||||||
import * as IERC20Bridge from '../test/generated-artifacts/IERC20Bridge.json';
|
import * as IERC20Bridge from '../test/generated-artifacts/IERC20Bridge.json';
|
||||||
@@ -49,6 +51,7 @@ export const artifacts = {
|
|||||||
MultiAssetProxy: MultiAssetProxy as ContractArtifact,
|
MultiAssetProxy: MultiAssetProxy as ContractArtifact,
|
||||||
StaticCallProxy: StaticCallProxy as ContractArtifact,
|
StaticCallProxy: StaticCallProxy as ContractArtifact,
|
||||||
ChaiBridge: ChaiBridge as ContractArtifact,
|
ChaiBridge: ChaiBridge as ContractArtifact,
|
||||||
|
CurveBridge: CurveBridge as ContractArtifact,
|
||||||
DydxBridge: DydxBridge as ContractArtifact,
|
DydxBridge: DydxBridge as ContractArtifact,
|
||||||
Eth2DaiBridge: Eth2DaiBridge as ContractArtifact,
|
Eth2DaiBridge: Eth2DaiBridge as ContractArtifact,
|
||||||
KyberBridge: KyberBridge as ContractArtifact,
|
KyberBridge: KyberBridge as ContractArtifact,
|
||||||
@@ -58,6 +61,7 @@ export const artifacts = {
|
|||||||
IAssetProxyDispatcher: IAssetProxyDispatcher as ContractArtifact,
|
IAssetProxyDispatcher: IAssetProxyDispatcher as ContractArtifact,
|
||||||
IAuthorizable: IAuthorizable as ContractArtifact,
|
IAuthorizable: IAuthorizable as ContractArtifact,
|
||||||
IChai: IChai as ContractArtifact,
|
IChai: IChai as ContractArtifact,
|
||||||
|
ICurve: ICurve as ContractArtifact,
|
||||||
IDydx: IDydx as ContractArtifact,
|
IDydx: IDydx as ContractArtifact,
|
||||||
IDydxBridge: IDydxBridge as ContractArtifact,
|
IDydxBridge: IDydxBridge as ContractArtifact,
|
||||||
IERC20Bridge: IERC20Bridge as ContractArtifact,
|
IERC20Bridge: IERC20Bridge as ContractArtifact,
|
||||||
|
@@ -4,6 +4,7 @@
|
|||||||
* -----------------------------------------------------------------------------
|
* -----------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
export * from '../test/generated-wrappers/chai_bridge';
|
export * from '../test/generated-wrappers/chai_bridge';
|
||||||
|
export * from '../test/generated-wrappers/curve_bridge';
|
||||||
export * from '../test/generated-wrappers/dydx_bridge';
|
export * from '../test/generated-wrappers/dydx_bridge';
|
||||||
export * from '../test/generated-wrappers/erc1155_proxy';
|
export * from '../test/generated-wrappers/erc1155_proxy';
|
||||||
export * from '../test/generated-wrappers/erc20_bridge_proxy';
|
export * from '../test/generated-wrappers/erc20_bridge_proxy';
|
||||||
@@ -15,6 +16,7 @@ export * from '../test/generated-wrappers/i_asset_proxy';
|
|||||||
export * from '../test/generated-wrappers/i_asset_proxy_dispatcher';
|
export * from '../test/generated-wrappers/i_asset_proxy_dispatcher';
|
||||||
export * from '../test/generated-wrappers/i_authorizable';
|
export * from '../test/generated-wrappers/i_authorizable';
|
||||||
export * from '../test/generated-wrappers/i_chai';
|
export * from '../test/generated-wrappers/i_chai';
|
||||||
|
export * from '../test/generated-wrappers/i_curve';
|
||||||
export * from '../test/generated-wrappers/i_dydx';
|
export * from '../test/generated-wrappers/i_dydx';
|
||||||
export * from '../test/generated-wrappers/i_dydx_bridge';
|
export * from '../test/generated-wrappers/i_dydx_bridge';
|
||||||
export * from '../test/generated-wrappers/i_erc20_bridge';
|
export * from '../test/generated-wrappers/i_erc20_bridge';
|
||||||
|
@@ -4,6 +4,7 @@
|
|||||||
"include": ["./src/**/*", "./test/**/*", "./generated-wrappers/**/*"],
|
"include": ["./src/**/*", "./test/**/*", "./generated-wrappers/**/*"],
|
||||||
"files": [
|
"files": [
|
||||||
"generated-artifacts/ChaiBridge.json",
|
"generated-artifacts/ChaiBridge.json",
|
||||||
|
"generated-artifacts/CurveBridge.json",
|
||||||
"generated-artifacts/DydxBridge.json",
|
"generated-artifacts/DydxBridge.json",
|
||||||
"generated-artifacts/ERC1155Proxy.json",
|
"generated-artifacts/ERC1155Proxy.json",
|
||||||
"generated-artifacts/ERC20BridgeProxy.json",
|
"generated-artifacts/ERC20BridgeProxy.json",
|
||||||
@@ -15,6 +16,7 @@
|
|||||||
"generated-artifacts/IAssetProxyDispatcher.json",
|
"generated-artifacts/IAssetProxyDispatcher.json",
|
||||||
"generated-artifacts/IAuthorizable.json",
|
"generated-artifacts/IAuthorizable.json",
|
||||||
"generated-artifacts/IChai.json",
|
"generated-artifacts/IChai.json",
|
||||||
|
"generated-artifacts/ICurve.json",
|
||||||
"generated-artifacts/IDydx.json",
|
"generated-artifacts/IDydx.json",
|
||||||
"generated-artifacts/IDydxBridge.json",
|
"generated-artifacts/IDydxBridge.json",
|
||||||
"generated-artifacts/IERC20Bridge.json",
|
"generated-artifacts/IERC20Bridge.json",
|
||||||
@@ -37,6 +39,7 @@
|
|||||||
"generated-artifacts/TestUniswapBridge.json",
|
"generated-artifacts/TestUniswapBridge.json",
|
||||||
"generated-artifacts/UniswapBridge.json",
|
"generated-artifacts/UniswapBridge.json",
|
||||||
"test/generated-artifacts/ChaiBridge.json",
|
"test/generated-artifacts/ChaiBridge.json",
|
||||||
|
"test/generated-artifacts/CurveBridge.json",
|
||||||
"test/generated-artifacts/DydxBridge.json",
|
"test/generated-artifacts/DydxBridge.json",
|
||||||
"test/generated-artifacts/ERC1155Proxy.json",
|
"test/generated-artifacts/ERC1155Proxy.json",
|
||||||
"test/generated-artifacts/ERC20BridgeProxy.json",
|
"test/generated-artifacts/ERC20BridgeProxy.json",
|
||||||
@@ -48,6 +51,7 @@
|
|||||||
"test/generated-artifacts/IAssetProxyDispatcher.json",
|
"test/generated-artifacts/IAssetProxyDispatcher.json",
|
||||||
"test/generated-artifacts/IAuthorizable.json",
|
"test/generated-artifacts/IAuthorizable.json",
|
||||||
"test/generated-artifacts/IChai.json",
|
"test/generated-artifacts/IChai.json",
|
||||||
|
"test/generated-artifacts/ICurve.json",
|
||||||
"test/generated-artifacts/IDydx.json",
|
"test/generated-artifacts/IDydx.json",
|
||||||
"test/generated-artifacts/IDydxBridge.json",
|
"test/generated-artifacts/IDydxBridge.json",
|
||||||
"test/generated-artifacts/IERC20Bridge.json",
|
"test/generated-artifacts/IERC20Bridge.json",
|
||||||
|
@@ -1,4 +1,14 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"version": "1.1.0",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Added decoders for broker data",
|
||||||
|
"pr": 2484
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timestamp": 1581748629
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"timestamp": 1581204851,
|
"timestamp": 1581204851,
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
|
@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
|
|||||||
|
|
||||||
CHANGELOG
|
CHANGELOG
|
||||||
|
|
||||||
|
## v1.1.0 - _February 15, 2020_
|
||||||
|
|
||||||
|
* Added decoders for broker data (#2484)
|
||||||
|
|
||||||
## v1.0.2 - _February 8, 2020_
|
## v1.0.2 - _February 8, 2020_
|
||||||
|
|
||||||
* Dependencies updated
|
* Dependencies updated
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@0x/contracts-broker",
|
"name": "@0x/contracts-broker",
|
||||||
"version": "1.0.2",
|
"version": "1.1.0",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.12"
|
"node": ">=6.12"
|
||||||
},
|
},
|
||||||
@@ -52,14 +52,14 @@
|
|||||||
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/extensions/README.md",
|
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/extensions/README.md",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@0x/abi-gen": "^5.2.0",
|
"@0x/abi-gen": "^5.2.0",
|
||||||
"@0x/contracts-asset-proxy": "^3.2.0",
|
"@0x/contracts-asset-proxy": "^3.2.1",
|
||||||
"@0x/contracts-erc20": "^3.1.0",
|
"@0x/contracts-erc20": "^3.1.1",
|
||||||
"@0x/contracts-erc721": "^3.1.0",
|
"@0x/contracts-erc721": "^3.1.1",
|
||||||
"@0x/contracts-exchange": "^3.2.0",
|
"@0x/contracts-exchange": "^3.2.1",
|
||||||
"@0x/contracts-exchange-libs": "^4.3.0",
|
"@0x/contracts-exchange-libs": "^4.3.1",
|
||||||
"@0x/contracts-gen": "^2.0.7",
|
"@0x/contracts-gen": "^2.0.7",
|
||||||
"@0x/contracts-test-utils": "^5.1.4",
|
"@0x/contracts-test-utils": "^5.1.5",
|
||||||
"@0x/contracts-utils": "^4.3.0",
|
"@0x/contracts-utils": "^4.3.1",
|
||||||
"@0x/sol-compiler": "^4.0.7",
|
"@0x/sol-compiler": "^4.0.7",
|
||||||
"@0x/ts-doc-gen": "^0.0.22",
|
"@0x/ts-doc-gen": "^0.0.22",
|
||||||
"@0x/tslint-config": "^4.0.0",
|
"@0x/tslint-config": "^4.0.0",
|
||||||
@@ -85,7 +85,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@0x/base-contract": "^6.2.0",
|
"@0x/base-contract": "^6.2.0",
|
||||||
"@0x/order-utils": "^10.2.0",
|
"@0x/order-utils": "^10.2.1",
|
||||||
"@0x/typescript-typings": "^5.0.2",
|
"@0x/typescript-typings": "^5.0.2",
|
||||||
"@0x/utils": "^5.4.0",
|
"@0x/utils": "^5.4.0",
|
||||||
"ethereum-types": "^3.1.0"
|
"ethereum-types": "^3.1.0"
|
||||||
|
@@ -1,42 +1,59 @@
|
|||||||
import { assetDataUtils } from '@0x/order-utils';
|
import { assetDataUtils } from '@0x/order-utils';
|
||||||
|
import { ERC1155AssetData } from '@0x/types';
|
||||||
import { AbiEncoder, BigNumber } from '@0x/utils';
|
import { AbiEncoder, BigNumber } from '@0x/utils';
|
||||||
|
|
||||||
export const godsUnchainedUtils = {
|
export interface GodsUnchainedProperties {
|
||||||
/**
|
proto: BigNumber | number;
|
||||||
* Encodes the given proto and quality into the bytes format expected by the GodsUnchainedValidator.
|
quality: BigNumber | number;
|
||||||
*/
|
}
|
||||||
encodePropertyData(proto: BigNumber, quality: BigNumber): string {
|
|
||||||
return AbiEncoder.create([{ name: 'proto', type: 'uint16' }, { name: 'quality', type: 'uint8' }]).encode({
|
const propertyDataEncoder = AbiEncoder.create([{ name: 'proto', type: 'uint16' }, { name: 'quality', type: 'uint8' }]);
|
||||||
proto,
|
const brokerDataEncoder = AbiEncoder.create([
|
||||||
quality,
|
{ name: 'godsUnchainedAddress', type: 'address' },
|
||||||
});
|
{ name: 'validatorAddress', type: 'address' },
|
||||||
},
|
{ name: 'propertyData', type: 'bytes' },
|
||||||
/**
|
]);
|
||||||
* Encodes the given proto and quality into ERC1155 asset data to be used as the takerAssetData
|
|
||||||
* of a property-based GodsUnchained order. Must also provide the addresses of the Broker,
|
/**
|
||||||
* GodsUnchained, and GodsUnchainedValidator contracts. The optional bundleSize parameter specifies
|
* Encodes the given proto and quality into the bytes format expected by the GodsUnchainedValidator.
|
||||||
* how many cards are expected for each "unit" of the takerAssetAmount. For example, If the
|
*/
|
||||||
* takerAssetAmount is 3 and the bundleSize is 2, the taker must provide 2, 4, or 6 cards
|
export function encodePropertyData(properties: GodsUnchainedProperties): string {
|
||||||
* with the given proto and quality to fill the order. If an odd number is provided, the fill fails.
|
return propertyDataEncoder.encode(properties);
|
||||||
*/
|
}
|
||||||
encodeBrokerAssetData(
|
|
||||||
brokerAddress: string,
|
/**
|
||||||
godsUnchainedAddress: string,
|
* Encodes the given proto and quality into ERC1155 asset data to be used as the takerAssetData
|
||||||
validatorAddress: string,
|
* of a property-based GodsUnchained order. Must also provide the addresses of the Broker,
|
||||||
proto: BigNumber,
|
* GodsUnchained, and GodsUnchainedValidator contracts. The optional bundleSize parameter specifies
|
||||||
quality: BigNumber,
|
* how many cards are expected for each "unit" of the takerAssetAmount. For example, If the
|
||||||
bundleSize: number = 1,
|
* takerAssetAmount is 3 and the bundleSize is 2, the taker must provide 2, 4, or 6 cards
|
||||||
): string {
|
* with the given proto and quality to fill the order. If an odd number is provided, the fill fails.
|
||||||
const dataEncoder = AbiEncoder.create([
|
*/
|
||||||
{ name: 'godsUnchainedAddress', type: 'address' },
|
export function encodeBrokerAssetData(
|
||||||
{ name: 'validatorAddress', type: 'address' },
|
brokerAddress: string,
|
||||||
{ name: 'propertyData', type: 'bytes' },
|
godsUnchainedAddress: string,
|
||||||
]);
|
validatorAddress: string,
|
||||||
const propertyData = AbiEncoder.create([
|
properties: GodsUnchainedProperties,
|
||||||
{ name: 'proto', type: 'uint16' },
|
bundleSize: number = 1,
|
||||||
{ name: 'quality', type: 'uint8' },
|
): string {
|
||||||
]).encode({ proto, quality });
|
const propertyData = propertyDataEncoder.encode(properties);
|
||||||
const data = dataEncoder.encode({ godsUnchainedAddress, validatorAddress, propertyData });
|
const brokerData = brokerDataEncoder.encode({ godsUnchainedAddress, validatorAddress, propertyData });
|
||||||
return assetDataUtils.encodeERC1155AssetData(brokerAddress, [], [new BigNumber(bundleSize)], data);
|
return assetDataUtils.encodeERC1155AssetData(brokerAddress, [], [new BigNumber(bundleSize)], brokerData);
|
||||||
},
|
}
|
||||||
};
|
|
||||||
|
/**
|
||||||
|
* Decodes proto and quality from the bytes format expected by the GodsUnchainedValidator.
|
||||||
|
*/
|
||||||
|
export function decodePropertyData(propertyData: string): GodsUnchainedProperties {
|
||||||
|
return propertyDataEncoder.decode(propertyData);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes proto and quality from the ERC1155 takerAssetData of a property-based GodsUnchained order.
|
||||||
|
*/
|
||||||
|
export function decodeBrokerAssetData(brokerAssetData: string): GodsUnchainedProperties {
|
||||||
|
// tslint:disable-next-line:no-unnecessary-type-assertion
|
||||||
|
const { callbackData: brokerData } = assetDataUtils.decodeAssetDataOrThrow(brokerAssetData) as ERC1155AssetData;
|
||||||
|
const { propertyData } = brokerDataEncoder.decode(brokerData);
|
||||||
|
return decodePropertyData(propertyData);
|
||||||
|
}
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
export { artifacts } from './artifacts';
|
export { artifacts } from './artifacts';
|
||||||
export { BrokerContract, GodsUnchainedValidatorContract, TestGodsUnchainedContract } from './wrappers';
|
export { BrokerContract, GodsUnchainedValidatorContract, TestGodsUnchainedContract } from './wrappers';
|
||||||
export { godsUnchainedUtils } from './gods_unchained_utils';
|
export * from './gods_unchained_utils';
|
||||||
export { BrokerRevertErrors } from '@0x/utils';
|
export { BrokerRevertErrors } from '@0x/utils';
|
||||||
export {
|
export {
|
||||||
ContractArtifact,
|
ContractArtifact,
|
||||||
|
@@ -2,7 +2,7 @@ import { blockchainTests, constants, expect, getRandomInteger } from '@0x/contra
|
|||||||
import { BigNumber } from '@0x/utils';
|
import { BigNumber } from '@0x/utils';
|
||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
|
|
||||||
import { godsUnchainedUtils } from '../src/gods_unchained_utils';
|
import { encodePropertyData } from '../src/gods_unchained_utils';
|
||||||
|
|
||||||
import { artifacts } from './artifacts';
|
import { artifacts } from './artifacts';
|
||||||
import { GodsUnchainedValidatorContract, TestGodsUnchainedContract } from './wrappers';
|
import { GodsUnchainedValidatorContract, TestGodsUnchainedContract } from './wrappers';
|
||||||
@@ -33,7 +33,7 @@ blockchainTests.resets('GodsUnchainedValidator unit tests', env => {
|
|||||||
describe('checkBrokerAsset', () => {
|
describe('checkBrokerAsset', () => {
|
||||||
const proto = new BigNumber(42);
|
const proto = new BigNumber(42);
|
||||||
const quality = new BigNumber(7);
|
const quality = new BigNumber(7);
|
||||||
const propertyData = godsUnchainedUtils.encodePropertyData(proto, quality);
|
const propertyData = encodePropertyData({ proto, quality });
|
||||||
|
|
||||||
it('succeeds if assetData proto and quality match propertyData', async () => {
|
it('succeeds if assetData proto and quality match propertyData', async () => {
|
||||||
const tokenId = getRandomInteger(0, constants.MAX_UINT256);
|
const tokenId = getRandomInteger(0, constants.MAX_UINT256);
|
||||||
|
@@ -1,4 +1,13 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"timestamp": 1581748629,
|
||||||
|
"version": "3.1.1",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Dependencies updated"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"version": "3.1.0",
|
"version": "3.1.0",
|
||||||
"changes": [
|
"changes": [
|
||||||
|
@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
|
|||||||
|
|
||||||
CHANGELOG
|
CHANGELOG
|
||||||
|
|
||||||
|
## v3.1.1 - _February 15, 2020_
|
||||||
|
|
||||||
|
* Dependencies updated
|
||||||
|
|
||||||
## v3.1.0 - _February 8, 2020_
|
## v3.1.0 - _February 8, 2020_
|
||||||
|
|
||||||
* Update tests. (#2462)
|
* Update tests. (#2462)
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@0x/contracts-coordinator",
|
"name": "@0x/contracts-coordinator",
|
||||||
"version": "3.1.0",
|
"version": "3.1.1",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.12"
|
"node": ">=6.12"
|
||||||
},
|
},
|
||||||
@@ -53,14 +53,14 @@
|
|||||||
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/extensions/README.md",
|
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/extensions/README.md",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@0x/abi-gen": "^5.2.0",
|
"@0x/abi-gen": "^5.2.0",
|
||||||
"@0x/contracts-asset-proxy": "^3.2.0",
|
"@0x/contracts-asset-proxy": "^3.2.1",
|
||||||
"@0x/contracts-dev-utils": "^1.1.0",
|
"@0x/contracts-dev-utils": "^1.1.1",
|
||||||
"@0x/contracts-erc20": "^3.1.0",
|
"@0x/contracts-erc20": "^3.1.1",
|
||||||
"@0x/contracts-exchange": "^3.2.0",
|
"@0x/contracts-exchange": "^3.2.1",
|
||||||
"@0x/contracts-gen": "^2.0.7",
|
"@0x/contracts-gen": "^2.0.7",
|
||||||
"@0x/contracts-test-utils": "^5.1.4",
|
"@0x/contracts-test-utils": "^5.1.5",
|
||||||
"@0x/dev-utils": "^3.2.0",
|
"@0x/dev-utils": "^3.2.0",
|
||||||
"@0x/order-utils": "^10.2.0",
|
"@0x/order-utils": "^10.2.1",
|
||||||
"@0x/sol-compiler": "^4.0.7",
|
"@0x/sol-compiler": "^4.0.7",
|
||||||
"@0x/ts-doc-gen": "^0.0.22",
|
"@0x/ts-doc-gen": "^0.0.22",
|
||||||
"@0x/tslint-config": "^4.0.0",
|
"@0x/tslint-config": "^4.0.0",
|
||||||
@@ -86,8 +86,8 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@0x/assert": "^3.0.6",
|
"@0x/assert": "^3.0.6",
|
||||||
"@0x/base-contract": "^6.2.0",
|
"@0x/base-contract": "^6.2.0",
|
||||||
"@0x/contract-addresses": "^4.5.0",
|
"@0x/contract-addresses": "^4.6.0",
|
||||||
"@0x/contracts-utils": "^4.3.0",
|
"@0x/contracts-utils": "^4.3.1",
|
||||||
"@0x/json-schemas": "^5.0.6",
|
"@0x/json-schemas": "^5.0.6",
|
||||||
"@0x/types": "^3.1.2",
|
"@0x/types": "^3.1.2",
|
||||||
"@0x/typescript-typings": "^5.0.2",
|
"@0x/typescript-typings": "^5.0.2",
|
||||||
|
@@ -1,4 +1,13 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"timestamp": 1581748629,
|
||||||
|
"version": "1.1.1",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Dependencies updated"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"changes": [
|
"changes": [
|
||||||
|
@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
|
|||||||
|
|
||||||
CHANGELOG
|
CHANGELOG
|
||||||
|
|
||||||
|
## v1.1.1 - _February 15, 2020_
|
||||||
|
|
||||||
|
* Dependencies updated
|
||||||
|
|
||||||
## v1.1.0 - _February 8, 2020_
|
## v1.1.0 - _February 8, 2020_
|
||||||
|
|
||||||
* Refactor mixins into public libraries. (#2464)
|
* Refactor mixins into public libraries. (#2464)
|
||||||
|
@@ -118,22 +118,14 @@ contract OrderValidationUtils is
|
|||||||
transferableTakerAssetAmount
|
transferableTakerAssetAmount
|
||||||
);
|
);
|
||||||
|
|
||||||
// Execute the maker transfers.
|
// Ensure that all of the asset data is valid. Fee asset data only needs
|
||||||
fillableTakerAssetAmount = LibOrderTransferSimulation.getSimulatedOrderMakerTransferResults(
|
// to be valid if the fees are nonzero.
|
||||||
exchangeAddress,
|
if (!_areOrderAssetDatasValid(order)) {
|
||||||
order,
|
|
||||||
order.takerAddress,
|
|
||||||
fillableTakerAssetAmount
|
|
||||||
) == LibOrderTransferSimulation.OrderTransferResults.TransfersSuccessful ? fillableTakerAssetAmount : 0;
|
|
||||||
|
|
||||||
if (!_isAssetDataValid(order.takerAssetData)) {
|
|
||||||
fillableTakerAssetAmount = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (order.takerFee != 0 && !_isAssetDataValid(order.takerFeeAssetData)) {
|
|
||||||
fillableTakerAssetAmount = 0;
|
fillableTakerAssetAmount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the order is not fillable, then the fillable taker asset amount is
|
||||||
|
// zero by definition.
|
||||||
if (orderInfo.orderStatus != LibOrder.OrderStatus.FILLABLE) {
|
if (orderInfo.orderStatus != LibOrder.OrderStatus.FILLABLE) {
|
||||||
fillableTakerAssetAmount = 0;
|
fillableTakerAssetAmount = 0;
|
||||||
}
|
}
|
||||||
@@ -210,6 +202,21 @@ contract OrderValidationUtils is
|
|||||||
return transferableAssetAmount;
|
return transferableAssetAmount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @dev Checks that the asset data contained in a ZeroEx is valid and returns
|
||||||
|
/// a boolean that indicates whether or not the asset data was found to be valid.
|
||||||
|
/// @param order A ZeroEx order to validate.
|
||||||
|
/// @return The validatity of the asset data.
|
||||||
|
function _areOrderAssetDatasValid(LibOrder.Order memory order)
|
||||||
|
internal
|
||||||
|
pure
|
||||||
|
returns (bool)
|
||||||
|
{
|
||||||
|
return _isAssetDataValid(order.makerAssetData) &&
|
||||||
|
(order.makerFee == 0 || _isAssetDataValid(order.makerFeeAssetData)) &&
|
||||||
|
_isAssetDataValid(order.takerAssetData) &&
|
||||||
|
(order.takerFee == 0 || _isAssetDataValid(order.takerFeeAssetData));
|
||||||
|
}
|
||||||
|
|
||||||
/// @dev This function handles the edge cases around taker validation. This function
|
/// @dev This function handles the edge cases around taker validation. This function
|
||||||
/// currently attempts to find duplicate ERC721 token's in the taker
|
/// currently attempts to find duplicate ERC721 token's in the taker
|
||||||
/// multiAssetData.
|
/// multiAssetData.
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@0x/contracts-dev-utils",
|
"name": "@0x/contracts-dev-utils",
|
||||||
"version": "1.1.0",
|
"version": "1.1.1",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.12"
|
"node": ">=6.12"
|
||||||
},
|
},
|
||||||
@@ -43,10 +43,10 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@0x/abi-gen": "^5.2.0",
|
"@0x/abi-gen": "^5.2.0",
|
||||||
"@0x/assert": "^3.0.6",
|
"@0x/assert": "^3.0.6",
|
||||||
"@0x/contracts-asset-proxy": "^3.2.0",
|
"@0x/contracts-asset-proxy": "^3.2.1",
|
||||||
"@0x/contracts-erc20": "^3.1.0",
|
"@0x/contracts-erc20": "^3.1.1",
|
||||||
"@0x/contracts-gen": "^2.0.7",
|
"@0x/contracts-gen": "^2.0.7",
|
||||||
"@0x/contracts-test-utils": "^5.1.4",
|
"@0x/contracts-test-utils": "^5.1.5",
|
||||||
"@0x/sol-compiler": "^4.0.7",
|
"@0x/sol-compiler": "^4.0.7",
|
||||||
"@0x/ts-doc-gen": "^0.0.22",
|
"@0x/ts-doc-gen": "^0.0.22",
|
||||||
"@0x/tslint-config": "^4.0.0",
|
"@0x/tslint-config": "^4.0.0",
|
||||||
|
@@ -1,4 +1,13 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"timestamp": 1581748629,
|
||||||
|
"version": "2.1.1",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Dependencies updated"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"version": "2.1.0",
|
"version": "2.1.0",
|
||||||
"changes": [
|
"changes": [
|
||||||
|
@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
|
|||||||
|
|
||||||
CHANGELOG
|
CHANGELOG
|
||||||
|
|
||||||
|
## v2.1.1 - _February 15, 2020_
|
||||||
|
|
||||||
|
* Dependencies updated
|
||||||
|
|
||||||
## v2.1.0 - _February 8, 2020_
|
## v2.1.0 - _February 8, 2020_
|
||||||
|
|
||||||
* Fix broken tests (#2462)
|
* Fix broken tests (#2462)
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@0x/contracts-erc1155",
|
"name": "@0x/contracts-erc1155",
|
||||||
"version": "2.1.0",
|
"version": "2.1.1",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.12"
|
"node": ">=6.12"
|
||||||
},
|
},
|
||||||
@@ -54,7 +54,7 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@0x/abi-gen": "^5.2.0",
|
"@0x/abi-gen": "^5.2.0",
|
||||||
"@0x/contracts-gen": "^2.0.7",
|
"@0x/contracts-gen": "^2.0.7",
|
||||||
"@0x/contracts-utils": "^4.3.0",
|
"@0x/contracts-utils": "^4.3.1",
|
||||||
"@0x/dev-utils": "^3.2.0",
|
"@0x/dev-utils": "^3.2.0",
|
||||||
"@0x/sol-compiler": "^4.0.7",
|
"@0x/sol-compiler": "^4.0.7",
|
||||||
"@0x/ts-doc-gen": "^0.0.22",
|
"@0x/ts-doc-gen": "^0.0.22",
|
||||||
@@ -81,7 +81,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@0x/base-contract": "^6.2.0",
|
"@0x/base-contract": "^6.2.0",
|
||||||
"@0x/contracts-test-utils": "^5.1.4",
|
"@0x/contracts-test-utils": "^5.1.5",
|
||||||
"@0x/utils": "^5.4.0",
|
"@0x/utils": "^5.4.0",
|
||||||
"@0x/web3-wrapper": "^7.0.6",
|
"@0x/web3-wrapper": "^7.0.6",
|
||||||
"lodash": "^4.17.11"
|
"lodash": "^4.17.11"
|
||||||
|
@@ -1,10 +1,24 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"version": "1.4.0",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Added Curve contract sampling",
|
||||||
|
"pr": 2483
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timestamp": 1581748629
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"version": "1.3.0",
|
"version": "1.3.0",
|
||||||
"changes": [
|
"changes": [
|
||||||
{
|
{
|
||||||
"note": "Catch reverts to `DevUtils` calls",
|
"note": "Catch reverts to `DevUtils` calls",
|
||||||
"pr": 2476
|
"pr": 2476
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Remove wrapper functions and introduce `batchCall()`",
|
||||||
|
"pr": 2477
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"timestamp": 1581204851
|
"timestamp": 1581204851
|
||||||
|
@@ -5,9 +5,14 @@ Edit the package's CHANGELOG.json file only.
|
|||||||
|
|
||||||
CHANGELOG
|
CHANGELOG
|
||||||
|
|
||||||
|
## v1.4.0 - _February 15, 2020_
|
||||||
|
|
||||||
|
* Added Curve contract sampling (#2483)
|
||||||
|
|
||||||
## v1.3.0 - _February 8, 2020_
|
## v1.3.0 - _February 8, 2020_
|
||||||
|
|
||||||
* Catch reverts to `DevUtils` calls (#2476)
|
* Catch reverts to `DevUtils` calls (#2476)
|
||||||
|
* Remove wrapper functions and introduce `batchCall()` (#2477)
|
||||||
|
|
||||||
## v1.2.1 - _February 6, 2020_
|
## v1.2.1 - _February 6, 2020_
|
||||||
|
|
||||||
|
@@ -21,7 +21,6 @@ pragma experimental ABIEncoderV2;
|
|||||||
|
|
||||||
import "@0x/contracts-asset-proxy/contracts/src/interfaces/IUniswapExchangeFactory.sol";
|
import "@0x/contracts-asset-proxy/contracts/src/interfaces/IUniswapExchangeFactory.sol";
|
||||||
import "@0x/contracts-erc20/contracts/src/LibERC20Token.sol";
|
import "@0x/contracts-erc20/contracts/src/LibERC20Token.sol";
|
||||||
import "@0x/contracts-exchange/contracts/src/interfaces/IExchange.sol";
|
|
||||||
import "@0x/contracts-exchange-libs/contracts/src/LibOrder.sol";
|
import "@0x/contracts-exchange-libs/contracts/src/LibOrder.sol";
|
||||||
import "@0x/contracts-exchange-libs/contracts/src/LibMath.sol";
|
import "@0x/contracts-exchange-libs/contracts/src/LibMath.sol";
|
||||||
import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol";
|
import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol";
|
||||||
@@ -30,160 +29,46 @@ import "./IERC20BridgeSampler.sol";
|
|||||||
import "./IEth2Dai.sol";
|
import "./IEth2Dai.sol";
|
||||||
import "./IKyberNetwork.sol";
|
import "./IKyberNetwork.sol";
|
||||||
import "./IUniswapExchangeQuotes.sol";
|
import "./IUniswapExchangeQuotes.sol";
|
||||||
|
import "./ICurve.sol";
|
||||||
|
|
||||||
|
|
||||||
contract ERC20BridgeSampler is
|
contract ERC20BridgeSampler is
|
||||||
IERC20BridgeSampler,
|
IERC20BridgeSampler,
|
||||||
DeploymentConstants
|
DeploymentConstants
|
||||||
{
|
{
|
||||||
bytes4 constant internal ERC20_PROXY_ID = 0xf47261b0; // bytes4(keccak256("ERC20Token(address)"));
|
/// @dev Gas limit for DevUtils calls.
|
||||||
uint256 constant internal KYBER_SAMPLE_CALL_GAS = 1500e3;
|
uint256 constant internal DEV_UTILS_CALL_GAS = 500e3; // 500k
|
||||||
uint256 constant internal UNISWAP_SAMPLE_CALL_GAS = 150e3;
|
/// @dev Gas limit for Kyber calls.
|
||||||
uint256 constant internal ETH2DAI_SAMPLE_CALL_GAS = 1000e3;
|
uint256 constant internal KYBER_CALL_GAS = 1500e3; // 1.5m
|
||||||
uint256 constant internal DEV_UTILS_CALL_GAS = 500e3;
|
/// @dev Gas limit for Uniswap calls.
|
||||||
address constant private UNISWAP_SOURCE = 0xc0a47dFe034B400B47bDaD5FecDa2621de6c4d95;
|
uint256 constant internal UNISWAP_CALL_GAS = 150e3; // 150k
|
||||||
address constant private ETH2DAI_SOURCE = 0x39755357759cE0d7f32dC8dC45414CCa409AE24e;
|
/// @dev Base gas limit for Eth2Dai calls.
|
||||||
address constant private KYBER_SOURCE = 0x818E6FECD516Ecc3849DAf6845e3EC868087B755;
|
uint256 constant internal ETH2DAI_CALL_GAS = 1000e3; // 1m
|
||||||
|
/// @dev Base gas limit for Curve calls. Some Curves have multiple tokens
|
||||||
|
/// So a reasonable ceil is 150k per token. Biggest Curve has 4 tokens.
|
||||||
|
uint256 constant internal CURVE_CALL_GAS = 600e3; // 600k
|
||||||
|
|
||||||
/// @dev Query batches of native orders and sample sell quotes on multiple DEXes at once.
|
/// @dev Call multiple public functions on this contract in a single transaction.
|
||||||
/// @param orders Batches of Native orders to query.
|
/// @param callDatas ABI-encoded call data for each function call.
|
||||||
/// @param orderSignatures Batches of Signatures for each respective order in `orders`.
|
/// @return callResults ABI-encoded results data for each call.
|
||||||
/// @param sources Address of each DEX. Passing in an unsupported DEX will throw.
|
function batchCall(bytes[] calldata callDatas)
|
||||||
/// @param takerTokenAmounts Batches of Taker token sell amount for each sample.
|
external
|
||||||
/// @return ordersAndSamples How much taker asset can be filled
|
|
||||||
/// by each order in `orders`. Maker amounts bought for each source at
|
|
||||||
/// each taker token amount. First indexed by source index, then sample
|
|
||||||
/// index.
|
|
||||||
function queryBatchOrdersAndSampleSells(
|
|
||||||
LibOrder.Order[][] memory orders,
|
|
||||||
bytes[][] memory orderSignatures,
|
|
||||||
address[] memory sources,
|
|
||||||
uint256[][] memory takerTokenAmounts
|
|
||||||
)
|
|
||||||
public
|
|
||||||
view
|
view
|
||||||
returns (
|
returns (bytes[] memory callResults)
|
||||||
OrdersAndSample[] memory ordersAndSamples
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
ordersAndSamples = new OrdersAndSample[](orders.length);
|
callResults = new bytes[](callDatas.length);
|
||||||
for (uint256 i = 0; i != orders.length; i++) {
|
for (uint256 i = 0; i != callDatas.length; ++i) {
|
||||||
(
|
(bool didSucceed, bytes memory resultData) = address(this).staticcall(callDatas[i]);
|
||||||
uint256[] memory orderFillableAssetAmounts,
|
if (!didSucceed) {
|
||||||
uint256[][] memory tokenAmountsBySource
|
assembly { revert(add(resultData, 0x20), mload(resultData)) }
|
||||||
) = queryOrdersAndSampleSells(orders[i], orderSignatures[i], sources, takerTokenAmounts[i]);
|
}
|
||||||
ordersAndSamples[i].orderFillableAssetAmounts = orderFillableAssetAmounts;
|
callResults[i] = resultData;
|
||||||
ordersAndSamples[i].tokenAmountsBySource = tokenAmountsBySource;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @dev Query batches of native orders and sample buy quotes on multiple DEXes at once.
|
|
||||||
/// @param orders Batches of Native orders to query.
|
|
||||||
/// @param orderSignatures Batches of Signatures for each respective order in `orders`.
|
|
||||||
/// @param sources Address of each DEX. Passing in an unsupported DEX will throw.
|
|
||||||
/// @param makerTokenAmounts Batches of Maker token sell amount for each sample.
|
|
||||||
/// @return ordersAndSamples How much taker asset can be filled
|
|
||||||
/// by each order in `orders`. Taker amounts sold for each source at
|
|
||||||
/// each maker token amount. First indexed by source index, then sample
|
|
||||||
/// index.
|
|
||||||
function queryBatchOrdersAndSampleBuys(
|
|
||||||
LibOrder.Order[][] memory orders,
|
|
||||||
bytes[][] memory orderSignatures,
|
|
||||||
address[] memory sources,
|
|
||||||
uint256[][] memory makerTokenAmounts
|
|
||||||
)
|
|
||||||
public
|
|
||||||
view
|
|
||||||
returns (
|
|
||||||
OrdersAndSample[] memory ordersAndSamples
|
|
||||||
)
|
|
||||||
{
|
|
||||||
ordersAndSamples = new OrdersAndSample[](orders.length);
|
|
||||||
for (uint256 i = 0; i != orders.length; i++) {
|
|
||||||
(
|
|
||||||
uint256[] memory orderFillableAssetAmounts,
|
|
||||||
uint256[][] memory tokenAmountsBySource
|
|
||||||
) = queryOrdersAndSampleBuys(orders[i], orderSignatures[i], sources, makerTokenAmounts[i]);
|
|
||||||
ordersAndSamples[i].orderFillableAssetAmounts = orderFillableAssetAmounts;
|
|
||||||
ordersAndSamples[i].tokenAmountsBySource = tokenAmountsBySource;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @dev Query native orders and sample sell quotes on multiple DEXes at once.
|
|
||||||
/// @param orders Native orders to query.
|
|
||||||
/// @param orderSignatures Signatures for each respective order in `orders`.
|
|
||||||
/// @param sources Address of each DEX. Passing in an unsupported DEX will throw.
|
|
||||||
/// @param takerTokenAmounts Taker token sell amount for each sample.
|
|
||||||
/// @return orderFillableTakerAssetAmounts How much taker asset can be filled
|
|
||||||
/// by each order in `orders`.
|
|
||||||
/// @return makerTokenAmountsBySource Maker amounts bought for each source at
|
|
||||||
/// each taker token amount. First indexed by source index, then sample
|
|
||||||
/// index.
|
|
||||||
function queryOrdersAndSampleSells(
|
|
||||||
LibOrder.Order[] memory orders,
|
|
||||||
bytes[] memory orderSignatures,
|
|
||||||
address[] memory sources,
|
|
||||||
uint256[] memory takerTokenAmounts
|
|
||||||
)
|
|
||||||
public
|
|
||||||
view
|
|
||||||
returns (
|
|
||||||
uint256[] memory orderFillableTakerAssetAmounts,
|
|
||||||
uint256[][] memory makerTokenAmountsBySource
|
|
||||||
)
|
|
||||||
{
|
|
||||||
require(orders.length != 0, "ERC20BridgeSampler/EMPTY_ORDERS");
|
|
||||||
orderFillableTakerAssetAmounts = getOrderFillableTakerAssetAmounts(
|
|
||||||
orders,
|
|
||||||
orderSignatures
|
|
||||||
);
|
|
||||||
makerTokenAmountsBySource = sampleSells(
|
|
||||||
sources,
|
|
||||||
_assetDataToTokenAddress(orders[0].takerAssetData),
|
|
||||||
_assetDataToTokenAddress(orders[0].makerAssetData),
|
|
||||||
takerTokenAmounts
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @dev Query native orders and sample buy quotes on multiple DEXes at once.
|
|
||||||
/// @param orders Native orders to query.
|
|
||||||
/// @param orderSignatures Signatures for each respective order in `orders`.
|
|
||||||
/// @param sources Address of each DEX. Passing in an unsupported DEX will throw.
|
|
||||||
/// @param makerTokenAmounts Maker token buy amount for each sample.
|
|
||||||
/// @return orderFillableMakerAssetAmounts How much maker asset can be filled
|
|
||||||
/// by each order in `orders`.
|
|
||||||
/// @return takerTokenAmountsBySource Taker amounts sold for each source at
|
|
||||||
/// each maker token amount. First indexed by source index, then sample
|
|
||||||
/// index.
|
|
||||||
function queryOrdersAndSampleBuys(
|
|
||||||
LibOrder.Order[] memory orders,
|
|
||||||
bytes[] memory orderSignatures,
|
|
||||||
address[] memory sources,
|
|
||||||
uint256[] memory makerTokenAmounts
|
|
||||||
)
|
|
||||||
public
|
|
||||||
view
|
|
||||||
returns (
|
|
||||||
uint256[] memory orderFillableMakerAssetAmounts,
|
|
||||||
uint256[][] memory makerTokenAmountsBySource
|
|
||||||
)
|
|
||||||
{
|
|
||||||
require(orders.length != 0, "ERC20BridgeSampler/EMPTY_ORDERS");
|
|
||||||
orderFillableMakerAssetAmounts = getOrderFillableMakerAssetAmounts(
|
|
||||||
orders,
|
|
||||||
orderSignatures
|
|
||||||
);
|
|
||||||
makerTokenAmountsBySource = sampleBuys(
|
|
||||||
sources,
|
|
||||||
_assetDataToTokenAddress(orders[0].takerAssetData),
|
|
||||||
_assetDataToTokenAddress(orders[0].makerAssetData),
|
|
||||||
makerTokenAmounts
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @dev Queries the fillable taker asset amounts of native orders.
|
/// @dev Queries the fillable taker asset amounts of native orders.
|
||||||
/// Effectively ignores orders that have empty signatures or
|
/// Effectively ignores orders that have empty signatures or
|
||||||
/// maker/taker asset amounts (returning 0).
|
/// maker/taker asset amounts (returning 0).
|
||||||
/// @param orders Native orders to query.
|
/// @param orders Native orders to query.
|
||||||
/// @param orderSignatures Signatures for each respective order in `orders`.
|
/// @param orderSignatures Signatures for each respective order in `orders`.
|
||||||
/// @return orderFillableTakerAssetAmounts How much taker asset can be filled
|
/// @return orderFillableTakerAssetAmounts How much taker asset can be filled
|
||||||
@@ -270,66 +155,6 @@ contract ERC20BridgeSampler is
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @dev Sample sell quotes on multiple DEXes at once.
|
|
||||||
/// @param sources Address of each DEX. Passing in an unsupported DEX will throw.
|
|
||||||
/// @param takerToken Address of the taker token (what to sell).
|
|
||||||
/// @param makerToken Address of the maker token (what to buy).
|
|
||||||
/// @param takerTokenAmounts Taker token sell amount for each sample.
|
|
||||||
/// @return makerTokenAmountsBySource Maker amounts bought for each source at
|
|
||||||
/// each taker token amount. First indexed by source index, then sample
|
|
||||||
/// index.
|
|
||||||
function sampleSells(
|
|
||||||
address[] memory sources,
|
|
||||||
address takerToken,
|
|
||||||
address makerToken,
|
|
||||||
uint256[] memory takerTokenAmounts
|
|
||||||
)
|
|
||||||
public
|
|
||||||
view
|
|
||||||
returns (uint256[][] memory makerTokenAmountsBySource)
|
|
||||||
{
|
|
||||||
uint256 numSources = sources.length;
|
|
||||||
makerTokenAmountsBySource = new uint256[][](numSources);
|
|
||||||
for (uint256 i = 0; i < numSources; i++) {
|
|
||||||
makerTokenAmountsBySource[i] = _sampleSellSource(
|
|
||||||
sources[i],
|
|
||||||
takerToken,
|
|
||||||
makerToken,
|
|
||||||
takerTokenAmounts
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @dev Query native orders and sample buy quotes on multiple DEXes at once.
|
|
||||||
/// @param sources Address of each DEX. Passing in an unsupported DEX will throw.
|
|
||||||
/// @param takerToken Address of the taker token (what to sell).
|
|
||||||
/// @param makerToken Address of the maker token (what to buy).
|
|
||||||
/// @param makerTokenAmounts Maker token buy amount for each sample.
|
|
||||||
/// @return takerTokenAmountsBySource Taker amounts sold for each source at
|
|
||||||
/// each maker token amount. First indexed by source index, then sample
|
|
||||||
/// index.
|
|
||||||
function sampleBuys(
|
|
||||||
address[] memory sources,
|
|
||||||
address takerToken,
|
|
||||||
address makerToken,
|
|
||||||
uint256[] memory makerTokenAmounts
|
|
||||||
)
|
|
||||||
public
|
|
||||||
view
|
|
||||||
returns (uint256[][] memory takerTokenAmountsBySource)
|
|
||||||
{
|
|
||||||
uint256 numSources = sources.length;
|
|
||||||
takerTokenAmountsBySource = new uint256[][](numSources);
|
|
||||||
for (uint256 i = 0; i < numSources; i++) {
|
|
||||||
takerTokenAmountsBySource[i] = _sampleBuySource(
|
|
||||||
sources[i],
|
|
||||||
takerToken,
|
|
||||||
makerToken,
|
|
||||||
makerTokenAmounts
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @dev Sample sell quotes from Kyber.
|
/// @dev Sample sell quotes from Kyber.
|
||||||
/// @param takerToken Address of the taker token (what to sell).
|
/// @param takerToken Address of the taker token (what to sell).
|
||||||
/// @param makerToken Address of the maker token (what to buy).
|
/// @param makerToken Address of the maker token (what to buy).
|
||||||
@@ -354,7 +179,7 @@ contract ERC20BridgeSampler is
|
|||||||
makerTokenAmounts = new uint256[](numSamples);
|
makerTokenAmounts = new uint256[](numSamples);
|
||||||
for (uint256 i = 0; i < numSamples; i++) {
|
for (uint256 i = 0; i < numSamples; i++) {
|
||||||
(bool didSucceed, bytes memory resultData) =
|
(bool didSucceed, bytes memory resultData) =
|
||||||
_getKyberNetworkProxyAddress().staticcall.gas(KYBER_SAMPLE_CALL_GAS)(
|
_getKyberNetworkProxyAddress().staticcall.gas(KYBER_CALL_GAS)(
|
||||||
abi.encodeWithSelector(
|
abi.encodeWithSelector(
|
||||||
IKyberNetwork(0).getExpectedRate.selector,
|
IKyberNetwork(0).getExpectedRate.selector,
|
||||||
_takerToken,
|
_takerToken,
|
||||||
@@ -396,7 +221,7 @@ contract ERC20BridgeSampler is
|
|||||||
makerTokenAmounts = new uint256[](numSamples);
|
makerTokenAmounts = new uint256[](numSamples);
|
||||||
for (uint256 i = 0; i < numSamples; i++) {
|
for (uint256 i = 0; i < numSamples; i++) {
|
||||||
(bool didSucceed, bytes memory resultData) =
|
(bool didSucceed, bytes memory resultData) =
|
||||||
_getEth2DaiAddress().staticcall.gas(ETH2DAI_SAMPLE_CALL_GAS)(
|
_getEth2DaiAddress().staticcall.gas(ETH2DAI_CALL_GAS)(
|
||||||
abi.encodeWithSelector(
|
abi.encodeWithSelector(
|
||||||
IEth2Dai(0).getBuyAmount.selector,
|
IEth2Dai(0).getBuyAmount.selector,
|
||||||
makerToken,
|
makerToken,
|
||||||
@@ -433,7 +258,7 @@ contract ERC20BridgeSampler is
|
|||||||
takerTokenAmounts = new uint256[](numSamples);
|
takerTokenAmounts = new uint256[](numSamples);
|
||||||
for (uint256 i = 0; i < numSamples; i++) {
|
for (uint256 i = 0; i < numSamples; i++) {
|
||||||
(bool didSucceed, bytes memory resultData) =
|
(bool didSucceed, bytes memory resultData) =
|
||||||
_getEth2DaiAddress().staticcall.gas(ETH2DAI_SAMPLE_CALL_GAS)(
|
_getEth2DaiAddress().staticcall.gas(ETH2DAI_CALL_GAS)(
|
||||||
abi.encodeWithSelector(
|
abi.encodeWithSelector(
|
||||||
IEth2Dai(0).getPayAmount.selector,
|
IEth2Dai(0).getPayAmount.selector,
|
||||||
takerToken,
|
takerToken,
|
||||||
@@ -568,6 +393,44 @@ contract ERC20BridgeSampler is
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @dev Sample sell quotes from Curve.
|
||||||
|
/// @param curveAddress Address of the Curve contract.
|
||||||
|
/// @param fromTokenIdx Index of the taker token (what to sell).
|
||||||
|
/// @param toTokenIdx Index of the maker token (what to buy).
|
||||||
|
/// @param takerTokenAmounts Taker token sell amount for each sample.
|
||||||
|
/// @return makerTokenAmounts Maker amounts bought at each taker token
|
||||||
|
/// amount.
|
||||||
|
function sampleSellsFromCurve(
|
||||||
|
address curveAddress,
|
||||||
|
int128 fromTokenIdx,
|
||||||
|
int128 toTokenIdx,
|
||||||
|
uint256[] memory takerTokenAmounts
|
||||||
|
)
|
||||||
|
public
|
||||||
|
view
|
||||||
|
returns (uint256[] memory makerTokenAmounts)
|
||||||
|
{
|
||||||
|
uint256 numSamples = takerTokenAmounts.length;
|
||||||
|
makerTokenAmounts = new uint256[](numSamples);
|
||||||
|
for (uint256 i = 0; i < numSamples; i++) {
|
||||||
|
(bool didSucceed, bytes memory resultData) =
|
||||||
|
curveAddress.staticcall.gas(CURVE_CALL_GAS)(
|
||||||
|
abi.encodeWithSelector(
|
||||||
|
ICurve(0).get_dy_underlying.selector,
|
||||||
|
fromTokenIdx,
|
||||||
|
toTokenIdx,
|
||||||
|
takerTokenAmounts[i]
|
||||||
|
));
|
||||||
|
uint256 buyAmount = 0;
|
||||||
|
if (didSucceed) {
|
||||||
|
buyAmount = abi.decode(resultData, (uint256));
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
makerTokenAmounts[i] = buyAmount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// @dev Overridable way to get token decimals.
|
/// @dev Overridable way to get token decimals.
|
||||||
/// @param tokenAddress Address of the token.
|
/// @param tokenAddress Address of the token.
|
||||||
/// @return decimals The decimal places for the token.
|
/// @return decimals The decimal places for the token.
|
||||||
@@ -599,7 +462,7 @@ contract ERC20BridgeSampler is
|
|||||||
}
|
}
|
||||||
bytes memory resultData;
|
bytes memory resultData;
|
||||||
(didSucceed, resultData) =
|
(didSucceed, resultData) =
|
||||||
uniswapExchangeAddress.staticcall.gas(UNISWAP_SAMPLE_CALL_GAS)(
|
uniswapExchangeAddress.staticcall.gas(UNISWAP_CALL_GAS)(
|
||||||
abi.encodeWithSelector(
|
abi.encodeWithSelector(
|
||||||
functionSelector,
|
functionSelector,
|
||||||
inputAmount
|
inputAmount
|
||||||
@@ -609,59 +472,6 @@ contract ERC20BridgeSampler is
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @dev Samples a supported sell source, defined by its address.
|
|
||||||
/// @param takerToken Address of the taker token (what to sell).
|
|
||||||
/// @param makerToken Address of the maker token (what to buy).
|
|
||||||
/// @param takerTokenAmounts Taker token sell amount for each sample.
|
|
||||||
/// @return makerTokenAmounts Maker amounts bought at each taker token
|
|
||||||
/// amount.
|
|
||||||
function _sampleSellSource(
|
|
||||||
address source,
|
|
||||||
address takerToken,
|
|
||||||
address makerToken,
|
|
||||||
uint256[] memory takerTokenAmounts
|
|
||||||
)
|
|
||||||
private
|
|
||||||
view
|
|
||||||
returns (uint256[] memory makerTokenAmounts)
|
|
||||||
{
|
|
||||||
if (source == ETH2DAI_SOURCE) {
|
|
||||||
return sampleSellsFromEth2Dai(takerToken, makerToken, takerTokenAmounts);
|
|
||||||
}
|
|
||||||
if (source == UNISWAP_SOURCE) {
|
|
||||||
return sampleSellsFromUniswap(takerToken, makerToken, takerTokenAmounts);
|
|
||||||
}
|
|
||||||
if (source == KYBER_SOURCE) {
|
|
||||||
return sampleSellsFromKyberNetwork(takerToken, makerToken, takerTokenAmounts);
|
|
||||||
}
|
|
||||||
revert("ERC20BridgeSampler/UNSUPPORTED_SOURCE");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @dev Samples a supported buy source, defined by its address.
|
|
||||||
/// @param takerToken Address of the taker token (what to sell).
|
|
||||||
/// @param makerToken Address of the maker token (what to buy).
|
|
||||||
/// @param makerTokenAmounts Maker token sell amount for each sample.
|
|
||||||
/// @return takerTokenAmounts Taker amounts sold at each maker token
|
|
||||||
/// amount.
|
|
||||||
function _sampleBuySource(
|
|
||||||
address source,
|
|
||||||
address takerToken,
|
|
||||||
address makerToken,
|
|
||||||
uint256[] memory makerTokenAmounts
|
|
||||||
)
|
|
||||||
private
|
|
||||||
view
|
|
||||||
returns (uint256[] memory takerTokenAmounts)
|
|
||||||
{
|
|
||||||
if (source == ETH2DAI_SOURCE) {
|
|
||||||
return sampleBuysFromEth2Dai(takerToken, makerToken, makerTokenAmounts);
|
|
||||||
}
|
|
||||||
if (source == UNISWAP_SOURCE) {
|
|
||||||
return sampleBuysFromUniswap(takerToken, makerToken, makerTokenAmounts);
|
|
||||||
}
|
|
||||||
revert("ERC20BridgeSampler/UNSUPPORTED_SOURCE");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @dev Retrive an existing Uniswap exchange contract.
|
/// @dev Retrive an existing Uniswap exchange contract.
|
||||||
/// Throws if the exchange does not exist.
|
/// Throws if the exchange does not exist.
|
||||||
/// @param tokenAddress Address of the token contract.
|
/// @param tokenAddress Address of the token contract.
|
||||||
@@ -677,23 +487,9 @@ contract ERC20BridgeSampler is
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @dev Extract the token address from ERC20 proxy asset data.
|
/// @dev Assert that the tokens in a trade pair are valid.
|
||||||
/// @param assetData ERC20 asset data.
|
/// @param makerToken Address of the maker token.
|
||||||
/// @return tokenAddress The decoded token address.
|
/// @param takerToken Address of the taker token.
|
||||||
function _assetDataToTokenAddress(bytes memory assetData)
|
|
||||||
private
|
|
||||||
pure
|
|
||||||
returns (address tokenAddress)
|
|
||||||
{
|
|
||||||
require(assetData.length == 36, "ERC20BridgeSampler/INVALID_ASSET_DATA");
|
|
||||||
bytes4 selector;
|
|
||||||
assembly {
|
|
||||||
selector := and(mload(add(assetData, 0x20)), 0xFFFFFFFF00000000000000000000000000000000000000000000000000000000)
|
|
||||||
tokenAddress := mload(add(assetData, 0x24))
|
|
||||||
}
|
|
||||||
require(selector == ERC20_PROXY_ID, "ERC20BridgeSampler/UNSUPPORTED_ASSET_PROXY");
|
|
||||||
}
|
|
||||||
|
|
||||||
function _assertValidPair(address makerToken, address takerToken)
|
function _assertValidPair(address makerToken, address takerToken)
|
||||||
private
|
private
|
||||||
pure
|
pure
|
||||||
|
87
contracts/erc20-bridge-sampler/contracts/src/ICurve.sol
Normal file
87
contracts/erc20-bridge-sampler/contracts/src/ICurve.sol
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright 2019 ZeroEx Intl.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
pragma solidity ^0.5.9;
|
||||||
|
|
||||||
|
|
||||||
|
// solhint-disable func-name-mixedcase
|
||||||
|
interface ICurve {
|
||||||
|
|
||||||
|
/// @dev Sell `sellAmount` of `fromToken` token and receive `toToken` token.
|
||||||
|
/// This function exists on early versions of Curve (USDC/DAI)
|
||||||
|
/// @param i The token index being sold.
|
||||||
|
/// @param j The token index being bought.
|
||||||
|
/// @param sellAmount The amount of token being bought.
|
||||||
|
/// @param minBuyAmount The minimum buy amount of the token being bought.
|
||||||
|
/// @param deadline The time in seconds when this operation should expire.
|
||||||
|
function exchange_underlying(
|
||||||
|
int128 i,
|
||||||
|
int128 j,
|
||||||
|
uint256 sellAmount,
|
||||||
|
uint256 minBuyAmount,
|
||||||
|
uint256 deadline
|
||||||
|
)
|
||||||
|
external;
|
||||||
|
|
||||||
|
/// @dev Sell `sellAmount` of `fromToken` token and receive `toToken` token.
|
||||||
|
/// This function exists on later versions of Curve (USDC/DAI/USDT)
|
||||||
|
/// @param i The token index being sold.
|
||||||
|
/// @param j The token index being bought.
|
||||||
|
/// @param sellAmount The amount of token being bought.
|
||||||
|
/// @param minBuyAmount The minimum buy amount of the token being bought.
|
||||||
|
function exchange_underlying(
|
||||||
|
int128 i,
|
||||||
|
int128 j,
|
||||||
|
uint256 sellAmount,
|
||||||
|
uint256 minBuyAmount
|
||||||
|
)
|
||||||
|
external;
|
||||||
|
|
||||||
|
/// @dev Get the amount of `toToken` by selling `sellAmount` of `fromToken`
|
||||||
|
/// @param i The token index being sold.
|
||||||
|
/// @param j The token index being bought.
|
||||||
|
/// @param sellAmount The amount of token being bought.
|
||||||
|
function get_dy_underlying(
|
||||||
|
int128 i,
|
||||||
|
int128 j,
|
||||||
|
uint256 sellAmount
|
||||||
|
)
|
||||||
|
external
|
||||||
|
returns (uint256 dy);
|
||||||
|
|
||||||
|
/// @dev Get the amount of `fromToken` by buying `buyAmount` of `toToken`
|
||||||
|
/// This function exists on later versions of Curve (USDC/DAI/USDT)
|
||||||
|
/// @param i The token index being sold.
|
||||||
|
/// @param j The token index being bought.
|
||||||
|
/// @param buyAmount The amount of token being bought.
|
||||||
|
function get_dx_underlying(
|
||||||
|
int128 i,
|
||||||
|
int128 j,
|
||||||
|
uint256 buyAmount
|
||||||
|
)
|
||||||
|
external
|
||||||
|
returns (uint256 dx);
|
||||||
|
|
||||||
|
/// @dev Get the underlying token address from the token index
|
||||||
|
/// @param i The token index.
|
||||||
|
function underlying_coins(
|
||||||
|
int128 i
|
||||||
|
)
|
||||||
|
external
|
||||||
|
returns (address tokenAddress);
|
||||||
|
}
|
@@ -23,98 +23,14 @@ import "@0x/contracts-exchange-libs/contracts/src/LibOrder.sol";
|
|||||||
|
|
||||||
|
|
||||||
interface IERC20BridgeSampler {
|
interface IERC20BridgeSampler {
|
||||||
struct OrdersAndSample {
|
|
||||||
uint256[] orderFillableAssetAmounts;
|
|
||||||
uint256[][] tokenAmountsBySource;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @dev Query batches of native orders and sample sell quotes on multiple DEXes at once.
|
/// @dev Call multiple public functions on this contract in a single transaction.
|
||||||
/// @param orders Batches of Native orders to query.
|
/// @param callDatas ABI-encoded call data for each function call.
|
||||||
/// @param orderSignatures Batches of Signatures for each respective order in `orders`.
|
/// @return callResults ABI-encoded results data for each call.
|
||||||
/// @param sources Address of each DEX. Passing in an unsupported DEX will throw.
|
function batchCall(bytes[] calldata callDatas)
|
||||||
/// @param takerTokenAmounts Batches of Taker token sell amount for each sample.
|
|
||||||
/// @return ordersAndSamples How much taker asset can be filled
|
|
||||||
/// by each order in `orders`. Maker amounts bought for each source at
|
|
||||||
/// each taker token amount. First indexed by source index, then sample
|
|
||||||
/// index.
|
|
||||||
function queryBatchOrdersAndSampleSells(
|
|
||||||
LibOrder.Order[][] calldata orders,
|
|
||||||
bytes[][] calldata orderSignatures,
|
|
||||||
address[] calldata sources,
|
|
||||||
uint256[][] calldata takerTokenAmounts
|
|
||||||
)
|
|
||||||
external
|
external
|
||||||
view
|
view
|
||||||
returns (
|
returns (bytes[] memory callResults);
|
||||||
OrdersAndSample[] memory ordersAndSamples
|
|
||||||
);
|
|
||||||
|
|
||||||
/// @dev Query batches of native orders and sample buy quotes on multiple DEXes at once.
|
|
||||||
/// @param orders Batches of Native orders to query.
|
|
||||||
/// @param orderSignatures Batches of Signatures for each respective order in `orders`.
|
|
||||||
/// @param sources Address of each DEX. Passing in an unsupported DEX will throw.
|
|
||||||
/// @param makerTokenAmounts Batches of Maker token sell amount for each sample.
|
|
||||||
/// @return ordersAndSamples How much taker asset can be filled
|
|
||||||
/// by each order in `orders`. Taker amounts sold for each source at
|
|
||||||
/// each maker token amount. First indexed by source index, then sample
|
|
||||||
/// index
|
|
||||||
function queryBatchOrdersAndSampleBuys(
|
|
||||||
LibOrder.Order[][] calldata orders,
|
|
||||||
bytes[][] calldata orderSignatures,
|
|
||||||
address[] calldata sources,
|
|
||||||
uint256[][] calldata makerTokenAmounts
|
|
||||||
)
|
|
||||||
external
|
|
||||||
view
|
|
||||||
returns (
|
|
||||||
OrdersAndSample[] memory ordersAndSamples
|
|
||||||
);
|
|
||||||
|
|
||||||
/// @dev Query native orders and sample sell quotes on multiple DEXes at once.
|
|
||||||
/// @param orders Native orders to query.
|
|
||||||
/// @param orderSignatures Signatures for each respective order in `orders`.
|
|
||||||
/// @param sources Address of each DEX. Passing in an unsupported DEX will throw.
|
|
||||||
/// @param takerTokenAmounts Taker token sell amount for each sample.
|
|
||||||
/// @return orderFillableTakerAssetAmounts How much taker asset can be filled
|
|
||||||
/// by each order in `orders`.
|
|
||||||
/// @return makerTokenAmountsBySource Maker amounts bought for each source at
|
|
||||||
/// each taker token amount. First indexed by source index, then sample
|
|
||||||
/// index.
|
|
||||||
function queryOrdersAndSampleSells(
|
|
||||||
LibOrder.Order[] calldata orders,
|
|
||||||
bytes[] calldata orderSignatures,
|
|
||||||
address[] calldata sources,
|
|
||||||
uint256[] calldata takerTokenAmounts
|
|
||||||
)
|
|
||||||
external
|
|
||||||
view
|
|
||||||
returns (
|
|
||||||
uint256[] memory orderFillableTakerAssetAmounts,
|
|
||||||
uint256[][] memory makerTokenAmountsBySource
|
|
||||||
);
|
|
||||||
|
|
||||||
/// @dev Query native orders and sample buy quotes on multiple DEXes at once.
|
|
||||||
/// @param orders Native orders to query.
|
|
||||||
/// @param orderSignatures Signatures for each respective order in `orders`.
|
|
||||||
/// @param sources Address of each DEX. Passing in an unsupported DEX will throw.
|
|
||||||
/// @param makerTokenAmounts Maker token buy amount for each sample.
|
|
||||||
/// @return orderFillableMakerAssetAmounts How much maker asset can be filled
|
|
||||||
/// by each order in `orders`.
|
|
||||||
/// @return takerTokenAmountsBySource Taker amounts sold for each source at
|
|
||||||
/// each maker token amount. First indexed by source index, then sample
|
|
||||||
/// index.
|
|
||||||
function queryOrdersAndSampleBuys(
|
|
||||||
LibOrder.Order[] calldata orders,
|
|
||||||
bytes[] calldata orderSignatures,
|
|
||||||
address[] calldata sources,
|
|
||||||
uint256[] calldata makerTokenAmounts
|
|
||||||
)
|
|
||||||
external
|
|
||||||
view
|
|
||||||
returns (
|
|
||||||
uint256[] memory orderFillableMakerAssetAmounts,
|
|
||||||
uint256[][] memory makerTokenAmountsBySource
|
|
||||||
);
|
|
||||||
|
|
||||||
/// @dev Queries the fillable taker asset amounts of native orders.
|
/// @dev Queries the fillable taker asset amounts of native orders.
|
||||||
/// @param orders Native orders to query.
|
/// @param orders Native orders to query.
|
||||||
@@ -142,39 +58,95 @@ interface IERC20BridgeSampler {
|
|||||||
view
|
view
|
||||||
returns (uint256[] memory orderFillableMakerAssetAmounts);
|
returns (uint256[] memory orderFillableMakerAssetAmounts);
|
||||||
|
|
||||||
/// @dev Sample sell quotes on multiple DEXes at once.
|
/// @dev Sample sell quotes from Kyber.
|
||||||
/// @param sources Address of each DEX. Passing in an unsupported DEX will throw.
|
|
||||||
/// @param takerToken Address of the taker token (what to sell).
|
/// @param takerToken Address of the taker token (what to sell).
|
||||||
/// @param makerToken Address of the maker token (what to buy).
|
/// @param makerToken Address of the maker token (what to buy).
|
||||||
/// @param takerTokenAmounts Taker token sell amount for each sample.
|
/// @param takerTokenAmounts Taker token sell amount for each sample.
|
||||||
/// @return makerTokenAmountsBySource Maker amounts bought for each source at
|
/// @return makerTokenAmounts Maker amounts bought at each taker token
|
||||||
/// each taker token amount. First indexed by source index, then sample
|
/// amount.
|
||||||
/// index.
|
function sampleSellsFromKyberNetwork(
|
||||||
function sampleSells(
|
|
||||||
address[] calldata sources,
|
|
||||||
address takerToken,
|
address takerToken,
|
||||||
address makerToken,
|
address makerToken,
|
||||||
uint256[] calldata takerTokenAmounts
|
uint256[] calldata takerTokenAmounts
|
||||||
)
|
)
|
||||||
external
|
external
|
||||||
view
|
view
|
||||||
returns (uint256[][] memory makerTokenAmountsBySource);
|
returns (uint256[] memory makerTokenAmounts);
|
||||||
|
|
||||||
/// @dev Query native orders and sample buy quotes on multiple DEXes at once.
|
/// @dev Sample sell quotes from Eth2Dai/Oasis.
|
||||||
/// @param sources Address of each DEX. Passing in an unsupported DEX will throw.
|
|
||||||
/// @param takerToken Address of the taker token (what to sell).
|
/// @param takerToken Address of the taker token (what to sell).
|
||||||
/// @param makerToken Address of the maker token (what to buy).
|
/// @param makerToken Address of the maker token (what to buy).
|
||||||
/// @param makerTokenAmounts Maker token buy amount for each sample.
|
/// @param takerTokenAmounts Taker token sell amount for each sample.
|
||||||
/// @return takerTokenAmountsBySource Taker amounts sold for each source at
|
/// @return makerTokenAmounts Maker amounts bought at each taker token
|
||||||
/// each maker token amount. First indexed by source index, then sample
|
/// amount.
|
||||||
/// index.
|
function sampleSellsFromEth2Dai(
|
||||||
function sampleBuys(
|
address takerToken,
|
||||||
address[] calldata sources,
|
address makerToken,
|
||||||
|
uint256[] calldata takerTokenAmounts
|
||||||
|
)
|
||||||
|
external
|
||||||
|
view
|
||||||
|
returns (uint256[] memory makerTokenAmounts);
|
||||||
|
|
||||||
|
/// @dev Sample sell quotes from Uniswap.
|
||||||
|
/// @param takerToken Address of the taker token (what to sell).
|
||||||
|
/// @param makerToken Address of the maker token (what to buy).
|
||||||
|
/// @param takerTokenAmounts Taker token sell amount for each sample.
|
||||||
|
/// @return makerTokenAmounts Maker amounts bought at each taker token
|
||||||
|
/// amount.
|
||||||
|
function sampleSellsFromUniswap(
|
||||||
|
address takerToken,
|
||||||
|
address makerToken,
|
||||||
|
uint256[] calldata takerTokenAmounts
|
||||||
|
)
|
||||||
|
external
|
||||||
|
view
|
||||||
|
returns (uint256[] memory makerTokenAmounts);
|
||||||
|
|
||||||
|
/// @dev Sample buy quotes from Uniswap.
|
||||||
|
/// @param takerToken Address of the taker token (what to sell).
|
||||||
|
/// @param makerToken Address of the maker token (what to buy).
|
||||||
|
/// @param makerTokenAmounts Maker token sell amount for each sample.
|
||||||
|
/// @return takerTokenAmounts Taker amounts sold at each maker token
|
||||||
|
/// amount.
|
||||||
|
function sampleBuysFromUniswap(
|
||||||
address takerToken,
|
address takerToken,
|
||||||
address makerToken,
|
address makerToken,
|
||||||
uint256[] calldata makerTokenAmounts
|
uint256[] calldata makerTokenAmounts
|
||||||
)
|
)
|
||||||
external
|
external
|
||||||
view
|
view
|
||||||
returns (uint256[][] memory takerTokenAmountsBySource);
|
returns (uint256[] memory takerTokenAmounts);
|
||||||
|
|
||||||
|
/// @dev Sample buy quotes from Eth2Dai/Oasis.
|
||||||
|
/// @param takerToken Address of the taker token (what to sell).
|
||||||
|
/// @param makerToken Address of the maker token (what to buy).
|
||||||
|
/// @param takerTokenAmounts Maker token sell amount for each sample.
|
||||||
|
/// @return takerTokenAmounts Taker amounts sold at each maker token
|
||||||
|
/// amount.
|
||||||
|
function sampleBuysFromEth2Dai(
|
||||||
|
address takerToken,
|
||||||
|
address makerToken,
|
||||||
|
uint256[] calldata makerTokenAmounts
|
||||||
|
)
|
||||||
|
external
|
||||||
|
view
|
||||||
|
returns (uint256[] memory takerTokenAmounts);
|
||||||
|
|
||||||
|
/// @dev Sample sell quotes from Curve.
|
||||||
|
/// @param curveAddress Address of the Curve contract.
|
||||||
|
/// @param fromTokenIdx Index of the taker token (what to sell).
|
||||||
|
/// @param toTokenIdx Index of the maker token (what to buy).
|
||||||
|
/// @param takerTokenAmounts Taker token sell amount for each sample.
|
||||||
|
/// @return makerTokenAmounts Maker amounts bought at each taker token
|
||||||
|
/// amount.
|
||||||
|
function sampleSellsFromCurve(
|
||||||
|
address curveAddress,
|
||||||
|
int128 fromTokenIdx,
|
||||||
|
int128 toTokenIdx,
|
||||||
|
uint256[] calldata takerTokenAmounts
|
||||||
|
)
|
||||||
|
external
|
||||||
|
view
|
||||||
|
returns (uint256[] memory makerTokenAmounts);
|
||||||
}
|
}
|
||||||
|
@@ -327,7 +327,6 @@ contract TestERC20BridgeSampler is
|
|||||||
bytes memory
|
bytes memory
|
||||||
)
|
)
|
||||||
public
|
public
|
||||||
view
|
|
||||||
returns (
|
returns (
|
||||||
LibOrder.OrderInfo memory orderInfo,
|
LibOrder.OrderInfo memory orderInfo,
|
||||||
uint256 fillableTakerAssetAmount,
|
uint256 fillableTakerAssetAmount,
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@0x/contracts-erc20-bridge-sampler",
|
"name": "@0x/contracts-erc20-bridge-sampler",
|
||||||
"version": "1.3.0",
|
"version": "1.4.0",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.12"
|
"node": ">=6.12"
|
||||||
},
|
},
|
||||||
@@ -38,7 +38,7 @@
|
|||||||
"config": {
|
"config": {
|
||||||
"publicInterfaceContracts": "ERC20BridgeSampler,IERC20BridgeSampler",
|
"publicInterfaceContracts": "ERC20BridgeSampler,IERC20BridgeSampler",
|
||||||
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually.",
|
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually.",
|
||||||
"abis": "./test/generated-artifacts/@(ERC20BridgeSampler|IDevUtils|IERC20BridgeSampler|IEth2Dai|IKyberNetwork|IUniswapExchangeQuotes|TestERC20BridgeSampler).json"
|
"abis": "./test/generated-artifacts/@(ERC20BridgeSampler|ICurve|IDevUtils|IERC20BridgeSampler|IEth2Dai|IKyberNetwork|IUniswapExchangeQuotes|TestERC20BridgeSampler).json"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
@@ -51,13 +51,13 @@
|
|||||||
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/protocol/README.md",
|
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/protocol/README.md",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@0x/abi-gen": "^5.2.0",
|
"@0x/abi-gen": "^5.2.0",
|
||||||
"@0x/contracts-asset-proxy": "^3.2.0",
|
"@0x/contracts-asset-proxy": "^3.2.1",
|
||||||
"@0x/contracts-erc20": "^3.1.0",
|
"@0x/contracts-erc20": "^3.1.1",
|
||||||
"@0x/contracts-exchange": "^3.2.0",
|
"@0x/contracts-exchange": "^3.2.1",
|
||||||
"@0x/contracts-exchange-libs": "^4.3.0",
|
"@0x/contracts-exchange-libs": "^4.3.1",
|
||||||
"@0x/contracts-gen": "^2.0.7",
|
"@0x/contracts-gen": "^2.0.7",
|
||||||
"@0x/contracts-test-utils": "^5.1.4",
|
"@0x/contracts-test-utils": "^5.1.5",
|
||||||
"@0x/contracts-utils": "^4.3.0",
|
"@0x/contracts-utils": "^4.3.1",
|
||||||
"@0x/dev-utils": "^3.2.0",
|
"@0x/dev-utils": "^3.2.0",
|
||||||
"@0x/sol-compiler": "^4.0.7",
|
"@0x/sol-compiler": "^4.0.7",
|
||||||
"@0x/tslint-config": "^4.0.0",
|
"@0x/tslint-config": "^4.0.0",
|
||||||
|
@@ -6,6 +6,7 @@
|
|||||||
import { ContractArtifact } from 'ethereum-types';
|
import { ContractArtifact } from 'ethereum-types';
|
||||||
|
|
||||||
import * as ERC20BridgeSampler from '../test/generated-artifacts/ERC20BridgeSampler.json';
|
import * as ERC20BridgeSampler from '../test/generated-artifacts/ERC20BridgeSampler.json';
|
||||||
|
import * as ICurve from '../test/generated-artifacts/ICurve.json';
|
||||||
import * as IDevUtils from '../test/generated-artifacts/IDevUtils.json';
|
import * as IDevUtils from '../test/generated-artifacts/IDevUtils.json';
|
||||||
import * as IERC20BridgeSampler from '../test/generated-artifacts/IERC20BridgeSampler.json';
|
import * as IERC20BridgeSampler from '../test/generated-artifacts/IERC20BridgeSampler.json';
|
||||||
import * as IEth2Dai from '../test/generated-artifacts/IEth2Dai.json';
|
import * as IEth2Dai from '../test/generated-artifacts/IEth2Dai.json';
|
||||||
@@ -14,6 +15,7 @@ import * as IUniswapExchangeQuotes from '../test/generated-artifacts/IUniswapExc
|
|||||||
import * as TestERC20BridgeSampler from '../test/generated-artifacts/TestERC20BridgeSampler.json';
|
import * as TestERC20BridgeSampler from '../test/generated-artifacts/TestERC20BridgeSampler.json';
|
||||||
export const artifacts = {
|
export const artifacts = {
|
||||||
ERC20BridgeSampler: ERC20BridgeSampler as ContractArtifact,
|
ERC20BridgeSampler: ERC20BridgeSampler as ContractArtifact,
|
||||||
|
ICurve: ICurve as ContractArtifact,
|
||||||
IDevUtils: IDevUtils as ContractArtifact,
|
IDevUtils: IDevUtils as ContractArtifact,
|
||||||
IERC20BridgeSampler: IERC20BridgeSampler as ContractArtifact,
|
IERC20BridgeSampler: IERC20BridgeSampler as ContractArtifact,
|
||||||
IEth2Dai: IEth2Dai as ContractArtifact,
|
IEth2Dai: IEth2Dai as ContractArtifact,
|
||||||
|
@@ -25,19 +25,6 @@ blockchainTests('erc20-bridge-sampler', env => {
|
|||||||
const ETH2DAI_SALT = '0xb713b61bb9bb2958a0f5d1534b21e94fc68c4c0c034b0902ed844f2f6cd1b4f7';
|
const ETH2DAI_SALT = '0xb713b61bb9bb2958a0f5d1534b21e94fc68c4c0c034b0902ed844f2f6cd1b4f7';
|
||||||
const UNISWAP_BASE_SALT = '0x1d6a6a0506b0b4a554b907a4c29d9f4674e461989d9c1921feb17b26716385ab';
|
const UNISWAP_BASE_SALT = '0x1d6a6a0506b0b4a554b907a4c29d9f4674e461989d9c1921feb17b26716385ab';
|
||||||
const ERC20_PROXY_ID = '0xf47261b0';
|
const ERC20_PROXY_ID = '0xf47261b0';
|
||||||
const INVALID_ASSET_PROXY_ASSET_DATA = hexUtils.concat('0xf47261b1', hexUtils.leftPad(randomAddress()));
|
|
||||||
const INVALID_ASSET_DATA = hexUtils.random(37);
|
|
||||||
const SELL_SOURCES = ['Eth2Dai', 'Kyber', 'Uniswap'];
|
|
||||||
const BUY_SOURCES = ['Eth2Dai', 'Uniswap'];
|
|
||||||
const SOURCE_IDS: { [source: string]: string } = {
|
|
||||||
Uniswap: '0xc0a47dfe034b400b47bdad5fecda2621de6c4d95',
|
|
||||||
Eth2Dai: '0x39755357759ce0d7f32dc8dc45414cca409ae24e',
|
|
||||||
Kyber: '0x818e6fecd516ecc3849daf6845e3ec868087b755',
|
|
||||||
};
|
|
||||||
const EMPTY_ORDERS_ERROR = 'ERC20BridgeSampler/EMPTY_ORDERS';
|
|
||||||
const UNSUPPORTED_ASSET_PROXY_ERROR = 'ERC20BridgeSampler/UNSUPPORTED_ASSET_PROXY';
|
|
||||||
const INVALID_ASSET_DATA_ERROR = 'ERC20BridgeSampler/INVALID_ASSET_DATA';
|
|
||||||
const UNSUPPORTED_SOURCE_ERROR = 'ERC20BridgeSampler/UNSUPPORTED_SOURCE';
|
|
||||||
const INVALID_TOKEN_PAIR_ERROR = 'ERC20BridgeSampler/INVALID_TOKEN_PAIR';
|
const INVALID_TOKEN_PAIR_ERROR = 'ERC20BridgeSampler/INVALID_TOKEN_PAIR';
|
||||||
const MAKER_TOKEN = randomAddress();
|
const MAKER_TOKEN = randomAddress();
|
||||||
const TAKER_TOKEN = randomAddress();
|
const TAKER_TOKEN = randomAddress();
|
||||||
@@ -190,7 +177,7 @@ blockchainTests('erc20-bridge-sampler', env => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getDeterministicFillableTakerAssetAmount(order: Order): BigNumber {
|
function getDeterministicFillableTakerAssetAmount(order: Order): BigNumber {
|
||||||
const hash = getPackedHash(hexUtils.toHex(order.salt, 32));
|
const hash = getPackedHash(hexUtils.leftPad(order.salt));
|
||||||
const orderStatus = new BigNumber(hash).mod(100).toNumber() > 90 ? 5 : 3;
|
const orderStatus = new BigNumber(hash).mod(100).toNumber() > 90 ? 5 : 3;
|
||||||
const isValidSignature = !!new BigNumber(hash).mod(2).toNumber();
|
const isValidSignature = !!new BigNumber(hash).mod(2).toNumber();
|
||||||
if (orderStatus !== 3 || !isValidSignature) {
|
if (orderStatus !== 3 || !isValidSignature) {
|
||||||
@@ -324,329 +311,6 @@ blockchainTests('erc20-bridge-sampler', env => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('queryOrdersAndSampleSells()', () => {
|
|
||||||
const ORDERS = createOrders(MAKER_TOKEN, TAKER_TOKEN);
|
|
||||||
const SIGNATURES: string[] = _.times(ORDERS.length, i => hexUtils.random());
|
|
||||||
|
|
||||||
before(async () => {
|
|
||||||
await testContract.createTokenExchanges([MAKER_TOKEN, TAKER_TOKEN]).awaitTransactionSuccessAsync();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('returns expected fillable amounts for each order', async () => {
|
|
||||||
const takerTokenAmounts = getSampleAmounts(TAKER_TOKEN);
|
|
||||||
const expectedFillableAmounts = ORDERS.map(getDeterministicFillableTakerAssetAmount);
|
|
||||||
const [orderInfos] = await testContract
|
|
||||||
.queryOrdersAndSampleSells(ORDERS, SIGNATURES, SELL_SOURCES.map(n => SOURCE_IDS[n]), takerTokenAmounts)
|
|
||||||
.callAsync();
|
|
||||||
expect(orderInfos).to.deep.eq(expectedFillableAmounts);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('can return quotes for all sources', async () => {
|
|
||||||
const sampleAmounts = getSampleAmounts(TAKER_TOKEN);
|
|
||||||
const expectedQuotes = getDeterministicSellQuotes(TAKER_TOKEN, MAKER_TOKEN, SELL_SOURCES, sampleAmounts);
|
|
||||||
const [, quotes] = await testContract
|
|
||||||
.queryOrdersAndSampleSells(ORDERS, SIGNATURES, SELL_SOURCES.map(n => SOURCE_IDS[n]), sampleAmounts)
|
|
||||||
.callAsync();
|
|
||||||
expect(quotes).to.deep.eq(expectedQuotes);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('throws if no orders are passed in', async () => {
|
|
||||||
const tx = testContract
|
|
||||||
.queryOrdersAndSampleSells([], [], SELL_SOURCES.map(n => SOURCE_IDS[n]), getSampleAmounts(TAKER_TOKEN))
|
|
||||||
.callAsync();
|
|
||||||
return expect(tx).to.revertWith(EMPTY_ORDERS_ERROR);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('throws with an unsupported source', async () => {
|
|
||||||
const tx = testContract
|
|
||||||
.queryOrdersAndSampleSells(
|
|
||||||
ORDERS,
|
|
||||||
SIGNATURES,
|
|
||||||
[...SELL_SOURCES.map(n => SOURCE_IDS[n]), randomAddress()],
|
|
||||||
getSampleAmounts(TAKER_TOKEN),
|
|
||||||
)
|
|
||||||
.callAsync();
|
|
||||||
return expect(tx).to.revertWith(UNSUPPORTED_SOURCE_ERROR);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('throws with non-ERC20 maker asset data', async () => {
|
|
||||||
const tx = testContract
|
|
||||||
.queryOrdersAndSampleSells(
|
|
||||||
ORDERS.map(o => ({
|
|
||||||
...o,
|
|
||||||
makerAssetData: INVALID_ASSET_PROXY_ASSET_DATA,
|
|
||||||
})),
|
|
||||||
SIGNATURES,
|
|
||||||
SELL_SOURCES.map(n => SOURCE_IDS[n]),
|
|
||||||
getSampleAmounts(TAKER_TOKEN),
|
|
||||||
)
|
|
||||||
.callAsync();
|
|
||||||
return expect(tx).to.revertWith(UNSUPPORTED_ASSET_PROXY_ERROR);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('throws with non-ERC20 taker asset data', async () => {
|
|
||||||
const tx = testContract
|
|
||||||
.queryOrdersAndSampleSells(
|
|
||||||
ORDERS.map(o => ({
|
|
||||||
...o,
|
|
||||||
takerAssetData: INVALID_ASSET_PROXY_ASSET_DATA,
|
|
||||||
})),
|
|
||||||
SIGNATURES,
|
|
||||||
SELL_SOURCES.map(n => SOURCE_IDS[n]),
|
|
||||||
getSampleAmounts(TAKER_TOKEN),
|
|
||||||
)
|
|
||||||
.callAsync();
|
|
||||||
return expect(tx).to.revertWith(UNSUPPORTED_ASSET_PROXY_ERROR);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('throws with invalid maker asset data', async () => {
|
|
||||||
const tx = testContract
|
|
||||||
.queryOrdersAndSampleSells(
|
|
||||||
ORDERS.map(o => ({
|
|
||||||
...o,
|
|
||||||
makerAssetData: INVALID_ASSET_DATA,
|
|
||||||
})),
|
|
||||||
SIGNATURES,
|
|
||||||
SELL_SOURCES.map(n => SOURCE_IDS[n]),
|
|
||||||
getSampleAmounts(TAKER_TOKEN),
|
|
||||||
)
|
|
||||||
.callAsync();
|
|
||||||
return expect(tx).to.revertWith(INVALID_ASSET_DATA_ERROR);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('throws with invalid taker asset data', async () => {
|
|
||||||
const tx = testContract
|
|
||||||
.queryOrdersAndSampleSells(
|
|
||||||
ORDERS.map(o => ({
|
|
||||||
...o,
|
|
||||||
takerAssetData: INVALID_ASSET_DATA,
|
|
||||||
})),
|
|
||||||
SIGNATURES,
|
|
||||||
SELL_SOURCES.map(n => SOURCE_IDS[n]),
|
|
||||||
getSampleAmounts(TAKER_TOKEN),
|
|
||||||
)
|
|
||||||
.callAsync();
|
|
||||||
return expect(tx).to.revertWith(INVALID_ASSET_DATA_ERROR);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('queryOrdersAndSampleBuys()', () => {
|
|
||||||
const ORDERS = createOrders(MAKER_TOKEN, TAKER_TOKEN);
|
|
||||||
const SIGNATURES: string[] = _.times(ORDERS.length, i => hexUtils.random());
|
|
||||||
|
|
||||||
before(async () => {
|
|
||||||
await testContract.createTokenExchanges([MAKER_TOKEN, TAKER_TOKEN]).awaitTransactionSuccessAsync();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('returns expected fillable amounts for each order', async () => {
|
|
||||||
const takerTokenAmounts = getSampleAmounts(MAKER_TOKEN);
|
|
||||||
const expectedFillableAmounts = ORDERS.map(getDeterministicFillableMakerAssetAmount);
|
|
||||||
const [orderInfos] = await testContract
|
|
||||||
.queryOrdersAndSampleBuys(ORDERS, SIGNATURES, BUY_SOURCES.map(n => SOURCE_IDS[n]), takerTokenAmounts)
|
|
||||||
.callAsync();
|
|
||||||
expect(orderInfos).to.deep.eq(expectedFillableAmounts);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('can return quotes for all sources', async () => {
|
|
||||||
const sampleAmounts = getSampleAmounts(MAKER_TOKEN);
|
|
||||||
const expectedQuotes = getDeterministicBuyQuotes(TAKER_TOKEN, MAKER_TOKEN, BUY_SOURCES, sampleAmounts);
|
|
||||||
const [, quotes] = await testContract
|
|
||||||
.queryOrdersAndSampleBuys(ORDERS, SIGNATURES, BUY_SOURCES.map(n => SOURCE_IDS[n]), sampleAmounts)
|
|
||||||
.callAsync();
|
|
||||||
expect(quotes).to.deep.eq(expectedQuotes);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('throws if no orders are passed in', async () => {
|
|
||||||
const tx = testContract
|
|
||||||
.queryOrdersAndSampleBuys([], [], BUY_SOURCES.map(n => SOURCE_IDS[n]), getSampleAmounts(MAKER_TOKEN))
|
|
||||||
.callAsync();
|
|
||||||
return expect(tx).to.revertWith(EMPTY_ORDERS_ERROR);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('throws with an unsupported source', async () => {
|
|
||||||
const tx = testContract
|
|
||||||
.queryOrdersAndSampleBuys(
|
|
||||||
ORDERS,
|
|
||||||
SIGNATURES,
|
|
||||||
[...BUY_SOURCES.map(n => SOURCE_IDS[n]), randomAddress()],
|
|
||||||
getSampleAmounts(MAKER_TOKEN),
|
|
||||||
)
|
|
||||||
.callAsync();
|
|
||||||
return expect(tx).to.revertWith(UNSUPPORTED_SOURCE_ERROR);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('throws if kyber is passed in as a source', async () => {
|
|
||||||
const sources = [...BUY_SOURCES, 'Kyber'];
|
|
||||||
const tx = testContract
|
|
||||||
.queryOrdersAndSampleBuys(
|
|
||||||
ORDERS,
|
|
||||||
SIGNATURES,
|
|
||||||
sources.map(n => SOURCE_IDS[n]),
|
|
||||||
getSampleAmounts(MAKER_TOKEN),
|
|
||||||
)
|
|
||||||
.callAsync();
|
|
||||||
return expect(tx).to.revertWith(UNSUPPORTED_SOURCE_ERROR);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('throws with non-ERC20 maker asset data', async () => {
|
|
||||||
const tx = testContract
|
|
||||||
.queryOrdersAndSampleBuys(
|
|
||||||
ORDERS.map(o => ({
|
|
||||||
...o,
|
|
||||||
makerAssetData: INVALID_ASSET_PROXY_ASSET_DATA,
|
|
||||||
})),
|
|
||||||
SIGNATURES,
|
|
||||||
BUY_SOURCES.map(n => SOURCE_IDS[n]),
|
|
||||||
getSampleAmounts(MAKER_TOKEN),
|
|
||||||
)
|
|
||||||
.callAsync();
|
|
||||||
return expect(tx).to.revertWith(UNSUPPORTED_ASSET_PROXY_ERROR);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('throws with non-ERC20 taker asset data', async () => {
|
|
||||||
const tx = testContract
|
|
||||||
.queryOrdersAndSampleBuys(
|
|
||||||
ORDERS.map(o => ({
|
|
||||||
...o,
|
|
||||||
takerAssetData: INVALID_ASSET_PROXY_ASSET_DATA,
|
|
||||||
})),
|
|
||||||
SIGNATURES,
|
|
||||||
BUY_SOURCES.map(n => SOURCE_IDS[n]),
|
|
||||||
getSampleAmounts(MAKER_TOKEN),
|
|
||||||
)
|
|
||||||
.callAsync();
|
|
||||||
return expect(tx).to.revertWith(UNSUPPORTED_ASSET_PROXY_ERROR);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('throws with invalid maker asset data', async () => {
|
|
||||||
const tx = testContract
|
|
||||||
.queryOrdersAndSampleBuys(
|
|
||||||
ORDERS.map(o => ({
|
|
||||||
...o,
|
|
||||||
makerAssetData: INVALID_ASSET_DATA,
|
|
||||||
})),
|
|
||||||
SIGNATURES,
|
|
||||||
BUY_SOURCES.map(n => SOURCE_IDS[n]),
|
|
||||||
getSampleAmounts(MAKER_TOKEN),
|
|
||||||
)
|
|
||||||
.callAsync();
|
|
||||||
return expect(tx).to.revertWith(INVALID_ASSET_DATA_ERROR);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('throws with invalid taker asset data', async () => {
|
|
||||||
const tx = testContract
|
|
||||||
.queryOrdersAndSampleBuys(
|
|
||||||
ORDERS.map(o => ({
|
|
||||||
...o,
|
|
||||||
takerAssetData: INVALID_ASSET_DATA,
|
|
||||||
})),
|
|
||||||
SIGNATURES,
|
|
||||||
BUY_SOURCES.map(n => SOURCE_IDS[n]),
|
|
||||||
getSampleAmounts(MAKER_TOKEN),
|
|
||||||
)
|
|
||||||
.callAsync();
|
|
||||||
return expect(tx).to.revertWith(INVALID_ASSET_DATA_ERROR);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('sampleSells()', () => {
|
|
||||||
before(async () => {
|
|
||||||
await testContract.createTokenExchanges([MAKER_TOKEN, TAKER_TOKEN]).awaitTransactionSuccessAsync();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('returns empty quotes with no sample amounts', async () => {
|
|
||||||
const emptyQuotes = _.times(SELL_SOURCES.length, () => []);
|
|
||||||
const quotes = await testContract
|
|
||||||
.sampleSells(SELL_SOURCES.map(n => SOURCE_IDS[n]), TAKER_TOKEN, MAKER_TOKEN, [])
|
|
||||||
.callAsync();
|
|
||||||
expect(quotes).to.deep.eq(emptyQuotes);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('can return quotes for all sources', async () => {
|
|
||||||
const sampleAmounts = getSampleAmounts(TAKER_TOKEN);
|
|
||||||
const expectedQuotes = getDeterministicSellQuotes(TAKER_TOKEN, MAKER_TOKEN, SELL_SOURCES, sampleAmounts);
|
|
||||||
const quotes = await testContract
|
|
||||||
.sampleSells(SELL_SOURCES.map(n => SOURCE_IDS[n]), TAKER_TOKEN, MAKER_TOKEN, sampleAmounts)
|
|
||||||
.callAsync();
|
|
||||||
expect(quotes).to.deep.eq(expectedQuotes);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('can return quotes for some sources', async () => {
|
|
||||||
const sampleAmounts = getSampleAmounts(TAKER_TOKEN);
|
|
||||||
const sources = _.sampleSize(SELL_SOURCES, 1);
|
|
||||||
const expectedQuotes = getDeterministicSellQuotes(TAKER_TOKEN, MAKER_TOKEN, sources, sampleAmounts);
|
|
||||||
const quotes = await testContract
|
|
||||||
.sampleSells(sources.map(n => SOURCE_IDS[n]), TAKER_TOKEN, MAKER_TOKEN, sampleAmounts)
|
|
||||||
.callAsync();
|
|
||||||
expect(quotes).to.deep.eq(expectedQuotes);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('throws with an unsupported source', async () => {
|
|
||||||
const tx = testContract
|
|
||||||
.sampleSells(
|
|
||||||
[...SELL_SOURCES.map(n => SOURCE_IDS[n]), randomAddress()],
|
|
||||||
TAKER_TOKEN,
|
|
||||||
MAKER_TOKEN,
|
|
||||||
getSampleAmounts(TAKER_TOKEN),
|
|
||||||
)
|
|
||||||
.callAsync();
|
|
||||||
return expect(tx).to.revertWith(UNSUPPORTED_SOURCE_ERROR);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('sampleBuys()', () => {
|
|
||||||
before(async () => {
|
|
||||||
await testContract.createTokenExchanges([MAKER_TOKEN, TAKER_TOKEN]).awaitTransactionSuccessAsync();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('returns empty quotes with no sample amounts', async () => {
|
|
||||||
const emptyQuotes = _.times(BUY_SOURCES.length, () => []);
|
|
||||||
const quotes = await testContract
|
|
||||||
.sampleBuys(BUY_SOURCES.map(n => SOURCE_IDS[n]), TAKER_TOKEN, MAKER_TOKEN, [])
|
|
||||||
.callAsync();
|
|
||||||
expect(quotes).to.deep.eq(emptyQuotes);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('can return quotes for all sources', async () => {
|
|
||||||
const sampleAmounts = getSampleAmounts(MAKER_TOKEN);
|
|
||||||
const expectedQuotes = getDeterministicBuyQuotes(TAKER_TOKEN, MAKER_TOKEN, BUY_SOURCES, sampleAmounts);
|
|
||||||
const quotes = await testContract
|
|
||||||
.sampleBuys(BUY_SOURCES.map(n => SOURCE_IDS[n]), TAKER_TOKEN, MAKER_TOKEN, sampleAmounts)
|
|
||||||
.callAsync();
|
|
||||||
expect(quotes).to.deep.eq(expectedQuotes);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('can return quotes for some sources', async () => {
|
|
||||||
const sampleAmounts = getSampleAmounts(MAKER_TOKEN);
|
|
||||||
const sources = _.sampleSize(BUY_SOURCES, 1);
|
|
||||||
const expectedQuotes = getDeterministicBuyQuotes(TAKER_TOKEN, MAKER_TOKEN, sources, sampleAmounts);
|
|
||||||
const quotes = await testContract
|
|
||||||
.sampleBuys(sources.map(n => SOURCE_IDS[n]), TAKER_TOKEN, MAKER_TOKEN, sampleAmounts)
|
|
||||||
.callAsync();
|
|
||||||
expect(quotes).to.deep.eq(expectedQuotes);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('throws with an unsupported source', async () => {
|
|
||||||
const tx = testContract
|
|
||||||
.sampleBuys(
|
|
||||||
[...BUY_SOURCES.map(n => SOURCE_IDS[n]), randomAddress()],
|
|
||||||
TAKER_TOKEN,
|
|
||||||
MAKER_TOKEN,
|
|
||||||
getSampleAmounts(MAKER_TOKEN),
|
|
||||||
)
|
|
||||||
.callAsync();
|
|
||||||
return expect(tx).to.revertWith(UNSUPPORTED_SOURCE_ERROR);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('throws if kyber is passed in as a source', async () => {
|
|
||||||
const sources = [...BUY_SOURCES, 'Kyber'];
|
|
||||||
const tx = testContract
|
|
||||||
.sampleBuys(sources.map(n => SOURCE_IDS[n]), TAKER_TOKEN, MAKER_TOKEN, getSampleAmounts(MAKER_TOKEN))
|
|
||||||
.callAsync();
|
|
||||||
return expect(tx).to.revertWith(UNSUPPORTED_SOURCE_ERROR);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
blockchainTests.resets('sampleSellsFromKyberNetwork()', () => {
|
blockchainTests.resets('sampleSellsFromKyberNetwork()', () => {
|
||||||
before(async () => {
|
before(async () => {
|
||||||
await testContract.createTokenExchanges([MAKER_TOKEN, TAKER_TOKEN]).awaitTransactionSuccessAsync();
|
await testContract.createTokenExchanges([MAKER_TOKEN, TAKER_TOKEN]).awaitTransactionSuccessAsync();
|
||||||
@@ -1051,4 +715,65 @@ blockchainTests('erc20-bridge-sampler', env => {
|
|||||||
expect(quotes).to.deep.eq(expectedQuotes);
|
expect(quotes).to.deep.eq(expectedQuotes);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('batchCall()', () => {
|
||||||
|
it('can call one function', async () => {
|
||||||
|
const orders = createOrders(MAKER_TOKEN, TAKER_TOKEN);
|
||||||
|
const signatures: string[] = _.times(orders.length, i => hexUtils.random());
|
||||||
|
const expected = orders.map(getDeterministicFillableTakerAssetAmount);
|
||||||
|
const calls = [
|
||||||
|
testContract.getOrderFillableTakerAssetAmounts(orders, signatures).getABIEncodedTransactionData(),
|
||||||
|
];
|
||||||
|
const r = await testContract.batchCall(calls).callAsync();
|
||||||
|
expect(r).to.be.length(1);
|
||||||
|
const actual = testContract.getABIDecodedReturnData<BigNumber[]>('getOrderFillableTakerAssetAmounts', r[0]);
|
||||||
|
expect(actual).to.deep.eq(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can call two functions', async () => {
|
||||||
|
const numOrders = _.random(1, 10);
|
||||||
|
const orders = _.times(2, () => createOrders(MAKER_TOKEN, TAKER_TOKEN, numOrders));
|
||||||
|
const signatures: string[] = _.times(numOrders, i => hexUtils.random());
|
||||||
|
const expecteds = [
|
||||||
|
orders[0].map(getDeterministicFillableTakerAssetAmount),
|
||||||
|
orders[1].map(getDeterministicFillableMakerAssetAmount),
|
||||||
|
];
|
||||||
|
const calls = [
|
||||||
|
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);
|
||||||
|
expect(testContract.getABIDecodedReturnData('getOrderFillableTakerAssetAmounts', r[0])).to.deep.eq(
|
||||||
|
expecteds[0],
|
||||||
|
);
|
||||||
|
expect(testContract.getABIDecodedReturnData('getOrderFillableMakerAssetAmounts', r[1])).to.deep.eq(
|
||||||
|
expecteds[1],
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can make recursive calls', async () => {
|
||||||
|
const numOrders = _.random(1, 10);
|
||||||
|
const orders = createOrders(MAKER_TOKEN, TAKER_TOKEN, numOrders);
|
||||||
|
const signatures: string[] = _.times(numOrders, i => hexUtils.random());
|
||||||
|
const expected = orders.map(getDeterministicFillableTakerAssetAmount);
|
||||||
|
let r = await testContract
|
||||||
|
.batchCall([
|
||||||
|
testContract
|
||||||
|
.batchCall([
|
||||||
|
testContract
|
||||||
|
.getOrderFillableTakerAssetAmounts(orders, signatures)
|
||||||
|
.getABIEncodedTransactionData(),
|
||||||
|
])
|
||||||
|
.getABIEncodedTransactionData(),
|
||||||
|
])
|
||||||
|
.callAsync();
|
||||||
|
expect(r).to.be.length(1);
|
||||||
|
r = testContract.getABIDecodedReturnData<string[]>('batchCall', r[0]);
|
||||||
|
expect(r).to.be.length(1);
|
||||||
|
expect(testContract.getABIDecodedReturnData('getOrderFillableTakerAssetAmounts', r[0])).to.deep.eq(
|
||||||
|
expected,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@@ -4,6 +4,7 @@
|
|||||||
* -----------------------------------------------------------------------------
|
* -----------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
export * from '../test/generated-wrappers/erc20_bridge_sampler';
|
export * from '../test/generated-wrappers/erc20_bridge_sampler';
|
||||||
|
export * from '../test/generated-wrappers/i_curve';
|
||||||
export * from '../test/generated-wrappers/i_dev_utils';
|
export * from '../test/generated-wrappers/i_dev_utils';
|
||||||
export * from '../test/generated-wrappers/i_erc20_bridge_sampler';
|
export * from '../test/generated-wrappers/i_erc20_bridge_sampler';
|
||||||
export * from '../test/generated-wrappers/i_eth2_dai';
|
export * from '../test/generated-wrappers/i_eth2_dai';
|
||||||
|
@@ -6,6 +6,7 @@
|
|||||||
"generated-artifacts/ERC20BridgeSampler.json",
|
"generated-artifacts/ERC20BridgeSampler.json",
|
||||||
"generated-artifacts/IERC20BridgeSampler.json",
|
"generated-artifacts/IERC20BridgeSampler.json",
|
||||||
"test/generated-artifacts/ERC20BridgeSampler.json",
|
"test/generated-artifacts/ERC20BridgeSampler.json",
|
||||||
|
"test/generated-artifacts/ICurve.json",
|
||||||
"test/generated-artifacts/IDevUtils.json",
|
"test/generated-artifacts/IDevUtils.json",
|
||||||
"test/generated-artifacts/IERC20BridgeSampler.json",
|
"test/generated-artifacts/IERC20BridgeSampler.json",
|
||||||
"test/generated-artifacts/IEth2Dai.json",
|
"test/generated-artifacts/IEth2Dai.json",
|
||||||
|
@@ -1,4 +1,13 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"timestamp": 1581748629,
|
||||||
|
"version": "3.1.1",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Dependencies updated"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"version": "3.1.0",
|
"version": "3.1.0",
|
||||||
"changes": [
|
"changes": [
|
||||||
|
@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
|
|||||||
|
|
||||||
CHANGELOG
|
CHANGELOG
|
||||||
|
|
||||||
|
## v3.1.1 - _February 15, 2020_
|
||||||
|
|
||||||
|
* Dependencies updated
|
||||||
|
|
||||||
## v3.1.0 - _February 8, 2020_
|
## v3.1.0 - _February 8, 2020_
|
||||||
|
|
||||||
* Add `allowance()` and `balanceOf()` to `LibERC20Token` (#2464)
|
* Add `allowance()` and `balanceOf()` to `LibERC20Token` (#2464)
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@0x/contracts-erc20",
|
"name": "@0x/contracts-erc20",
|
||||||
"version": "3.1.0",
|
"version": "3.1.1",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.12"
|
"node": ">=6.12"
|
||||||
},
|
},
|
||||||
@@ -53,8 +53,8 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@0x/abi-gen": "^5.2.0",
|
"@0x/abi-gen": "^5.2.0",
|
||||||
"@0x/contracts-gen": "^2.0.7",
|
"@0x/contracts-gen": "^2.0.7",
|
||||||
"@0x/contracts-test-utils": "^5.1.4",
|
"@0x/contracts-test-utils": "^5.1.5",
|
||||||
"@0x/contracts-utils": "^4.3.0",
|
"@0x/contracts-utils": "^4.3.1",
|
||||||
"@0x/dev-utils": "^3.2.0",
|
"@0x/dev-utils": "^3.2.0",
|
||||||
"@0x/sol-compiler": "^4.0.7",
|
"@0x/sol-compiler": "^4.0.7",
|
||||||
"@0x/ts-doc-gen": "^0.0.22",
|
"@0x/ts-doc-gen": "^0.0.22",
|
||||||
|
@@ -1,4 +1,13 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"timestamp": 1581748629,
|
||||||
|
"version": "3.1.1",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Dependencies updated"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"version": "3.1.0",
|
"version": "3.1.0",
|
||||||
"changes": [
|
"changes": [
|
||||||
|
@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
|
|||||||
|
|
||||||
CHANGELOG
|
CHANGELOG
|
||||||
|
|
||||||
|
## v3.1.1 - _February 15, 2020_
|
||||||
|
|
||||||
|
* Dependencies updated
|
||||||
|
|
||||||
## v3.1.0 - _February 8, 2020_
|
## v3.1.0 - _February 8, 2020_
|
||||||
|
|
||||||
* Fix broken tests (#2462)
|
* Fix broken tests (#2462)
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@0x/contracts-erc721",
|
"name": "@0x/contracts-erc721",
|
||||||
"version": "3.1.0",
|
"version": "3.1.1",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.12"
|
"node": ">=6.12"
|
||||||
},
|
},
|
||||||
@@ -54,8 +54,8 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@0x/abi-gen": "^5.2.0",
|
"@0x/abi-gen": "^5.2.0",
|
||||||
"@0x/contracts-gen": "^2.0.7",
|
"@0x/contracts-gen": "^2.0.7",
|
||||||
"@0x/contracts-test-utils": "^5.1.4",
|
"@0x/contracts-test-utils": "^5.1.5",
|
||||||
"@0x/contracts-utils": "^4.3.0",
|
"@0x/contracts-utils": "^4.3.1",
|
||||||
"@0x/dev-utils": "^3.2.0",
|
"@0x/dev-utils": "^3.2.0",
|
||||||
"@0x/sol-compiler": "^4.0.7",
|
"@0x/sol-compiler": "^4.0.7",
|
||||||
"@0x/ts-doc-gen": "^0.0.22",
|
"@0x/ts-doc-gen": "^0.0.22",
|
||||||
|
@@ -1,4 +1,13 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"timestamp": 1581748629,
|
||||||
|
"version": "4.2.1",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Dependencies updated"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"version": "4.2.0",
|
"version": "4.2.0",
|
||||||
"changes": [
|
"changes": [
|
||||||
|
@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
|
|||||||
|
|
||||||
CHANGELOG
|
CHANGELOG
|
||||||
|
|
||||||
|
## v4.2.1 - _February 15, 2020_
|
||||||
|
|
||||||
|
* Dependencies updated
|
||||||
|
|
||||||
## v4.2.0 - _February 8, 2020_
|
## v4.2.0 - _February 8, 2020_
|
||||||
|
|
||||||
* Export `EvmBytecodeOutputLinkReferences` type. (#2462)
|
* Export `EvmBytecodeOutputLinkReferences` type. (#2462)
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@0x/contracts-exchange-forwarder",
|
"name": "@0x/contracts-exchange-forwarder",
|
||||||
"version": "4.2.0",
|
"version": "4.2.1",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.12"
|
"node": ">=6.12"
|
||||||
},
|
},
|
||||||
@@ -53,18 +53,18 @@
|
|||||||
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/extensions/README.md",
|
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/extensions/README.md",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@0x/abi-gen": "^5.2.0",
|
"@0x/abi-gen": "^5.2.0",
|
||||||
"@0x/contracts-asset-proxy": "^3.2.0",
|
"@0x/contracts-asset-proxy": "^3.2.1",
|
||||||
"@0x/contracts-dev-utils": "^1.1.0",
|
"@0x/contracts-dev-utils": "^1.1.1",
|
||||||
"@0x/contracts-erc1155": "^2.1.0",
|
"@0x/contracts-erc1155": "^2.1.1",
|
||||||
"@0x/contracts-erc20": "^3.1.0",
|
"@0x/contracts-erc20": "^3.1.1",
|
||||||
"@0x/contracts-erc721": "^3.1.0",
|
"@0x/contracts-erc721": "^3.1.1",
|
||||||
"@0x/contracts-exchange": "^3.2.0",
|
"@0x/contracts-exchange": "^3.2.1",
|
||||||
"@0x/contracts-exchange-libs": "^4.3.0",
|
"@0x/contracts-exchange-libs": "^4.3.1",
|
||||||
"@0x/contracts-gen": "^2.0.7",
|
"@0x/contracts-gen": "^2.0.7",
|
||||||
"@0x/contracts-test-utils": "^5.1.4",
|
"@0x/contracts-test-utils": "^5.1.5",
|
||||||
"@0x/contracts-utils": "^4.3.0",
|
"@0x/contracts-utils": "^4.3.1",
|
||||||
"@0x/dev-utils": "^3.2.0",
|
"@0x/dev-utils": "^3.2.0",
|
||||||
"@0x/order-utils": "^10.2.0",
|
"@0x/order-utils": "^10.2.1",
|
||||||
"@0x/sol-compiler": "^4.0.7",
|
"@0x/sol-compiler": "^4.0.7",
|
||||||
"@0x/ts-doc-gen": "^0.0.22",
|
"@0x/ts-doc-gen": "^0.0.22",
|
||||||
"@0x/tslint-config": "^4.0.0",
|
"@0x/tslint-config": "^4.0.0",
|
||||||
|
@@ -1,4 +1,13 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"timestamp": 1581748629,
|
||||||
|
"version": "4.3.1",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Dependencies updated"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"version": "4.3.0",
|
"version": "4.3.0",
|
||||||
"changes": [
|
"changes": [
|
||||||
|
@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
|
|||||||
|
|
||||||
CHANGELOG
|
CHANGELOG
|
||||||
|
|
||||||
|
## v4.3.1 - _February 15, 2020_
|
||||||
|
|
||||||
|
* Dependencies updated
|
||||||
|
|
||||||
## v4.3.0 - _February 8, 2020_
|
## v4.3.0 - _February 8, 2020_
|
||||||
|
|
||||||
* Export `EvmBytecodeOutputLinkReferences` type. (#2462)
|
* Export `EvmBytecodeOutputLinkReferences` type. (#2462)
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@0x/contracts-exchange-libs",
|
"name": "@0x/contracts-exchange-libs",
|
||||||
"version": "4.3.0",
|
"version": "4.3.1",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.12"
|
"node": ">=6.12"
|
||||||
},
|
},
|
||||||
@@ -81,9 +81,9 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@0x/base-contract": "^6.2.0",
|
"@0x/base-contract": "^6.2.0",
|
||||||
"@0x/contracts-test-utils": "^5.1.4",
|
"@0x/contracts-test-utils": "^5.1.5",
|
||||||
"@0x/contracts-utils": "^4.3.0",
|
"@0x/contracts-utils": "^4.3.1",
|
||||||
"@0x/order-utils": "^10.2.0",
|
"@0x/order-utils": "^10.2.1",
|
||||||
"@0x/types": "^3.1.2",
|
"@0x/types": "^3.1.2",
|
||||||
"@0x/typescript-typings": "^5.0.2",
|
"@0x/typescript-typings": "^5.0.2",
|
||||||
"@0x/utils": "^5.4.0",
|
"@0x/utils": "^5.4.0",
|
||||||
|
@@ -1,4 +1,13 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"timestamp": 1581748629,
|
||||||
|
"version": "3.2.1",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Dependencies updated"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"version": "3.2.0",
|
"version": "3.2.0",
|
||||||
"changes": [
|
"changes": [
|
||||||
|
@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
|
|||||||
|
|
||||||
CHANGELOG
|
CHANGELOG
|
||||||
|
|
||||||
|
## v3.2.1 - _February 15, 2020_
|
||||||
|
|
||||||
|
* Dependencies updated
|
||||||
|
|
||||||
## v3.2.0 - _February 8, 2020_
|
## v3.2.0 - _February 8, 2020_
|
||||||
|
|
||||||
* Flip `LibExchangeRichErrorDecoder` to an actual library. (#2462)
|
* Flip `LibExchangeRichErrorDecoder` to an actual library. (#2462)
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@0x/contracts-exchange",
|
"name": "@0x/contracts-exchange",
|
||||||
"version": "3.2.0",
|
"version": "3.2.1",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.12"
|
"node": ">=6.12"
|
||||||
},
|
},
|
||||||
@@ -53,13 +53,13 @@
|
|||||||
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/protocol/README.md",
|
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/protocol/README.md",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@0x/abi-gen": "^5.2.0",
|
"@0x/abi-gen": "^5.2.0",
|
||||||
"@0x/contracts-asset-proxy": "^3.2.0",
|
"@0x/contracts-asset-proxy": "^3.2.1",
|
||||||
"@0x/contracts-exchange-libs": "^4.3.0",
|
"@0x/contracts-exchange-libs": "^4.3.1",
|
||||||
"@0x/contracts-gen": "^2.0.7",
|
"@0x/contracts-gen": "^2.0.7",
|
||||||
"@0x/contracts-multisig": "^4.1.0",
|
"@0x/contracts-multisig": "^4.1.1",
|
||||||
"@0x/contracts-staking": "^2.0.7",
|
"@0x/contracts-staking": "^2.0.8",
|
||||||
"@0x/contracts-test-utils": "^5.1.4",
|
"@0x/contracts-test-utils": "^5.1.5",
|
||||||
"@0x/contracts-utils": "^4.3.0",
|
"@0x/contracts-utils": "^4.3.1",
|
||||||
"@0x/dev-utils": "^3.2.0",
|
"@0x/dev-utils": "^3.2.0",
|
||||||
"@0x/sol-compiler": "^4.0.7",
|
"@0x/sol-compiler": "^4.0.7",
|
||||||
"@0x/ts-doc-gen": "^0.0.22",
|
"@0x/ts-doc-gen": "^0.0.22",
|
||||||
@@ -89,11 +89,11 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@0x/base-contract": "^6.2.0",
|
"@0x/base-contract": "^6.2.0",
|
||||||
"@0x/contracts-dev-utils": "^1.1.0",
|
"@0x/contracts-dev-utils": "^1.1.1",
|
||||||
"@0x/contracts-erc1155": "^2.1.0",
|
"@0x/contracts-erc1155": "^2.1.1",
|
||||||
"@0x/contracts-erc20": "^3.1.0",
|
"@0x/contracts-erc20": "^3.1.1",
|
||||||
"@0x/contracts-erc721": "^3.1.0",
|
"@0x/contracts-erc721": "^3.1.1",
|
||||||
"@0x/order-utils": "^10.2.0",
|
"@0x/order-utils": "^10.2.1",
|
||||||
"@0x/utils": "^5.4.0",
|
"@0x/utils": "^5.4.0",
|
||||||
"lodash": "^4.17.11"
|
"lodash": "^4.17.11"
|
||||||
},
|
},
|
||||||
|
@@ -1,4 +1,13 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"timestamp": 1581748629,
|
||||||
|
"version": "6.1.1",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Dependencies updated"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"version": "6.1.0",
|
"version": "6.1.0",
|
||||||
"changes": [
|
"changes": [
|
||||||
|
@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
|
|||||||
|
|
||||||
CHANGELOG
|
CHANGELOG
|
||||||
|
|
||||||
|
## v6.1.1 - _February 15, 2020_
|
||||||
|
|
||||||
|
* Dependencies updated
|
||||||
|
|
||||||
## v6.1.0 - _February 8, 2020_
|
## v6.1.0 - _February 8, 2020_
|
||||||
|
|
||||||
* Export `EvmBytecodeOutputLinkReferences` type. (#2462)
|
* Export `EvmBytecodeOutputLinkReferences` type. (#2462)
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@0x/contracts-extensions",
|
"name": "@0x/contracts-extensions",
|
||||||
"version": "6.1.0",
|
"version": "6.1.1",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.12"
|
"node": ">=6.12"
|
||||||
},
|
},
|
||||||
@@ -52,17 +52,17 @@
|
|||||||
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/extensions/README.md",
|
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/extensions/README.md",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@0x/abi-gen": "^5.2.0",
|
"@0x/abi-gen": "^5.2.0",
|
||||||
"@0x/contracts-asset-proxy": "^3.2.0",
|
"@0x/contracts-asset-proxy": "^3.2.1",
|
||||||
"@0x/contracts-dev-utils": "^1.1.0",
|
"@0x/contracts-dev-utils": "^1.1.1",
|
||||||
"@0x/contracts-erc20": "^3.1.0",
|
"@0x/contracts-erc20": "^3.1.1",
|
||||||
"@0x/contracts-erc721": "^3.1.0",
|
"@0x/contracts-erc721": "^3.1.1",
|
||||||
"@0x/contracts-exchange": "^3.2.0",
|
"@0x/contracts-exchange": "^3.2.1",
|
||||||
"@0x/contracts-exchange-libs": "^4.3.0",
|
"@0x/contracts-exchange-libs": "^4.3.1",
|
||||||
"@0x/contracts-gen": "^2.0.7",
|
"@0x/contracts-gen": "^2.0.7",
|
||||||
"@0x/contracts-test-utils": "^5.1.4",
|
"@0x/contracts-test-utils": "^5.1.5",
|
||||||
"@0x/contracts-utils": "^4.3.0",
|
"@0x/contracts-utils": "^4.3.1",
|
||||||
"@0x/dev-utils": "^3.2.0",
|
"@0x/dev-utils": "^3.2.0",
|
||||||
"@0x/order-utils": "^10.2.0",
|
"@0x/order-utils": "^10.2.1",
|
||||||
"@0x/sol-compiler": "^4.0.7",
|
"@0x/sol-compiler": "^4.0.7",
|
||||||
"@0x/ts-doc-gen": "^0.0.22",
|
"@0x/ts-doc-gen": "^0.0.22",
|
||||||
"@0x/tslint-config": "^4.0.0",
|
"@0x/tslint-config": "^4.0.0",
|
||||||
|
@@ -1,4 +1,26 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"version": "2.4.0",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Added ChainlinkStopLimit contract and tests",
|
||||||
|
"pr": 2473
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Fixed the mainnet dYdX Bridge tests.",
|
||||||
|
"pr": 2479
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Addded decoders for stop-limit data",
|
||||||
|
"pr": 2484
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Added ERC20Sampler and Curve Mainnet test",
|
||||||
|
"pr": 2483
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timestamp": 1581748629
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"version": "2.3.0",
|
"version": "2.3.0",
|
||||||
"changes": [
|
"changes": [
|
||||||
|
@@ -5,6 +5,13 @@ Edit the package's CHANGELOG.json file only.
|
|||||||
|
|
||||||
CHANGELOG
|
CHANGELOG
|
||||||
|
|
||||||
|
## v2.4.0 - _February 15, 2020_
|
||||||
|
|
||||||
|
* Added ChainlinkStopLimit contract and tests (#2473)
|
||||||
|
* Fixed the mainnet dYdX Bridge tests. (#2479)
|
||||||
|
* Addded decoders for stop-limit data (#2484)
|
||||||
|
* Added ERC20Sampler and Curve Mainnet test (#2483)
|
||||||
|
|
||||||
## v2.3.0 - _February 8, 2020_
|
## v2.3.0 - _February 8, 2020_
|
||||||
|
|
||||||
* Remove dependency on `DevUtils` for asset data encoding/decoding (#2462)
|
* Remove dependency on `DevUtils` for asset data encoding/decoding (#2462)
|
||||||
|
50
contracts/integrations/contracts/src/ChainlinkStopLimit.sol
Normal file
50
contracts/integrations/contracts/src/ChainlinkStopLimit.sol
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright 2019 ZeroEx Intl.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
pragma solidity ^0.5.9;
|
||||||
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
|
import "./interfaces/IChainlinkAggregator.sol";
|
||||||
|
|
||||||
|
|
||||||
|
contract ChainlinkStopLimit {
|
||||||
|
|
||||||
|
/// @dev Checks that the price returned by the encoded Chainlink reference contract is
|
||||||
|
/// within the encoded price range.
|
||||||
|
/// @param stopLimitData Encodes the address of the Chainlink reference contract and the
|
||||||
|
/// valid price range.
|
||||||
|
function checkStopLimit(bytes calldata stopLimitData)
|
||||||
|
external
|
||||||
|
view
|
||||||
|
{
|
||||||
|
(
|
||||||
|
address oracle,
|
||||||
|
int256 minPrice,
|
||||||
|
int256 maxPrice
|
||||||
|
) = abi.decode(
|
||||||
|
stopLimitData,
|
||||||
|
(address, int256, int256)
|
||||||
|
);
|
||||||
|
|
||||||
|
int256 latestPrice = IChainlinkAggregator(oracle).latestAnswer();
|
||||||
|
require(
|
||||||
|
latestPrice >= minPrice && latestPrice <= maxPrice,
|
||||||
|
"ChainlinkStopLimit/OUT_OF_PRICE_RANGE"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright 2019 ZeroEx Intl.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
pragma solidity ^0.5.9;
|
||||||
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
|
|
||||||
|
// A subset of https://github.com/smartcontractkit/chainlink/blob/master/evm/contracts/interfaces/AggregatorInterface.sol
|
||||||
|
interface IChainlinkAggregator {
|
||||||
|
|
||||||
|
/// @dev Returns the latest data value recorded by the contract.
|
||||||
|
/// @return answer The latest data value recorded. For a price oracle aggregator, this will be
|
||||||
|
/// the price of the given asset in USD, multipled by 10^8
|
||||||
|
function latestAnswer() external view returns (int256 answer);
|
||||||
|
}
|
@@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright 2019 ZeroEx Intl.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
pragma solidity ^0.5.9;
|
||||||
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
|
import "../src/interfaces/IChainlinkAggregator.sol";
|
||||||
|
|
||||||
|
|
||||||
|
contract TestChainlinkAggregator is
|
||||||
|
IChainlinkAggregator
|
||||||
|
{
|
||||||
|
int256 internal _price;
|
||||||
|
|
||||||
|
function setPrice(int256 price_)
|
||||||
|
external
|
||||||
|
{
|
||||||
|
_price = price_;
|
||||||
|
}
|
||||||
|
|
||||||
|
function latestAnswer()
|
||||||
|
external
|
||||||
|
view
|
||||||
|
returns (int256)
|
||||||
|
{
|
||||||
|
return _price;
|
||||||
|
}
|
||||||
|
}
|
@@ -130,7 +130,7 @@ interface IDydx {
|
|||||||
/// @dev Deploy this contract and call `init` to run the mainnet DydxBridge integration tests.
|
/// @dev Deploy this contract and call `init` to run the mainnet DydxBridge integration tests.
|
||||||
contract TestDydxUser {
|
contract TestDydxUser {
|
||||||
|
|
||||||
address public constant DYDX_BRIDGE_ADDRESS = 0x96DdBa19b69D6EA2549f6a12d005595167414744;
|
address public constant DYDX_BRIDGE_ADDRESS = 0x55dC8f21D20D4c6ED3C82916A438A413ca68e335;
|
||||||
address public constant DYDX_ADDRESS = 0x1E0447b19BB6EcFdAe1e4AE1694b0C3659614e4e;
|
address public constant DYDX_ADDRESS = 0x1E0447b19BB6EcFdAe1e4AE1694b0C3659614e4e;
|
||||||
address public constant DAI_ADDRESS = 0x6B175474E89094C44Da98b954EedeAC495271d0F;
|
address public constant DAI_ADDRESS = 0x6B175474E89094C44Da98b954EedeAC495271d0F;
|
||||||
uint256 public constant DYDX_DAI_MARKET_ID = 3;
|
uint256 public constant DYDX_DAI_MARKET_ID = 3;
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@0x/contracts-integrations",
|
"name": "@0x/contracts-integrations",
|
||||||
"version": "2.3.0",
|
"version": "2.4.0",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.12"
|
"node": ">=6.12"
|
||||||
},
|
},
|
||||||
@@ -38,7 +38,7 @@
|
|||||||
},
|
},
|
||||||
"config": {
|
"config": {
|
||||||
"publicInterfaceContracts": "TestFramework",
|
"publicInterfaceContracts": "TestFramework",
|
||||||
"abis": "./test/generated-artifacts/@(TestContractWrapper|TestDydxUser|TestEth2Dai|TestEth2DaiBridge|TestFramework|TestMainnetAggregatorFills|TestSignatureValidationWallet|TestUniswapBridge|TestUniswapExchange|TestUniswapExchangeFactory).json",
|
"abis": "./test/generated-artifacts/@(ChainlinkStopLimit|IChainlinkAggregator|TestChainlinkAggregator|TestContractWrapper|TestDydxUser|TestEth2Dai|TestEth2DaiBridge|TestFramework|TestMainnetAggregatorFills|TestSignatureValidationWallet|TestUniswapBridge|TestUniswapExchange|TestUniswapExchangeFactory).json",
|
||||||
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually."
|
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually."
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
@@ -52,20 +52,21 @@
|
|||||||
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/extensions/README.md",
|
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/extensions/README.md",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@0x/abi-gen": "^5.2.0",
|
"@0x/abi-gen": "^5.2.0",
|
||||||
"@0x/contract-addresses": "^4.5.0",
|
"@0x/contract-addresses": "^4.6.0",
|
||||||
"@0x/contract-wrappers": "^13.5.0",
|
"@0x/contract-wrappers": "^13.6.0",
|
||||||
"@0x/contracts-broker": "^1.0.2",
|
"@0x/contracts-broker": "^1.1.0",
|
||||||
"@0x/contracts-coordinator": "^3.1.0",
|
"@0x/contracts-coordinator": "^3.1.1",
|
||||||
"@0x/contracts-dev-utils": "^1.1.0",
|
"@0x/contracts-dev-utils": "^1.1.1",
|
||||||
"@0x/contracts-exchange-forwarder": "^4.2.0",
|
"@0x/contracts-erc20-bridge-sampler": "^1.4.0",
|
||||||
"@0x/contracts-exchange-libs": "^4.3.0",
|
"@0x/contracts-exchange-forwarder": "^4.2.1",
|
||||||
"@0x/contracts-extensions": "^6.1.0",
|
"@0x/contracts-exchange-libs": "^4.3.1",
|
||||||
|
"@0x/contracts-extensions": "^6.1.1",
|
||||||
"@0x/contracts-gen": "^2.0.7",
|
"@0x/contracts-gen": "^2.0.7",
|
||||||
"@0x/contracts-utils": "^4.3.0",
|
"@0x/contracts-utils": "^4.3.1",
|
||||||
"@0x/coordinator-server": "^1.0.5",
|
"@0x/coordinator-server": "^1.0.5",
|
||||||
"@0x/dev-utils": "^3.2.0",
|
"@0x/dev-utils": "^3.2.0",
|
||||||
"@0x/migrations": "^6.1.0",
|
"@0x/migrations": "^6.2.0",
|
||||||
"@0x/order-utils": "^10.2.0",
|
"@0x/order-utils": "^10.2.1",
|
||||||
"@0x/sol-compiler": "^4.0.7",
|
"@0x/sol-compiler": "^4.0.7",
|
||||||
"@0x/tslint-config": "^4.0.0",
|
"@0x/tslint-config": "^4.0.0",
|
||||||
"@0x/web3-wrapper": "^7.0.6",
|
"@0x/web3-wrapper": "^7.0.6",
|
||||||
@@ -91,16 +92,16 @@
|
|||||||
"typescript": "3.0.1"
|
"typescript": "3.0.1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@0x/asset-swapper": "^4.1.2",
|
"@0x/asset-swapper": "^4.2.0",
|
||||||
"@0x/base-contract": "^6.2.0",
|
"@0x/base-contract": "^6.2.0",
|
||||||
"@0x/contracts-asset-proxy": "^3.2.0",
|
"@0x/contracts-asset-proxy": "^3.2.1",
|
||||||
"@0x/contracts-erc1155": "^2.1.0",
|
"@0x/contracts-erc1155": "^2.1.1",
|
||||||
"@0x/contracts-erc20": "^3.1.0",
|
"@0x/contracts-erc20": "^3.1.1",
|
||||||
"@0x/contracts-erc721": "^3.1.0",
|
"@0x/contracts-erc721": "^3.1.1",
|
||||||
"@0x/contracts-exchange": "^3.2.0",
|
"@0x/contracts-exchange": "^3.2.1",
|
||||||
"@0x/contracts-multisig": "^4.1.0",
|
"@0x/contracts-multisig": "^4.1.1",
|
||||||
"@0x/contracts-staking": "^2.0.7",
|
"@0x/contracts-staking": "^2.0.8",
|
||||||
"@0x/contracts-test-utils": "^5.1.4",
|
"@0x/contracts-test-utils": "^5.1.5",
|
||||||
"@0x/types": "^3.1.2",
|
"@0x/types": "^3.1.2",
|
||||||
"@0x/typescript-typings": "^5.0.2",
|
"@0x/typescript-typings": "^5.0.2",
|
||||||
"@0x/utils": "^5.4.0",
|
"@0x/utils": "^5.4.0",
|
||||||
|
58
contracts/integrations/src/chainlink_utils.ts
Normal file
58
contracts/integrations/src/chainlink_utils.ts
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
import { constants } from '@0x/contracts-test-utils';
|
||||||
|
import { assetDataUtils } from '@0x/order-utils';
|
||||||
|
import { StaticCallAssetData } from '@0x/types';
|
||||||
|
import { AbiEncoder, BigNumber } from '@0x/utils';
|
||||||
|
|
||||||
|
export interface StopLimitParameters {
|
||||||
|
oracle: string;
|
||||||
|
minPrice: BigNumber;
|
||||||
|
maxPrice: BigNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
const stopLimitDataEncoder = AbiEncoder.create([
|
||||||
|
{ name: 'oracle', type: 'address' },
|
||||||
|
{ name: 'minPrice', type: 'int256' },
|
||||||
|
{ name: 'maxPrice', type: 'int256' },
|
||||||
|
]);
|
||||||
|
|
||||||
|
const stopLimitMethodEncoder = AbiEncoder.createMethod('checkStopLimit', [{ name: 'stopLimitData', type: 'bytes' }]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encodes the given stop limit data parameters into the bytes format expected by the
|
||||||
|
* ChainlinkStopLimit contract.
|
||||||
|
*/
|
||||||
|
export function encodeChainlinkStopLimitData(params: StopLimitParameters): string {
|
||||||
|
return stopLimitDataEncoder.encode(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encodes the given stop limit data parameters into StaticCall asset data so that it can be used
|
||||||
|
* in a 0x order.
|
||||||
|
*/
|
||||||
|
export function encodeStopLimitStaticCallData(chainlinkStopLimitAddress: string, params: StopLimitParameters): string {
|
||||||
|
const staticCallData = stopLimitMethodEncoder.encode({
|
||||||
|
stopLimitData: encodeChainlinkStopLimitData(params),
|
||||||
|
});
|
||||||
|
return assetDataUtils.encodeStaticCallAssetData(
|
||||||
|
chainlinkStopLimitAddress,
|
||||||
|
staticCallData,
|
||||||
|
constants.KECCAK256_NULL,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes stop limit data parameters from the bytes format expected by the ChainlinkStopLimit contract.
|
||||||
|
*/
|
||||||
|
export function decodeChainlinkStopLimitData(stopLimitData: string): StopLimitParameters {
|
||||||
|
return stopLimitDataEncoder.decode(stopLimitData);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes stop limit data parameters from stop limit StaticCall asset data.
|
||||||
|
*/
|
||||||
|
export function decodeStopLimitStaticCallData(assetData: string): StopLimitParameters {
|
||||||
|
// tslint:disable-next-line:no-unnecessary-type-assertion
|
||||||
|
const { staticCallData } = assetDataUtils.decodeAssetDataOrThrow(assetData) as StaticCallAssetData;
|
||||||
|
const stopLimitData = stopLimitMethodEncoder.strictDecode<string>(staticCallData);
|
||||||
|
return decodeChainlinkStopLimitData(stopLimitData);
|
||||||
|
}
|
@@ -1,2 +1,3 @@
|
|||||||
export { artifacts } from './artifacts';
|
export { artifacts } from './artifacts';
|
||||||
export * from './wrappers';
|
export * from './wrappers';
|
||||||
|
export * from './chainlink_utils';
|
||||||
|
@@ -5,6 +5,9 @@
|
|||||||
*/
|
*/
|
||||||
import { ContractArtifact } from 'ethereum-types';
|
import { ContractArtifact } from 'ethereum-types';
|
||||||
|
|
||||||
|
import * as ChainlinkStopLimit from '../test/generated-artifacts/ChainlinkStopLimit.json';
|
||||||
|
import * as IChainlinkAggregator from '../test/generated-artifacts/IChainlinkAggregator.json';
|
||||||
|
import * as TestChainlinkAggregator from '../test/generated-artifacts/TestChainlinkAggregator.json';
|
||||||
import * as TestContractWrapper from '../test/generated-artifacts/TestContractWrapper.json';
|
import * as TestContractWrapper from '../test/generated-artifacts/TestContractWrapper.json';
|
||||||
import * as TestDydxUser from '../test/generated-artifacts/TestDydxUser.json';
|
import * as TestDydxUser from '../test/generated-artifacts/TestDydxUser.json';
|
||||||
import * as TestEth2Dai from '../test/generated-artifacts/TestEth2Dai.json';
|
import * as TestEth2Dai from '../test/generated-artifacts/TestEth2Dai.json';
|
||||||
@@ -16,6 +19,9 @@ import * as TestUniswapBridge from '../test/generated-artifacts/TestUniswapBridg
|
|||||||
import * as TestUniswapExchange from '../test/generated-artifacts/TestUniswapExchange.json';
|
import * as TestUniswapExchange from '../test/generated-artifacts/TestUniswapExchange.json';
|
||||||
import * as TestUniswapExchangeFactory from '../test/generated-artifacts/TestUniswapExchangeFactory.json';
|
import * as TestUniswapExchangeFactory from '../test/generated-artifacts/TestUniswapExchangeFactory.json';
|
||||||
export const artifacts = {
|
export const artifacts = {
|
||||||
|
ChainlinkStopLimit: ChainlinkStopLimit as ContractArtifact,
|
||||||
|
IChainlinkAggregator: IChainlinkAggregator as ContractArtifact,
|
||||||
|
TestChainlinkAggregator: TestChainlinkAggregator as ContractArtifact,
|
||||||
TestContractWrapper: TestContractWrapper as ContractArtifact,
|
TestContractWrapper: TestContractWrapper as ContractArtifact,
|
||||||
TestDydxUser: TestDydxUser as ContractArtifact,
|
TestDydxUser: TestDydxUser as ContractArtifact,
|
||||||
TestEth2Dai: TestEth2Dai as ContractArtifact,
|
TestEth2Dai: TestEth2Dai as ContractArtifact,
|
||||||
|
@@ -0,0 +1,37 @@
|
|||||||
|
import { artifacts, ERC20BridgeSamplerContract } from '@0x/contracts-erc20-bridge-sampler';
|
||||||
|
import { blockchainTests, describe, expect, toBaseUnitAmount } from '@0x/contracts-test-utils';
|
||||||
|
import { BigNumber } from '@0x/utils';
|
||||||
|
|
||||||
|
blockchainTests.fork.resets('Mainnet Sampler Tests', env => {
|
||||||
|
let testContract: ERC20BridgeSamplerContract;
|
||||||
|
before(async () => {
|
||||||
|
testContract = await ERC20BridgeSamplerContract.deployFrom0xArtifactAsync(
|
||||||
|
artifacts.ERC20BridgeSampler,
|
||||||
|
env.provider,
|
||||||
|
{ ...env.txDefaults, from: '0x6cc5f688a315f3dc28a7781717a9a798a59fda7b' },
|
||||||
|
{},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('sampleSellsFromCurve()', () => {
|
||||||
|
const curveAddress = '0x45f783cce6b7ff23b2ab2d70e416cdb7d6055f51';
|
||||||
|
const daiTokenIdx = new BigNumber(0);
|
||||||
|
const usdcTokenIdx = new BigNumber(1);
|
||||||
|
|
||||||
|
it('samples sells from Curve DAI->USDC', async () => {
|
||||||
|
const samples = await testContract
|
||||||
|
.sampleSellsFromCurve(curveAddress, daiTokenIdx, usdcTokenIdx, [toBaseUnitAmount(1)])
|
||||||
|
.callAsync();
|
||||||
|
expect(samples.length).to.be.bignumber.greaterThan(0);
|
||||||
|
expect(samples[0]).to.be.bignumber.greaterThan(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('samples sells from Curve USDC->DAI', async () => {
|
||||||
|
const samples = await testContract
|
||||||
|
.sampleSellsFromCurve(curveAddress, usdcTokenIdx, daiTokenIdx, [toBaseUnitAmount(1, 6)])
|
||||||
|
.callAsync();
|
||||||
|
expect(samples.length).to.be.bignumber.greaterThan(0);
|
||||||
|
expect(samples[0]).to.be.bignumber.greaterThan(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
111
contracts/integrations/test/bridges/curve_bridge_mainnet_test.ts
Normal file
111
contracts/integrations/test/bridges/curve_bridge_mainnet_test.ts
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
import { artifacts as assetProxyArtifacts } from '@0x/contracts-asset-proxy';
|
||||||
|
import { CurveBridgeContract } from '@0x/contracts-asset-proxy/lib/src/wrappers';
|
||||||
|
import { ERC20TokenContract } from '@0x/contracts-erc20';
|
||||||
|
import { blockchainTests, constants, describe, toBaseUnitAmount } from '@0x/contracts-test-utils';
|
||||||
|
import { AbiEncoder } from '@0x/utils';
|
||||||
|
|
||||||
|
blockchainTests.fork.resets('Mainnet curve bridge tests', env => {
|
||||||
|
let testContract: CurveBridgeContract;
|
||||||
|
const receiver = '0x986ccf5234d9cfbb25246f1a5bfa51f4ccfcb308';
|
||||||
|
const usdcWallet = '0xF977814e90dA44bFA03b6295A0616a897441aceC';
|
||||||
|
const usdcAddress = '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48';
|
||||||
|
const daiWallet = '0x6cc5f688a315f3dc28a7781717a9a798a59fda7b';
|
||||||
|
const daiAddress = '0x6B175474E89094C44Da98b954EedeAC495271d0F';
|
||||||
|
const curveAddressUsdcDai = '0x2e60CF74d81ac34eB21eEff58Db4D385920ef419';
|
||||||
|
const curveAddressUsdcDaiUsdt = '0x52EA46506B9CC5Ef470C5bf89f17Dc28bB35D85C';
|
||||||
|
const daiTokenIdx = 0;
|
||||||
|
const usdcTokenIdx = 1;
|
||||||
|
const bridgeDataEncoder = AbiEncoder.create([
|
||||||
|
{ name: 'curveAddress', type: 'address' },
|
||||||
|
{ name: 'fromTokenIdx', type: 'int128' },
|
||||||
|
{ name: 'toTokenIdx', type: 'int128' },
|
||||||
|
{ name: 'version', type: 'int128' },
|
||||||
|
]);
|
||||||
|
before(async () => {
|
||||||
|
testContract = await CurveBridgeContract.deployFrom0xArtifactAsync(
|
||||||
|
assetProxyArtifacts.CurveBridge,
|
||||||
|
env.provider,
|
||||||
|
{ ...env.txDefaults, from: daiWallet },
|
||||||
|
{},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('bridgeTransferFrom()', () => {
|
||||||
|
describe('Version 0', () => {
|
||||||
|
const version = 0;
|
||||||
|
it('succeeds exchanges DAI for USDC', async () => {
|
||||||
|
const bridgeData = bridgeDataEncoder.encode([curveAddressUsdcDai, daiTokenIdx, usdcTokenIdx, version]);
|
||||||
|
// Fund the Bridge
|
||||||
|
const dai = new ERC20TokenContract(daiAddress, env.provider, { ...env.txDefaults, from: daiWallet });
|
||||||
|
await dai
|
||||||
|
.transfer(testContract.address, toBaseUnitAmount(1))
|
||||||
|
.awaitTransactionSuccessAsync({ from: daiWallet }, { shouldValidate: false });
|
||||||
|
// Exchange via Curve
|
||||||
|
await testContract
|
||||||
|
.bridgeTransferFrom(
|
||||||
|
usdcAddress,
|
||||||
|
constants.NULL_ADDRESS,
|
||||||
|
receiver,
|
||||||
|
constants.ZERO_AMOUNT,
|
||||||
|
bridgeData,
|
||||||
|
)
|
||||||
|
.awaitTransactionSuccessAsync({ from: daiWallet, gasPrice: 1 }, { shouldValidate: false });
|
||||||
|
});
|
||||||
|
it('succeeds exchanges USDC for DAI', async () => {
|
||||||
|
const bridgeData = bridgeDataEncoder.encode([curveAddressUsdcDai, usdcTokenIdx, daiTokenIdx, version]);
|
||||||
|
// Fund the Bridge
|
||||||
|
const usdc = new ERC20TokenContract(usdcAddress, env.provider, { ...env.txDefaults, from: usdcWallet });
|
||||||
|
await usdc
|
||||||
|
.transfer(testContract.address, toBaseUnitAmount(1, 6))
|
||||||
|
.awaitTransactionSuccessAsync({ from: usdcWallet }, { shouldValidate: false });
|
||||||
|
// Exchange via Curve
|
||||||
|
await testContract
|
||||||
|
.bridgeTransferFrom(daiAddress, constants.NULL_ADDRESS, receiver, constants.ZERO_AMOUNT, bridgeData)
|
||||||
|
.awaitTransactionSuccessAsync({ from: usdcWallet, gasPrice: 1 }, { shouldValidate: false });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe('Version 1', () => {
|
||||||
|
const version = 1;
|
||||||
|
it('succeeds exchanges DAI for USDC', async () => {
|
||||||
|
const bridgeData = bridgeDataEncoder.encode([
|
||||||
|
curveAddressUsdcDaiUsdt,
|
||||||
|
daiTokenIdx,
|
||||||
|
usdcTokenIdx,
|
||||||
|
version,
|
||||||
|
]);
|
||||||
|
// Fund the Bridge
|
||||||
|
const dai = new ERC20TokenContract(daiAddress, env.provider, { ...env.txDefaults, from: daiWallet });
|
||||||
|
await dai
|
||||||
|
.transfer(testContract.address, toBaseUnitAmount(1))
|
||||||
|
.awaitTransactionSuccessAsync({ from: daiWallet }, { shouldValidate: false });
|
||||||
|
// Exchange via Curve
|
||||||
|
await testContract
|
||||||
|
.bridgeTransferFrom(
|
||||||
|
usdcAddress,
|
||||||
|
constants.NULL_ADDRESS,
|
||||||
|
receiver,
|
||||||
|
constants.ZERO_AMOUNT,
|
||||||
|
bridgeData,
|
||||||
|
)
|
||||||
|
.awaitTransactionSuccessAsync({ from: daiWallet, gasPrice: 1 }, { shouldValidate: false });
|
||||||
|
});
|
||||||
|
it('succeeds exchanges USDC for DAI', async () => {
|
||||||
|
const bridgeData = bridgeDataEncoder.encode([
|
||||||
|
curveAddressUsdcDaiUsdt,
|
||||||
|
usdcTokenIdx,
|
||||||
|
daiTokenIdx,
|
||||||
|
version,
|
||||||
|
]);
|
||||||
|
// Fund the Bridge
|
||||||
|
const usdc = new ERC20TokenContract(usdcAddress, env.provider, { ...env.txDefaults, from: usdcWallet });
|
||||||
|
await usdc
|
||||||
|
.transfer(testContract.address, toBaseUnitAmount(1, 6))
|
||||||
|
.awaitTransactionSuccessAsync({ from: usdcWallet }, { shouldValidate: false });
|
||||||
|
// Exchange via Curve
|
||||||
|
await testContract
|
||||||
|
.bridgeTransferFrom(daiAddress, constants.NULL_ADDRESS, receiver, constants.ZERO_AMOUNT, bridgeData)
|
||||||
|
.awaitTransactionSuccessAsync({ from: usdcWallet, gasPrice: 1 }, { shouldValidate: false });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@@ -14,7 +14,7 @@ import { contractAddresses, dydxAccountOwner } from '../mainnet_fork_utils';
|
|||||||
|
|
||||||
import { dydxEvents } from './abi/dydxEvents';
|
import { dydxEvents } from './abi/dydxEvents';
|
||||||
|
|
||||||
blockchainTests.fork.skip('Mainnet dydx bridge tests', env => {
|
blockchainTests.fork.resets('Mainnet dydx bridge tests', env => {
|
||||||
let testContract: DydxBridgeContract;
|
let testContract: DydxBridgeContract;
|
||||||
// random account to receive tokens from dydx
|
// random account to receive tokens from dydx
|
||||||
const receiver = '0x986ccf5234d9cfbb25246f1a5bfa51f4ccfcb308';
|
const receiver = '0x986ccf5234d9cfbb25246f1a5bfa51f4ccfcb308';
|
||||||
@@ -73,7 +73,7 @@ blockchainTests.fork.skip('Mainnet dydx bridge tests', env => {
|
|||||||
accountOwner: dydxAccountOwner,
|
accountOwner: dydxAccountOwner,
|
||||||
accountNumber: bridgeData.accountNumbers[action.accountId.toNumber()],
|
accountNumber: bridgeData.accountNumbers[action.accountId.toNumber()],
|
||||||
market: action.marketId,
|
market: action.marketId,
|
||||||
update: [[true, scaledAmount]],
|
update: { deltaWei: { sign: true, value: scaledAmount } },
|
||||||
from: dydxAccountOwner,
|
from: dydxAccountOwner,
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
@@ -83,7 +83,7 @@ blockchainTests.fork.skip('Mainnet dydx bridge tests', env => {
|
|||||||
accountOwner: dydxAccountOwner,
|
accountOwner: dydxAccountOwner,
|
||||||
accountNumber: bridgeData.accountNumbers[action.accountId.toNumber()],
|
accountNumber: bridgeData.accountNumbers[action.accountId.toNumber()],
|
||||||
market: action.marketId,
|
market: action.marketId,
|
||||||
update: [[false, scaledAmount]],
|
update: { deltaWei: { sign: false, value: scaledAmount } },
|
||||||
to: receiver,
|
to: receiver,
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
@@ -112,10 +112,10 @@ blockchainTests.fork.skip('Mainnet dydx bridge tests', env => {
|
|||||||
expect(log.args.from, 'from').to.equal(expectedEvent.from);
|
expect(log.args.from, 'from').to.equal(expectedEvent.from);
|
||||||
// We only check the first update field because it's the delta balance (amount deposited).
|
// We only check the first update field because it's the delta balance (amount deposited).
|
||||||
// The next field is the new total, which depends on interest rates at the time of execution.
|
// The next field is the new total, which depends on interest rates at the time of execution.
|
||||||
expect(log.args.update[0][0], 'update sign').to.equal(expectedEvent.update[0][0]);
|
expect(log.args.update.deltaWei.sign, 'update sign').to.equal(expectedEvent.update.deltaWei.sign);
|
||||||
const updateValueHex = log.args.update[0][1]._hex;
|
expect(log.args.update.deltaWei.value, 'update value').to.bignumber.equal(
|
||||||
const updateValueBn = new BigNumber(updateValueHex, 16);
|
expectedEvent.update.deltaWei.value,
|
||||||
expect(updateValueBn, 'update value').to.bignumber.equal(expectedEvent.update[0][1]);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -1,14 +1,17 @@
|
|||||||
import {
|
import {
|
||||||
artifacts as BrokerArtifacts,
|
artifacts as BrokerArtifacts,
|
||||||
BrokerContract,
|
BrokerContract,
|
||||||
godsUnchainedUtils,
|
decodeBrokerAssetData,
|
||||||
|
decodePropertyData,
|
||||||
|
encodeBrokerAssetData,
|
||||||
|
encodePropertyData,
|
||||||
GodsUnchainedValidatorContract,
|
GodsUnchainedValidatorContract,
|
||||||
TestGodsUnchainedContract,
|
TestGodsUnchainedContract,
|
||||||
} from '@0x/contracts-broker';
|
} from '@0x/contracts-broker';
|
||||||
import { DummyERC721TokenContract } from '@0x/contracts-erc721';
|
import { DummyERC721TokenContract } from '@0x/contracts-erc721';
|
||||||
import { ExchangeFunctionName, ExchangeRevertErrors } from '@0x/contracts-exchange';
|
import { ExchangeFunctionName, ExchangeRevertErrors } from '@0x/contracts-exchange';
|
||||||
import { ReferenceFunctions } from '@0x/contracts-exchange-libs';
|
import { ReferenceFunctions } from '@0x/contracts-exchange-libs';
|
||||||
import { blockchainTests, constants, expect } from '@0x/contracts-test-utils';
|
import { blockchainTests, constants, expect, getRandomInteger, randomAddress } from '@0x/contracts-test-utils';
|
||||||
import { assetDataUtils } from '@0x/order-utils';
|
import { assetDataUtils } from '@0x/order-utils';
|
||||||
import { SignedOrder } from '@0x/types';
|
import { SignedOrder } from '@0x/types';
|
||||||
import { BigNumber } from '@0x/utils';
|
import { BigNumber } from '@0x/utils';
|
||||||
@@ -72,13 +75,10 @@ blockchainTests.resets('Broker <> Gods Unchained integration tests', env => {
|
|||||||
deployment.tokens.weth.address,
|
deployment.tokens.weth.address,
|
||||||
);
|
);
|
||||||
|
|
||||||
const takerAssetData = godsUnchainedUtils.encodeBrokerAssetData(
|
const takerAssetData = encodeBrokerAssetData(broker.address, godsUnchained.address, validator.address, {
|
||||||
broker.address,
|
proto: makerSpecifiedProto,
|
||||||
godsUnchained.address,
|
quality: makerSpecifiedQuality,
|
||||||
validator.address,
|
});
|
||||||
makerSpecifiedProto,
|
|
||||||
makerSpecifiedQuality,
|
|
||||||
);
|
|
||||||
|
|
||||||
const orderConfig = {
|
const orderConfig = {
|
||||||
feeRecipientAddress: constants.NULL_ADDRESS,
|
feeRecipientAddress: constants.NULL_ADDRESS,
|
||||||
@@ -530,22 +530,16 @@ blockchainTests.resets('Broker <> Gods Unchained integration tests', env => {
|
|||||||
|
|
||||||
orders = [
|
orders = [
|
||||||
await maker.signOrderAsync({
|
await maker.signOrderAsync({
|
||||||
takerAssetData: godsUnchainedUtils.encodeBrokerAssetData(
|
takerAssetData: encodeBrokerAssetData(broker.address, godsUnchained.address, validator.address, {
|
||||||
broker.address,
|
proto: firstOrderProto,
|
||||||
godsUnchained.address,
|
quality: firstOrderQuality,
|
||||||
validator.address,
|
}),
|
||||||
firstOrderProto,
|
|
||||||
firstOrderQuality,
|
|
||||||
),
|
|
||||||
}),
|
}),
|
||||||
await maker.signOrderAsync({
|
await maker.signOrderAsync({
|
||||||
takerAssetData: godsUnchainedUtils.encodeBrokerAssetData(
|
takerAssetData: encodeBrokerAssetData(broker.address, godsUnchained.address, validator.address, {
|
||||||
broker.address,
|
proto: secondOrderProto,
|
||||||
godsUnchained.address,
|
quality: secondOrderQuality,
|
||||||
validator.address,
|
}),
|
||||||
secondOrderProto,
|
|
||||||
secondOrderQuality,
|
|
||||||
),
|
|
||||||
}),
|
}),
|
||||||
];
|
];
|
||||||
});
|
});
|
||||||
@@ -718,4 +712,30 @@ blockchainTests.resets('Broker <> Gods Unchained integration tests', env => {
|
|||||||
balanceStore.assertEquals(expectedBalances);
|
balanceStore.assertEquals(expectedBalances);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('Data encoding/decoding tools', () => {
|
||||||
|
const MAX_UINT8 = 2 ** 8 - 1;
|
||||||
|
const MAX_UINT16 = 2 ** 16 - 1;
|
||||||
|
|
||||||
|
it('correctly decodes property data', async () => {
|
||||||
|
const properties = {
|
||||||
|
proto: getRandomInteger(0, MAX_UINT16),
|
||||||
|
quality: getRandomInteger(0, MAX_UINT8),
|
||||||
|
};
|
||||||
|
const encoded = encodePropertyData(properties);
|
||||||
|
const decoded = decodePropertyData(encoded);
|
||||||
|
expect(decoded.proto).to.bignumber.equal(properties.proto);
|
||||||
|
expect(decoded.quality).to.bignumber.equal(properties.quality);
|
||||||
|
});
|
||||||
|
it('correctly decodes broker asset data', async () => {
|
||||||
|
const properties = {
|
||||||
|
proto: getRandomInteger(0, MAX_UINT16),
|
||||||
|
quality: getRandomInteger(0, MAX_UINT8),
|
||||||
|
};
|
||||||
|
const encoded = encodeBrokerAssetData(randomAddress(), randomAddress(), randomAddress(), properties);
|
||||||
|
const decoded = decodeBrokerAssetData(encoded);
|
||||||
|
expect(decoded.proto).to.bignumber.equal(properties.proto);
|
||||||
|
expect(decoded.quality).to.bignumber.equal(properties.quality);
|
||||||
|
});
|
||||||
|
});
|
||||||
}); // tslint:disable-line:max-file-line-count
|
}); // tslint:disable-line:max-file-line-count
|
||||||
|
@@ -434,6 +434,25 @@ blockchainTests.resets('OrderValidationUtils/OrderTransferSimulatorUtils', env =
|
|||||||
expect(fillableTakerAssetAmount).to.bignumber.equal(signedOrder.takerAssetAmount);
|
expect(fillableTakerAssetAmount).to.bignumber.equal(signedOrder.takerAssetAmount);
|
||||||
expect(isValidSignature).to.equal(true);
|
expect(isValidSignature).to.equal(true);
|
||||||
});
|
});
|
||||||
|
it('should not revert when rounding errors occur', async () => {
|
||||||
|
signedOrder = await maker.signOrderAsync({
|
||||||
|
makerAssetAmount: new BigNumber('2040250070'),
|
||||||
|
takerAssetAmount: new BigNumber('2040250070000000000000'),
|
||||||
|
makerFee: new BigNumber(0),
|
||||||
|
takerFee: new BigNumber(0),
|
||||||
|
});
|
||||||
|
await erc20Token.setBalance(maker.address, signedOrder.makerAssetAmount).awaitTransactionSuccessAsync();
|
||||||
|
await erc20Token.approve(erc20Proxy.address, signedOrder.makerAssetAmount).awaitTransactionSuccessAsync({
|
||||||
|
from: maker.address,
|
||||||
|
});
|
||||||
|
await erc20Token2.setBalance(taker.address, signedOrder.takerAssetAmount).awaitTransactionSuccessAsync();
|
||||||
|
await erc20Token2.approve(erc20Proxy.address, signedOrder.takerAssetAmount).awaitTransactionSuccessAsync({
|
||||||
|
from: taker.address,
|
||||||
|
});
|
||||||
|
await taker.configureERC20TokenAsync(deployment.tokens.weth, deployment.staking.stakingProxy.address);
|
||||||
|
await taker.fillOrderAsync(signedOrder, new BigNumber('2040250069999999999990'));
|
||||||
|
await devUtils.getOrderRelevantState(signedOrder, signedOrder.signature).callAsync();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
describe('getOrderRelevantStates', async () => {
|
describe('getOrderRelevantStates', async () => {
|
||||||
it('should return the correct information for multiple orders', async () => {
|
it('should return the correct information for multiple orders', async () => {
|
||||||
|
@@ -3,7 +3,7 @@ import { ContractWrappers } from '@0x/contract-wrappers';
|
|||||||
import { Web3ProviderEngine } from '@0x/dev-utils';
|
import { Web3ProviderEngine } from '@0x/dev-utils';
|
||||||
|
|
||||||
const chainId = 1;
|
const chainId = 1;
|
||||||
export const dydxAccountOwner = '0xeb58c2caa96f39626dcceb74fdbb7a9a8b54ec18';
|
export const dydxAccountOwner = '0xfdac948232c5bfbe24b770326ee4dff7a8dd8484';
|
||||||
export const contractAddresses = getContractAddressesForChainOrThrow(chainId);
|
export const contractAddresses = getContractAddressesForChainOrThrow(chainId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -0,0 +1,192 @@
|
|||||||
|
import { ExchangeRevertErrors } from '@0x/contracts-exchange';
|
||||||
|
import {
|
||||||
|
blockchainTests,
|
||||||
|
constants,
|
||||||
|
expect,
|
||||||
|
getRandomInteger,
|
||||||
|
orderHashUtils,
|
||||||
|
randomAddress,
|
||||||
|
} from '@0x/contracts-test-utils';
|
||||||
|
import { assetDataUtils } from '@0x/order-utils';
|
||||||
|
import { SignedOrder } from '@0x/types';
|
||||||
|
import { BigNumber, StringRevertError } from '@0x/utils';
|
||||||
|
|
||||||
|
import {
|
||||||
|
decodeChainlinkStopLimitData,
|
||||||
|
decodeStopLimitStaticCallData,
|
||||||
|
encodeChainlinkStopLimitData,
|
||||||
|
encodeStopLimitStaticCallData,
|
||||||
|
} from '../../src/chainlink_utils';
|
||||||
|
|
||||||
|
import { artifacts } from '../artifacts';
|
||||||
|
import { Actor } from '../framework/actors/base';
|
||||||
|
import { Maker } from '../framework/actors/maker';
|
||||||
|
import { Taker } from '../framework/actors/taker';
|
||||||
|
import { BlockchainBalanceStore } from '../framework/balances/blockchain_balance_store';
|
||||||
|
import { LocalBalanceStore } from '../framework/balances/local_balance_store';
|
||||||
|
import { DeploymentManager } from '../framework/deployment_manager';
|
||||||
|
import { ChainlinkStopLimitContract, TestChainlinkAggregatorContract } from '../wrappers';
|
||||||
|
|
||||||
|
blockchainTests.resets('Chainlink stop-limit order tests', env => {
|
||||||
|
let deployment: DeploymentManager;
|
||||||
|
let balanceStore: BlockchainBalanceStore;
|
||||||
|
let initialBalances: LocalBalanceStore;
|
||||||
|
|
||||||
|
let chainLinkAggregator: TestChainlinkAggregatorContract;
|
||||||
|
let chainlinkStopLimit: ChainlinkStopLimitContract;
|
||||||
|
|
||||||
|
let maker: Maker;
|
||||||
|
let taker: Taker;
|
||||||
|
|
||||||
|
let order: SignedOrder;
|
||||||
|
|
||||||
|
const minPrice = new BigNumber(42);
|
||||||
|
const maxPrice = new BigNumber(1337);
|
||||||
|
|
||||||
|
before(async () => {
|
||||||
|
deployment = await DeploymentManager.deployAsync(env, {
|
||||||
|
numErc20TokensToDeploy: 2,
|
||||||
|
numErc721TokensToDeploy: 0,
|
||||||
|
numErc1155TokensToDeploy: 0,
|
||||||
|
});
|
||||||
|
const [makerToken, takerToken] = deployment.tokens.erc20;
|
||||||
|
|
||||||
|
chainlinkStopLimit = await ChainlinkStopLimitContract.deployFrom0xArtifactAsync(
|
||||||
|
artifacts.ChainlinkStopLimit,
|
||||||
|
env.provider,
|
||||||
|
env.txDefaults,
|
||||||
|
artifacts,
|
||||||
|
);
|
||||||
|
chainLinkAggregator = await TestChainlinkAggregatorContract.deployFrom0xArtifactAsync(
|
||||||
|
artifacts.TestChainlinkAggregator,
|
||||||
|
env.provider,
|
||||||
|
env.txDefaults,
|
||||||
|
artifacts,
|
||||||
|
);
|
||||||
|
|
||||||
|
const makerAssetData = assetDataUtils.encodeMultiAssetData(
|
||||||
|
[new BigNumber(1), new BigNumber(1)],
|
||||||
|
[
|
||||||
|
assetDataUtils.encodeERC20AssetData(makerToken.address),
|
||||||
|
encodeStopLimitStaticCallData(chainlinkStopLimit.address, {
|
||||||
|
oracle: chainLinkAggregator.address,
|
||||||
|
minPrice,
|
||||||
|
maxPrice,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
const orderConfig = {
|
||||||
|
feeRecipientAddress: constants.NULL_ADDRESS,
|
||||||
|
makerAssetData,
|
||||||
|
takerAssetData: assetDataUtils.encodeERC20AssetData(takerToken.address),
|
||||||
|
makerFeeAssetData: constants.NULL_BYTES,
|
||||||
|
takerFeeAssetData: constants.NULL_BYTES,
|
||||||
|
makerFee: constants.ZERO_AMOUNT,
|
||||||
|
takerFee: constants.ZERO_AMOUNT,
|
||||||
|
};
|
||||||
|
|
||||||
|
maker = new Maker({
|
||||||
|
name: 'Maker',
|
||||||
|
deployment,
|
||||||
|
orderConfig,
|
||||||
|
});
|
||||||
|
taker = new Taker({ name: 'Taker', deployment });
|
||||||
|
|
||||||
|
// Set balances and allowances
|
||||||
|
await maker.configureERC20TokenAsync(makerToken);
|
||||||
|
await taker.configureERC20TokenAsync(takerToken);
|
||||||
|
|
||||||
|
order = await maker.signOrderAsync();
|
||||||
|
|
||||||
|
// Set up balance stores
|
||||||
|
const tokenOwners = {
|
||||||
|
Maker: maker.address,
|
||||||
|
Taker: taker.address,
|
||||||
|
};
|
||||||
|
const tokenContracts = {
|
||||||
|
erc20: { makerToken, takerToken },
|
||||||
|
};
|
||||||
|
balanceStore = new BlockchainBalanceStore(tokenOwners, tokenContracts);
|
||||||
|
await balanceStore.updateBalancesAsync();
|
||||||
|
initialBalances = LocalBalanceStore.create(balanceStore);
|
||||||
|
});
|
||||||
|
|
||||||
|
after(async () => {
|
||||||
|
Actor.reset();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('filling stop-limit orders', () => {
|
||||||
|
it('fillOrder reverts if price < minPrice', async () => {
|
||||||
|
await chainLinkAggregator.setPrice(minPrice.minus(1)).awaitTransactionSuccessAsync();
|
||||||
|
const tx = taker.fillOrderAsync(order, order.takerAssetAmount);
|
||||||
|
const expectedError = new ExchangeRevertErrors.AssetProxyTransferError(
|
||||||
|
orderHashUtils.getOrderHashHex(order),
|
||||||
|
order.makerAssetData,
|
||||||
|
new StringRevertError('ChainlinkStopLimit/OUT_OF_PRICE_RANGE').encode(),
|
||||||
|
);
|
||||||
|
return expect(tx).to.revertWith(expectedError);
|
||||||
|
});
|
||||||
|
it('fillOrder reverts price > maxPrice', async () => {
|
||||||
|
await chainLinkAggregator.setPrice(maxPrice.plus(1)).awaitTransactionSuccessAsync();
|
||||||
|
const tx = taker.fillOrderAsync(order, order.takerAssetAmount);
|
||||||
|
const expectedError = new ExchangeRevertErrors.AssetProxyTransferError(
|
||||||
|
orderHashUtils.getOrderHashHex(order),
|
||||||
|
order.makerAssetData,
|
||||||
|
new StringRevertError('ChainlinkStopLimit/OUT_OF_PRICE_RANGE').encode(),
|
||||||
|
);
|
||||||
|
return expect(tx).to.revertWith(expectedError);
|
||||||
|
});
|
||||||
|
it('fillOrder succeeds if price = minPrice', async () => {
|
||||||
|
await chainLinkAggregator.setPrice(minPrice).awaitTransactionSuccessAsync();
|
||||||
|
const receipt = await taker.fillOrderAsync(order, order.takerAssetAmount);
|
||||||
|
const expectedBalances = LocalBalanceStore.create(initialBalances);
|
||||||
|
expectedBalances.simulateFills([order], taker.address, receipt, deployment, DeploymentManager.protocolFee);
|
||||||
|
await balanceStore.updateBalancesAsync();
|
||||||
|
balanceStore.assertEquals(expectedBalances);
|
||||||
|
});
|
||||||
|
it('fillOrder succeeds if price = maxPrice', async () => {
|
||||||
|
await chainLinkAggregator.setPrice(maxPrice).awaitTransactionSuccessAsync();
|
||||||
|
const receipt = await taker.fillOrderAsync(order, order.takerAssetAmount);
|
||||||
|
const expectedBalances = LocalBalanceStore.create(initialBalances);
|
||||||
|
expectedBalances.simulateFills([order], taker.address, receipt, deployment, DeploymentManager.protocolFee);
|
||||||
|
await balanceStore.updateBalancesAsync();
|
||||||
|
balanceStore.assertEquals(expectedBalances);
|
||||||
|
});
|
||||||
|
it('fillOrder succeeds if minPrice < price < maxPrice', async () => {
|
||||||
|
await chainLinkAggregator
|
||||||
|
.setPrice(minPrice.plus(maxPrice).dividedToIntegerBy(2))
|
||||||
|
.awaitTransactionSuccessAsync();
|
||||||
|
const receipt = await taker.fillOrderAsync(order, order.takerAssetAmount);
|
||||||
|
const expectedBalances = LocalBalanceStore.create(initialBalances);
|
||||||
|
expectedBalances.simulateFills([order], taker.address, receipt, deployment, DeploymentManager.protocolFee);
|
||||||
|
await balanceStore.updateBalancesAsync();
|
||||||
|
balanceStore.assertEquals(expectedBalances);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Data encoding/decoding tools', () => {
|
||||||
|
const MAX_INT256 = new BigNumber(2).exponentiatedBy(255).minus(1);
|
||||||
|
|
||||||
|
it('correctly decodes chainlink stop-limit params', async () => {
|
||||||
|
const params = {
|
||||||
|
oracle: randomAddress(),
|
||||||
|
minPrice: getRandomInteger(0, MAX_INT256),
|
||||||
|
maxPrice: getRandomInteger(0, MAX_INT256),
|
||||||
|
};
|
||||||
|
const encoded = encodeChainlinkStopLimitData(params);
|
||||||
|
const decoded = decodeChainlinkStopLimitData(encoded);
|
||||||
|
expect(decoded).to.deep.equal(params);
|
||||||
|
});
|
||||||
|
it('correctly decodes stop-limit assetData', async () => {
|
||||||
|
const params = {
|
||||||
|
oracle: randomAddress(),
|
||||||
|
minPrice: getRandomInteger(0, MAX_INT256),
|
||||||
|
maxPrice: getRandomInteger(0, MAX_INT256),
|
||||||
|
};
|
||||||
|
const encoded = encodeStopLimitStaticCallData(chainlinkStopLimit.address, params);
|
||||||
|
const decoded = decodeStopLimitStaticCallData(encoded);
|
||||||
|
expect(decoded).to.deep.equal(params);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@@ -3,6 +3,9 @@
|
|||||||
* Warning: This file is auto-generated by contracts-gen. Don't edit manually.
|
* Warning: This file is auto-generated by contracts-gen. Don't edit manually.
|
||||||
* -----------------------------------------------------------------------------
|
* -----------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
export * from '../test/generated-wrappers/chainlink_stop_limit';
|
||||||
|
export * from '../test/generated-wrappers/i_chainlink_aggregator';
|
||||||
|
export * from '../test/generated-wrappers/test_chainlink_aggregator';
|
||||||
export * from '../test/generated-wrappers/test_contract_wrapper';
|
export * from '../test/generated-wrappers/test_contract_wrapper';
|
||||||
export * from '../test/generated-wrappers/test_dydx_user';
|
export * from '../test/generated-wrappers/test_dydx_user';
|
||||||
export * from '../test/generated-wrappers/test_eth2_dai';
|
export * from '../test/generated-wrappers/test_eth2_dai';
|
||||||
|
@@ -4,6 +4,9 @@
|
|||||||
"include": ["./src/**/*", "./test/**/*", "./generated-wrappers/**/*"],
|
"include": ["./src/**/*", "./test/**/*", "./generated-wrappers/**/*"],
|
||||||
"files": [
|
"files": [
|
||||||
"generated-artifacts/TestFramework.json",
|
"generated-artifacts/TestFramework.json",
|
||||||
|
"test/generated-artifacts/ChainlinkStopLimit.json",
|
||||||
|
"test/generated-artifacts/IChainlinkAggregator.json",
|
||||||
|
"test/generated-artifacts/TestChainlinkAggregator.json",
|
||||||
"test/generated-artifacts/TestContractWrapper.json",
|
"test/generated-artifacts/TestContractWrapper.json",
|
||||||
"test/generated-artifacts/TestDydxUser.json",
|
"test/generated-artifacts/TestDydxUser.json",
|
||||||
"test/generated-artifacts/TestEth2Dai.json",
|
"test/generated-artifacts/TestEth2Dai.json",
|
||||||
|
@@ -1,4 +1,13 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"timestamp": 1581748629,
|
||||||
|
"version": "4.1.1",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Dependencies updated"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"version": "4.1.0",
|
"version": "4.1.0",
|
||||||
"changes": [
|
"changes": [
|
||||||
|
@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
|
|||||||
|
|
||||||
CHANGELOG
|
CHANGELOG
|
||||||
|
|
||||||
|
## v4.1.1 - _February 15, 2020_
|
||||||
|
|
||||||
|
* Dependencies updated
|
||||||
|
|
||||||
## v4.1.0 - _February 8, 2020_
|
## v4.1.0 - _February 8, 2020_
|
||||||
|
|
||||||
* Fix broken tests (#2462)
|
* Fix broken tests (#2462)
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@0x/contracts-multisig",
|
"name": "@0x/contracts-multisig",
|
||||||
"version": "4.1.0",
|
"version": "4.1.1",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.12"
|
"node": ">=6.12"
|
||||||
},
|
},
|
||||||
@@ -50,11 +50,11 @@
|
|||||||
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/multisig/README.md",
|
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/multisig/README.md",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@0x/abi-gen": "^5.2.0",
|
"@0x/abi-gen": "^5.2.0",
|
||||||
"@0x/contracts-asset-proxy": "^3.2.0",
|
"@0x/contracts-asset-proxy": "^3.2.1",
|
||||||
"@0x/contracts-erc20": "^3.1.0",
|
"@0x/contracts-erc20": "^3.1.1",
|
||||||
"@0x/contracts-gen": "^2.0.7",
|
"@0x/contracts-gen": "^2.0.7",
|
||||||
"@0x/contracts-test-utils": "^5.1.4",
|
"@0x/contracts-test-utils": "^5.1.5",
|
||||||
"@0x/contracts-utils": "^4.3.0",
|
"@0x/contracts-utils": "^4.3.1",
|
||||||
"@0x/dev-utils": "^3.2.0",
|
"@0x/dev-utils": "^3.2.0",
|
||||||
"@0x/sol-compiler": "^4.0.7",
|
"@0x/sol-compiler": "^4.0.7",
|
||||||
"@0x/tslint-config": "^4.0.0",
|
"@0x/tslint-config": "^4.0.0",
|
||||||
|
@@ -1,4 +1,13 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"timestamp": 1581748629,
|
||||||
|
"version": "2.0.8",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Dependencies updated"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"version": "2.0.7",
|
"version": "2.0.7",
|
||||||
"changes": [
|
"changes": [
|
||||||
|
@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
|
|||||||
|
|
||||||
CHANGELOG
|
CHANGELOG
|
||||||
|
|
||||||
|
## v2.0.8 - _February 15, 2020_
|
||||||
|
|
||||||
|
* Dependencies updated
|
||||||
|
|
||||||
## v2.0.7 - _February 8, 2020_
|
## v2.0.7 - _February 8, 2020_
|
||||||
|
|
||||||
* Fix revert for `LibFixedMath.mul(x, 0)`. (#2462)
|
* Fix revert for `LibFixedMath.mul(x, 0)`. (#2462)
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@0x/contracts-staking",
|
"name": "@0x/contracts-staking",
|
||||||
"version": "2.0.7",
|
"version": "2.0.8",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.12"
|
"node": ">=6.12"
|
||||||
},
|
},
|
||||||
@@ -54,14 +54,14 @@
|
|||||||
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/tokens/README.md",
|
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/tokens/README.md",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@0x/abi-gen": "^5.2.0",
|
"@0x/abi-gen": "^5.2.0",
|
||||||
"@0x/contracts-asset-proxy": "^3.2.0",
|
"@0x/contracts-asset-proxy": "^3.2.1",
|
||||||
"@0x/contracts-dev-utils": "^1.1.0",
|
"@0x/contracts-dev-utils": "^1.1.1",
|
||||||
"@0x/contracts-erc20": "^3.1.0",
|
"@0x/contracts-erc20": "^3.1.1",
|
||||||
"@0x/contracts-exchange-libs": "^4.3.0",
|
"@0x/contracts-exchange-libs": "^4.3.1",
|
||||||
"@0x/contracts-gen": "^2.0.7",
|
"@0x/contracts-gen": "^2.0.7",
|
||||||
"@0x/contracts-utils": "^4.3.0",
|
"@0x/contracts-utils": "^4.3.1",
|
||||||
"@0x/dev-utils": "^3.2.0",
|
"@0x/dev-utils": "^3.2.0",
|
||||||
"@0x/order-utils": "^10.2.0",
|
"@0x/order-utils": "^10.2.1",
|
||||||
"@0x/sol-compiler": "^4.0.7",
|
"@0x/sol-compiler": "^4.0.7",
|
||||||
"@0x/ts-doc-gen": "^0.0.22",
|
"@0x/ts-doc-gen": "^0.0.22",
|
||||||
"@0x/tslint-config": "^4.0.0",
|
"@0x/tslint-config": "^4.0.0",
|
||||||
@@ -88,7 +88,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@0x/base-contract": "^6.2.0",
|
"@0x/base-contract": "^6.2.0",
|
||||||
"@0x/contracts-test-utils": "^5.1.4",
|
"@0x/contracts-test-utils": "^5.1.5",
|
||||||
"@0x/typescript-typings": "^5.0.2",
|
"@0x/typescript-typings": "^5.0.2",
|
||||||
"@0x/utils": "^5.4.0",
|
"@0x/utils": "^5.4.0",
|
||||||
"ethereum-types": "^3.1.0",
|
"ethereum-types": "^3.1.0",
|
||||||
|
@@ -1,4 +1,13 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"timestamp": 1581748629,
|
||||||
|
"version": "5.1.5",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Dependencies updated"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"timestamp": 1581204851,
|
"timestamp": 1581204851,
|
||||||
"version": "5.1.4",
|
"version": "5.1.4",
|
||||||
|
@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
|
|||||||
|
|
||||||
CHANGELOG
|
CHANGELOG
|
||||||
|
|
||||||
|
## v5.1.5 - _February 15, 2020_
|
||||||
|
|
||||||
|
* Dependencies updated
|
||||||
|
|
||||||
## v5.1.4 - _February 8, 2020_
|
## v5.1.4 - _February 8, 2020_
|
||||||
|
|
||||||
* Dependencies updated
|
* Dependencies updated
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@0x/contracts-test-utils",
|
"name": "@0x/contracts-test-utils",
|
||||||
"version": "5.1.4",
|
"version": "5.1.5",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.12"
|
"node": ">=6.12"
|
||||||
},
|
},
|
||||||
@@ -44,10 +44,10 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@0x/assert": "^3.0.6",
|
"@0x/assert": "^3.0.6",
|
||||||
"@0x/base-contract": "^6.2.0",
|
"@0x/base-contract": "^6.2.0",
|
||||||
"@0x/contract-addresses": "^4.5.0",
|
"@0x/contract-addresses": "^4.6.0",
|
||||||
"@0x/dev-utils": "^3.2.0",
|
"@0x/dev-utils": "^3.2.0",
|
||||||
"@0x/json-schemas": "^5.0.6",
|
"@0x/json-schemas": "^5.0.6",
|
||||||
"@0x/order-utils": "^10.2.0",
|
"@0x/order-utils": "^10.2.1",
|
||||||
"@0x/sol-coverage": "^4.0.7",
|
"@0x/sol-coverage": "^4.0.7",
|
||||||
"@0x/sol-profiler": "^4.0.7",
|
"@0x/sol-profiler": "^4.0.7",
|
||||||
"@0x/sol-trace": "^3.0.7",
|
"@0x/sol-trace": "^3.0.7",
|
||||||
|
@@ -20,7 +20,12 @@ export let providerConfigs: Web3Config = {
|
|||||||
shouldUseInProcessGanache: true,
|
shouldUseInProcessGanache: true,
|
||||||
shouldAllowUnlimitedContractSize: true,
|
shouldAllowUnlimitedContractSize: true,
|
||||||
hardfork: 'istanbul',
|
hardfork: 'istanbul',
|
||||||
unlocked_accounts: ['0x6cc5f688a315f3dc28a7781717a9a798a59fda7b', '0x55dc8f21d20d4c6ed3c82916a438a413ca68e335'],
|
unlocked_accounts: [
|
||||||
|
'0x6cc5f688a315f3dc28a7781717a9a798a59fda7b',
|
||||||
|
'0x55dc8f21d20d4c6ed3c82916a438a413ca68e335',
|
||||||
|
'0x8ed95d1746bf1e4dab58d8ed4724f1ef95b20db0', // ERC20BridgeProxy
|
||||||
|
'0xf977814e90da44bfa03b6295a0616a897441acec', // Binance: USDC, TUSD
|
||||||
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
export const provider: Web3ProviderEngine = web3Factory.getRpcProvider(providerConfigs);
|
export const provider: Web3ProviderEngine = web3Factory.getRpcProvider(providerConfigs);
|
||||||
|
@@ -1,4 +1,13 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"timestamp": 1581748629,
|
||||||
|
"version": "4.3.1",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Dependencies updated"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"version": "4.3.0",
|
"version": "4.3.0",
|
||||||
"changes": [
|
"changes": [
|
||||||
|
@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
|
|||||||
|
|
||||||
CHANGELOG
|
CHANGELOG
|
||||||
|
|
||||||
|
## v4.3.1 - _February 15, 2020_
|
||||||
|
|
||||||
|
* Dependencies updated
|
||||||
|
|
||||||
## v4.3.0 - _February 8, 2020_
|
## v4.3.0 - _February 8, 2020_
|
||||||
|
|
||||||
* Update Eth2Dai addresses in `DeploymentConstants` (#2474)
|
* Update Eth2Dai addresses in `DeploymentConstants` (#2474)
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@0x/contracts-utils",
|
"name": "@0x/contracts-utils",
|
||||||
"version": "4.3.0",
|
"version": "4.3.1",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.12"
|
"node": ">=6.12"
|
||||||
},
|
},
|
||||||
@@ -52,9 +52,9 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@0x/abi-gen": "^5.2.0",
|
"@0x/abi-gen": "^5.2.0",
|
||||||
"@0x/contracts-gen": "^2.0.7",
|
"@0x/contracts-gen": "^2.0.7",
|
||||||
"@0x/contracts-test-utils": "^5.1.4",
|
"@0x/contracts-test-utils": "^5.1.5",
|
||||||
"@0x/dev-utils": "^3.2.0",
|
"@0x/dev-utils": "^3.2.0",
|
||||||
"@0x/order-utils": "^10.2.0",
|
"@0x/order-utils": "^10.2.1",
|
||||||
"@0x/sol-compiler": "^4.0.7",
|
"@0x/sol-compiler": "^4.0.7",
|
||||||
"@0x/tslint-config": "^4.0.0",
|
"@0x/tslint-config": "^4.0.0",
|
||||||
"@0x/types": "^3.1.2",
|
"@0x/types": "^3.1.2",
|
||||||
|
@@ -1,4 +1,13 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"timestamp": 1581748629,
|
||||||
|
"version": "9.1.1",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Dependencies updated"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"version": "9.1.0",
|
"version": "9.1.0",
|
||||||
"changes": [
|
"changes": [
|
||||||
|
@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
|
|||||||
|
|
||||||
CHANGELOG
|
CHANGELOG
|
||||||
|
|
||||||
|
## v9.1.1 - _February 15, 2020_
|
||||||
|
|
||||||
|
* Dependencies updated
|
||||||
|
|
||||||
## v9.1.0 - _February 8, 2020_
|
## v9.1.0 - _February 8, 2020_
|
||||||
|
|
||||||
* Export `EvmBytecodeOutputLinkReferences` (#2462)
|
* Export `EvmBytecodeOutputLinkReferences` (#2462)
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "0x.js",
|
"name": "0x.js",
|
||||||
"version": "9.1.0",
|
"version": "9.1.1",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.12"
|
"node": ">=6.12"
|
||||||
},
|
},
|
||||||
@@ -46,9 +46,9 @@
|
|||||||
},
|
},
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@0x/contract-addresses": "^4.5.0",
|
"@0x/contract-addresses": "^4.6.0",
|
||||||
"@0x/dev-utils": "^3.2.0",
|
"@0x/dev-utils": "^3.2.0",
|
||||||
"@0x/migrations": "^6.1.0",
|
"@0x/migrations": "^6.2.0",
|
||||||
"@0x/ts-doc-gen": "^0.0.22",
|
"@0x/ts-doc-gen": "^0.0.22",
|
||||||
"@0x/tslint-config": "^4.0.0",
|
"@0x/tslint-config": "^4.0.0",
|
||||||
"@types/lodash": "4.14.104",
|
"@types/lodash": "4.14.104",
|
||||||
@@ -79,10 +79,10 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@0x/abi-gen-wrappers": "^5.4.0-beta.3",
|
"@0x/abi-gen-wrappers": "^5.4.0-beta.3",
|
||||||
"@0x/assert": "^3.0.6",
|
"@0x/assert": "^3.0.6",
|
||||||
"@0x/asset-swapper": "^4.1.2",
|
"@0x/asset-swapper": "^4.2.0",
|
||||||
"@0x/base-contract": "^6.2.0",
|
"@0x/base-contract": "^6.2.0",
|
||||||
"@0x/contract-wrappers": "^13.5.0",
|
"@0x/contract-wrappers": "^13.6.0",
|
||||||
"@0x/order-utils": "^10.2.0",
|
"@0x/order-utils": "^10.2.1",
|
||||||
"@0x/subproviders": "^6.0.7",
|
"@0x/subproviders": "^6.0.7",
|
||||||
"@0x/types": "^3.1.2",
|
"@0x/types": "^3.1.2",
|
||||||
"@0x/typescript-typings": "^5.0.2",
|
"@0x/typescript-typings": "^5.0.2",
|
||||||
|
@@ -1,4 +1,18 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"version": "4.2.0",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Use `batchCall()` version of the `ERC20BridgeSampler` contract",
|
||||||
|
"pr": 2477
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Support for sampling Curve contracts",
|
||||||
|
"pr": 2483
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timestamp": 1581748629
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"timestamp": 1581204851,
|
"timestamp": 1581204851,
|
||||||
"version": "4.1.2",
|
"version": "4.1.2",
|
||||||
|
@@ -5,6 +5,11 @@ Edit the package's CHANGELOG.json file only.
|
|||||||
|
|
||||||
CHANGELOG
|
CHANGELOG
|
||||||
|
|
||||||
|
## v4.2.0 - _February 15, 2020_
|
||||||
|
|
||||||
|
* Use `batchCall()` version of the `ERC20BridgeSampler` contract (#2477)
|
||||||
|
* Support for sampling Curve contracts (#2483)
|
||||||
|
|
||||||
## v4.1.2 - _February 8, 2020_
|
## v4.1.2 - _February 8, 2020_
|
||||||
|
|
||||||
* Dependencies updated
|
* Dependencies updated
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@0x/asset-swapper",
|
"name": "@0x/asset-swapper",
|
||||||
"version": "4.1.2",
|
"version": "4.2.0",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.12"
|
"node": ">=6.12"
|
||||||
},
|
},
|
||||||
@@ -42,11 +42,11 @@
|
|||||||
"homepage": "https://0x.org/asset-swapper",
|
"homepage": "https://0x.org/asset-swapper",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@0x/assert": "^3.0.6",
|
"@0x/assert": "^3.0.6",
|
||||||
"@0x/contract-addresses": "^4.5.0",
|
"@0x/contract-addresses": "^4.6.0",
|
||||||
"@0x/contract-wrappers": "^13.5.0",
|
"@0x/contract-wrappers": "^13.6.0",
|
||||||
"@0x/json-schemas": "^5.0.6",
|
"@0x/json-schemas": "^5.0.6",
|
||||||
"@0x/order-utils": "^10.2.0",
|
"@0x/order-utils": "^10.2.1",
|
||||||
"@0x/orderbook": "^2.2.0",
|
"@0x/orderbook": "^2.2.1",
|
||||||
"@0x/utils": "^5.4.0",
|
"@0x/utils": "^5.4.0",
|
||||||
"@0x/web3-wrapper": "^7.0.6",
|
"@0x/web3-wrapper": "^7.0.6",
|
||||||
"heartbeats": "^5.0.1",
|
"heartbeats": "^5.0.1",
|
||||||
@@ -54,10 +54,10 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@0x/base-contract": "^6.2.0",
|
"@0x/base-contract": "^6.2.0",
|
||||||
"@0x/contracts-test-utils": "^5.1.4",
|
"@0x/contracts-test-utils": "^5.1.5",
|
||||||
"@0x/dev-utils": "^3.2.0",
|
"@0x/dev-utils": "^3.2.0",
|
||||||
"@0x/mesh-rpc-client": "^7.0.4-beta-0xv3",
|
"@0x/mesh-rpc-client": "^7.0.4-beta-0xv3",
|
||||||
"@0x/migrations": "^6.1.0",
|
"@0x/migrations": "^6.2.0",
|
||||||
"@0x/subproviders": "^6.0.7",
|
"@0x/subproviders": "^6.0.7",
|
||||||
"@0x/ts-doc-gen": "^0.0.22",
|
"@0x/ts-doc-gen": "^0.0.22",
|
||||||
"@0x/tslint-config": "^4.0.0",
|
"@0x/tslint-config": "^4.0.0",
|
||||||
|
@@ -12,6 +12,7 @@ import {
|
|||||||
} from './types';
|
} from './types';
|
||||||
|
|
||||||
import { constants as marketOperationUtilConstants } from './utils/market_operation_utils/constants';
|
import { constants as marketOperationUtilConstants } from './utils/market_operation_utils/constants';
|
||||||
|
import { ERC20BridgeSource } from './utils/market_operation_utils/types';
|
||||||
|
|
||||||
const ETH_GAS_STATION_API_BASE_URL = 'https://ethgasstation.info';
|
const ETH_GAS_STATION_API_BASE_URL = 'https://ethgasstation.info';
|
||||||
const NULL_BYTES = '0x';
|
const NULL_BYTES = '0x';
|
||||||
@@ -42,7 +43,7 @@ const DEFAULT_SWAP_QUOTER_OPTS: SwapQuoterOpts = {
|
|||||||
orderRefreshIntervalMs: 10000, // 10 seconds
|
orderRefreshIntervalMs: 10000, // 10 seconds
|
||||||
},
|
},
|
||||||
...DEFAULT_ORDER_PRUNER_OPTS,
|
...DEFAULT_ORDER_PRUNER_OPTS,
|
||||||
samplerGasLimit: 36e6,
|
samplerGasLimit: 59e6,
|
||||||
};
|
};
|
||||||
|
|
||||||
const DEFAULT_FORWARDER_EXTENSION_CONTRACT_OPTS: ForwarderExtensionContractOpts = {
|
const DEFAULT_FORWARDER_EXTENSION_CONTRACT_OPTS: ForwarderExtensionContractOpts = {
|
||||||
@@ -64,6 +65,34 @@ const DEFAULT_SWAP_QUOTE_REQUEST_OPTS: SwapQuoteRequestOpts = {
|
|||||||
...marketOperationUtilConstants.DEFAULT_GET_MARKET_ORDERS_OPTS,
|
...marketOperationUtilConstants.DEFAULT_GET_MARKET_ORDERS_OPTS,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Mainnet Curve configuration
|
||||||
|
const DEFAULT_CURVE_OPTS: { [source: string]: { version: number; curveAddress: string; tokens: string[] } } = {
|
||||||
|
[ERC20BridgeSource.CurveUsdcDai]: {
|
||||||
|
version: 0,
|
||||||
|
curveAddress: '0x2e60cf74d81ac34eb21eeff58db4d385920ef419',
|
||||||
|
tokens: ['0x6b175474e89094c44da98b954eedeac495271d0f', '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48'],
|
||||||
|
},
|
||||||
|
[ERC20BridgeSource.CurveUsdcDaiUsdt]: {
|
||||||
|
version: 1,
|
||||||
|
curveAddress: '0x52ea46506b9cc5ef470c5bf89f17dc28bb35d85c',
|
||||||
|
tokens: [
|
||||||
|
'0x6b175474e89094c44da98b954eedeac495271d0f',
|
||||||
|
'0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
|
||||||
|
'0xdac17f958d2ee523a2206206994597c13d831ec7',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
[ERC20BridgeSource.CurveUsdcDaiUsdtTusd]: {
|
||||||
|
version: 1,
|
||||||
|
curveAddress: '0x45f783cce6b7ff23b2ab2d70e416cdb7d6055f51',
|
||||||
|
tokens: [
|
||||||
|
'0x6b175474e89094c44da98b954eedeac495271d0f',
|
||||||
|
'0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
|
||||||
|
'0xdac17f958d2ee523a2206206994597c13d831ec7',
|
||||||
|
'0x0000000000085d4780b73119b644ae5ecd22b376',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
export const constants = {
|
export const constants = {
|
||||||
ETH_GAS_STATION_API_BASE_URL,
|
ETH_GAS_STATION_API_BASE_URL,
|
||||||
PROTOCOL_FEE_MULTIPLIER,
|
PROTOCOL_FEE_MULTIPLIER,
|
||||||
@@ -84,4 +113,5 @@ export const constants = {
|
|||||||
PROTOCOL_FEE_UTILS_POLLING_INTERVAL_IN_MS,
|
PROTOCOL_FEE_UTILS_POLLING_INTERVAL_IN_MS,
|
||||||
MARKET_UTILS_AMOUNT_BUFFER_PERCENTAGE,
|
MARKET_UTILS_AMOUNT_BUFFER_PERCENTAGE,
|
||||||
BRIDGE_ASSET_DATA_PREFIX: '0xdc1600f3',
|
BRIDGE_ASSET_DATA_PREFIX: '0xdc1600f3',
|
||||||
|
DEFAULT_CURVE_OPTS,
|
||||||
};
|
};
|
||||||
|
@@ -21,7 +21,7 @@ import {
|
|||||||
} from './types';
|
} from './types';
|
||||||
import { assert } from './utils/assert';
|
import { assert } from './utils/assert';
|
||||||
import { calculateLiquidity } from './utils/calculate_liquidity';
|
import { calculateLiquidity } from './utils/calculate_liquidity';
|
||||||
import { MarketOperationUtils } from './utils/market_operation_utils';
|
import { DexOrderSampler, MarketOperationUtils } from './utils/market_operation_utils';
|
||||||
import { dummyOrderUtils } from './utils/market_operation_utils/dummy_order_utils';
|
import { dummyOrderUtils } from './utils/market_operation_utils/dummy_order_utils';
|
||||||
import { orderPrunerUtils } from './utils/order_prune_utils';
|
import { orderPrunerUtils } from './utils/order_prune_utils';
|
||||||
import { OrderStateUtils } from './utils/order_state_utils';
|
import { OrderStateUtils } from './utils/order_state_utils';
|
||||||
@@ -162,12 +162,12 @@ export class SwapQuoter {
|
|||||||
this._devUtilsContract = new DevUtilsContract(this._contractAddresses.devUtils, provider);
|
this._devUtilsContract = new DevUtilsContract(this._contractAddresses.devUtils, provider);
|
||||||
this._protocolFeeUtils = new ProtocolFeeUtils(constants.PROTOCOL_FEE_UTILS_POLLING_INTERVAL_IN_MS);
|
this._protocolFeeUtils = new ProtocolFeeUtils(constants.PROTOCOL_FEE_UTILS_POLLING_INTERVAL_IN_MS);
|
||||||
this._orderStateUtils = new OrderStateUtils(this._devUtilsContract);
|
this._orderStateUtils = new OrderStateUtils(this._devUtilsContract);
|
||||||
const samplerContract = new IERC20BridgeSamplerContract(
|
const sampler = new DexOrderSampler(
|
||||||
this._contractAddresses.erc20BridgeSampler,
|
new IERC20BridgeSamplerContract(this._contractAddresses.erc20BridgeSampler, this.provider, {
|
||||||
this.provider,
|
gas: samplerGasLimit,
|
||||||
{ gas: samplerGasLimit },
|
}),
|
||||||
);
|
);
|
||||||
this._marketOperationUtils = new MarketOperationUtils(samplerContract, this._contractAddresses, {
|
this._marketOperationUtils = new MarketOperationUtils(sampler, this._contractAddresses, {
|
||||||
chainId,
|
chainId,
|
||||||
exchangeAddress: this._contractAddresses.exchange,
|
exchangeAddress: this._contractAddresses.exchange,
|
||||||
});
|
});
|
||||||
|
@@ -4,19 +4,17 @@ import { ERC20BridgeSource, GetMarketOrdersOpts } from './types';
|
|||||||
|
|
||||||
const INFINITE_TIMESTAMP_SEC = new BigNumber(2524604400);
|
const INFINITE_TIMESTAMP_SEC = new BigNumber(2524604400);
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert a source to a canonical address used by the sampler contract.
|
|
||||||
*/
|
|
||||||
const SOURCE_TO_ADDRESS: { [key: string]: string } = {
|
|
||||||
[ERC20BridgeSource.Eth2Dai]: '0x39755357759ce0d7f32dc8dc45414cca409ae24e',
|
|
||||||
[ERC20BridgeSource.Uniswap]: '0xc0a47dfe034b400b47bdad5fecda2621de6c4d95',
|
|
||||||
[ERC20BridgeSource.Kyber]: '0x818e6fecd516ecc3849daf6845e3ec868087b755',
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Valid sources for market sell.
|
* Valid sources for market sell.
|
||||||
*/
|
*/
|
||||||
export const SELL_SOURCES = [ERC20BridgeSource.Uniswap, ERC20BridgeSource.Eth2Dai, ERC20BridgeSource.Kyber];
|
export const SELL_SOURCES = [
|
||||||
|
ERC20BridgeSource.Uniswap,
|
||||||
|
ERC20BridgeSource.Eth2Dai,
|
||||||
|
ERC20BridgeSource.Kyber,
|
||||||
|
ERC20BridgeSource.CurveUsdcDai,
|
||||||
|
ERC20BridgeSource.CurveUsdcDaiUsdt,
|
||||||
|
ERC20BridgeSource.CurveUsdcDaiUsdtTusd,
|
||||||
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Valid sources for market buy.
|
* Valid sources for market buy.
|
||||||
@@ -36,7 +34,6 @@ export const DEFAULT_GET_MARKET_ORDERS_OPTS: GetMarketOrdersOpts = {
|
|||||||
|
|
||||||
export const constants = {
|
export const constants = {
|
||||||
INFINITE_TIMESTAMP_SEC,
|
INFINITE_TIMESTAMP_SEC,
|
||||||
SOURCE_TO_ADDRESS,
|
|
||||||
SELL_SOURCES,
|
SELL_SOURCES,
|
||||||
BUY_SOURCES,
|
BUY_SOURCES,
|
||||||
DEFAULT_GET_MARKET_ORDERS_OPTS,
|
DEFAULT_GET_MARKET_ORDERS_OPTS,
|
||||||
|
@@ -90,6 +90,10 @@ export class CreateOrderUtils {
|
|||||||
return this._contractAddress.kyberBridge;
|
return this._contractAddress.kyberBridge;
|
||||||
case ERC20BridgeSource.Uniswap:
|
case ERC20BridgeSource.Uniswap:
|
||||||
return this._contractAddress.uniswapBridge;
|
return this._contractAddress.uniswapBridge;
|
||||||
|
case ERC20BridgeSource.CurveUsdcDai:
|
||||||
|
case ERC20BridgeSource.CurveUsdcDaiUsdt:
|
||||||
|
case ERC20BridgeSource.CurveUsdcDaiUsdtTusd:
|
||||||
|
return this._contractAddress.curveBridge;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -106,13 +110,30 @@ function createBridgeOrder(
|
|||||||
slippage: number,
|
slippage: number,
|
||||||
isBuy: boolean = false,
|
isBuy: boolean = false,
|
||||||
): OptimizedMarketOrder {
|
): OptimizedMarketOrder {
|
||||||
return {
|
let makerAssetData;
|
||||||
makerAddress: bridgeAddress,
|
if (
|
||||||
makerAssetData: assetDataUtils.encodeERC20BridgeAssetData(
|
fill.source === ERC20BridgeSource.CurveUsdcDai ||
|
||||||
|
fill.source === ERC20BridgeSource.CurveUsdcDaiUsdt ||
|
||||||
|
fill.source === ERC20BridgeSource.CurveUsdcDaiUsdtTusd
|
||||||
|
) {
|
||||||
|
const { curveAddress, tokens, version } = constants.DEFAULT_CURVE_OPTS[fill.source];
|
||||||
|
const fromTokenIdx = tokens.indexOf(takerToken);
|
||||||
|
const toTokenIdx = tokens.indexOf(makerToken);
|
||||||
|
makerAssetData = assetDataUtils.encodeERC20BridgeAssetData(
|
||||||
|
makerToken,
|
||||||
|
bridgeAddress,
|
||||||
|
createCurveBridgeData(curveAddress, fromTokenIdx, toTokenIdx, version),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
makerAssetData = assetDataUtils.encodeERC20BridgeAssetData(
|
||||||
makerToken,
|
makerToken,
|
||||||
bridgeAddress,
|
bridgeAddress,
|
||||||
createBridgeData(takerToken),
|
createBridgeData(takerToken),
|
||||||
),
|
);
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
makerAddress: bridgeAddress,
|
||||||
|
makerAssetData,
|
||||||
takerAssetData: assetDataUtils.encodeERC20AssetData(takerToken),
|
takerAssetData: assetDataUtils.encodeERC20AssetData(takerToken),
|
||||||
...createCommonOrderFields(orderDomain, fill, slippage, isBuy),
|
...createCommonOrderFields(orderDomain, fill, slippage, isBuy),
|
||||||
};
|
};
|
||||||
@@ -123,6 +144,21 @@ function createBridgeData(tokenAddress: string): string {
|
|||||||
return encoder.encode({ tokenAddress });
|
return encoder.encode({ tokenAddress });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function createCurveBridgeData(
|
||||||
|
curveAddress: string,
|
||||||
|
fromTokenIdx: number,
|
||||||
|
toTokenIdx: number,
|
||||||
|
version: number,
|
||||||
|
): string {
|
||||||
|
const curveBridgeDataEncoder = AbiEncoder.create([
|
||||||
|
{ name: 'curveAddress', type: 'address' },
|
||||||
|
{ name: 'fromTokenIdx', type: 'int128' },
|
||||||
|
{ name: 'toTokenIdx', type: 'int128' },
|
||||||
|
{ name: 'version', type: 'int128' },
|
||||||
|
]);
|
||||||
|
return curveBridgeDataEncoder.encode([curveAddress, fromTokenIdx, toTokenIdx, version]);
|
||||||
|
}
|
||||||
|
|
||||||
type CommonOrderFields = Pick<
|
type CommonOrderFields = Pick<
|
||||||
OptimizedMarketOrder,
|
OptimizedMarketOrder,
|
||||||
Exclude<keyof OptimizedMarketOrder, 'makerAddress' | 'makerAssetData' | 'takerAssetData'>
|
Exclude<keyof OptimizedMarketOrder, 'makerAddress' | 'makerAssetData' | 'takerAssetData'>
|
||||||
|
@@ -1,5 +1,4 @@
|
|||||||
import { ContractAddresses } from '@0x/contract-addresses';
|
import { ContractAddresses } from '@0x/contract-addresses';
|
||||||
import { IERC20BridgeSamplerContract } from '@0x/contract-wrappers';
|
|
||||||
import { assetDataUtils, ERC20AssetData, orderCalculationUtils } from '@0x/order-utils';
|
import { assetDataUtils, ERC20AssetData, orderCalculationUtils } from '@0x/order-utils';
|
||||||
import { SignedOrder } from '@0x/types';
|
import { SignedOrder } from '@0x/types';
|
||||||
import { BigNumber } from '@0x/utils';
|
import { BigNumber } from '@0x/utils';
|
||||||
@@ -11,7 +10,7 @@ import { fillableAmountsUtils } from '../fillable_amounts_utils';
|
|||||||
import { constants as marketOperationUtilConstants } from './constants';
|
import { constants as marketOperationUtilConstants } from './constants';
|
||||||
import { CreateOrderUtils } from './create_order';
|
import { CreateOrderUtils } from './create_order';
|
||||||
import { comparePathOutputs, FillsOptimizer, getPathOutput } from './fill_optimizer';
|
import { comparePathOutputs, FillsOptimizer, getPathOutput } from './fill_optimizer';
|
||||||
import { DexOrderSampler } from './sampler';
|
import { DexOrderSampler, getSampleAmounts } from './sampler';
|
||||||
import {
|
import {
|
||||||
AggregationError,
|
AggregationError,
|
||||||
CollapsedFill,
|
CollapsedFill,
|
||||||
@@ -27,22 +26,20 @@ import {
|
|||||||
OrderDomain,
|
OrderDomain,
|
||||||
} from './types';
|
} from './types';
|
||||||
|
|
||||||
|
export { DexOrderSampler } from './sampler';
|
||||||
|
|
||||||
const { ZERO_AMOUNT } = constants;
|
const { ZERO_AMOUNT } = constants;
|
||||||
const { BUY_SOURCES, DEFAULT_GET_MARKET_ORDERS_OPTS, ERC20_PROXY_ID, SELL_SOURCES } = marketOperationUtilConstants;
|
const { BUY_SOURCES, DEFAULT_GET_MARKET_ORDERS_OPTS, ERC20_PROXY_ID, SELL_SOURCES } = marketOperationUtilConstants;
|
||||||
|
|
||||||
export class MarketOperationUtils {
|
export class MarketOperationUtils {
|
||||||
private readonly _dexSampler: DexOrderSampler;
|
|
||||||
private readonly _createOrderUtils: CreateOrderUtils;
|
private readonly _createOrderUtils: CreateOrderUtils;
|
||||||
private readonly _orderDomain: OrderDomain;
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
samplerContract: IERC20BridgeSamplerContract,
|
private readonly _sampler: DexOrderSampler,
|
||||||
contractAddresses: ContractAddresses,
|
contractAddresses: ContractAddresses,
|
||||||
orderDomain: OrderDomain,
|
private readonly _orderDomain: OrderDomain,
|
||||||
) {
|
) {
|
||||||
this._dexSampler = new DexOrderSampler(samplerContract);
|
|
||||||
this._createOrderUtils = new CreateOrderUtils(contractAddresses);
|
this._createOrderUtils = new CreateOrderUtils(contractAddresses);
|
||||||
this._orderDomain = orderDomain;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -65,10 +62,15 @@ export class MarketOperationUtils {
|
|||||||
...DEFAULT_GET_MARKET_ORDERS_OPTS,
|
...DEFAULT_GET_MARKET_ORDERS_OPTS,
|
||||||
...opts,
|
...opts,
|
||||||
};
|
};
|
||||||
const [fillableAmounts, dexQuotes] = await this._dexSampler.getFillableAmountsAndSampleMarketSellAsync(
|
const [makerToken, takerToken] = getOrderTokens(nativeOrders[0]);
|
||||||
nativeOrders,
|
const [fillableAmounts, dexQuotes] = await this._sampler.executeAsync(
|
||||||
DexOrderSampler.getSampleAmounts(takerAmount, _opts.numSamples, _opts.sampleDistributionBase),
|
DexOrderSampler.ops.getOrderFillableTakerAmounts(nativeOrders),
|
||||||
difference(SELL_SOURCES, _opts.excludedSources),
|
DexOrderSampler.ops.getSellQuotes(
|
||||||
|
difference(SELL_SOURCES, _opts.excludedSources),
|
||||||
|
makerToken,
|
||||||
|
takerToken,
|
||||||
|
getSampleAmounts(takerAmount, _opts.numSamples, _opts.sampleDistributionBase),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
const nativeOrdersWithFillableAmounts = createSignedOrdersWithFillableAmounts(
|
const nativeOrdersWithFillableAmounts = createSignedOrdersWithFillableAmounts(
|
||||||
nativeOrders,
|
nativeOrders,
|
||||||
@@ -104,11 +106,10 @@ export class MarketOperationUtils {
|
|||||||
if (!optimalPath) {
|
if (!optimalPath) {
|
||||||
throw new Error(AggregationError.NoOptimalPath);
|
throw new Error(AggregationError.NoOptimalPath);
|
||||||
}
|
}
|
||||||
const [outputToken, inputToken] = getOrderTokens(nativeOrders[0]);
|
|
||||||
return this._createOrderUtils.createSellOrdersFromPath(
|
return this._createOrderUtils.createSellOrdersFromPath(
|
||||||
this._orderDomain,
|
this._orderDomain,
|
||||||
inputToken,
|
takerToken,
|
||||||
outputToken,
|
makerToken,
|
||||||
collapsePath(optimalPath, false),
|
collapsePath(optimalPath, false),
|
||||||
_opts.bridgeSlippage,
|
_opts.bridgeSlippage,
|
||||||
);
|
);
|
||||||
@@ -134,11 +135,15 @@ export class MarketOperationUtils {
|
|||||||
...DEFAULT_GET_MARKET_ORDERS_OPTS,
|
...DEFAULT_GET_MARKET_ORDERS_OPTS,
|
||||||
...opts,
|
...opts,
|
||||||
};
|
};
|
||||||
|
const [makerToken, takerToken] = getOrderTokens(nativeOrders[0]);
|
||||||
const [fillableAmounts, dexQuotes] = await this._dexSampler.getFillableAmountsAndSampleMarketBuyAsync(
|
const [fillableAmounts, dexQuotes] = await this._sampler.executeAsync(
|
||||||
nativeOrders,
|
DexOrderSampler.ops.getOrderFillableMakerAmounts(nativeOrders),
|
||||||
DexOrderSampler.getSampleAmounts(makerAmount, _opts.numSamples, _opts.sampleDistributionBase),
|
DexOrderSampler.ops.getBuyQuotes(
|
||||||
difference(BUY_SOURCES, _opts.excludedSources),
|
difference(BUY_SOURCES, _opts.excludedSources),
|
||||||
|
makerToken,
|
||||||
|
takerToken,
|
||||||
|
getSampleAmounts(makerAmount, _opts.numSamples, _opts.sampleDistributionBase),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
const signedOrderWithFillableAmounts = this._createBuyOrdersPathFromSamplerResultIfExists(
|
const signedOrderWithFillableAmounts = this._createBuyOrdersPathFromSamplerResultIfExists(
|
||||||
nativeOrders,
|
nativeOrders,
|
||||||
@@ -174,17 +179,25 @@ export class MarketOperationUtils {
|
|||||||
...opts,
|
...opts,
|
||||||
};
|
};
|
||||||
|
|
||||||
const batchSampleResults = await this._dexSampler.getBatchFillableAmountsAndSampleMarketBuyAsync(
|
const sources = difference(BUY_SOURCES, _opts.excludedSources);
|
||||||
batchNativeOrders,
|
const ops = [
|
||||||
makerAmounts.map(makerAmount => DexOrderSampler.getSampleAmounts(makerAmount, _opts.numSamples)),
|
...batchNativeOrders.map(orders => DexOrderSampler.ops.getOrderFillableMakerAmounts(orders)),
|
||||||
difference(BUY_SOURCES, _opts.excludedSources),
|
...batchNativeOrders.map((orders, i) =>
|
||||||
);
|
DexOrderSampler.ops.getBuyQuotes(sources, getOrderTokens(orders[0])[0], getOrderTokens(orders[0])[1], [
|
||||||
return batchSampleResults.map(([fillableAmounts, dexQuotes], i) =>
|
makerAmounts[i],
|
||||||
|
]),
|
||||||
|
),
|
||||||
|
];
|
||||||
|
const executeResults = await this._sampler.executeBatchAsync(ops);
|
||||||
|
const batchFillableAmounts = executeResults.slice(0, batchNativeOrders.length) as BigNumber[][];
|
||||||
|
const batchDexQuotes = executeResults.slice(batchNativeOrders.length) as DexSample[][][];
|
||||||
|
|
||||||
|
return batchFillableAmounts.map((fillableAmounts, i) =>
|
||||||
this._createBuyOrdersPathFromSamplerResultIfExists(
|
this._createBuyOrdersPathFromSamplerResultIfExists(
|
||||||
batchNativeOrders[i],
|
batchNativeOrders[i],
|
||||||
makerAmounts[i],
|
makerAmounts[i],
|
||||||
fillableAmounts,
|
fillableAmounts,
|
||||||
dexQuotes,
|
batchDexQuotes[i],
|
||||||
_opts,
|
_opts,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@@ -2,99 +2,379 @@ import { IERC20BridgeSamplerContract } from '@0x/contract-wrappers';
|
|||||||
import { SignedOrder } from '@0x/types';
|
import { SignedOrder } from '@0x/types';
|
||||||
import { BigNumber } from '@0x/utils';
|
import { BigNumber } from '@0x/utils';
|
||||||
|
|
||||||
import { constants as marketOperationUtilConstants } from './constants';
|
import { constants } from '../../constants';
|
||||||
|
|
||||||
import { DexSample, ERC20BridgeSource } from './types';
|
import { DexSample, ERC20BridgeSource } from './types';
|
||||||
|
|
||||||
const { SOURCE_TO_ADDRESS } = marketOperationUtilConstants;
|
/**
|
||||||
|
* A composable operation the be run in `DexOrderSampler.executeAsync()`.
|
||||||
|
*/
|
||||||
|
export interface BatchedOperation<TResult> {
|
||||||
|
encodeCall(contract: IERC20BridgeSamplerContract): string;
|
||||||
|
handleCallResultsAsync(contract: IERC20BridgeSamplerContract, callResults: string): Promise<TResult>;
|
||||||
|
}
|
||||||
|
|
||||||
export class DexOrderSampler {
|
/**
|
||||||
private readonly _samplerContract: IERC20BridgeSamplerContract;
|
* Composable operations that can be batched in a single transaction,
|
||||||
|
* for use with `DexOrderSampler.executeAsync()`.
|
||||||
/**
|
*/
|
||||||
* Generate sample amounts up to `maxFillAmount`.
|
const samplerOperations = {
|
||||||
*/
|
getOrderFillableTakerAmounts(orders: SignedOrder[]): BatchedOperation<BigNumber[]> {
|
||||||
public static getSampleAmounts(maxFillAmount: BigNumber, numSamples: number, expBase: number = 1): BigNumber[] {
|
return {
|
||||||
const distribution = [...Array<BigNumber>(numSamples)].map((v, i) => new BigNumber(expBase).pow(i));
|
encodeCall: contract => {
|
||||||
const stepSizes = distribution.map(d => d.div(BigNumber.sum(...distribution)));
|
return contract
|
||||||
const amounts = stepSizes.map((s, i) => {
|
.getOrderFillableTakerAssetAmounts(orders, orders.map(o => o.signature))
|
||||||
return maxFillAmount
|
.getABIEncodedTransactionData();
|
||||||
.times(BigNumber.sum(...[0, ...stepSizes.slice(0, i + 1)]))
|
},
|
||||||
.integerValue(BigNumber.ROUND_UP);
|
handleCallResultsAsync: async (contract, callResults) => {
|
||||||
|
return contract.getABIDecodedReturnData<BigNumber[]>('getOrderFillableTakerAssetAmounts', callResults);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
getOrderFillableMakerAmounts(orders: SignedOrder[]): BatchedOperation<BigNumber[]> {
|
||||||
|
return {
|
||||||
|
encodeCall: contract => {
|
||||||
|
return contract
|
||||||
|
.getOrderFillableMakerAssetAmounts(orders, orders.map(o => o.signature))
|
||||||
|
.getABIEncodedTransactionData();
|
||||||
|
},
|
||||||
|
handleCallResultsAsync: async (contract, callResults) => {
|
||||||
|
return contract.getABIDecodedReturnData<BigNumber[]>('getOrderFillableMakerAssetAmounts', callResults);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
getKyberSellQuotes(
|
||||||
|
makerToken: string,
|
||||||
|
takerToken: string,
|
||||||
|
takerFillAmounts: BigNumber[],
|
||||||
|
): BatchedOperation<BigNumber[]> {
|
||||||
|
return {
|
||||||
|
encodeCall: contract => {
|
||||||
|
return contract
|
||||||
|
.sampleSellsFromKyberNetwork(takerToken, makerToken, takerFillAmounts)
|
||||||
|
.getABIEncodedTransactionData();
|
||||||
|
},
|
||||||
|
handleCallResultsAsync: async (contract, callResults) => {
|
||||||
|
return contract.getABIDecodedReturnData<BigNumber[]>('sampleSellsFromKyberNetwork', callResults);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
getUniswapSellQuotes(
|
||||||
|
makerToken: string,
|
||||||
|
takerToken: string,
|
||||||
|
takerFillAmounts: BigNumber[],
|
||||||
|
): BatchedOperation<BigNumber[]> {
|
||||||
|
return {
|
||||||
|
encodeCall: contract => {
|
||||||
|
return contract
|
||||||
|
.sampleSellsFromUniswap(takerToken, makerToken, takerFillAmounts)
|
||||||
|
.getABIEncodedTransactionData();
|
||||||
|
},
|
||||||
|
handleCallResultsAsync: async (contract, callResults) => {
|
||||||
|
return contract.getABIDecodedReturnData<BigNumber[]>('sampleSellsFromUniswap', callResults);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
getEth2DaiSellQuotes(
|
||||||
|
makerToken: string,
|
||||||
|
takerToken: string,
|
||||||
|
takerFillAmounts: BigNumber[],
|
||||||
|
): BatchedOperation<BigNumber[]> {
|
||||||
|
return {
|
||||||
|
encodeCall: contract => {
|
||||||
|
return contract
|
||||||
|
.sampleSellsFromEth2Dai(takerToken, makerToken, takerFillAmounts)
|
||||||
|
.getABIEncodedTransactionData();
|
||||||
|
},
|
||||||
|
handleCallResultsAsync: async (contract, callResults) => {
|
||||||
|
return contract.getABIDecodedReturnData<BigNumber[]>('sampleSellsFromEth2Dai', callResults);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
getCurveSellQuotes(
|
||||||
|
curveAddress: string,
|
||||||
|
fromTokenIdx: number,
|
||||||
|
toTokenIdx: number,
|
||||||
|
takerFillAmounts: BigNumber[],
|
||||||
|
): BatchedOperation<BigNumber[]> {
|
||||||
|
return {
|
||||||
|
encodeCall: contract => {
|
||||||
|
return contract
|
||||||
|
.sampleSellsFromCurve(
|
||||||
|
curveAddress,
|
||||||
|
new BigNumber(fromTokenIdx),
|
||||||
|
new BigNumber(toTokenIdx),
|
||||||
|
takerFillAmounts,
|
||||||
|
)
|
||||||
|
.getABIEncodedTransactionData();
|
||||||
|
},
|
||||||
|
handleCallResultsAsync: async (contract, callResults) => {
|
||||||
|
return contract.getABIDecodedReturnData<BigNumber[]>('sampleSellsFromCurve', callResults);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
getUniswapBuyQuotes(
|
||||||
|
makerToken: string,
|
||||||
|
takerToken: string,
|
||||||
|
makerFillAmounts: BigNumber[],
|
||||||
|
): BatchedOperation<BigNumber[]> {
|
||||||
|
return {
|
||||||
|
encodeCall: contract => {
|
||||||
|
return contract
|
||||||
|
.sampleBuysFromUniswap(takerToken, makerToken, makerFillAmounts)
|
||||||
|
.getABIEncodedTransactionData();
|
||||||
|
},
|
||||||
|
handleCallResultsAsync: async (contract, callResults) => {
|
||||||
|
return contract.getABIDecodedReturnData<BigNumber[]>('sampleBuysFromUniswap', callResults);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
getEth2DaiBuyQuotes(
|
||||||
|
makerToken: string,
|
||||||
|
takerToken: string,
|
||||||
|
makerFillAmounts: BigNumber[],
|
||||||
|
): BatchedOperation<BigNumber[]> {
|
||||||
|
return {
|
||||||
|
encodeCall: contract => {
|
||||||
|
return contract
|
||||||
|
.sampleBuysFromEth2Dai(takerToken, makerToken, makerFillAmounts)
|
||||||
|
.getABIEncodedTransactionData();
|
||||||
|
},
|
||||||
|
handleCallResultsAsync: async (contract, callResults) => {
|
||||||
|
return contract.getABIDecodedReturnData<BigNumber[]>('sampleBuysFromEth2Dai', callResults);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
getSellQuotes(
|
||||||
|
sources: ERC20BridgeSource[],
|
||||||
|
makerToken: string,
|
||||||
|
takerToken: string,
|
||||||
|
takerFillAmounts: BigNumber[],
|
||||||
|
): BatchedOperation<DexSample[][]> {
|
||||||
|
const subOps = sources
|
||||||
|
.map(source => {
|
||||||
|
let batchedOperation;
|
||||||
|
if (source === ERC20BridgeSource.Eth2Dai) {
|
||||||
|
batchedOperation = samplerOperations.getEth2DaiSellQuotes(makerToken, takerToken, takerFillAmounts);
|
||||||
|
} else if (source === ERC20BridgeSource.Uniswap) {
|
||||||
|
batchedOperation = samplerOperations.getUniswapSellQuotes(makerToken, takerToken, takerFillAmounts);
|
||||||
|
} else if (source === ERC20BridgeSource.Kyber) {
|
||||||
|
batchedOperation = samplerOperations.getKyberSellQuotes(makerToken, takerToken, takerFillAmounts);
|
||||||
|
} else if (
|
||||||
|
source === ERC20BridgeSource.CurveUsdcDai ||
|
||||||
|
source === ERC20BridgeSource.CurveUsdcDaiUsdt ||
|
||||||
|
source === ERC20BridgeSource.CurveUsdcDaiUsdtTusd
|
||||||
|
) {
|
||||||
|
const { curveAddress, tokens } = constants.DEFAULT_CURVE_OPTS[source];
|
||||||
|
const fromTokenIdx = tokens.indexOf(takerToken);
|
||||||
|
const toTokenIdx = tokens.indexOf(makerToken);
|
||||||
|
if (fromTokenIdx !== -1 && toTokenIdx !== -1) {
|
||||||
|
batchedOperation = samplerOperations.getCurveSellQuotes(
|
||||||
|
curveAddress,
|
||||||
|
fromTokenIdx,
|
||||||
|
toTokenIdx,
|
||||||
|
takerFillAmounts,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new Error(`Unsupported sell sample source: ${source}`);
|
||||||
|
}
|
||||||
|
return { batchedOperation, source };
|
||||||
|
})
|
||||||
|
.filter(op => op.batchedOperation) as Array<{
|
||||||
|
batchedOperation: BatchedOperation<BigNumber[]>;
|
||||||
|
source: ERC20BridgeSource;
|
||||||
|
}>;
|
||||||
|
return {
|
||||||
|
encodeCall: contract => {
|
||||||
|
const subCalls = subOps.map(op => op.batchedOperation.encodeCall(contract));
|
||||||
|
return contract.batchCall(subCalls).getABIEncodedTransactionData();
|
||||||
|
},
|
||||||
|
handleCallResultsAsync: async (contract, callResults) => {
|
||||||
|
const rawSubCallResults = contract.getABIDecodedReturnData<string[]>('batchCall', callResults);
|
||||||
|
const samples = await Promise.all(
|
||||||
|
subOps.map(async (op, i) =>
|
||||||
|
op.batchedOperation.handleCallResultsAsync(contract, rawSubCallResults[i]),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
return subOps.map((op, i) => {
|
||||||
|
return samples[i].map((output, j) => ({
|
||||||
|
source: op.source,
|
||||||
|
output,
|
||||||
|
input: takerFillAmounts[j],
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
getBuyQuotes(
|
||||||
|
sources: ERC20BridgeSource[],
|
||||||
|
makerToken: string,
|
||||||
|
takerToken: string,
|
||||||
|
makerFillAmounts: BigNumber[],
|
||||||
|
): BatchedOperation<DexSample[][]> {
|
||||||
|
const subOps = sources.map(source => {
|
||||||
|
if (source === ERC20BridgeSource.Eth2Dai) {
|
||||||
|
return samplerOperations.getEth2DaiBuyQuotes(makerToken, takerToken, makerFillAmounts);
|
||||||
|
} else if (source === ERC20BridgeSource.Uniswap) {
|
||||||
|
return samplerOperations.getUniswapBuyQuotes(makerToken, takerToken, makerFillAmounts);
|
||||||
|
} else {
|
||||||
|
throw new Error(`Unsupported buy sample source: ${source}`);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
return amounts;
|
return {
|
||||||
}
|
encodeCall: contract => {
|
||||||
|
const subCalls = subOps.map(op => op.encodeCall(contract));
|
||||||
|
return contract.batchCall(subCalls).getABIEncodedTransactionData();
|
||||||
|
},
|
||||||
|
handleCallResultsAsync: async (contract, callResults) => {
|
||||||
|
const rawSubCallResults = contract.getABIDecodedReturnData<string[]>('batchCall', callResults);
|
||||||
|
const samples = await Promise.all(
|
||||||
|
subOps.map(async (op, i) => op.handleCallResultsAsync(contract, rawSubCallResults[i])),
|
||||||
|
);
|
||||||
|
return sources.map((source, i) => {
|
||||||
|
return samples[i].map((output, j) => ({
|
||||||
|
source,
|
||||||
|
output,
|
||||||
|
input: makerFillAmounts[j],
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate sample amounts up to `maxFillAmount`.
|
||||||
|
*/
|
||||||
|
export function getSampleAmounts(maxFillAmount: BigNumber, numSamples: number, expBase: number = 1): BigNumber[] {
|
||||||
|
const distribution = [...Array<BigNumber>(numSamples)].map((v, i) => new BigNumber(expBase).pow(i));
|
||||||
|
const stepSizes = distribution.map(d => d.div(BigNumber.sum(...distribution)));
|
||||||
|
const amounts = stepSizes.map((s, i) => {
|
||||||
|
return maxFillAmount
|
||||||
|
.times(BigNumber.sum(...[0, ...stepSizes.slice(0, i + 1)]))
|
||||||
|
.integerValue(BigNumber.ROUND_UP);
|
||||||
|
});
|
||||||
|
return amounts;
|
||||||
|
}
|
||||||
|
|
||||||
|
type BatchedOperationResult<T> = T extends BatchedOperation<infer TResult> ? TResult : never;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encapsulates interactions with the `ERC20BridgeSampler` contract.
|
||||||
|
*/
|
||||||
|
export class DexOrderSampler {
|
||||||
|
/**
|
||||||
|
* Composable operations that can be batched in a single transaction,
|
||||||
|
* for use with `DexOrderSampler.executeAsync()`.
|
||||||
|
*/
|
||||||
|
public static ops = samplerOperations;
|
||||||
|
private readonly _samplerContract: IERC20BridgeSamplerContract;
|
||||||
|
|
||||||
constructor(samplerContract: IERC20BridgeSamplerContract) {
|
constructor(samplerContract: IERC20BridgeSamplerContract) {
|
||||||
this._samplerContract = samplerContract;
|
this._samplerContract = samplerContract;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getFillableAmountsAndSampleMarketBuyAsync(
|
/* Type overloads for `executeAsync()`. Could skip this if we would upgrade TS. */
|
||||||
nativeOrders: SignedOrder[],
|
|
||||||
sampleAmounts: BigNumber[],
|
// prettier-ignore
|
||||||
sources: ERC20BridgeSource[],
|
public async executeAsync<
|
||||||
): Promise<[BigNumber[], DexSample[][]]> {
|
T1
|
||||||
const signatures = nativeOrders.map(o => o.signature);
|
>(...ops: [T1]): Promise<[
|
||||||
const [fillableAmount, rawSamples] = await this._samplerContract
|
BatchedOperationResult<T1>
|
||||||
.queryOrdersAndSampleBuys(nativeOrders, signatures, sources.map(s => SOURCE_TO_ADDRESS[s]), sampleAmounts)
|
]>;
|
||||||
.callAsync();
|
|
||||||
const quotes = rawSamples.map((rawDexSamples, sourceIdx) => {
|
// prettier-ignore
|
||||||
const source = sources[sourceIdx];
|
public async executeAsync<
|
||||||
return rawDexSamples.map((sample, sampleIdx) => ({
|
T1, T2
|
||||||
source,
|
>(...ops: [T1, T2]): Promise<[
|
||||||
input: sampleAmounts[sampleIdx],
|
BatchedOperationResult<T1>,
|
||||||
output: sample,
|
BatchedOperationResult<T2>
|
||||||
}));
|
]>;
|
||||||
});
|
|
||||||
return [fillableAmount, quotes];
|
// prettier-ignore
|
||||||
|
public async executeAsync<
|
||||||
|
T1, T2, T3
|
||||||
|
>(...ops: [T1, T2, T3]): Promise<[
|
||||||
|
BatchedOperationResult<T1>,
|
||||||
|
BatchedOperationResult<T2>,
|
||||||
|
BatchedOperationResult<T3>
|
||||||
|
]>;
|
||||||
|
|
||||||
|
// prettier-ignore
|
||||||
|
public async executeAsync<
|
||||||
|
T1, T2, T3, T4
|
||||||
|
>(...ops: [T1, T2, T3, T4]): Promise<[
|
||||||
|
BatchedOperationResult<T1>,
|
||||||
|
BatchedOperationResult<T2>,
|
||||||
|
BatchedOperationResult<T3>,
|
||||||
|
BatchedOperationResult<T4>
|
||||||
|
]>;
|
||||||
|
|
||||||
|
// prettier-ignore
|
||||||
|
public async executeAsync<
|
||||||
|
T1, T2, T3, T4, T5
|
||||||
|
>(...ops: [T1, T2, T3, T4, T5]): Promise<[
|
||||||
|
BatchedOperationResult<T1>,
|
||||||
|
BatchedOperationResult<T2>,
|
||||||
|
BatchedOperationResult<T3>,
|
||||||
|
BatchedOperationResult<T4>,
|
||||||
|
BatchedOperationResult<T5>
|
||||||
|
]>;
|
||||||
|
|
||||||
|
// prettier-ignore
|
||||||
|
public async executeAsync<
|
||||||
|
T1, T2, T3, T4, T5, T6
|
||||||
|
>(...ops: [T1, T2, T3, T4, T5, T6]): Promise<[
|
||||||
|
BatchedOperationResult<T1>,
|
||||||
|
BatchedOperationResult<T2>,
|
||||||
|
BatchedOperationResult<T3>,
|
||||||
|
BatchedOperationResult<T4>,
|
||||||
|
BatchedOperationResult<T5>,
|
||||||
|
BatchedOperationResult<T6>
|
||||||
|
]>;
|
||||||
|
|
||||||
|
// prettier-ignore
|
||||||
|
public async executeAsync<
|
||||||
|
T1, T2, T3, T4, T5, T6, T7
|
||||||
|
>(...ops: [T1, T2, T3, T4, T5, T6, T7]): Promise<[
|
||||||
|
BatchedOperationResult<T1>,
|
||||||
|
BatchedOperationResult<T2>,
|
||||||
|
BatchedOperationResult<T3>,
|
||||||
|
BatchedOperationResult<T4>,
|
||||||
|
BatchedOperationResult<T5>,
|
||||||
|
BatchedOperationResult<T6>,
|
||||||
|
BatchedOperationResult<T7>
|
||||||
|
]>;
|
||||||
|
|
||||||
|
// prettier-ignore
|
||||||
|
public async executeAsync<
|
||||||
|
T1, T2, T3, T4, T5, T6, T7, T8
|
||||||
|
>(...ops: [T1, T2, T3, T4, T5, T6, T7, T8]): Promise<[
|
||||||
|
BatchedOperationResult<T1>,
|
||||||
|
BatchedOperationResult<T2>,
|
||||||
|
BatchedOperationResult<T3>,
|
||||||
|
BatchedOperationResult<T4>,
|
||||||
|
BatchedOperationResult<T5>,
|
||||||
|
BatchedOperationResult<T6>,
|
||||||
|
BatchedOperationResult<T7>,
|
||||||
|
BatchedOperationResult<T8>
|
||||||
|
]>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run a series of operations from `DexOrderSampler.ops` in a single transaction.
|
||||||
|
*/
|
||||||
|
public async executeAsync(...ops: any[]): Promise<any[]> {
|
||||||
|
return this.executeBatchAsync(ops);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getBatchFillableAmountsAndSampleMarketBuyAsync(
|
/**
|
||||||
nativeOrders: SignedOrder[][],
|
* Run a series of operations from `DexOrderSampler.ops` in a single transaction.
|
||||||
sampleAmounts: BigNumber[][],
|
* Takes an arbitrary length array, but is not typesafe.
|
||||||
sources: ERC20BridgeSource[],
|
*/
|
||||||
): Promise<Array<[BigNumber[], DexSample[][]]>> {
|
public async executeBatchAsync<T extends Array<BatchedOperation<any>>>(ops: T): Promise<any[]> {
|
||||||
const signatures = nativeOrders.map(o => o.map(i => i.signature));
|
const callDatas = ops.map(o => o.encodeCall(this._samplerContract));
|
||||||
const fillableAmountsAndSamples = await this._samplerContract
|
const callResults = await this._samplerContract.batchCall(callDatas).callAsync();
|
||||||
.queryBatchOrdersAndSampleBuys(
|
return Promise.all(callResults.map(async (r, i) => ops[i].handleCallResultsAsync(this._samplerContract, r)));
|
||||||
nativeOrders,
|
|
||||||
signatures,
|
|
||||||
sources.map(s => SOURCE_TO_ADDRESS[s]),
|
|
||||||
sampleAmounts,
|
|
||||||
)
|
|
||||||
.callAsync();
|
|
||||||
const batchFillableAmountsAndQuotes: Array<[BigNumber[], DexSample[][]]> = [];
|
|
||||||
fillableAmountsAndSamples.forEach((sampleResult, i) => {
|
|
||||||
const { tokenAmountsBySource, orderFillableAssetAmounts } = sampleResult;
|
|
||||||
const quotes = tokenAmountsBySource.map((rawDexSamples, sourceIdx) => {
|
|
||||||
const source = sources[sourceIdx];
|
|
||||||
return rawDexSamples.map((sample, sampleIdx) => ({
|
|
||||||
source,
|
|
||||||
input: sampleAmounts[i][sampleIdx],
|
|
||||||
output: sample,
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
batchFillableAmountsAndQuotes.push([orderFillableAssetAmounts, quotes]);
|
|
||||||
});
|
|
||||||
return batchFillableAmountsAndQuotes;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async getFillableAmountsAndSampleMarketSellAsync(
|
|
||||||
nativeOrders: SignedOrder[],
|
|
||||||
sampleAmounts: BigNumber[],
|
|
||||||
sources: ERC20BridgeSource[],
|
|
||||||
): Promise<[BigNumber[], DexSample[][]]> {
|
|
||||||
const signatures = nativeOrders.map(o => o.signature);
|
|
||||||
const [fillableAmount, rawSamples] = await this._samplerContract
|
|
||||||
.queryOrdersAndSampleSells(nativeOrders, signatures, sources.map(s => SOURCE_TO_ADDRESS[s]), sampleAmounts)
|
|
||||||
.callAsync();
|
|
||||||
const quotes = rawSamples.map((rawDexSamples, sourceIdx) => {
|
|
||||||
const source = sources[sourceIdx];
|
|
||||||
return rawDexSamples.map((sample, sampleIdx) => ({
|
|
||||||
source,
|
|
||||||
input: sampleAmounts[sampleIdx],
|
|
||||||
output: sample,
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
return [fillableAmount, quotes];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user