Compare commits
16 Commits
@0x/contra
...
@0x/contra
Author | SHA1 | Date | |
---|---|---|---|
|
7fd25be02e | ||
|
aa688c4a92 | ||
|
fb437551c9 | ||
|
6fa1de7889 | ||
|
7a42df9a65 | ||
|
15a508f3ea | ||
|
b3c20ff909 | ||
|
682c07cb73 | ||
|
602605ab4b | ||
|
0eff2548d5 | ||
|
93ee681204 | ||
|
d7bea98075 | ||
|
437a3b048d | ||
|
f55a9454b5 | ||
|
3b03ad0db4 | ||
|
27d679e1f1 |
@@ -1,4 +1,23 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1608245516,
|
||||
"version": "3.7.1",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "3.7.0",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Fix Bancor support of ETH",
|
||||
"pr": 88
|
||||
}
|
||||
],
|
||||
"timestamp": 1608105788
|
||||
},
|
||||
{
|
||||
"timestamp": 1607485227,
|
||||
"version": "3.6.9",
|
||||
|
@@ -5,6 +5,14 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
CHANGELOG
|
||||
|
||||
## v3.7.1 - _December 17, 2020_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.7.0 - _December 16, 2020_
|
||||
|
||||
* Fix Bancor support of ETH (#88)
|
||||
|
||||
## v3.6.9 - _December 9, 2020_
|
||||
|
||||
* Dependencies updated
|
||||
|
@@ -21,6 +21,7 @@ pragma solidity ^0.5.9;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol";
|
||||
import "@0x/contracts-erc20/contracts/src/interfaces/IEtherToken.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";
|
||||
@@ -36,6 +37,20 @@ contract BancorBridge is
|
||||
struct TransferState {
|
||||
address bancorNetworkAddress;
|
||||
address[] path;
|
||||
IEtherToken weth;
|
||||
}
|
||||
|
||||
/// @dev Bancor ETH pseudo-address.
|
||||
address constant public BANCOR_ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
|
||||
|
||||
// solhint-disable no-empty-blocks
|
||||
/// @dev Payable fallback to receive ETH from Bancor/WETH.
|
||||
function ()
|
||||
external
|
||||
payable
|
||||
{
|
||||
// Poor man's receive in 0.5.9
|
||||
require(msg.data.length == 0);
|
||||
}
|
||||
|
||||
/// @dev Callback for `IERC20Bridge`. Tries to buy `amount` of
|
||||
@@ -60,7 +75,6 @@ contract BancorBridge is
|
||||
{
|
||||
// hold variables to get around stack depth limitations
|
||||
TransferState memory state;
|
||||
|
||||
// Decode the bridge data.
|
||||
(
|
||||
state.path,
|
||||
@@ -68,34 +82,42 @@ contract BancorBridge is
|
||||
// solhint-disable indent
|
||||
) = abi.decode(bridgeData, (address[], address));
|
||||
// solhint-enable indent
|
||||
state.weth = IEtherToken(_getWethAddress());
|
||||
|
||||
require(state.path.length > 0, "BancorBridge/PATH_MUST_EXIST");
|
||||
// Just transfer the tokens if they're the same.
|
||||
if (state.path[0] == toTokenAddress) {
|
||||
LibERC20Token.transfer(state.path[0], to, amount);
|
||||
return BRIDGE_SUCCESS;
|
||||
require(state.path.length >= 2, "BancorBridge/PATH_LENGTH_MUST_BE_GREATER_THAN_TWO");
|
||||
|
||||
// Grant an allowance to the Bancor Network to spend `fromTokenAddress` token.
|
||||
uint256 fromTokenBalance;
|
||||
uint256 payableAmount = 0;
|
||||
// If it's ETH in the path then withdraw from WETH
|
||||
// The Bancor path will have ETH as the 0xeee address
|
||||
// Bancor expects to be paid in ETH not WETH
|
||||
if (state.path[0] == BANCOR_ETH_ADDRESS) {
|
||||
fromTokenBalance = state.weth.balanceOf(address(this));
|
||||
state.weth.withdraw(fromTokenBalance);
|
||||
payableAmount = fromTokenBalance;
|
||||
} else {
|
||||
fromTokenBalance = IERC20Token(state.path[0]).balanceOf(address(this));
|
||||
LibERC20Token.approveIfBelow(state.path[0], state.bancorNetworkAddress, fromTokenBalance);
|
||||
}
|
||||
|
||||
// Otherwise use Bancor to convert
|
||||
require(state.path.length > 2, "BancorBridge/PATH_LENGTH_MUST_BE_GREATER_THAN_TWO");
|
||||
require(state.path[state.path.length - 1] == toTokenAddress, "BancorBridge/LAST_ELEMENT_OF_PATH_MUST_MATCH_OUTPUT_TOKEN");
|
||||
|
||||
// // Grant an allowance to the Bancor Network to spend `fromTokenAddress` token.
|
||||
uint256 fromTokenBalance = IERC20Token(state.path[0]).balanceOf(address(this));
|
||||
LibERC20Token.approveIfBelow(state.path[0], state.bancorNetworkAddress, fromTokenBalance);
|
||||
|
||||
// Convert the tokens
|
||||
uint256 boughtAmount = IBancorNetwork(state.bancorNetworkAddress).convertByPath(
|
||||
uint256 boughtAmount = IBancorNetwork(state.bancorNetworkAddress).convertByPath.value(payableAmount)(
|
||||
state.path, // path originating with source token and terminating in destination token
|
||||
fromTokenBalance, // amount of source token to trade
|
||||
amount, // minimum amount of destination token expected to receive
|
||||
to, // beneficiary
|
||||
state.path[state.path.length-1] == BANCOR_ETH_ADDRESS ? address(this) : to, // beneficiary
|
||||
address(0), // affiliateAccount; no fee paid
|
||||
0 // affiliateFee; no fee paid
|
||||
);
|
||||
|
||||
if (state.path[state.path.length-1] == BANCOR_ETH_ADDRESS) {
|
||||
state.weth.deposit.value(boughtAmount)();
|
||||
state.weth.transfer(to, boughtAmount);
|
||||
}
|
||||
|
||||
emit ERC20BridgeTransfer(
|
||||
state.path[0], // fromTokenAddress
|
||||
state.path[0] == BANCOR_ETH_ADDRESS ? address(state.weth) : state.path[0],
|
||||
toTokenAddress,
|
||||
fromTokenBalance,
|
||||
boughtAmount,
|
||||
@@ -118,5 +140,5 @@ contract BancorBridge is
|
||||
{
|
||||
return LEGACY_WALLET_MAGIC_VALUE;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@@ -56,11 +56,14 @@ contract KyberBridge is
|
||||
uint256 constant private KYBER_RATE_BASE = 10 ** 18;
|
||||
|
||||
// solhint-disable no-empty-blocks
|
||||
/// @dev Payable fallback to receive ETH from Kyber.
|
||||
/// @dev Payable fallback to receive ETH from Kyber/WETH.
|
||||
function ()
|
||||
external
|
||||
payable
|
||||
{}
|
||||
{
|
||||
// Poor man's receive in 0.5.9
|
||||
require(msg.data.length == 0);
|
||||
}
|
||||
|
||||
/// @dev Callback for `IKyberBridge`. Tries to buy `amount` of
|
||||
/// `toTokenAddress` tokens by selling the entirety of the opposing asset
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@0x/contracts-asset-proxy",
|
||||
"version": "3.6.9",
|
||||
"version": "3.7.1",
|
||||
"engines": {
|
||||
"node": ">=6.12"
|
||||
},
|
||||
@@ -52,10 +52,10 @@
|
||||
"homepage": "https://github.com/0xProject/protocol/tree/main/contracts/protocol",
|
||||
"devDependencies": {
|
||||
"@0x/abi-gen": "^5.4.13",
|
||||
"@0x/contract-wrappers": "^13.11.0",
|
||||
"@0x/contract-wrappers": "^13.11.1",
|
||||
"@0x/contracts-gen": "^2.0.24",
|
||||
"@0x/contracts-test-utils": "^5.3.15",
|
||||
"@0x/contracts-utils": "^4.6.3",
|
||||
"@0x/contracts-test-utils": "^5.3.16",
|
||||
"@0x/contracts-utils": "^4.6.4",
|
||||
"@0x/dev-utils": "^4.1.3",
|
||||
"@0x/sol-compiler": "^4.4.1",
|
||||
"@0x/ts-doc-gen": "^0.0.28",
|
||||
@@ -80,11 +80,11 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@0x/base-contract": "^6.2.14",
|
||||
"@0x/contracts-erc1155": "^2.1.18",
|
||||
"@0x/contracts-erc20": "^3.2.12",
|
||||
"@0x/contracts-erc721": "^3.1.18",
|
||||
"@0x/contracts-exchange-libs": "^4.3.18",
|
||||
"@0x/order-utils": "^10.4.10",
|
||||
"@0x/contracts-erc1155": "^2.1.19",
|
||||
"@0x/contracts-erc20": "^3.2.13",
|
||||
"@0x/contracts-erc721": "^3.1.19",
|
||||
"@0x/contracts-exchange-libs": "^4.3.19",
|
||||
"@0x/order-utils": "^10.4.11",
|
||||
"@0x/types": "^3.3.1",
|
||||
"@0x/typescript-typings": "^5.1.6",
|
||||
"@0x/utils": "^6.1.1",
|
||||
|
@@ -12,13 +12,11 @@ import { DecodedLogs } from 'ethereum-types';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import { artifacts } from './artifacts';
|
||||
|
||||
import { TestBancorBridgeContract } from './generated-wrappers/test_bancor_bridge';
|
||||
import {
|
||||
TestBancorBridgeConvertByPathInputEventArgs as ConvertByPathArgs,
|
||||
TestBancorBridgeEvents as ContractEvents,
|
||||
TestBancorBridgeTokenApproveEventArgs as TokenApproveArgs,
|
||||
TestBancorBridgeTokenTransferEventArgs as TokenTransferArgs,
|
||||
} from './wrappers';
|
||||
|
||||
blockchainTests.resets('Bancor unit tests', env => {
|
||||
@@ -128,24 +126,6 @@ blockchainTests.resets('Bancor unit tests', env => {
|
||||
expect(result).to.eq(AssetProxyId.ERC20Bridge);
|
||||
});
|
||||
|
||||
it('performs transfer when both tokens are the same', async () => {
|
||||
const createTokenFn = testContract.createToken(constants.NULL_ADDRESS);
|
||||
const tokenAddress = await createTokenFn.callAsync();
|
||||
await createTokenFn.awaitTransactionSuccessAsync();
|
||||
|
||||
const { opts, result, logs } = await transferFromAsync({
|
||||
tokenAddressesPath: [tokenAddress, tokenAddress],
|
||||
});
|
||||
expect(result).to.eq(AssetProxyId.ERC20Bridge, 'asset proxy id');
|
||||
const transfers = filterLogsToArguments<TokenTransferArgs>(logs, ContractEvents.TokenTransfer);
|
||||
|
||||
expect(transfers.length).to.eq(1);
|
||||
expect(transfers[0].token).to.eq(tokenAddress, 'input token address');
|
||||
expect(transfers[0].from).to.eq(testContract.address);
|
||||
expect(transfers[0].to).to.eq(opts.toAddress, 'recipient address');
|
||||
expect(transfers[0].amount).to.bignumber.eq(opts.amount, 'amount');
|
||||
});
|
||||
|
||||
describe('token -> token', async () => {
|
||||
it('calls BancorNetwork.convertByPath()', async () => {
|
||||
const { opts, result, logs } = await transferFromAsync();
|
||||
|
@@ -1,4 +1,22 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1608245516,
|
||||
"version": "1.1.19",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1608105788,
|
||||
"version": "1.1.18",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1607485227,
|
||||
"version": "1.1.17",
|
||||
|
@@ -5,6 +5,14 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
CHANGELOG
|
||||
|
||||
## v1.1.19 - _December 17, 2020_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v1.1.18 - _December 16, 2020_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v1.1.17 - _December 9, 2020_
|
||||
|
||||
* Dependencies updated
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@0x/contracts-broker",
|
||||
"version": "1.1.17",
|
||||
"version": "1.1.19",
|
||||
"engines": {
|
||||
"node": ">=6.12"
|
||||
},
|
||||
@@ -52,14 +52,14 @@
|
||||
"homepage": "https://github.com/0xProject/protocol/tree/main/contracts/extensions",
|
||||
"devDependencies": {
|
||||
"@0x/abi-gen": "^5.4.13",
|
||||
"@0x/contracts-asset-proxy": "^3.6.9",
|
||||
"@0x/contracts-erc20": "^3.2.12",
|
||||
"@0x/contracts-erc721": "^3.1.18",
|
||||
"@0x/contracts-exchange": "^3.2.18",
|
||||
"@0x/contracts-exchange-libs": "^4.3.18",
|
||||
"@0x/contracts-asset-proxy": "^3.7.1",
|
||||
"@0x/contracts-erc20": "^3.2.13",
|
||||
"@0x/contracts-erc721": "^3.1.19",
|
||||
"@0x/contracts-exchange": "^3.2.20",
|
||||
"@0x/contracts-exchange-libs": "^4.3.19",
|
||||
"@0x/contracts-gen": "^2.0.24",
|
||||
"@0x/contracts-test-utils": "^5.3.15",
|
||||
"@0x/contracts-utils": "^4.6.3",
|
||||
"@0x/contracts-test-utils": "^5.3.16",
|
||||
"@0x/contracts-utils": "^4.6.4",
|
||||
"@0x/sol-compiler": "^4.4.1",
|
||||
"@0x/ts-doc-gen": "^0.0.28",
|
||||
"@0x/tslint-config": "^4.1.3",
|
||||
@@ -85,7 +85,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@0x/base-contract": "^6.2.14",
|
||||
"@0x/order-utils": "^10.4.10",
|
||||
"@0x/order-utils": "^10.4.11",
|
||||
"@0x/typescript-typings": "^5.1.6",
|
||||
"@0x/utils": "^6.1.1",
|
||||
"ethereum-types": "^3.4.0"
|
||||
|
@@ -1,4 +1,22 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1608245516,
|
||||
"version": "3.1.20",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1608105788,
|
||||
"version": "3.1.19",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1607485227,
|
||||
"version": "3.1.18",
|
||||
|
@@ -5,6 +5,14 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
CHANGELOG
|
||||
|
||||
## v3.1.20 - _December 17, 2020_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.1.19 - _December 16, 2020_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.1.18 - _December 9, 2020_
|
||||
|
||||
* Dependencies updated
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@0x/contracts-coordinator",
|
||||
"version": "3.1.18",
|
||||
"version": "3.1.20",
|
||||
"engines": {
|
||||
"node": ">=6.12"
|
||||
},
|
||||
@@ -53,12 +53,12 @@
|
||||
"homepage": "https://github.com/0xProject/protocol/tree/main/contracts/extensions",
|
||||
"devDependencies": {
|
||||
"@0x/abi-gen": "^5.4.13",
|
||||
"@0x/contracts-asset-proxy": "^3.6.9",
|
||||
"@0x/contracts-dev-utils": "^1.3.16",
|
||||
"@0x/contracts-erc20": "^3.2.12",
|
||||
"@0x/contracts-asset-proxy": "^3.7.1",
|
||||
"@0x/contracts-dev-utils": "^1.3.18",
|
||||
"@0x/contracts-erc20": "^3.2.13",
|
||||
"@0x/contracts-gen": "^2.0.24",
|
||||
"@0x/dev-utils": "^4.1.3",
|
||||
"@0x/order-utils": "^10.4.10",
|
||||
"@0x/order-utils": "^10.4.11",
|
||||
"@0x/sol-compiler": "^4.4.1",
|
||||
"@0x/ts-doc-gen": "^0.0.28",
|
||||
"@0x/tslint-config": "^4.1.3",
|
||||
@@ -84,10 +84,10 @@
|
||||
"dependencies": {
|
||||
"@0x/assert": "^3.0.19",
|
||||
"@0x/base-contract": "^6.2.14",
|
||||
"@0x/contract-addresses": "^5.6.0",
|
||||
"@0x/contracts-exchange": "^3.2.18",
|
||||
"@0x/contracts-test-utils": "^5.3.15",
|
||||
"@0x/contracts-utils": "^4.6.3",
|
||||
"@0x/contract-addresses": "^5.7.0",
|
||||
"@0x/contracts-exchange": "^3.2.20",
|
||||
"@0x/contracts-test-utils": "^5.3.16",
|
||||
"@0x/contracts-utils": "^4.6.4",
|
||||
"@0x/json-schemas": "^5.3.4",
|
||||
"@0x/types": "^3.3.1",
|
||||
"@0x/typescript-typings": "^5.1.6",
|
||||
|
@@ -1,4 +1,22 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1608245516,
|
||||
"version": "1.3.18",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1608105788,
|
||||
"version": "1.3.17",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1607485227,
|
||||
"version": "1.3.16",
|
||||
|
@@ -5,6 +5,14 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
CHANGELOG
|
||||
|
||||
## v1.3.18 - _December 17, 2020_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v1.3.17 - _December 16, 2020_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v1.3.16 - _December 9, 2020_
|
||||
|
||||
* Dependencies updated
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@0x/contracts-dev-utils",
|
||||
"version": "1.3.16",
|
||||
"version": "1.3.18",
|
||||
"engines": {
|
||||
"node": ">=6.12"
|
||||
},
|
||||
@@ -43,10 +43,10 @@
|
||||
"devDependencies": {
|
||||
"@0x/abi-gen": "^5.4.13",
|
||||
"@0x/assert": "^3.0.19",
|
||||
"@0x/contracts-asset-proxy": "^3.6.9",
|
||||
"@0x/contracts-erc20": "^3.2.12",
|
||||
"@0x/contracts-asset-proxy": "^3.7.1",
|
||||
"@0x/contracts-erc20": "^3.2.13",
|
||||
"@0x/contracts-gen": "^2.0.24",
|
||||
"@0x/contracts-test-utils": "^5.3.15",
|
||||
"@0x/contracts-test-utils": "^5.3.16",
|
||||
"@0x/sol-compiler": "^4.4.1",
|
||||
"@0x/ts-doc-gen": "^0.0.28",
|
||||
"@0x/tslint-config": "^4.1.3",
|
||||
|
@@ -1,4 +1,13 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1608245516,
|
||||
"version": "2.1.19",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1607485227,
|
||||
"version": "2.1.18",
|
||||
|
@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
CHANGELOG
|
||||
|
||||
## v2.1.19 - _December 17, 2020_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v2.1.18 - _December 9, 2020_
|
||||
|
||||
* Dependencies updated
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@0x/contracts-erc1155",
|
||||
"version": "2.1.18",
|
||||
"version": "2.1.19",
|
||||
"engines": {
|
||||
"node": ">=6.12"
|
||||
},
|
||||
@@ -54,7 +54,7 @@
|
||||
"devDependencies": {
|
||||
"@0x/abi-gen": "^5.4.13",
|
||||
"@0x/contracts-gen": "^2.0.24",
|
||||
"@0x/contracts-utils": "^4.6.3",
|
||||
"@0x/contracts-utils": "^4.6.4",
|
||||
"@0x/dev-utils": "^4.1.3",
|
||||
"@0x/sol-compiler": "^4.4.1",
|
||||
"@0x/ts-doc-gen": "^0.0.28",
|
||||
@@ -81,7 +81,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@0x/base-contract": "^6.2.14",
|
||||
"@0x/contracts-test-utils": "^5.3.15",
|
||||
"@0x/contracts-test-utils": "^5.3.16",
|
||||
"@0x/utils": "^6.1.1",
|
||||
"@0x/web3-wrapper": "^7.3.0",
|
||||
"lodash": "^4.17.11"
|
||||
|
@@ -1,4 +1,13 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1608245516,
|
||||
"version": "3.2.13",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1607485227,
|
||||
"version": "3.2.12",
|
||||
|
@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
CHANGELOG
|
||||
|
||||
## v3.2.13 - _December 17, 2020_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.2.12 - _December 9, 2020_
|
||||
|
||||
* Dependencies updated
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@0x/contracts-erc20",
|
||||
"version": "3.2.12",
|
||||
"version": "3.2.13",
|
||||
"engines": {
|
||||
"node": ">=6.12"
|
||||
},
|
||||
@@ -53,8 +53,8 @@
|
||||
"devDependencies": {
|
||||
"@0x/abi-gen": "^5.4.13",
|
||||
"@0x/contracts-gen": "^2.0.24",
|
||||
"@0x/contracts-test-utils": "^5.3.15",
|
||||
"@0x/contracts-utils": "^4.6.3",
|
||||
"@0x/contracts-test-utils": "^5.3.16",
|
||||
"@0x/contracts-utils": "^4.6.4",
|
||||
"@0x/dev-utils": "^4.1.3",
|
||||
"@0x/sol-compiler": "^4.4.1",
|
||||
"@0x/ts-doc-gen": "^0.0.28",
|
||||
|
@@ -1,4 +1,13 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1608245516,
|
||||
"version": "3.1.19",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1607485227,
|
||||
"version": "3.1.18",
|
||||
|
@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
CHANGELOG
|
||||
|
||||
## v3.1.19 - _December 17, 2020_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.1.18 - _December 9, 2020_
|
||||
|
||||
* Dependencies updated
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@0x/contracts-erc721",
|
||||
"version": "3.1.18",
|
||||
"version": "3.1.19",
|
||||
"engines": {
|
||||
"node": ">=6.12"
|
||||
},
|
||||
@@ -54,8 +54,8 @@
|
||||
"devDependencies": {
|
||||
"@0x/abi-gen": "^5.4.13",
|
||||
"@0x/contracts-gen": "^2.0.24",
|
||||
"@0x/contracts-test-utils": "^5.3.15",
|
||||
"@0x/contracts-utils": "^4.6.3",
|
||||
"@0x/contracts-test-utils": "^5.3.16",
|
||||
"@0x/contracts-utils": "^4.6.4",
|
||||
"@0x/dev-utils": "^4.1.3",
|
||||
"@0x/sol-compiler": "^4.4.1",
|
||||
"@0x/ts-doc-gen": "^0.0.28",
|
||||
|
@@ -1,4 +1,22 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1608245516,
|
||||
"version": "4.2.20",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1608105788,
|
||||
"version": "4.2.19",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1607485227,
|
||||
"version": "4.2.18",
|
||||
|
@@ -5,6 +5,14 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
CHANGELOG
|
||||
|
||||
## v4.2.20 - _December 17, 2020_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v4.2.19 - _December 16, 2020_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v4.2.18 - _December 9, 2020_
|
||||
|
||||
* Dependencies updated
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@0x/contracts-exchange-forwarder",
|
||||
"version": "4.2.18",
|
||||
"version": "4.2.20",
|
||||
"engines": {
|
||||
"node": ">=6.12"
|
||||
},
|
||||
@@ -53,18 +53,18 @@
|
||||
"homepage": "https://github.com/0xProject/protocol/tree/main/contracts/extensions",
|
||||
"devDependencies": {
|
||||
"@0x/abi-gen": "^5.4.13",
|
||||
"@0x/contracts-asset-proxy": "^3.6.9",
|
||||
"@0x/contracts-dev-utils": "^1.3.16",
|
||||
"@0x/contracts-erc1155": "^2.1.18",
|
||||
"@0x/contracts-erc20": "^3.2.12",
|
||||
"@0x/contracts-erc721": "^3.1.18",
|
||||
"@0x/contracts-exchange": "^3.2.18",
|
||||
"@0x/contracts-exchange-libs": "^4.3.18",
|
||||
"@0x/contracts-asset-proxy": "^3.7.1",
|
||||
"@0x/contracts-dev-utils": "^1.3.18",
|
||||
"@0x/contracts-erc1155": "^2.1.19",
|
||||
"@0x/contracts-erc20": "^3.2.13",
|
||||
"@0x/contracts-erc721": "^3.1.19",
|
||||
"@0x/contracts-exchange": "^3.2.20",
|
||||
"@0x/contracts-exchange-libs": "^4.3.19",
|
||||
"@0x/contracts-gen": "^2.0.24",
|
||||
"@0x/contracts-test-utils": "^5.3.15",
|
||||
"@0x/contracts-utils": "^4.6.3",
|
||||
"@0x/contracts-test-utils": "^5.3.16",
|
||||
"@0x/contracts-utils": "^4.6.4",
|
||||
"@0x/dev-utils": "^4.1.3",
|
||||
"@0x/order-utils": "^10.4.10",
|
||||
"@0x/order-utils": "^10.4.11",
|
||||
"@0x/sol-compiler": "^4.4.1",
|
||||
"@0x/ts-doc-gen": "^0.0.28",
|
||||
"@0x/tslint-config": "^4.1.3",
|
||||
|
@@ -1,4 +1,13 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1608245516,
|
||||
"version": "4.3.19",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1607485227,
|
||||
"version": "4.3.18",
|
||||
|
@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
CHANGELOG
|
||||
|
||||
## v4.3.19 - _December 17, 2020_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v4.3.18 - _December 9, 2020_
|
||||
|
||||
* Dependencies updated
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@0x/contracts-exchange-libs",
|
||||
"version": "4.3.18",
|
||||
"version": "4.3.19",
|
||||
"engines": {
|
||||
"node": ">=6.12"
|
||||
},
|
||||
@@ -81,9 +81,9 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@0x/base-contract": "^6.2.14",
|
||||
"@0x/contracts-test-utils": "^5.3.15",
|
||||
"@0x/contracts-utils": "^4.6.3",
|
||||
"@0x/order-utils": "^10.4.10",
|
||||
"@0x/contracts-test-utils": "^5.3.16",
|
||||
"@0x/contracts-utils": "^4.6.4",
|
||||
"@0x/order-utils": "^10.4.11",
|
||||
"@0x/types": "^3.3.1",
|
||||
"@0x/typescript-typings": "^5.1.6",
|
||||
"@0x/utils": "^6.1.1",
|
||||
|
@@ -1,4 +1,22 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1608245516,
|
||||
"version": "3.2.20",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1608105788,
|
||||
"version": "3.2.19",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1607485227,
|
||||
"version": "3.2.18",
|
||||
|
@@ -5,6 +5,14 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
CHANGELOG
|
||||
|
||||
## v3.2.20 - _December 17, 2020_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.2.19 - _December 16, 2020_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.2.18 - _December 9, 2020_
|
||||
|
||||
* Dependencies updated
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@0x/contracts-exchange",
|
||||
"version": "3.2.18",
|
||||
"version": "3.2.20",
|
||||
"engines": {
|
||||
"node": ">=6.12"
|
||||
},
|
||||
@@ -53,13 +53,13 @@
|
||||
"homepage": "https://github.com/0xProject/protocol/tree/main/contracts/protocol",
|
||||
"devDependencies": {
|
||||
"@0x/abi-gen": "^5.4.13",
|
||||
"@0x/contracts-asset-proxy": "^3.6.9",
|
||||
"@0x/contracts-exchange-libs": "^4.3.18",
|
||||
"@0x/contracts-asset-proxy": "^3.7.1",
|
||||
"@0x/contracts-exchange-libs": "^4.3.19",
|
||||
"@0x/contracts-gen": "^2.0.24",
|
||||
"@0x/contracts-multisig": "^4.1.18",
|
||||
"@0x/contracts-staking": "^2.0.25",
|
||||
"@0x/contracts-test-utils": "^5.3.15",
|
||||
"@0x/contracts-utils": "^4.6.3",
|
||||
"@0x/contracts-multisig": "^4.1.20",
|
||||
"@0x/contracts-staking": "^2.0.27",
|
||||
"@0x/contracts-test-utils": "^5.3.16",
|
||||
"@0x/contracts-utils": "^4.6.4",
|
||||
"@0x/dev-utils": "^4.1.3",
|
||||
"@0x/sol-compiler": "^4.4.1",
|
||||
"@0x/ts-doc-gen": "^0.0.28",
|
||||
@@ -89,11 +89,11 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@0x/base-contract": "^6.2.14",
|
||||
"@0x/contracts-dev-utils": "^1.3.16",
|
||||
"@0x/contracts-erc1155": "^2.1.18",
|
||||
"@0x/contracts-erc20": "^3.2.12",
|
||||
"@0x/contracts-erc721": "^3.1.18",
|
||||
"@0x/order-utils": "^10.4.10",
|
||||
"@0x/contracts-dev-utils": "^1.3.18",
|
||||
"@0x/contracts-erc1155": "^2.1.19",
|
||||
"@0x/contracts-erc20": "^3.2.13",
|
||||
"@0x/contracts-erc721": "^3.1.19",
|
||||
"@0x/order-utils": "^10.4.11",
|
||||
"@0x/utils": "^6.1.1",
|
||||
"lodash": "^4.17.11"
|
||||
},
|
||||
|
@@ -1,4 +1,22 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1608245516,
|
||||
"version": "6.2.14",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1608105788,
|
||||
"version": "6.2.13",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1607485227,
|
||||
"version": "6.2.12",
|
||||
|
@@ -5,6 +5,14 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
CHANGELOG
|
||||
|
||||
## v6.2.14 - _December 17, 2020_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v6.2.13 - _December 16, 2020_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v6.2.12 - _December 9, 2020_
|
||||
|
||||
* Dependencies updated
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@0x/contracts-extensions",
|
||||
"version": "6.2.12",
|
||||
"version": "6.2.14",
|
||||
"engines": {
|
||||
"node": ">=6.12"
|
||||
},
|
||||
@@ -53,16 +53,16 @@
|
||||
"homepage": "https://github.com/0xProject/protocol/tree/main/contracts/extensions",
|
||||
"devDependencies": {
|
||||
"@0x/abi-gen": "^5.4.13",
|
||||
"@0x/contracts-asset-proxy": "^3.6.9",
|
||||
"@0x/contracts-dev-utils": "^1.3.16",
|
||||
"@0x/contracts-erc20": "^3.2.12",
|
||||
"@0x/contracts-erc721": "^3.1.18",
|
||||
"@0x/contracts-exchange": "^3.2.18",
|
||||
"@0x/contracts-exchange-libs": "^4.3.18",
|
||||
"@0x/contracts-asset-proxy": "^3.7.1",
|
||||
"@0x/contracts-dev-utils": "^1.3.18",
|
||||
"@0x/contracts-erc20": "^3.2.13",
|
||||
"@0x/contracts-erc721": "^3.1.19",
|
||||
"@0x/contracts-exchange": "^3.2.20",
|
||||
"@0x/contracts-exchange-libs": "^4.3.19",
|
||||
"@0x/contracts-gen": "^2.0.24",
|
||||
"@0x/contracts-utils": "^4.6.3",
|
||||
"@0x/contracts-utils": "^4.6.4",
|
||||
"@0x/dev-utils": "^4.1.3",
|
||||
"@0x/order-utils": "^10.4.10",
|
||||
"@0x/order-utils": "^10.4.11",
|
||||
"@0x/sol-compiler": "^4.4.1",
|
||||
"@0x/ts-doc-gen": "^0.0.28",
|
||||
"@0x/tslint-config": "^4.1.3",
|
||||
@@ -91,7 +91,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@0x/base-contract": "^6.2.14",
|
||||
"@0x/contracts-test-utils": "^5.3.15",
|
||||
"@0x/contracts-test-utils": "^5.3.16",
|
||||
"@0x/typescript-typings": "^5.1.6",
|
||||
"ethereum-types": "^3.4.0"
|
||||
},
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@0x/contracts-integrations",
|
||||
"version": "2.7.15",
|
||||
"version": "2.7.18",
|
||||
"private": true,
|
||||
"engines": {
|
||||
"node": ">=6.12"
|
||||
@@ -53,21 +53,21 @@
|
||||
"homepage": "https://github.com/0xProject/protocol/tree/main/contracts/extensions",
|
||||
"devDependencies": {
|
||||
"@0x/abi-gen": "^5.4.13",
|
||||
"@0x/contract-addresses": "^5.6.0",
|
||||
"@0x/contract-wrappers": "^13.11.0",
|
||||
"@0x/contracts-broker": "^1.1.17",
|
||||
"@0x/contracts-coordinator": "^3.1.18",
|
||||
"@0x/contracts-dev-utils": "^1.3.16",
|
||||
"@0x/contracts-exchange-forwarder": "^4.2.18",
|
||||
"@0x/contracts-exchange-libs": "^4.3.18",
|
||||
"@0x/contracts-extensions": "^6.2.12",
|
||||
"@0x/contract-addresses": "^5.7.0",
|
||||
"@0x/contract-wrappers": "^13.11.1",
|
||||
"@0x/contracts-broker": "^1.1.19",
|
||||
"@0x/contracts-coordinator": "^3.1.20",
|
||||
"@0x/contracts-dev-utils": "^1.3.18",
|
||||
"@0x/contracts-exchange-forwarder": "^4.2.20",
|
||||
"@0x/contracts-exchange-libs": "^4.3.19",
|
||||
"@0x/contracts-extensions": "^6.2.14",
|
||||
"@0x/contracts-gen": "^2.0.24",
|
||||
"@0x/contracts-utils": "^4.6.3",
|
||||
"@0x/contracts-utils": "^4.6.4",
|
||||
"@0x/coordinator-server": "^1.0.5",
|
||||
"@0x/dev-utils": "^4.1.3",
|
||||
"@0x/migrations": "^6.5.4",
|
||||
"@0x/order-utils": "^10.4.10",
|
||||
"@0x/protocol-utils": "^1.0.1",
|
||||
"@0x/migrations": "^6.5.7",
|
||||
"@0x/order-utils": "^10.4.11",
|
||||
"@0x/protocol-utils": "^1.1.1",
|
||||
"@0x/sol-compiler": "^4.4.1",
|
||||
"@0x/tslint-config": "^4.1.3",
|
||||
"@0x/web3-wrapper": "^7.3.0",
|
||||
@@ -93,17 +93,17 @@
|
||||
"typescript": "3.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@0x/asset-swapper": "^5.4.2",
|
||||
"@0x/asset-swapper": "^5.5.2",
|
||||
"@0x/base-contract": "^6.2.14",
|
||||
"@0x/contracts-asset-proxy": "^3.6.9",
|
||||
"@0x/contracts-erc1155": "^2.1.18",
|
||||
"@0x/contracts-erc20": "^3.2.12",
|
||||
"@0x/contracts-erc721": "^3.1.18",
|
||||
"@0x/contracts-exchange": "^3.2.18",
|
||||
"@0x/contracts-multisig": "^4.1.18",
|
||||
"@0x/contracts-staking": "^2.0.25",
|
||||
"@0x/contracts-test-utils": "^5.3.15",
|
||||
"@0x/contracts-zero-ex": "^0.12.0",
|
||||
"@0x/contracts-asset-proxy": "^3.7.1",
|
||||
"@0x/contracts-erc1155": "^2.1.19",
|
||||
"@0x/contracts-erc20": "^3.2.13",
|
||||
"@0x/contracts-erc721": "^3.1.19",
|
||||
"@0x/contracts-exchange": "^3.2.20",
|
||||
"@0x/contracts-multisig": "^4.1.20",
|
||||
"@0x/contracts-staking": "^2.0.27",
|
||||
"@0x/contracts-test-utils": "^5.3.16",
|
||||
"@0x/contracts-zero-ex": "^0.15.0",
|
||||
"@0x/subproviders": "^6.2.3",
|
||||
"@0x/types": "^3.3.1",
|
||||
"@0x/typescript-typings": "^5.1.6",
|
||||
|
@@ -1,4 +1,22 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1608245516,
|
||||
"version": "4.1.20",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1608105788,
|
||||
"version": "4.1.19",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1607485227,
|
||||
"version": "4.1.18",
|
||||
|
@@ -5,6 +5,14 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
CHANGELOG
|
||||
|
||||
## v4.1.20 - _December 17, 2020_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v4.1.19 - _December 16, 2020_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v4.1.18 - _December 9, 2020_
|
||||
|
||||
* Dependencies updated
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@0x/contracts-multisig",
|
||||
"version": "4.1.18",
|
||||
"version": "4.1.20",
|
||||
"engines": {
|
||||
"node": ">=6.12"
|
||||
},
|
||||
@@ -50,11 +50,11 @@
|
||||
"homepage": "https://github.com/0xProject/protocol/tree/main/contracts/multisig",
|
||||
"devDependencies": {
|
||||
"@0x/abi-gen": "^5.4.13",
|
||||
"@0x/contracts-asset-proxy": "^3.6.9",
|
||||
"@0x/contracts-erc20": "^3.2.12",
|
||||
"@0x/contracts-asset-proxy": "^3.7.1",
|
||||
"@0x/contracts-erc20": "^3.2.13",
|
||||
"@0x/contracts-gen": "^2.0.24",
|
||||
"@0x/contracts-test-utils": "^5.3.15",
|
||||
"@0x/contracts-utils": "^4.6.3",
|
||||
"@0x/contracts-test-utils": "^5.3.16",
|
||||
"@0x/contracts-utils": "^4.6.4",
|
||||
"@0x/dev-utils": "^4.1.3",
|
||||
"@0x/sol-compiler": "^4.4.1",
|
||||
"@0x/tslint-config": "^4.1.3",
|
||||
|
@@ -1,4 +1,22 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1608245516,
|
||||
"version": "2.0.27",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1608105788,
|
||||
"version": "2.0.26",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1607485227,
|
||||
"version": "2.0.25",
|
||||
|
@@ -5,6 +5,14 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
CHANGELOG
|
||||
|
||||
## v2.0.27 - _December 17, 2020_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v2.0.26 - _December 16, 2020_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v2.0.25 - _December 9, 2020_
|
||||
|
||||
* Dependencies updated
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@0x/contracts-staking",
|
||||
"version": "2.0.25",
|
||||
"version": "2.0.27",
|
||||
"engines": {
|
||||
"node": ">=6.12"
|
||||
},
|
||||
@@ -54,14 +54,14 @@
|
||||
"homepage": "https://github.com/0xProject/protocol/tree/main/contracts/tokens",
|
||||
"devDependencies": {
|
||||
"@0x/abi-gen": "^5.4.13",
|
||||
"@0x/contracts-asset-proxy": "^3.6.9",
|
||||
"@0x/contracts-dev-utils": "^1.3.16",
|
||||
"@0x/contracts-erc20": "^3.2.12",
|
||||
"@0x/contracts-exchange-libs": "^4.3.18",
|
||||
"@0x/contracts-asset-proxy": "^3.7.1",
|
||||
"@0x/contracts-dev-utils": "^1.3.18",
|
||||
"@0x/contracts-erc20": "^3.2.13",
|
||||
"@0x/contracts-exchange-libs": "^4.3.19",
|
||||
"@0x/contracts-gen": "^2.0.24",
|
||||
"@0x/contracts-utils": "^4.6.3",
|
||||
"@0x/contracts-utils": "^4.6.4",
|
||||
"@0x/dev-utils": "^4.1.3",
|
||||
"@0x/order-utils": "^10.4.10",
|
||||
"@0x/order-utils": "^10.4.11",
|
||||
"@0x/sol-compiler": "^4.4.1",
|
||||
"@0x/ts-doc-gen": "^0.0.28",
|
||||
"@0x/tslint-config": "^4.1.3",
|
||||
@@ -88,7 +88,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@0x/base-contract": "^6.2.14",
|
||||
"@0x/contracts-test-utils": "^5.3.15",
|
||||
"@0x/contracts-test-utils": "^5.3.16",
|
||||
"@0x/typescript-typings": "^5.1.6",
|
||||
"@0x/utils": "^6.1.1",
|
||||
"ethereum-types": "^3.4.0",
|
||||
|
@@ -1,4 +1,13 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1608245516,
|
||||
"version": "5.3.16",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1607485227,
|
||||
"version": "5.3.15",
|
||||
|
@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
CHANGELOG
|
||||
|
||||
## v5.3.16 - _December 17, 2020_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v5.3.15 - _December 9, 2020_
|
||||
|
||||
* Dependencies updated
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@0x/contracts-test-utils",
|
||||
"version": "5.3.15",
|
||||
"version": "5.3.16",
|
||||
"engines": {
|
||||
"node": ">=6.12"
|
||||
},
|
||||
@@ -44,10 +44,10 @@
|
||||
"dependencies": {
|
||||
"@0x/assert": "^3.0.19",
|
||||
"@0x/base-contract": "^6.2.14",
|
||||
"@0x/contract-addresses": "^5.6.0",
|
||||
"@0x/contract-addresses": "^5.7.0",
|
||||
"@0x/dev-utils": "^4.1.3",
|
||||
"@0x/json-schemas": "^5.3.4",
|
||||
"@0x/order-utils": "^10.4.10",
|
||||
"@0x/order-utils": "^10.4.11",
|
||||
"@0x/sol-coverage": "^4.0.24",
|
||||
"@0x/sol-profiler": "^4.1.14",
|
||||
"@0x/sol-trace": "^3.0.24",
|
||||
|
@@ -1,4 +1,13 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1608245516,
|
||||
"version": "4.6.4",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1607485227,
|
||||
"version": "4.6.3",
|
||||
|
@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
CHANGELOG
|
||||
|
||||
## v4.6.4 - _December 17, 2020_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v4.6.3 - _December 9, 2020_
|
||||
|
||||
* Dependencies updated
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@0x/contracts-utils",
|
||||
"version": "4.6.3",
|
||||
"version": "4.6.4",
|
||||
"engines": {
|
||||
"node": ">=6.12"
|
||||
},
|
||||
@@ -52,9 +52,9 @@
|
||||
"devDependencies": {
|
||||
"@0x/abi-gen": "^5.4.13",
|
||||
"@0x/contracts-gen": "^2.0.24",
|
||||
"@0x/contracts-test-utils": "^5.3.15",
|
||||
"@0x/contracts-test-utils": "^5.3.16",
|
||||
"@0x/dev-utils": "^4.1.3",
|
||||
"@0x/order-utils": "^10.4.10",
|
||||
"@0x/order-utils": "^10.4.11",
|
||||
"@0x/sol-compiler": "^4.4.1",
|
||||
"@0x/tslint-config": "^4.1.3",
|
||||
"@0x/types": "^3.3.1",
|
||||
|
@@ -8,3 +8,4 @@
|
||||
# Blacklist tests in lib
|
||||
/lib/test/*
|
||||
# Package specific ignore
|
||||
/lib/scripts/*
|
||||
|
@@ -1,4 +1,46 @@
|
||||
[
|
||||
{
|
||||
"version": "0.15.0",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Add MixinBancor to BridgeAdapter",
|
||||
"pr": 91
|
||||
},
|
||||
{
|
||||
"note": "Add MixinCoFiX to BridgeAdapter",
|
||||
"pr": 92
|
||||
}
|
||||
],
|
||||
"timestamp": 1608245516
|
||||
},
|
||||
{
|
||||
"version": "0.14.0",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Use the `MetaTransaction` class from `@0x/protocol-utils` in tests.",
|
||||
"pr": 90
|
||||
}
|
||||
],
|
||||
"timestamp": 1608149382
|
||||
},
|
||||
{
|
||||
"version": "0.13.0",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Address audit feedback in UniswapFeature",
|
||||
"pr": 82
|
||||
},
|
||||
{
|
||||
"note": "Always transfer `msg.value` to the liquidity provider contract in LiquidityProviderFeature to",
|
||||
"pr": 82
|
||||
},
|
||||
{
|
||||
"note": "Remove backwards compatibility with old PLP/bridge interface in `LiquidityProviderFeature` and `MixinZeroExBridge`",
|
||||
"pr": 85
|
||||
}
|
||||
],
|
||||
"timestamp": 1608105788
|
||||
},
|
||||
{
|
||||
"version": "0.12.0",
|
||||
"changes": [
|
||||
|
@@ -5,6 +5,21 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
CHANGELOG
|
||||
|
||||
## v0.15.0 - _December 17, 2020_
|
||||
|
||||
* Add MixinBancor to BridgeAdapter (#91)
|
||||
* Add MixinCoFiX to BridgeAdapter (#92)
|
||||
|
||||
## v0.14.0 - _December 16, 2020_
|
||||
|
||||
* Use the `MetaTransaction` class from `@0x/protocol-utils` in tests. (#90)
|
||||
|
||||
## v0.13.0 - _December 16, 2020_
|
||||
|
||||
* Address audit feedback in UniswapFeature (#82)
|
||||
* Always transfer `msg.value` to the liquidity provider contract in LiquidityProviderFeature to (#82)
|
||||
* Remove backwards compatibility with old PLP/bridge interface in `LiquidityProviderFeature` and `MixinZeroExBridge` (#85)
|
||||
|
||||
## v0.12.0 - _December 9, 2020_
|
||||
|
||||
* Add test for selector collisions on the proxy (#74)
|
||||
|
@@ -57,7 +57,6 @@ contract FeeCollector is AuthorizableV06 {
|
||||
external
|
||||
onlyAuthorized
|
||||
{
|
||||
// Leave 1 wei behind to avoid expensive zero-->non-zero state change.
|
||||
if (address(this).balance > 0) {
|
||||
weth.deposit{value: address(this).balance}();
|
||||
}
|
||||
|
@@ -68,21 +68,13 @@ contract LiquidityProviderSandbox is
|
||||
onlyOwner
|
||||
override
|
||||
{
|
||||
try ILiquidityProvider(provider).sellTokenForToken(
|
||||
ILiquidityProvider(provider).sellTokenForToken(
|
||||
inputToken,
|
||||
outputToken,
|
||||
recipient,
|
||||
minBuyAmount,
|
||||
auxiliaryData
|
||||
) {} catch {
|
||||
IERC20Bridge(provider).bridgeTransferFrom(
|
||||
outputToken,
|
||||
provider,
|
||||
recipient,
|
||||
minBuyAmount,
|
||||
auxiliaryData
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/// @dev Calls `sellEthForToken` on the given `provider` contract to
|
||||
|
@@ -44,7 +44,7 @@ contract LiquidityProviderFeature is
|
||||
/// @dev Name of this feature.
|
||||
string public constant override FEATURE_NAME = "LiquidityProviderFeature";
|
||||
/// @dev Version of this feature.
|
||||
uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 0, 1);
|
||||
uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 0, 2);
|
||||
|
||||
/// @dev ETH pseudo-token address.
|
||||
address constant internal ETH_TOKEN_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
|
||||
@@ -111,9 +111,13 @@ contract LiquidityProviderFeature is
|
||||
recipient = msg.sender;
|
||||
}
|
||||
|
||||
if (inputToken == ETH_TOKEN_ADDRESS) {
|
||||
provider.transfer(sellAmount);
|
||||
} else {
|
||||
// Forward all attached ETH to the provider.
|
||||
if (msg.value > 0) {
|
||||
provider.transfer(msg.value);
|
||||
}
|
||||
|
||||
if (inputToken != ETH_TOKEN_ADDRESS) {
|
||||
// Transfer input ERC20 tokens to the provider.
|
||||
_transferERC20Tokens(
|
||||
IERC20TokenV06(inputToken),
|
||||
msg.sender,
|
||||
|
@@ -37,7 +37,7 @@ contract UniswapFeature is
|
||||
/// @dev Name of this feature.
|
||||
string public constant override FEATURE_NAME = "UniswapFeature";
|
||||
/// @dev Version of this feature.
|
||||
uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 1, 0);
|
||||
uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 1, 1);
|
||||
/// @dev A bloom filter for tokens that consume all gas when `transferFrom()` fails.
|
||||
bytes32 public immutable GREEDY_TOKENS_BLOOM_FILTER;
|
||||
/// @dev WETH contract.
|
||||
@@ -167,8 +167,13 @@ contract UniswapFeature is
|
||||
}
|
||||
|
||||
if iszero(i) {
|
||||
// This is the first token in the path.
|
||||
switch eq(sellToken, ETH_TOKEN_ADDRESS_32)
|
||||
case 0 { // Not selling ETH. Selling an ERC20 instead.
|
||||
// Make sure ETH was not attached to the call.
|
||||
if gt(callvalue(), 0) {
|
||||
revert(0, 0)
|
||||
}
|
||||
// For the first pair we need to transfer sellTokens into the
|
||||
// pair contract.
|
||||
moveTakerTokensTo(sellToken, pair, sellAmount)
|
||||
@@ -203,6 +208,10 @@ contract UniswapFeature is
|
||||
if iszero(staticcall(gas(), pair, 0xB00, 0x4, 0xC00, 0x40)) {
|
||||
bubbleRevert()
|
||||
}
|
||||
// Revert if the pair contract does not return two words.
|
||||
if iszero(eq(returndatasize(), 0x40)) {
|
||||
revert(0,0)
|
||||
}
|
||||
|
||||
// Sell amount for this hop is the previous buy amount.
|
||||
let pairSellAmount := buyAmount
|
||||
@@ -374,11 +383,15 @@ contract UniswapFeature is
|
||||
mstore(0xB00, ALLOWANCE_CALL_SELECTOR_32)
|
||||
mstore(0xB04, caller())
|
||||
mstore(0xB24, address())
|
||||
let success := call(gas(), token, 0, 0xB00, 0x44, 0xC00, 0x20)
|
||||
let success := staticcall(gas(), token, 0xB00, 0x44, 0xC00, 0x20)
|
||||
if iszero(success) {
|
||||
// Call to allowance() failed.
|
||||
bubbleRevert()
|
||||
}
|
||||
// Make sure the allowance call returned a single word.
|
||||
if iszero(eq(returndatasize(), 0x20)) {
|
||||
revert(0, 0)
|
||||
}
|
||||
// Call succeeded.
|
||||
// Result is stored in 0xC00-0xC20.
|
||||
if lt(mload(0xC00), amount) {
|
||||
@@ -397,8 +410,6 @@ contract UniswapFeature is
|
||||
mstore(0xB44, amount)
|
||||
|
||||
let success := call(
|
||||
// Cap the gas limit to prvent all gas being consumed
|
||||
// if the token reverts.
|
||||
gas(),
|
||||
token,
|
||||
0,
|
||||
|
@@ -21,6 +21,8 @@ pragma experimental ABIEncoderV2;
|
||||
|
||||
import "./mixins/MixinAdapterAddresses.sol";
|
||||
import "./mixins/MixinBalancer.sol";
|
||||
import "./mixins/MixinBancor.sol";
|
||||
import "./mixins/MixinCoFiX.sol";
|
||||
import "./mixins/MixinCurve.sol";
|
||||
import "./mixins/MixinCryptoCom.sol";
|
||||
import "./mixins/MixinDodo.sol";
|
||||
@@ -37,6 +39,8 @@ import "./mixins/MixinZeroExBridge.sol";
|
||||
contract BridgeAdapter is
|
||||
MixinAdapterAddresses,
|
||||
MixinBalancer,
|
||||
MixinBancor,
|
||||
MixinCoFiX,
|
||||
MixinCurve,
|
||||
MixinCryptoCom,
|
||||
MixinDodo,
|
||||
@@ -51,7 +55,25 @@ contract BridgeAdapter is
|
||||
MixinZeroExBridge
|
||||
{
|
||||
|
||||
/// @dev Emitted when a trade occurs.
|
||||
/// @param inputToken The token the bridge is converting from.
|
||||
/// @param outputToken The token the bridge is converting to.
|
||||
/// @param inputTokenAmount Amount of input token.
|
||||
/// @param outputTokenAmount Amount of output token.
|
||||
/// @param from The bridge address, indicating the underlying source of the fill.
|
||||
/// @param to The `to` address, currrently `address(this)`
|
||||
event ERC20BridgeTransfer(
|
||||
IERC20TokenV06 inputToken,
|
||||
IERC20TokenV06 outputToken,
|
||||
uint256 inputTokenAmount,
|
||||
uint256 outputTokenAmount,
|
||||
address from,
|
||||
address to
|
||||
);
|
||||
|
||||
address private immutable BALANCER_BRIDGE_ADDRESS;
|
||||
address private immutable BANCOR_BRIDGE_ADDRESS;
|
||||
address private immutable COFIX_BRIDGE_ADDRESS;
|
||||
address private immutable CREAM_BRIDGE_ADDRESS;
|
||||
address private immutable CURVE_BRIDGE_ADDRESS;
|
||||
address private immutable CRYPTO_COM_BRIDGE_ADDRESS;
|
||||
@@ -70,6 +92,8 @@ contract BridgeAdapter is
|
||||
constructor(AdapterAddresses memory addresses)
|
||||
public
|
||||
MixinBalancer()
|
||||
MixinBancor(addresses)
|
||||
MixinCoFiX()
|
||||
MixinCurve()
|
||||
MixinCryptoCom(addresses)
|
||||
MixinDodo(addresses)
|
||||
@@ -84,6 +108,8 @@ contract BridgeAdapter is
|
||||
MixinZeroExBridge()
|
||||
{
|
||||
BALANCER_BRIDGE_ADDRESS = addresses.balancerBridge;
|
||||
BANCOR_BRIDGE_ADDRESS = addresses.bancorBridge;
|
||||
COFIX_BRIDGE_ADDRESS = addresses.cofixBridge;
|
||||
CURVE_BRIDGE_ADDRESS = addresses.curveBridge;
|
||||
CRYPTO_COM_BRIDGE_ADDRESS = addresses.cryptoComBridge;
|
||||
KYBER_BRIDGE_ADDRESS = addresses.kyberBridge;
|
||||
@@ -196,6 +222,18 @@ contract BridgeAdapter is
|
||||
sellAmount,
|
||||
bridgeData
|
||||
);
|
||||
} else if (bridgeAddress == BANCOR_BRIDGE_ADDRESS) {
|
||||
boughtAmount = _tradeBancor(
|
||||
buyToken,
|
||||
sellAmount,
|
||||
bridgeData
|
||||
);
|
||||
} else if (bridgeAddress == COFIX_BRIDGE_ADDRESS) {
|
||||
boughtAmount = _tradeCoFiX(
|
||||
buyToken,
|
||||
sellAmount,
|
||||
bridgeData
|
||||
);
|
||||
} else {
|
||||
boughtAmount = _tradeZeroExBridge(
|
||||
bridgeAddress,
|
||||
@@ -204,9 +242,6 @@ contract BridgeAdapter is
|
||||
sellAmount,
|
||||
bridgeData
|
||||
);
|
||||
// Old bridge contracts should emit an `ERC20BridgeTransfer` themselves,
|
||||
// otherwise an event will be emitted from `_tradeZeroExBridge`.
|
||||
return boughtAmount;
|
||||
}
|
||||
|
||||
emit ERC20BridgeTransfer(
|
||||
|
@@ -24,6 +24,8 @@ contract MixinAdapterAddresses
|
||||
struct AdapterAddresses {
|
||||
// Bridges
|
||||
address balancerBridge;
|
||||
address bancorBridge;
|
||||
address cofixBridge;
|
||||
address creamBridge;
|
||||
address curveBridge;
|
||||
address cryptoComBridge;
|
||||
|
@@ -0,0 +1,111 @@
|
||||
|
||||
/*
|
||||
|
||||
Copyright 2020 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.6.5;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "@0x/contracts-erc20/contracts/src/v06/LibERC20TokenV06.sol";
|
||||
import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
|
||||
import "@0x/contracts-erc20/contracts/src/v06/IEtherTokenV06.sol";
|
||||
import "./MixinAdapterAddresses.sol";
|
||||
|
||||
|
||||
interface IBancorNetwork {
|
||||
function convertByPath(
|
||||
address[] calldata _path,
|
||||
uint256 _amount,
|
||||
uint256 _minReturn,
|
||||
address _beneficiary,
|
||||
address _affiliateAccount,
|
||||
uint256 _affiliateFee
|
||||
)
|
||||
external
|
||||
payable
|
||||
returns (uint256);
|
||||
}
|
||||
|
||||
|
||||
contract MixinBancor is
|
||||
MixinAdapterAddresses
|
||||
{
|
||||
/// @dev Bancor ETH pseudo-address.
|
||||
address constant public BANCOR_ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
|
||||
IEtherTokenV06 private immutable WETH;
|
||||
|
||||
constructor(AdapterAddresses memory addresses)
|
||||
public
|
||||
{
|
||||
WETH = IEtherTokenV06(addresses.weth);
|
||||
}
|
||||
|
||||
function _tradeBancor(
|
||||
IERC20TokenV06 buyToken,
|
||||
uint256 sellAmount,
|
||||
bytes memory bridgeData
|
||||
)
|
||||
internal
|
||||
returns (uint256 boughtAmount)
|
||||
{
|
||||
// Decode the bridge data.
|
||||
(
|
||||
address[] memory path,
|
||||
address bancorNetworkAddress
|
||||
// solhint-disable indent
|
||||
) = abi.decode(bridgeData, (address[], address));
|
||||
// solhint-enable indent
|
||||
|
||||
require(path.length >= 2, "MixinBancor/PATH_LENGTH_MUST_BE_AT_LEAST_TWO");
|
||||
require(
|
||||
path[path.length - 1] == address(buyToken) ||
|
||||
(path[path.length - 1] == BANCOR_ETH_ADDRESS && address(buyToken) == address(WETH)),
|
||||
"MixinBancor/LAST_ELEMENT_OF_PATH_MUST_MATCH_OUTPUT_TOKEN"
|
||||
);
|
||||
|
||||
uint256 payableAmount = 0;
|
||||
// If it's ETH in the path then withdraw from WETH
|
||||
// The Bancor path will have ETH as the 0xeee address
|
||||
// Bancor expects to be paid in ETH not WETH
|
||||
if (path[0] == BANCOR_ETH_ADDRESS) {
|
||||
WETH.withdraw(sellAmount);
|
||||
payableAmount = sellAmount;
|
||||
} else {
|
||||
// Grant an allowance to the Bancor Network.
|
||||
LibERC20TokenV06.approveIfBelow(
|
||||
IERC20TokenV06(path[0]),
|
||||
bancorNetworkAddress,
|
||||
sellAmount
|
||||
);
|
||||
}
|
||||
|
||||
// Convert the tokens
|
||||
boughtAmount = IBancorNetwork(bancorNetworkAddress).convertByPath{value: payableAmount}(
|
||||
path, // path originating with source token and terminating in destination token
|
||||
sellAmount, // amount of source token to trade
|
||||
1, // minimum amount of destination token expected to receive
|
||||
address(this), // beneficiary
|
||||
address(0), // affiliateAccount; no fee paid
|
||||
0 // affiliateFee; no fee paid
|
||||
);
|
||||
if (path[path.length - 1] == BANCOR_ETH_ADDRESS) {
|
||||
WETH.deposit{value: boughtAmount}();
|
||||
}
|
||||
|
||||
return boughtAmount;
|
||||
}
|
||||
}
|
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
|
||||
Copyright 2020 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.6.5;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "@0x/contracts-erc20/contracts/src/v06/LibERC20TokenV06.sol";
|
||||
import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
|
||||
import "@0x/contracts-erc20/contracts/src/v06/IEtherTokenV06.sol";
|
||||
import "./MixinAdapterAddresses.sol";
|
||||
|
||||
|
||||
interface ICoFiXRouter {
|
||||
// msg.value = fee
|
||||
function swapExactTokensForETH(
|
||||
address token,
|
||||
uint amountIn,
|
||||
uint amountOutMin,
|
||||
address to,
|
||||
address rewardTo,
|
||||
uint deadline
|
||||
) external payable returns (uint _amountIn, uint _amountOut);
|
||||
|
||||
// msg.value = amountIn + fee
|
||||
function swapExactETHForTokens(
|
||||
address token,
|
||||
uint amountIn,
|
||||
uint amountOutMin,
|
||||
address to,
|
||||
address rewardTo,
|
||||
uint deadline
|
||||
) external payable returns (uint _amountIn, uint _amountOut);
|
||||
}
|
||||
|
||||
interface ICoFiXPair {
|
||||
|
||||
function swapWithExact(address outToken, address to)
|
||||
external
|
||||
payable
|
||||
returns (uint amountIn, uint amountOut, uint oracleFeeChange, uint256[4] memory tradeInfo);
|
||||
}
|
||||
|
||||
contract MixinCoFiX is
|
||||
MixinAdapterAddresses
|
||||
{
|
||||
using LibERC20TokenV06 for IERC20TokenV06;
|
||||
|
||||
function _tradeCoFiX(
|
||||
IERC20TokenV06 buyToken,
|
||||
uint256 sellAmount,
|
||||
bytes memory bridgeData
|
||||
)
|
||||
internal
|
||||
returns (uint256 boughtAmount)
|
||||
{
|
||||
(address fromTokenAddress, uint256 fee, address pool) = abi.decode(bridgeData, (address, uint256, address));
|
||||
// Transfer tokens into the pool
|
||||
LibERC20TokenV06.compatTransfer(
|
||||
IERC20TokenV06(fromTokenAddress),
|
||||
pool,
|
||||
sellAmount);
|
||||
// Call the swap exact with the tokens now in the pool
|
||||
// pay the NEST Oracle fee with ETH
|
||||
(/* In */, boughtAmount, , ) = ICoFiXPair(pool).swapWithExact{value: fee}(
|
||||
address(buyToken),
|
||||
address(this)
|
||||
);
|
||||
|
||||
return boughtAmount;
|
||||
}
|
||||
}
|
@@ -22,7 +22,6 @@ import "@0x/contracts-erc20/contracts/src/v06/LibERC20TokenV06.sol";
|
||||
import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
|
||||
import "@0x/contracts-utils/contracts/src/v06/LibSafeMathV06.sol";
|
||||
import "../../../vendor/ILiquidityProvider.sol";
|
||||
import "../../../vendor/v3/IERC20Bridge.sol";
|
||||
|
||||
|
||||
contract MixinZeroExBridge {
|
||||
@@ -30,22 +29,6 @@ contract MixinZeroExBridge {
|
||||
using LibERC20TokenV06 for IERC20TokenV06;
|
||||
using LibSafeMathV06 for uint256;
|
||||
|
||||
/// @dev Emitted when a trade occurs.
|
||||
/// @param inputToken The token the bridge is converting from.
|
||||
/// @param outputToken The token the bridge is converting to.
|
||||
/// @param inputTokenAmount Amount of input token.
|
||||
/// @param outputTokenAmount Amount of output token.
|
||||
/// @param from The bridge address, indicating the underlying source of the fill.
|
||||
/// @param to The `to` address, currrently `address(this)`
|
||||
event ERC20BridgeTransfer(
|
||||
IERC20TokenV06 inputToken,
|
||||
IERC20TokenV06 outputToken,
|
||||
uint256 inputTokenAmount,
|
||||
uint256 outputTokenAmount,
|
||||
address from,
|
||||
address to
|
||||
);
|
||||
|
||||
function _tradeZeroExBridge(
|
||||
address bridgeAddress,
|
||||
IERC20TokenV06 sellToken,
|
||||
@@ -61,32 +44,12 @@ contract MixinZeroExBridge {
|
||||
bridgeAddress,
|
||||
sellAmount
|
||||
);
|
||||
try ILiquidityProvider(bridgeAddress).sellTokenForToken(
|
||||
address(sellToken),
|
||||
address(buyToken),
|
||||
address(this), // recipient
|
||||
1, // minBuyAmount
|
||||
bridgeData
|
||||
) returns (uint256 _boughtAmount) {
|
||||
boughtAmount = _boughtAmount;
|
||||
emit ERC20BridgeTransfer(
|
||||
sellToken,
|
||||
buyToken,
|
||||
sellAmount,
|
||||
boughtAmount,
|
||||
bridgeAddress,
|
||||
address(this)
|
||||
);
|
||||
} catch {
|
||||
uint256 balanceBefore = buyToken.balanceOf(address(this));
|
||||
IERC20Bridge(bridgeAddress).bridgeTransferFrom(
|
||||
address(buyToken),
|
||||
bridgeAddress,
|
||||
address(this), // recipient
|
||||
1, // minBuyAmount
|
||||
bridgeData
|
||||
);
|
||||
boughtAmount = buyToken.balanceOf(address(this)).safeSub(balanceBefore);
|
||||
}
|
||||
boughtAmount = ILiquidityProvider(bridgeAddress).sellTokenForToken(
|
||||
address(sellToken),
|
||||
address(buyToken),
|
||||
address(this), // recipient
|
||||
1, // minBuyAmount
|
||||
bridgeData
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@0x/contracts-zero-ex",
|
||||
"version": "0.12.0",
|
||||
"version": "0.15.0",
|
||||
"engines": {
|
||||
"node": ">=6.12"
|
||||
},
|
||||
@@ -37,12 +37,13 @@
|
||||
"compile:truffle": "truffle compile",
|
||||
"docs:md": "ts-doc-gen --sourceDir='$PROJECT_FILES' --output=$MD_FILE_DIR --fileExtension=mdx --tsconfig=./typedoc-tsconfig.json",
|
||||
"docs:json": "typedoc --excludePrivate --excludeExternals --excludeProtected --ignoreCompilerErrors --target ES5 --tsconfig typedoc-tsconfig.json --json $JSON_FILE_PATH $PROJECT_FILES",
|
||||
"publish:private": "yarn build && gitpkg publish"
|
||||
"publish:private": "yarn build && gitpkg publish",
|
||||
"rollback": "node ./lib/scripts/rollback.js"
|
||||
},
|
||||
"config": {
|
||||
"publicInterfaceContracts": "IZeroEx,ZeroEx,FullMigration,InitialMigration,IFlashWallet,IAllowanceTarget,IERC20Transformer,IOwnableFeature,ISimpleFunctionRegistryFeature,ITokenSpenderFeature,ITransformERC20Feature,FillQuoteTransformer,PayTakerTransformer,WethTransformer,OwnableFeature,SimpleFunctionRegistryFeature,TransformERC20Feature,TokenSpenderFeature,AffiliateFeeTransformer,SignatureValidatorFeature,MetaTransactionsFeature,LogMetadataTransformer,BridgeAdapter,LiquidityProviderFeature,ILiquidityProviderFeature,NativeOrdersFeature,INativeOrdersFeature,FeeCollectorController,FeeCollector",
|
||||
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually.",
|
||||
"abis": "./test/generated-artifacts/@(AffiliateFeeTransformer|AllowanceTarget|BootstrapFeature|BridgeAdapter|FeeCollector|FeeCollectorController|FillQuoteTransformer|FixinCommon|FixinEIP712|FixinProtocolFees|FixinReentrancyGuard|FixinTokenSpender|FlashWallet|FullMigration|IAllowanceTarget|IBootstrapFeature|IBridgeAdapter|IERC20Bridge|IERC20Transformer|IExchange|IFeature|IFlashWallet|IGasToken|ILiquidityProvider|ILiquidityProviderFeature|ILiquidityProviderSandbox|IMetaTransactionsFeature|INativeOrdersFeature|IOwnableFeature|ISignatureValidatorFeature|ISimpleFunctionRegistryFeature|IStaking|ITestSimpleFunctionRegistryFeature|ITokenSpenderFeature|ITransformERC20Feature|IUniswapFeature|IZeroEx|InitialMigration|LibBootstrap|LibCommonRichErrors|LibERC20Transformer|LibFeeCollector|LibLiquidityProviderRichErrors|LibMetaTransactionsRichErrors|LibMetaTransactionsStorage|LibMigrate|LibNativeOrder|LibNativeOrdersRichErrors|LibNativeOrdersStorage|LibOrderHash|LibOwnableRichErrors|LibOwnableStorage|LibProxyRichErrors|LibProxyStorage|LibReentrancyGuardStorage|LibSignature|LibSignatureRichErrors|LibSimpleFunctionRegistryRichErrors|LibSimpleFunctionRegistryStorage|LibSpenderRichErrors|LibStorage|LibTokenSpenderStorage|LibTransformERC20RichErrors|LibTransformERC20Storage|LibWalletRichErrors|LiquidityProviderFeature|LiquidityProviderSandbox|LogMetadataTransformer|MetaTransactionsFeature|MixinAdapterAddresses|MixinBalancer|MixinCryptoCom|MixinCurve|MixinDodo|MixinKyber|MixinMStable|MixinMooniswap|MixinOasis|MixinShell|MixinSushiswap|MixinUniswap|MixinUniswapV2|MixinZeroExBridge|NativeOrdersFeature|OwnableFeature|PayTakerTransformer|PermissionlessTransformerDeployer|SignatureValidatorFeature|SimpleFunctionRegistryFeature|TestBridge|TestCallTarget|TestDelegateCaller|TestFeeCollectorController|TestFillQuoteTransformerBridge|TestFillQuoteTransformerExchange|TestFillQuoteTransformerHost|TestFixinProtocolFees|TestFixinTokenSpender|TestFullMigration|TestInitialMigration|TestLibNativeOrder|TestLibSignature|TestLiquidityProvider|TestMetaTransactionsNativeOrdersFeature|TestMetaTransactionsTransformERC20Feature|TestMigrator|TestMintTokenERC20Transformer|TestMintableERC20Token|TestNativeOrdersFeature|TestPermissionlessTransformerDeployerSuicidal|TestPermissionlessTransformerDeployerTransformer|TestRfqOriginRegistration|TestSimpleFunctionRegistryFeatureImpl1|TestSimpleFunctionRegistryFeatureImpl2|TestStaking|TestTokenSpender|TestTokenSpenderERC20Token|TestTransformERC20|TestTransformerBase|TestTransformerDeployerTransformer|TestTransformerHost|TestWeth|TestWethTransformerHost|TestZeroExFeature|TokenSpenderFeature|TransformERC20Feature|Transformer|TransformerDeployer|UniswapFeature|WethTransformer|ZeroEx|ZeroExOptimized).json"
|
||||
"abis": "./test/generated-artifacts/@(AffiliateFeeTransformer|AllowanceTarget|BootstrapFeature|BridgeAdapter|FeeCollector|FeeCollectorController|FillQuoteTransformer|FixinCommon|FixinEIP712|FixinProtocolFees|FixinReentrancyGuard|FixinTokenSpender|FlashWallet|FullMigration|IAllowanceTarget|IBootstrapFeature|IBridgeAdapter|IERC20Bridge|IERC20Transformer|IExchange|IFeature|IFlashWallet|IGasToken|ILiquidityProvider|ILiquidityProviderFeature|ILiquidityProviderSandbox|IMetaTransactionsFeature|INativeOrdersFeature|IOwnableFeature|ISignatureValidatorFeature|ISimpleFunctionRegistryFeature|IStaking|ITestSimpleFunctionRegistryFeature|ITokenSpenderFeature|ITransformERC20Feature|IUniswapFeature|IZeroEx|InitialMigration|LibBootstrap|LibCommonRichErrors|LibERC20Transformer|LibFeeCollector|LibLiquidityProviderRichErrors|LibMetaTransactionsRichErrors|LibMetaTransactionsStorage|LibMigrate|LibNativeOrder|LibNativeOrdersRichErrors|LibNativeOrdersStorage|LibOrderHash|LibOwnableRichErrors|LibOwnableStorage|LibProxyRichErrors|LibProxyStorage|LibReentrancyGuardStorage|LibSignature|LibSignatureRichErrors|LibSimpleFunctionRegistryRichErrors|LibSimpleFunctionRegistryStorage|LibSpenderRichErrors|LibStorage|LibTokenSpenderStorage|LibTransformERC20RichErrors|LibTransformERC20Storage|LibWalletRichErrors|LiquidityProviderFeature|LiquidityProviderSandbox|LogMetadataTransformer|MetaTransactionsFeature|MixinAdapterAddresses|MixinBalancer|MixinBancor|MixinCoFiX|MixinCryptoCom|MixinCurve|MixinDodo|MixinKyber|MixinMStable|MixinMooniswap|MixinOasis|MixinShell|MixinSushiswap|MixinUniswap|MixinUniswapV2|MixinZeroExBridge|NativeOrdersFeature|OwnableFeature|PayTakerTransformer|PermissionlessTransformerDeployer|SignatureValidatorFeature|SimpleFunctionRegistryFeature|TestBridge|TestCallTarget|TestDelegateCaller|TestFeeCollectorController|TestFillQuoteTransformerBridge|TestFillQuoteTransformerExchange|TestFillQuoteTransformerHost|TestFixinProtocolFees|TestFixinTokenSpender|TestFullMigration|TestInitialMigration|TestLibNativeOrder|TestLibSignature|TestLiquidityProvider|TestMetaTransactionsNativeOrdersFeature|TestMetaTransactionsTransformERC20Feature|TestMigrator|TestMintTokenERC20Transformer|TestMintableERC20Token|TestNativeOrdersFeature|TestPermissionlessTransformerDeployerSuicidal|TestPermissionlessTransformerDeployerTransformer|TestRfqOriginRegistration|TestSimpleFunctionRegistryFeatureImpl1|TestSimpleFunctionRegistryFeatureImpl2|TestStaking|TestTokenSpender|TestTokenSpenderERC20Token|TestTransformERC20|TestTransformerBase|TestTransformerDeployerTransformer|TestTransformerHost|TestWeth|TestWethTransformerHost|TestZeroExFeature|TokenSpenderFeature|TransformERC20Feature|Transformer|TransformerDeployer|UniswapFeature|WethTransformer|ZeroEx|ZeroExOptimized).json"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -55,18 +56,24 @@
|
||||
"homepage": "https://github.com/0xProject/protocol/tree/main/contracts/zero-ex",
|
||||
"devDependencies": {
|
||||
"@0x/abi-gen": "^5.4.13",
|
||||
"@0x/contracts-erc20": "^3.2.12",
|
||||
"@0x/contract-addresses": "^5.7.0",
|
||||
"@0x/contracts-erc20": "^3.2.13",
|
||||
"@0x/contracts-gen": "^2.0.24",
|
||||
"@0x/contracts-test-utils": "^5.3.15",
|
||||
"@0x/contracts-test-utils": "^5.3.16",
|
||||
"@0x/dev-utils": "^4.1.3",
|
||||
"@0x/order-utils": "^10.4.11",
|
||||
"@0x/sol-compiler": "^4.4.1",
|
||||
"@0x/ts-doc-gen": "^0.0.28",
|
||||
"@0x/tslint-config": "^4.1.3",
|
||||
"@types/isomorphic-fetch": "^0.0.35",
|
||||
"@types/lodash": "4.14.104",
|
||||
"@types/mocha": "^5.2.7",
|
||||
"@types/prompts": "^2.0.9",
|
||||
"isomorphic-fetch": "^3.0.0",
|
||||
"lodash": "^4.17.11",
|
||||
"mocha": "^6.2.0",
|
||||
"npm-run-all": "^4.1.2",
|
||||
"prompts": "^2.4.0",
|
||||
"shx": "^0.2.2",
|
||||
"solhint": "^1.4.1",
|
||||
"truffle": "^5.0.32",
|
||||
@@ -76,8 +83,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@0x/base-contract": "^6.2.14",
|
||||
"@0x/order-utils": "^10.4.10",
|
||||
"@0x/protocol-utils": "^1.0.1",
|
||||
"@0x/protocol-utils": "^1.1.1",
|
||||
"@0x/subproviders": "^6.2.3",
|
||||
"@0x/types": "^3.3.1",
|
||||
"@0x/typescript-typings": "^5.1.6",
|
||||
|
427
contracts/zero-ex/scripts/rollback.ts
Normal file
427
contracts/zero-ex/scripts/rollback.ts
Normal file
@@ -0,0 +1,427 @@
|
||||
import { getContractAddressesForChainOrThrow } from '@0x/contract-addresses';
|
||||
import { constants } from '@0x/contracts-test-utils';
|
||||
import { RPCSubprovider, SupportedProvider, Web3ProviderEngine } from '@0x/subproviders';
|
||||
import { AbiEncoder, BigNumber, logUtils, providerUtils } from '@0x/utils';
|
||||
import { Web3Wrapper } from '@0x/web3-wrapper';
|
||||
import { MethodAbi } from 'ethereum-types';
|
||||
import * as fetch from 'isomorphic-fetch';
|
||||
import * as _ from 'lodash';
|
||||
import * as prompts from 'prompts';
|
||||
|
||||
import * as wrappers from '../src/wrappers';
|
||||
|
||||
const SUBGRAPH_URL = 'https://api.thegraph.com/subgraphs/name/mzhu25/zeroex-migrations';
|
||||
|
||||
const ownableFeature = new wrappers.OwnableFeatureContract(constants.NULL_ADDRESS, new Web3ProviderEngine());
|
||||
const simpleFunctionRegistryFeature = new wrappers.SimpleFunctionRegistryFeatureContract(
|
||||
constants.NULL_ADDRESS,
|
||||
new Web3ProviderEngine(),
|
||||
);
|
||||
const DO_NOT_ROLLBACK = [
|
||||
ownableFeature.getSelector('migrate'),
|
||||
ownableFeature.getSelector('transferOwnership'),
|
||||
simpleFunctionRegistryFeature.getSelector('rollback'),
|
||||
simpleFunctionRegistryFeature.getSelector('extend'),
|
||||
];
|
||||
|
||||
const governorEncoder = AbiEncoder.create('(bytes[], address[], uint256[])');
|
||||
|
||||
const selectorToSignature: { [selector: string]: string } = {};
|
||||
for (const wrapper of Object.values(wrappers)) {
|
||||
if (typeof wrapper === 'function') {
|
||||
const contract = new wrapper(constants.NULL_ADDRESS, new Web3ProviderEngine());
|
||||
contract.abi
|
||||
.filter(abiDef => abiDef.type === 'function')
|
||||
.map(method => {
|
||||
const methodName = (method as MethodAbi).name;
|
||||
const selector = contract.getSelector(methodName);
|
||||
const signature = contract.getFunctionSignature(methodName);
|
||||
selectorToSignature[selector] = signature;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
interface ProxyFunctionEntity {
|
||||
id: string;
|
||||
currentImpl: string;
|
||||
fullHistory: Array<{ impl: string; timestamp: string }>;
|
||||
}
|
||||
|
||||
interface Deployment {
|
||||
time: string;
|
||||
updates: Array<{ selector: string; signature?: string; previousImpl: string; newImpl: string }>;
|
||||
}
|
||||
|
||||
async function querySubgraphAsync(): Promise<ProxyFunctionEntity[]> {
|
||||
const query = `
|
||||
{
|
||||
proxyFunctions {
|
||||
id
|
||||
currentImpl
|
||||
fullHistory {
|
||||
impl
|
||||
timestamp
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const response = await fetch(SUBGRAPH_URL, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
query,
|
||||
}),
|
||||
});
|
||||
const {
|
||||
data: { proxyFunctions },
|
||||
} = await response.json();
|
||||
// Sort the history in chronological order
|
||||
proxyFunctions.map((fn: ProxyFunctionEntity) =>
|
||||
fn.fullHistory.sort((a, b) => Number.parseInt(a.timestamp, 10) - Number.parseInt(b.timestamp, 10)),
|
||||
);
|
||||
return proxyFunctions;
|
||||
}
|
||||
|
||||
function reconstructDeployments(proxyFunctions: ProxyFunctionEntity[]): Deployment[] {
|
||||
const deploymentsByTimestamp: { [timestamp: string]: Deployment } = {};
|
||||
proxyFunctions.map(fn => {
|
||||
fn.fullHistory.map((update, i) => {
|
||||
const { updates } = (deploymentsByTimestamp[update.timestamp] = deploymentsByTimestamp[
|
||||
update.timestamp
|
||||
] || { time: timestampToUTC(update.timestamp), updates: [] });
|
||||
updates.push({
|
||||
selector: fn.id,
|
||||
signature: selectorToSignature[fn.id],
|
||||
previousImpl: i > 0 ? fn.fullHistory[i - 1].impl : constants.NULL_ADDRESS,
|
||||
newImpl: update.impl,
|
||||
});
|
||||
});
|
||||
});
|
||||
return Object.keys(deploymentsByTimestamp)
|
||||
.sort()
|
||||
.map(timestamp => deploymentsByTimestamp[timestamp]);
|
||||
}
|
||||
|
||||
function timestampToUTC(timestamp: string): string {
|
||||
return new Date(Number.parseInt(timestamp, 10) * 1000).toUTCString();
|
||||
}
|
||||
|
||||
enum CommandLineActions {
|
||||
History = 'History',
|
||||
Function = 'Function',
|
||||
Current = 'Current',
|
||||
Rollback = 'Rollback',
|
||||
Emergency = 'Emergency',
|
||||
Exit = 'Exit',
|
||||
}
|
||||
|
||||
async function confirmRollbackAsync(
|
||||
rollbackTargets: { [selector: string]: string },
|
||||
proxyFunctions: ProxyFunctionEntity[],
|
||||
): Promise<boolean> {
|
||||
const { confirmed } = await prompts({
|
||||
type: 'confirm',
|
||||
name: 'confirmed',
|
||||
message: `Are these the correct rollbacks?\n${Object.entries(rollbackTargets)
|
||||
.map(
|
||||
([selector, target]) =>
|
||||
`[${selector}] ${selectorToSignature[selector] || '(function signature not found)'} \n ${
|
||||
proxyFunctions.find(fn => fn.id === selector)!.currentImpl
|
||||
} => ${target}`,
|
||||
)
|
||||
.join('\n')}`,
|
||||
});
|
||||
return confirmed;
|
||||
}
|
||||
|
||||
async function printRollbackCalldataAsync(
|
||||
rollbackTargets: { [selector: string]: string },
|
||||
zeroEx: wrappers.IZeroExContract,
|
||||
): Promise<void> {
|
||||
const numRollbacks = Object.keys(rollbackTargets).length;
|
||||
const { numTxns } = await prompts({
|
||||
type: 'number',
|
||||
name: 'numTxns',
|
||||
message:
|
||||
'To avoid limitations on calldata size, the full rollback can be split into multiple transactions. How many transactions would you like to split it into?',
|
||||
initial: 1,
|
||||
style: 'default',
|
||||
min: 1,
|
||||
max: numRollbacks,
|
||||
});
|
||||
for (let i = 0; i < numTxns; i++) {
|
||||
const startIndex = i * Math.trunc(numRollbacks / numTxns);
|
||||
const endIndex = startIndex + Math.trunc(numRollbacks / numTxns) + (i < numRollbacks % numTxns ? 1 : 0);
|
||||
const rollbacks = Object.entries(rollbackTargets).slice(startIndex, endIndex);
|
||||
const rollbackCallData = governorEncoder.encode([
|
||||
rollbacks.map(([selector, target]) => zeroEx.rollback(selector, target).getABIEncodedTransactionData()),
|
||||
new Array(rollbacks.length).fill(zeroEx.address),
|
||||
new Array(rollbacks.length).fill(constants.ZERO_AMOUNT),
|
||||
]);
|
||||
if (numTxns > 1) {
|
||||
logUtils.log(`======================== Governor Calldata #${i + 1} ========================`);
|
||||
}
|
||||
logUtils.log(rollbackCallData);
|
||||
}
|
||||
}
|
||||
|
||||
async function deploymentHistoryAsync(deployments: Deployment[], proxyFunctions: ProxyFunctionEntity[]): Promise<void> {
|
||||
const { index } = await prompts({
|
||||
type: 'select',
|
||||
name: 'index',
|
||||
message: 'Choose a deployment:',
|
||||
choices: deployments.map((deployment, i) => ({
|
||||
title: deployment.time,
|
||||
value: i,
|
||||
})),
|
||||
});
|
||||
|
||||
const { action } = await prompts({
|
||||
type: 'select',
|
||||
name: 'action',
|
||||
message: 'What would you like to do?',
|
||||
choices: [
|
||||
{ title: 'Deployment info', value: 'info' },
|
||||
{ title: 'Rollback this deployment', value: 'rollback' },
|
||||
],
|
||||
});
|
||||
|
||||
if (action === 'info') {
|
||||
logUtils.log(
|
||||
deployments[index].updates.map(update => ({
|
||||
selector: update.selector,
|
||||
signature: update.signature || '(function signature not found)',
|
||||
update: `${update.previousImpl} => ${update.newImpl}`,
|
||||
})),
|
||||
);
|
||||
} else {
|
||||
const zeroEx = await getMainnetContractAsync();
|
||||
const rollbackTargets: { [selector: string]: string } = {};
|
||||
for (const update of deployments[index].updates) {
|
||||
rollbackTargets[update.selector] = update.previousImpl;
|
||||
const rollbackLength = (await zeroEx.getRollbackLength(update.selector).callAsync()).toNumber();
|
||||
for (let i = rollbackLength - 1; i >= 0; i--) {
|
||||
const entry = await zeroEx.getRollbackEntryAtIndex(update.selector, new BigNumber(i)).callAsync();
|
||||
if (entry === update.previousImpl) {
|
||||
break;
|
||||
} else if (i === 0) {
|
||||
logUtils.log(
|
||||
'Cannot rollback this deployment. The following update from this deployment cannot be rolled back:',
|
||||
);
|
||||
logUtils.log(`\t[${update.selector}] ${update.signature || '(function signature not found)'}`);
|
||||
logUtils.log(`\t${update.previousImpl} => ${update.newImpl}`);
|
||||
logUtils.log(
|
||||
`Cannot find ${
|
||||
update.previousImpl
|
||||
} in the selector's rollback history. It itself may have been previously rolled back.`,
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
const isConfirmed = await confirmRollbackAsync(rollbackTargets, proxyFunctions);
|
||||
if (isConfirmed) {
|
||||
await printRollbackCalldataAsync(rollbackTargets, zeroEx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function functionHistoryAsync(proxyFunctions: ProxyFunctionEntity[]): Promise<void> {
|
||||
const { fnSelector } = await prompts({
|
||||
type: 'autocomplete',
|
||||
name: 'fnSelector',
|
||||
message: 'Enter the selector or name of the function:',
|
||||
choices: [
|
||||
...proxyFunctions.map(fn => ({
|
||||
title: fn.id,
|
||||
value: fn.id,
|
||||
description: selectorToSignature[fn.id] || '(function signature not found)',
|
||||
})),
|
||||
...proxyFunctions.map(fn => ({
|
||||
title: selectorToSignature[fn.id] || '(function signature not found)',
|
||||
value: fn.id,
|
||||
description: fn.id,
|
||||
})),
|
||||
],
|
||||
});
|
||||
const functionEntity = proxyFunctions.find(fn => fn.id === fnSelector);
|
||||
if (functionEntity === undefined) {
|
||||
logUtils.log(`Couldn't find deployment history for selector ${fnSelector}`);
|
||||
} else {
|
||||
logUtils.log(
|
||||
functionEntity.fullHistory.map(update => ({
|
||||
date: timestampToUTC(update.timestamp),
|
||||
impl: update.impl,
|
||||
})),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
async function currentFunctionsAsync(proxyFunctions: ProxyFunctionEntity[]): Promise<void> {
|
||||
const currentFunctions: {
|
||||
[selector: string]: { signature: string; impl: string; lastUpdated: string };
|
||||
} = {};
|
||||
proxyFunctions
|
||||
.filter(fn => fn.currentImpl !== constants.NULL_ADDRESS)
|
||||
.map(fn => {
|
||||
currentFunctions[fn.id] = {
|
||||
signature: selectorToSignature[fn.id] || '(function signature not found)',
|
||||
impl: fn.currentImpl,
|
||||
lastUpdated: timestampToUTC(fn.fullHistory.slice(-1)[0].timestamp),
|
||||
};
|
||||
});
|
||||
logUtils.log(currentFunctions);
|
||||
}
|
||||
|
||||
async function generateRollbackAsync(proxyFunctions: ProxyFunctionEntity[]): Promise<void> {
|
||||
const zeroEx = await getMainnetContractAsync();
|
||||
const { selected } = await prompts({
|
||||
type: 'autocompleteMultiselect',
|
||||
name: 'selected',
|
||||
message: 'Select the functions to rollback:',
|
||||
choices: _.flatMap(proxyFunctions.filter(fn => fn.currentImpl !== constants.NULL_ADDRESS), fn => [
|
||||
{
|
||||
title: [
|
||||
`[${fn.id}]`,
|
||||
`Implemented @ ${fn.currentImpl}`,
|
||||
selectorToSignature[fn.id] || '(function signature not found)',
|
||||
].join('\n\t\t\t\t'),
|
||||
value: fn.id,
|
||||
},
|
||||
]),
|
||||
});
|
||||
const rollbackTargets: { [selector: string]: string } = {};
|
||||
for (const selector of selected) {
|
||||
const rollbackLength = (await zeroEx.getRollbackLength(selector).callAsync()).toNumber();
|
||||
const rollbackHistory = await Promise.all(
|
||||
_.range(rollbackLength).map(async i =>
|
||||
zeroEx.getRollbackEntryAtIndex(selector, new BigNumber(i)).callAsync(),
|
||||
),
|
||||
);
|
||||
const fullHistory = proxyFunctions.find(fn => fn.id === selector)!.fullHistory;
|
||||
const previousImpl = rollbackHistory[rollbackLength - 1];
|
||||
const { target } = await prompts({
|
||||
type: 'select',
|
||||
name: 'target',
|
||||
message: 'Select the implementation to rollback to',
|
||||
hint: `[${selector}] ${selectorToSignature[selector] || '(function signature not found)'}`,
|
||||
choices: [
|
||||
{
|
||||
title: 'DISABLE',
|
||||
value: constants.NULL_ADDRESS,
|
||||
description: 'Rolls back to address(0)',
|
||||
},
|
||||
...(previousImpl !== constants.NULL_ADDRESS
|
||||
? [
|
||||
{
|
||||
title: 'PREVIOUS',
|
||||
value: previousImpl,
|
||||
description: `${previousImpl} (${timestampToUTC(
|
||||
_.findLast(fullHistory, update => update.impl === previousImpl)!.timestamp,
|
||||
)})`,
|
||||
},
|
||||
]
|
||||
: []),
|
||||
...[...new Set(rollbackHistory)]
|
||||
.filter(impl => impl !== constants.NULL_ADDRESS)
|
||||
.map(impl => ({
|
||||
title: impl,
|
||||
value: impl,
|
||||
description: timestampToUTC(_.findLast(fullHistory, update => update.impl === impl)!.timestamp),
|
||||
})),
|
||||
],
|
||||
});
|
||||
rollbackTargets[selector] = target;
|
||||
}
|
||||
|
||||
const isConfirmed = await confirmRollbackAsync(rollbackTargets, proxyFunctions);
|
||||
if (isConfirmed) {
|
||||
await printRollbackCalldataAsync(rollbackTargets, zeroEx);
|
||||
}
|
||||
}
|
||||
|
||||
async function generateEmergencyRollbackAsync(proxyFunctions: ProxyFunctionEntity[]): Promise<void> {
|
||||
const zeroEx = new wrappers.IZeroExContract(
|
||||
getContractAddressesForChainOrThrow(1).exchangeProxy,
|
||||
new Web3ProviderEngine(),
|
||||
);
|
||||
const allSelectors = proxyFunctions
|
||||
.filter(fn => fn.currentImpl !== constants.NULL_ADDRESS && !DO_NOT_ROLLBACK.includes(fn.id))
|
||||
.map(fn => fn.id);
|
||||
await printRollbackCalldataAsync(
|
||||
_.zipObject(allSelectors, new Array(allSelectors.length).fill(constants.NULL_ADDRESS)),
|
||||
zeroEx,
|
||||
);
|
||||
}
|
||||
|
||||
let provider: SupportedProvider | undefined = process.env.RPC_URL ? createWeb3Provider(process.env.RPC_URL) : undefined;
|
||||
|
||||
function createWeb3Provider(rpcUrl: string): SupportedProvider {
|
||||
const providerEngine = new Web3ProviderEngine();
|
||||
providerEngine.addProvider(new RPCSubprovider(rpcUrl));
|
||||
providerUtils.startProviderEngine(providerEngine);
|
||||
return providerEngine;
|
||||
}
|
||||
|
||||
async function getMainnetContractAsync(): Promise<wrappers.IZeroExContract> {
|
||||
if (provider === undefined) {
|
||||
const { rpcUrl } = await prompts({
|
||||
type: 'text',
|
||||
name: 'rpcUrl',
|
||||
message: 'Enter an RPC endpoint:',
|
||||
});
|
||||
provider = createWeb3Provider(rpcUrl);
|
||||
}
|
||||
const chainId = await new Web3Wrapper(provider).getChainIdAsync();
|
||||
const { exchangeProxy } = getContractAddressesForChainOrThrow(chainId);
|
||||
return new wrappers.IZeroExContract(exchangeProxy, provider);
|
||||
}
|
||||
|
||||
(async () => {
|
||||
const proxyFunctions = await querySubgraphAsync();
|
||||
const deployments = reconstructDeployments(proxyFunctions);
|
||||
|
||||
while (true) {
|
||||
const { action } = await prompts({
|
||||
type: 'select',
|
||||
name: 'action',
|
||||
message: 'What would you like to do?',
|
||||
choices: [
|
||||
{ title: '🚢 Deployment history', value: CommandLineActions.History },
|
||||
{ title: '📜 Function history', value: CommandLineActions.Function },
|
||||
{ title: '🗺️ Currently registered functions', value: CommandLineActions.Current },
|
||||
{ title: '🔙 Generate rollback calldata', value: CommandLineActions.Rollback },
|
||||
{ title: '🚨 Emergency shutdown calldata', value: CommandLineActions.Emergency },
|
||||
{ title: '👋 Exit', value: CommandLineActions.Exit },
|
||||
],
|
||||
});
|
||||
|
||||
switch (action) {
|
||||
case CommandLineActions.History:
|
||||
await deploymentHistoryAsync(deployments, proxyFunctions);
|
||||
break;
|
||||
case CommandLineActions.Function:
|
||||
await functionHistoryAsync(proxyFunctions);
|
||||
break;
|
||||
case CommandLineActions.Current:
|
||||
await currentFunctionsAsync(proxyFunctions);
|
||||
break;
|
||||
case CommandLineActions.Rollback:
|
||||
await generateRollbackAsync(proxyFunctions);
|
||||
break;
|
||||
case CommandLineActions.Emergency:
|
||||
await generateEmergencyRollbackAsync(proxyFunctions);
|
||||
break;
|
||||
case CommandLineActions.Exit:
|
||||
default:
|
||||
process.exit(0);
|
||||
}
|
||||
}
|
||||
})().catch(err => {
|
||||
logUtils.log(err);
|
||||
process.exit(1);
|
||||
});
|
@@ -76,6 +76,8 @@ import * as LogMetadataTransformer from '../test/generated-artifacts/LogMetadata
|
||||
import * as MetaTransactionsFeature from '../test/generated-artifacts/MetaTransactionsFeature.json';
|
||||
import * as MixinAdapterAddresses from '../test/generated-artifacts/MixinAdapterAddresses.json';
|
||||
import * as MixinBalancer from '../test/generated-artifacts/MixinBalancer.json';
|
||||
import * as MixinBancor from '../test/generated-artifacts/MixinBancor.json';
|
||||
import * as MixinCoFiX from '../test/generated-artifacts/MixinCoFiX.json';
|
||||
import * as MixinCryptoCom from '../test/generated-artifacts/MixinCryptoCom.json';
|
||||
import * as MixinCurve from '../test/generated-artifacts/MixinCurve.json';
|
||||
import * as MixinDodo from '../test/generated-artifacts/MixinDodo.json';
|
||||
@@ -216,6 +218,8 @@ export const artifacts = {
|
||||
IBridgeAdapter: IBridgeAdapter as ContractArtifact,
|
||||
MixinAdapterAddresses: MixinAdapterAddresses as ContractArtifact,
|
||||
MixinBalancer: MixinBalancer as ContractArtifact,
|
||||
MixinBancor: MixinBancor as ContractArtifact,
|
||||
MixinCoFiX: MixinCoFiX as ContractArtifact,
|
||||
MixinCryptoCom: MixinCryptoCom as ContractArtifact,
|
||||
MixinCurve: MixinCurve as ContractArtifact,
|
||||
MixinDodo: MixinDodo as ContractArtifact,
|
||||
|
@@ -9,8 +9,6 @@ import { abis } from '../utils/abis';
|
||||
import { fullMigrateAsync } from '../utils/migration';
|
||||
import {
|
||||
LiquidityProviderSandboxContract,
|
||||
TestBridgeContract,
|
||||
TestBridgeEvents,
|
||||
TestLiquidityProviderContract,
|
||||
TestLiquidityProviderEvents,
|
||||
TestWethContract,
|
||||
@@ -148,41 +146,6 @@ blockchainTests('LiquidityProvider feature', env => {
|
||||
TestLiquidityProviderEvents.SellTokenForToken,
|
||||
);
|
||||
});
|
||||
it('Successfully executes an ERC20-ERC20 swap (backwards-compatibility)', async () => {
|
||||
const bridge = await TestBridgeContract.deployFrom0xArtifactAsync(
|
||||
artifacts.TestBridge,
|
||||
env.provider,
|
||||
env.txDefaults,
|
||||
artifacts,
|
||||
weth.address,
|
||||
token.address,
|
||||
);
|
||||
const tx = await feature
|
||||
.sellToLiquidityProvider(
|
||||
token.address,
|
||||
weth.address,
|
||||
bridge.address,
|
||||
constants.NULL_ADDRESS,
|
||||
constants.ONE_ETHER,
|
||||
constants.ZERO_AMOUNT,
|
||||
constants.NULL_BYTES,
|
||||
)
|
||||
.awaitTransactionSuccessAsync({ from: taker });
|
||||
verifyEventsFromLogs(
|
||||
tx.logs,
|
||||
[
|
||||
{
|
||||
inputToken: token.address,
|
||||
outputToken: weth.address,
|
||||
inputTokenAmount: constants.ONE_ETHER,
|
||||
outputTokenAmount: constants.ZERO_AMOUNT,
|
||||
from: bridge.address,
|
||||
to: taker,
|
||||
},
|
||||
],
|
||||
TestBridgeEvents.ERC20BridgeTransfer,
|
||||
);
|
||||
});
|
||||
it('Reverts if cannot fulfill the minimum buy amount', async () => {
|
||||
const minBuyAmount = new BigNumber(1);
|
||||
const tx = feature
|
||||
|
@@ -6,9 +6,7 @@ import {
|
||||
randomAddress,
|
||||
verifyEventsFromLogs,
|
||||
} from '@0x/contracts-test-utils';
|
||||
import { getExchangeProxyMetaTransactionHash, signatureUtils } from '@0x/order-utils';
|
||||
import { Signature } from '@0x/protocol-utils';
|
||||
import { ExchangeProxyMetaTransaction } from '@0x/types';
|
||||
import { MetaTransaction, MetaTransactionFields } from '@0x/protocol-utils';
|
||||
import { BigNumber, hexUtils, StringRevertError, ZeroExRevertErrors } from '@0x/utils';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
@@ -31,6 +29,7 @@ blockchainTests.resets('MetaTransactions feature', env => {
|
||||
let owner: string;
|
||||
let maker: string;
|
||||
let sender: string;
|
||||
let notSigner: string;
|
||||
let signers: string[];
|
||||
let zeroEx: IZeroExContract;
|
||||
let feature: MetaTransactionsFeatureContract;
|
||||
@@ -45,7 +44,7 @@ blockchainTests.resets('MetaTransactions feature', env => {
|
||||
const REENTRANCY_FLAG_MTX = 0x1;
|
||||
|
||||
before(async () => {
|
||||
[owner, maker, sender, ...signers] = await env.getAccountAddressesAsync();
|
||||
[owner, maker, sender, notSigner, ...signers] = await env.getAccountAddressesAsync();
|
||||
transformERC20Feature = await TestMetaTransactionsTransformERC20FeatureContract.deployFrom0xArtifactAsync(
|
||||
artifacts.TestMetaTransactionsTransformERC20Feature,
|
||||
env.provider,
|
||||
@@ -83,19 +82,8 @@ blockchainTests.resets('MetaTransactions feature', env => {
|
||||
);
|
||||
});
|
||||
|
||||
function sigstruct(signature: string): Signature {
|
||||
return {
|
||||
v: parseInt(hexUtils.slice(signature, 0, 1), 16),
|
||||
signatureType: parseInt(hexUtils.slice(signature, 65, 66), 16),
|
||||
r: hexUtils.slice(signature, 1, 33),
|
||||
s: hexUtils.slice(signature, 33, 65),
|
||||
};
|
||||
}
|
||||
|
||||
function getRandomMetaTransaction(
|
||||
fields: Partial<ExchangeProxyMetaTransaction> = {},
|
||||
): ExchangeProxyMetaTransaction {
|
||||
return {
|
||||
function getRandomMetaTransaction(fields: Partial<MetaTransactionFields> = {}): MetaTransaction {
|
||||
return new MetaTransaction({
|
||||
signer: _.sampleSize(signers)[0],
|
||||
sender,
|
||||
minGasPrice: getRandomInteger('2', '1e9'),
|
||||
@@ -106,28 +94,16 @@ blockchainTests.resets('MetaTransactions feature', env => {
|
||||
value: getRandomInteger(1, '1e18'),
|
||||
feeToken: feeToken.address,
|
||||
feeAmount: getRandomInteger(1, MAX_FEE_AMOUNT),
|
||||
domain: {
|
||||
chainId: 1, // Ganache's `chainid` opcode is hardcoded as 1
|
||||
verifyingContract: zeroEx.address,
|
||||
},
|
||||
chainId: 1, // Ganache's `chainid` opcode is hardcoded as 1
|
||||
verifyingContract: zeroEx.address,
|
||||
...fields,
|
||||
};
|
||||
}
|
||||
|
||||
async function signMetaTransactionAsync(mtx: ExchangeProxyMetaTransaction, signer?: string): Promise<Signature> {
|
||||
return sigstruct(
|
||||
await signatureUtils.ecSignHashAsync(
|
||||
env.provider,
|
||||
getExchangeProxyMetaTransactionHash(mtx),
|
||||
signer || mtx.signer,
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
describe('getMetaTransactionHash()', () => {
|
||||
it('generates the correct hash', async () => {
|
||||
const mtx = getRandomMetaTransaction();
|
||||
const expected = getExchangeProxyMetaTransactionHash(mtx);
|
||||
const expected = mtx.getHash();
|
||||
const actual = await feature.getMetaTransactionHash(mtx).callAsync();
|
||||
expect(actual).to.eq(expected);
|
||||
});
|
||||
@@ -163,7 +139,7 @@ blockchainTests.resets('MetaTransactions feature', env => {
|
||||
const mtx = getRandomMetaTransaction({
|
||||
callData: nativeOrdersFeature.fillLimitOrder(order, sig, fillAmount).getABIEncodedTransactionData(),
|
||||
});
|
||||
const signature = await signMetaTransactionAsync(mtx);
|
||||
const signature = await mtx.getSignatureWithProviderAsync(env.provider);
|
||||
const callOpts = {
|
||||
gasPrice: mtx.minGasPrice,
|
||||
value: mtx.value,
|
||||
@@ -198,7 +174,7 @@ blockchainTests.resets('MetaTransactions feature', env => {
|
||||
callData: nativeOrdersFeature.fillRfqOrder(order, sig, fillAmount).getABIEncodedTransactionData(),
|
||||
value: ZERO_AMOUNT,
|
||||
});
|
||||
const signature = await signMetaTransactionAsync(mtx);
|
||||
const signature = await mtx.getSignatureWithProviderAsync(env.provider);
|
||||
const callOpts = {
|
||||
gasPrice: mtx.minGasPrice,
|
||||
value: 0,
|
||||
@@ -237,7 +213,7 @@ blockchainTests.resets('MetaTransactions feature', env => {
|
||||
)
|
||||
.getABIEncodedTransactionData(),
|
||||
});
|
||||
const signature = await signMetaTransactionAsync(mtx);
|
||||
const signature = await mtx.getSignatureWithProviderAsync(env.provider);
|
||||
const callOpts = {
|
||||
gasPrice: mtx.minGasPrice,
|
||||
value: mtx.value,
|
||||
@@ -275,7 +251,7 @@ blockchainTests.resets('MetaTransactions feature', env => {
|
||||
)
|
||||
.getABIEncodedTransactionData();
|
||||
const mtx = getRandomMetaTransaction({ callData });
|
||||
const signature = await signMetaTransactionAsync(mtx);
|
||||
const signature = await mtx.getSignatureWithProviderAsync(env.provider);
|
||||
const callOpts = {
|
||||
gasPrice: mtx.minGasPrice,
|
||||
value: mtx.value,
|
||||
@@ -315,7 +291,7 @@ blockchainTests.resets('MetaTransactions feature', env => {
|
||||
)
|
||||
.getABIEncodedTransactionData(),
|
||||
});
|
||||
const signature = await signMetaTransactionAsync(mtx);
|
||||
const signature = await mtx.getSignatureWithProviderAsync(env.provider);
|
||||
const callOpts = {
|
||||
gasPrice: mtx.minGasPrice,
|
||||
value: mtx.value,
|
||||
@@ -340,7 +316,7 @@ blockchainTests.resets('MetaTransactions feature', env => {
|
||||
)
|
||||
.getABIEncodedTransactionData(),
|
||||
});
|
||||
const signature = await signMetaTransactionAsync(mtx);
|
||||
const signature = await mtx.getSignatureWithProviderAsync(env.provider);
|
||||
const callOpts = {
|
||||
gasPrice: mtx.minGasPrice,
|
||||
value: mtx.value,
|
||||
@@ -363,8 +339,8 @@ blockchainTests.resets('MetaTransactions feature', env => {
|
||||
)
|
||||
.getABIEncodedTransactionData(),
|
||||
});
|
||||
const mtxHash = getExchangeProxyMetaTransactionHash(mtx);
|
||||
const signature = await signMetaTransactionAsync(mtx);
|
||||
const mtxHash = mtx.getHash();
|
||||
const signature = await mtx.getSignatureWithProviderAsync(env.provider);
|
||||
const callOpts = {
|
||||
gasPrice: mtx.minGasPrice,
|
||||
value: mtx.value,
|
||||
@@ -393,8 +369,8 @@ blockchainTests.resets('MetaTransactions feature', env => {
|
||||
const mtx = getRandomMetaTransaction({
|
||||
callData: transformERC20Feature.createTransformWallet().getABIEncodedTransactionData(),
|
||||
});
|
||||
const mtxHash = getExchangeProxyMetaTransactionHash(mtx);
|
||||
const signature = await signMetaTransactionAsync(mtx);
|
||||
const mtxHash = mtx.getHash();
|
||||
const signature = await mtx.getSignatureWithProviderAsync(env.provider);
|
||||
const callOpts = {
|
||||
gasPrice: mtx.minGasPrice,
|
||||
value: mtx.value,
|
||||
@@ -421,8 +397,8 @@ blockchainTests.resets('MetaTransactions feature', env => {
|
||||
)
|
||||
.getABIEncodedTransactionData(),
|
||||
});
|
||||
const mtxHash = getExchangeProxyMetaTransactionHash(mtx);
|
||||
const signature = await signMetaTransactionAsync(mtx);
|
||||
const mtxHash = mtx.getHash();
|
||||
const signature = await mtx.getSignatureWithProviderAsync(env.provider);
|
||||
const callOpts = {
|
||||
gasPrice: mtx.minGasPrice,
|
||||
value: mtx.value,
|
||||
@@ -439,8 +415,8 @@ blockchainTests.resets('MetaTransactions feature', env => {
|
||||
|
||||
it('fails if not enough ETH provided', async () => {
|
||||
const mtx = getRandomMetaTransaction();
|
||||
const mtxHash = getExchangeProxyMetaTransactionHash(mtx);
|
||||
const signature = await signMetaTransactionAsync(mtx);
|
||||
const mtxHash = mtx.getHash();
|
||||
const signature = await mtx.getSignatureWithProviderAsync(env.provider);
|
||||
const callOpts = {
|
||||
gasPrice: mtx.minGasPrice,
|
||||
value: mtx.value.minus(1),
|
||||
@@ -457,8 +433,8 @@ blockchainTests.resets('MetaTransactions feature', env => {
|
||||
|
||||
it('fails if gas price too low', async () => {
|
||||
const mtx = getRandomMetaTransaction();
|
||||
const mtxHash = getExchangeProxyMetaTransactionHash(mtx);
|
||||
const signature = await signMetaTransactionAsync(mtx);
|
||||
const mtxHash = mtx.getHash();
|
||||
const signature = await mtx.getSignatureWithProviderAsync(env.provider);
|
||||
const callOpts = {
|
||||
gasPrice: mtx.minGasPrice.minus(1),
|
||||
value: mtx.value,
|
||||
@@ -476,8 +452,8 @@ blockchainTests.resets('MetaTransactions feature', env => {
|
||||
|
||||
it('fails if gas price too high', async () => {
|
||||
const mtx = getRandomMetaTransaction();
|
||||
const mtxHash = getExchangeProxyMetaTransactionHash(mtx);
|
||||
const signature = await signMetaTransactionAsync(mtx);
|
||||
const mtxHash = mtx.getHash();
|
||||
const signature = await mtx.getSignatureWithProviderAsync(env.provider);
|
||||
const callOpts = {
|
||||
gasPrice: mtx.maxGasPrice.plus(1),
|
||||
value: mtx.value,
|
||||
@@ -497,8 +473,8 @@ blockchainTests.resets('MetaTransactions feature', env => {
|
||||
const mtx = getRandomMetaTransaction({
|
||||
expirationTimeSeconds: new BigNumber(Math.floor(_.now() / 1000 - 60)),
|
||||
});
|
||||
const mtxHash = getExchangeProxyMetaTransactionHash(mtx);
|
||||
const signature = await signMetaTransactionAsync(mtx);
|
||||
const mtxHash = mtx.getHash();
|
||||
const signature = await mtx.getSignatureWithProviderAsync(env.provider);
|
||||
const callOpts = {
|
||||
gasPrice: mtx.maxGasPrice,
|
||||
value: mtx.value,
|
||||
@@ -518,8 +494,8 @@ blockchainTests.resets('MetaTransactions feature', env => {
|
||||
const mtx = getRandomMetaTransaction({
|
||||
sender: requiredSender,
|
||||
});
|
||||
const mtxHash = getExchangeProxyMetaTransactionHash(mtx);
|
||||
const signature = await signMetaTransactionAsync(mtx);
|
||||
const mtxHash = mtx.getHash();
|
||||
const signature = await mtx.getSignatureWithProviderAsync(env.provider);
|
||||
const callOpts = {
|
||||
gasPrice: mtx.maxGasPrice,
|
||||
value: mtx.value,
|
||||
@@ -536,8 +512,8 @@ blockchainTests.resets('MetaTransactions feature', env => {
|
||||
|
||||
it('fails if signature is wrong', async () => {
|
||||
const mtx = getRandomMetaTransaction({ signer: signers[0] });
|
||||
const mtxHash = getExchangeProxyMetaTransactionHash(mtx);
|
||||
const signature = await signMetaTransactionAsync(mtx, signers[1]);
|
||||
const mtxHash = mtx.getHash();
|
||||
const signature = await mtx.clone({ signer: notSigner }).getSignatureWithProviderAsync(env.provider);
|
||||
const callOpts = {
|
||||
gasPrice: mtx.maxGasPrice,
|
||||
value: mtx.value,
|
||||
@@ -567,8 +543,8 @@ blockchainTests.resets('MetaTransactions feature', env => {
|
||||
.getABIEncodedTransactionData(),
|
||||
value: TRANSFORM_ERC20_REENTER_VALUE,
|
||||
});
|
||||
const mtxHash = getExchangeProxyMetaTransactionHash(mtx);
|
||||
const signature = await signMetaTransactionAsync(mtx);
|
||||
const mtxHash = mtx.getHash();
|
||||
const signature = await mtx.getSignatureWithProviderAsync(env.provider);
|
||||
const callOpts = {
|
||||
gasPrice: mtx.maxGasPrice,
|
||||
value: mtx.value,
|
||||
@@ -600,8 +576,8 @@ blockchainTests.resets('MetaTransactions feature', env => {
|
||||
.getABIEncodedTransactionData(),
|
||||
value: TRANSFORM_ERC20_BATCH_REENTER_VALUE,
|
||||
});
|
||||
const mtxHash = getExchangeProxyMetaTransactionHash(mtx);
|
||||
const signature = await signMetaTransactionAsync(mtx);
|
||||
const mtxHash = mtx.getHash();
|
||||
const signature = await mtx.getSignatureWithProviderAsync(env.provider);
|
||||
const callOpts = {
|
||||
gasPrice: mtx.maxGasPrice,
|
||||
value: mtx.value,
|
||||
@@ -633,8 +609,8 @@ blockchainTests.resets('MetaTransactions feature', env => {
|
||||
.getABIEncodedTransactionData(),
|
||||
value: TRANSFORM_ERC20_REENTER_VALUE,
|
||||
});
|
||||
const mtxHash = getExchangeProxyMetaTransactionHash(mtx);
|
||||
const signature = await signMetaTransactionAsync(mtx);
|
||||
const mtxHash = mtx.getHash();
|
||||
const signature = await mtx.getSignatureWithProviderAsync(env.provider);
|
||||
const callOpts = {
|
||||
gasPrice: mtx.maxGasPrice,
|
||||
value: mtx.value,
|
||||
@@ -666,8 +642,8 @@ blockchainTests.resets('MetaTransactions feature', env => {
|
||||
.getABIEncodedTransactionData(),
|
||||
value: TRANSFORM_ERC20_BATCH_REENTER_VALUE,
|
||||
});
|
||||
const mtxHash = getExchangeProxyMetaTransactionHash(mtx);
|
||||
const signature = await signMetaTransactionAsync(mtx);
|
||||
const mtxHash = mtx.getHash();
|
||||
const signature = await mtx.getSignatureWithProviderAsync(env.provider);
|
||||
const callOpts = {
|
||||
gasPrice: mtx.maxGasPrice,
|
||||
value: mtx.value,
|
||||
@@ -703,7 +679,9 @@ blockchainTests.resets('MetaTransactions feature', env => {
|
||||
.getABIEncodedTransactionData(),
|
||||
});
|
||||
});
|
||||
const signatures = await Promise.all(mtxs.map(async mtx => signMetaTransactionAsync(mtx)));
|
||||
const signatures = await Promise.all(
|
||||
mtxs.map(async mtx => mtx.getSignatureWithProviderAsync(env.provider)),
|
||||
);
|
||||
const callOpts = {
|
||||
gasPrice: BigNumber.max(...mtxs.map(mtx => mtx.minGasPrice)),
|
||||
value: BigNumber.sum(...mtxs.map(mtx => mtx.value)),
|
||||
@@ -728,9 +706,9 @@ blockchainTests.resets('MetaTransactions feature', env => {
|
||||
.getABIEncodedTransactionData(),
|
||||
});
|
||||
})();
|
||||
const mtxHash = getExchangeProxyMetaTransactionHash(mtx);
|
||||
const mtxHash = mtx.getHash();
|
||||
const mtxs = _.times(2, () => mtx);
|
||||
const signatures = await Promise.all(mtxs.map(async m => signMetaTransactionAsync(m)));
|
||||
const signatures = await Promise.all(mtxs.map(async m => m.getSignatureWithProviderAsync(env.provider)));
|
||||
const callOpts = {
|
||||
gasPrice: BigNumber.max(...mtxs.map(m => m.minGasPrice)),
|
||||
value: BigNumber.sum(...mtxs.map(m => m.value)),
|
||||
@@ -756,8 +734,8 @@ blockchainTests.resets('MetaTransactions feature', env => {
|
||||
)
|
||||
.getABIEncodedTransactionData(),
|
||||
});
|
||||
const mtxHash = getExchangeProxyMetaTransactionHash(mtx);
|
||||
const signature = await signMetaTransactionAsync(mtx);
|
||||
const mtxHash = mtx.getHash();
|
||||
const signature = await mtx.getSignatureWithProviderAsync(env.provider);
|
||||
const callOpts = {
|
||||
gasPrice: mtx.minGasPrice,
|
||||
value: mtx.value,
|
||||
@@ -786,8 +764,8 @@ blockchainTests.resets('MetaTransactions feature', env => {
|
||||
.getABIEncodedTransactionData(),
|
||||
value: TRANSFORM_ERC20_REENTER_VALUE,
|
||||
});
|
||||
const mtxHash = getExchangeProxyMetaTransactionHash(mtx);
|
||||
const signature = await signMetaTransactionAsync(mtx);
|
||||
const mtxHash = mtx.getHash();
|
||||
const signature = await mtx.getSignatureWithProviderAsync(env.provider);
|
||||
const callOpts = {
|
||||
gasPrice: mtx.maxGasPrice,
|
||||
value: mtx.value,
|
||||
@@ -819,8 +797,8 @@ blockchainTests.resets('MetaTransactions feature', env => {
|
||||
.getABIEncodedTransactionData(),
|
||||
value: TRANSFORM_ERC20_BATCH_REENTER_VALUE,
|
||||
});
|
||||
const mtxHash = getExchangeProxyMetaTransactionHash(mtx);
|
||||
const signature = await signMetaTransactionAsync(mtx);
|
||||
const mtxHash = mtx.getHash();
|
||||
const signature = await mtx.getSignatureWithProviderAsync(env.provider);
|
||||
const callOpts = {
|
||||
gasPrice: mtx.maxGasPrice,
|
||||
value: mtx.value,
|
||||
@@ -859,7 +837,7 @@ blockchainTests.resets('MetaTransactions feature', env => {
|
||||
)
|
||||
.getABIEncodedTransactionData(),
|
||||
});
|
||||
const signature = await signMetaTransactionAsync(mtx);
|
||||
const signature = await mtx.getSignatureWithProviderAsync(env.provider);
|
||||
const callOpts = {
|
||||
gasPrice: mtx.minGasPrice,
|
||||
value: mtx.value,
|
||||
@@ -873,7 +851,7 @@ blockchainTests.resets('MetaTransactions feature', env => {
|
||||
describe('getMetaTransactionHashExecutedBlock()', () => {
|
||||
it('returns zero for an unexecuted mtx', async () => {
|
||||
const mtx = getRandomMetaTransaction();
|
||||
const mtxHash = getExchangeProxyMetaTransactionHash(mtx);
|
||||
const mtxHash = mtx.getHash();
|
||||
const block = await feature.getMetaTransactionHashExecutedBlock(mtxHash).callAsync();
|
||||
expect(block).to.bignumber.eq(0);
|
||||
});
|
||||
@@ -891,13 +869,13 @@ blockchainTests.resets('MetaTransactions feature', env => {
|
||||
)
|
||||
.getABIEncodedTransactionData(),
|
||||
});
|
||||
const signature = await signMetaTransactionAsync(mtx);
|
||||
const signature = await mtx.getSignatureWithProviderAsync(env.provider);
|
||||
const callOpts = {
|
||||
gasPrice: mtx.minGasPrice,
|
||||
value: mtx.value,
|
||||
};
|
||||
const receipt = await feature.executeMetaTransaction(mtx, signature).awaitTransactionSuccessAsync(callOpts);
|
||||
const mtxHash = getExchangeProxyMetaTransactionHash(mtx);
|
||||
const mtxHash = mtx.getHash();
|
||||
const block = await feature.getMetaTransactionHashExecutedBlock(mtxHash).callAsync();
|
||||
expect(block).to.bignumber.eq(receipt.blockNumber);
|
||||
});
|
||||
|
@@ -78,6 +78,8 @@ blockchainTests.resets('FillQuoteTransformer', env => {
|
||||
dodoHelper: NULL_ADDRESS,
|
||||
snowSwapBridge: NULL_ADDRESS,
|
||||
cryptoComBridge: NULL_ADDRESS,
|
||||
bancorBridge: NULL_ADDRESS,
|
||||
cofixBridge: NULL_ADDRESS,
|
||||
},
|
||||
);
|
||||
transformer = await FillQuoteTransformerContract.deployFrom0xArtifactAsync(
|
||||
|
@@ -74,6 +74,8 @@ export * from '../test/generated-wrappers/log_metadata_transformer';
|
||||
export * from '../test/generated-wrappers/meta_transactions_feature';
|
||||
export * from '../test/generated-wrappers/mixin_adapter_addresses';
|
||||
export * from '../test/generated-wrappers/mixin_balancer';
|
||||
export * from '../test/generated-wrappers/mixin_bancor';
|
||||
export * from '../test/generated-wrappers/mixin_co_fi_x';
|
||||
export * from '../test/generated-wrappers/mixin_crypto_com';
|
||||
export * from '../test/generated-wrappers/mixin_curve';
|
||||
export * from '../test/generated-wrappers/mixin_dodo';
|
||||
|
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"extends": "../../tsconfig",
|
||||
"compilerOptions": { "outDir": "lib", "rootDir": ".", "resolveJsonModule": true },
|
||||
"include": ["./src/**/*", "./test/**/*", "./generated-wrappers/**/*"],
|
||||
"include": ["./src/**/*", "./test/**/*", "./generated-wrappers/**/*", "./scripts/**/*"],
|
||||
"files": [
|
||||
"generated-artifacts/AffiliateFeeTransformer.json",
|
||||
"generated-artifacts/BridgeAdapter.json",
|
||||
@@ -103,6 +103,8 @@
|
||||
"test/generated-artifacts/MetaTransactionsFeature.json",
|
||||
"test/generated-artifacts/MixinAdapterAddresses.json",
|
||||
"test/generated-artifacts/MixinBalancer.json",
|
||||
"test/generated-artifacts/MixinBancor.json",
|
||||
"test/generated-artifacts/MixinCoFiX.json",
|
||||
"test/generated-artifacts/MixinCryptoCom.json",
|
||||
"test/generated-artifacts/MixinCurve.json",
|
||||
"test/generated-artifacts/MixinDodo.json",
|
||||
|
99
docs/additional/emergency.rst
Normal file
99
docs/additional/emergency.rst
Normal file
File diff suppressed because one or more lines are too long
@@ -137,4 +137,34 @@ In both cases, the ``@0x/protocol-utils`` package simplifies generating these si
|
||||
|
||||
The Orderbook
|
||||
=======================
|
||||
Orders are shared through a decentralized and permissionless network, called `0x Mesh <https://0x.org/mesh>`_. The simplest way to post and discover orders is through `0x API <https://0x.org/api>`_. See `this guide <https://0x.org/docs/guides/market-making-on-0x>`_ tailored for Market Makers.
|
||||
Orders are shared through a decentralized and permissionless network, called `0x Mesh <https://0x.org/mesh>`_. The simplest way to post and discover orders is through `0x API <https://0x.org/api>`_. See `this guide <https://0x.org/docs/guides/market-making-on-0x>`_ tailored for Market Makers.
|
||||
|
||||
Orders are usually represented as a JSON object off-chain. Below is a table represention and example of how orders should be formatted off-chain.
|
||||
|
||||
JSON representation of RFQ Orders
|
||||
*********************************
|
||||
|
||||
A ``RFQOrder`` should be serialized to JSON as following:
|
||||
|
||||
.. code-block:: typescript
|
||||
|
||||
interface RfqOrderJson {
|
||||
"maker": string,
|
||||
"taker": string,
|
||||
"makerToken": string,
|
||||
"takerToken": string,
|
||||
"makerAmount": string,
|
||||
"takerAmount": string,
|
||||
"txOrigin": string,
|
||||
"pool": string,
|
||||
"expiry": number,
|
||||
"salt": string,
|
||||
"chainId": number, // Ethereum Chain Id where the transaction is submitted.
|
||||
"verifyingContract": string, // Address of the contract where the transaction should be sent.
|
||||
"signature": {
|
||||
"signatureType": number,
|
||||
"v": number,
|
||||
"s": string,
|
||||
"r": string,
|
||||
}
|
||||
}
|
@@ -65,6 +65,7 @@ Chat with our team privately on `Discord <https://discord.com/invite/d3FTX3M>`_
|
||||
additional/contributing.rst
|
||||
additional/exceptional_erc20s.rst
|
||||
additional/releases.rst
|
||||
additional/emergency.rst
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
@@ -1,4 +1,32 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1608245516,
|
||||
"version": "5.5.2",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1608149382,
|
||||
"version": "5.5.1",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "5.5.0",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Bancor now supported in all pairs",
|
||||
"pr": 88
|
||||
}
|
||||
],
|
||||
"timestamp": 1608105788
|
||||
},
|
||||
{
|
||||
"timestamp": 1607485227,
|
||||
"version": "5.4.2",
|
||||
|
@@ -5,6 +5,18 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
CHANGELOG
|
||||
|
||||
## v5.5.2 - _December 17, 2020_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v5.5.1 - _December 16, 2020_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v5.5.0 - _December 16, 2020_
|
||||
|
||||
* Bancor now supported in all pairs (#88)
|
||||
|
||||
## v5.4.2 - _December 9, 2020_
|
||||
|
||||
* Dependencies updated
|
||||
|
131
packages/asset-swapper/contracts/src/BancorSampler.sol
Normal file
131
packages/asset-swapper/contracts/src/BancorSampler.sol
Normal file
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
|
||||
Copyright 2020 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.6;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "./DeploymentConstants.sol";
|
||||
import "./interfaces/IBancor.sol";
|
||||
|
||||
|
||||
|
||||
contract BancorSampler is
|
||||
DeploymentConstants
|
||||
{
|
||||
|
||||
/// @dev Base gas limit for Bancor calls.
|
||||
uint256 constant private BANCOR_CALL_GAS = 300e3; // 300k
|
||||
address constant private BANCOR_ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
|
||||
|
||||
/// @dev Sample sell quotes from Bancor.
|
||||
/// @param paths The paths to check for Bancor. Only the best is used
|
||||
/// @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 bancorNetwork the Bancor Network address
|
||||
/// @return path the selected conversion path from bancor
|
||||
/// @return makerTokenAmounts Maker amounts bought at each taker token
|
||||
/// amount.
|
||||
function sampleSellsFromBancor(
|
||||
address[][] memory paths,
|
||||
address takerToken,
|
||||
address makerToken,
|
||||
uint256[] memory takerTokenAmounts
|
||||
)
|
||||
public
|
||||
view
|
||||
returns (address bancorNetwork, address[] memory path, uint256[] memory makerTokenAmounts)
|
||||
{
|
||||
bancorNetwork = _getBancorNetwork();
|
||||
if (paths.length == 0) {
|
||||
return (bancorNetwork, path, makerTokenAmounts);
|
||||
}
|
||||
uint256 maxBoughtAmount = 0;
|
||||
// Find the best path by selling the largest taker amount
|
||||
for (uint256 i = 0; i < paths.length; i++) {
|
||||
if (paths[i].length < 2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try
|
||||
IBancorNetwork(bancorNetwork)
|
||||
.rateByPath
|
||||
{gas: BANCOR_CALL_GAS}
|
||||
(paths[i], takerTokenAmounts[takerTokenAmounts.length-1])
|
||||
returns (uint256 amount)
|
||||
{
|
||||
if (amount > maxBoughtAmount) {
|
||||
maxBoughtAmount = amount;
|
||||
path = paths[i];
|
||||
}
|
||||
} catch {
|
||||
// Swallow failures, leaving all results as zero.
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
uint256 numSamples = takerTokenAmounts.length;
|
||||
makerTokenAmounts = new uint256[](numSamples);
|
||||
|
||||
for (uint256 i = 0; i < numSamples; i++) {
|
||||
try
|
||||
IBancorNetwork(bancorNetwork)
|
||||
.rateByPath
|
||||
{gas: BANCOR_CALL_GAS}
|
||||
(path, takerTokenAmounts[i])
|
||||
returns (uint256 amount)
|
||||
{
|
||||
makerTokenAmounts[i] = amount;
|
||||
} catch {
|
||||
// Swallow failures, leaving all results as zero.
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (bancorNetwork, path, makerTokenAmounts);
|
||||
}
|
||||
|
||||
/// @dev Sample buy quotes from Bancor. Unimplemented
|
||||
/// @param paths The paths to check for Bancor. Only the best is used
|
||||
/// @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 bancorNetwork the Bancor Network address
|
||||
/// @return path the selected conversion path from bancor
|
||||
/// @return takerTokenAmounts Taker amounts sold at each maker token
|
||||
/// amount.
|
||||
function sampleBuysFromBancor(
|
||||
address[][] memory paths,
|
||||
address takerToken,
|
||||
address makerToken,
|
||||
uint256[] memory makerTokenAmounts
|
||||
)
|
||||
public
|
||||
view
|
||||
returns (address bancorNetwork, address[] memory path, uint256[] memory takerTokenAmounts)
|
||||
{
|
||||
}
|
||||
|
||||
function _getBancorNetwork()
|
||||
private
|
||||
view
|
||||
returns (address)
|
||||
{
|
||||
IBancorRegistry registry = IBancorRegistry(_getBancorRegistryAddress());
|
||||
return registry.getAddress(registry.BANCOR_NETWORK());
|
||||
}
|
||||
}
|
@@ -62,6 +62,8 @@ contract DeploymentConstants {
|
||||
address constant private DODO_REGISTRY = 0x3A97247DF274a17C59A3bd12735ea3FcDFb49950;
|
||||
/// @dev Mainnet address of the DODO Helper contract
|
||||
address constant private DODO_HELPER = 0x533dA777aeDCE766CEAe696bf90f8541A4bA80Eb;
|
||||
/// @dev Mainnet address of the Bancor Registry contract
|
||||
address constant private BANCOR_REGISTRY = 0x52Ae12ABe5D8BD778BD5397F99cA900624CfADD4;
|
||||
|
||||
// // Ropsten addresses ///////////////////////////////////////////////////////
|
||||
// /// @dev Mainnet address of the WETH contract.
|
||||
@@ -337,4 +339,14 @@ contract DeploymentConstants {
|
||||
{
|
||||
return DODO_HELPER;
|
||||
}
|
||||
|
||||
/// @dev An overridable way to retrieve the Bancor Registry contract address.
|
||||
/// @return registry The Bancor registry contract address.
|
||||
function _getBancorRegistryAddress()
|
||||
internal
|
||||
view
|
||||
returns (address registry)
|
||||
{
|
||||
return BANCOR_REGISTRY;
|
||||
}
|
||||
}
|
||||
|
@@ -20,6 +20,7 @@ pragma solidity ^0.6;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "./BalancerSampler.sol";
|
||||
import "./BancorSampler.sol";
|
||||
import "./CurveSampler.sol";
|
||||
import "./DODOSampler.sol";
|
||||
import "./Eth2DaiSampler.sol";
|
||||
@@ -38,6 +39,7 @@ import "./UniswapV2Sampler.sol";
|
||||
|
||||
contract ERC20BridgeSampler is
|
||||
BalancerSampler,
|
||||
BancorSampler,
|
||||
CurveSampler,
|
||||
DODOSampler,
|
||||
Eth2DaiSampler,
|
||||
|
32
packages/asset-swapper/contracts/src/interfaces/IBancor.sol
Normal file
32
packages/asset-swapper/contracts/src/interfaces/IBancor.sol
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
|
||||
Copyright 2020 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.6;
|
||||
|
||||
|
||||
interface IBancor {}
|
||||
|
||||
interface IBancorNetwork {
|
||||
function conversionPath(address _sourceToken, address _targetToken) external view returns (address[] memory);
|
||||
function rateByPath(address[] memory _path, uint256 _amount) external view returns (uint256);
|
||||
}
|
||||
|
||||
interface IBancorRegistry {
|
||||
function getAddress(bytes32 _contractName) external view returns (address);
|
||||
function BANCOR_NETWORK() external view returns (bytes32);
|
||||
}
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@0x/asset-swapper",
|
||||
"version": "5.4.2",
|
||||
"version": "5.5.2",
|
||||
"engines": {
|
||||
"node": ">=6.12"
|
||||
},
|
||||
@@ -38,7 +38,7 @@
|
||||
"config": {
|
||||
"publicInterfaceContracts": "ERC20BridgeSampler,BalanceChecker",
|
||||
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually.",
|
||||
"abis": "./test/generated-artifacts/@(ApproximateBuys|BalanceChecker|BalancerSampler|CurveSampler|DODOSampler|DeploymentConstants|DummyLiquidityProvider|ERC20BridgeSampler|Eth2DaiSampler|IBalancer|ICurve|IEth2Dai|IKyberNetwork|IMStable|IMooniswap|IMultiBridge|IShell|IUniswapExchangeQuotes|IUniswapV2Router01|KyberSampler|LiquidityProviderSampler|MStableSampler|MooniswapSampler|MultiBridgeSampler|NativeOrderSampler|SamplerUtils|ShellSampler|SushiSwapSampler|TestERC20BridgeSampler|TestNativeOrderSampler|TwoHopSampler|UniswapSampler|UniswapV2Sampler).json",
|
||||
"abis": "./test/generated-artifacts/@(ApproximateBuys|BalanceChecker|BalancerSampler|BancorSampler|CurveSampler|DODOSampler|DeploymentConstants|DummyLiquidityProvider|ERC20BridgeSampler|Eth2DaiSampler|IBalancer|IBancor|ICurve|IEth2Dai|IKyberNetwork|IMStable|IMooniswap|IMultiBridge|IShell|IUniswapExchangeQuotes|IUniswapV2Router01|KyberSampler|LiquidityProviderSampler|MStableSampler|MooniswapSampler|MultiBridgeSampler|NativeOrderSampler|SamplerUtils|ShellSampler|SushiSwapSampler|TestERC20BridgeSampler|TestNativeOrderSampler|TwoHopSampler|UniswapSampler|UniswapV2Sampler).json",
|
||||
"postpublish": {
|
||||
"assets": []
|
||||
}
|
||||
@@ -59,11 +59,11 @@
|
||||
"dependencies": {
|
||||
"@0x/assert": "^3.0.19",
|
||||
"@0x/base-contract": "^6.2.14",
|
||||
"@0x/contract-addresses": "^5.6.0",
|
||||
"@0x/contract-wrappers": "^13.11.0",
|
||||
"@0x/contract-addresses": "^5.7.0",
|
||||
"@0x/contract-wrappers": "^13.11.1",
|
||||
"@0x/dev-utils": "^4.1.3",
|
||||
"@0x/json-schemas": "^5.3.4",
|
||||
"@0x/order-utils": "^10.4.10",
|
||||
"@0x/order-utils": "^10.4.11",
|
||||
"@0x/orderbook": "0xProject/gitpkg-registry#0x-orderbook-v2.2.7-e10a81023",
|
||||
"@0x/quote-server": "^3.1.0",
|
||||
"@0x/types": "^3.3.1",
|
||||
@@ -71,7 +71,7 @@
|
||||
"@0x/utils": "^6.1.1",
|
||||
"@0x/web3-wrapper": "^7.3.0",
|
||||
"@balancer-labs/sor": "0.3.2",
|
||||
"@bancor/sdk": "^0.2.9",
|
||||
"@bancor/sdk": "0.2.9",
|
||||
"@ethersproject/abi": "^5.0.1",
|
||||
"@ethersproject/address": "^5.0.1",
|
||||
"@ethersproject/contracts": "^5.0.1",
|
||||
@@ -87,16 +87,16 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@0x/base-contract": "^6.2.14",
|
||||
"@0x/contracts-asset-proxy": "^3.6.9",
|
||||
"@0x/contracts-erc20": "^3.2.12",
|
||||
"@0x/contracts-exchange": "^3.2.18",
|
||||
"@0x/contracts-exchange-libs": "^4.3.18",
|
||||
"@0x/contracts-asset-proxy": "^3.7.1",
|
||||
"@0x/contracts-erc20": "^3.2.13",
|
||||
"@0x/contracts-exchange": "^3.2.20",
|
||||
"@0x/contracts-exchange-libs": "^4.3.19",
|
||||
"@0x/contracts-gen": "^2.0.24",
|
||||
"@0x/contracts-test-utils": "^5.3.15",
|
||||
"@0x/contracts-utils": "^4.6.3",
|
||||
"@0x/contracts-zero-ex": "^0.12.0",
|
||||
"@0x/contracts-test-utils": "^5.3.16",
|
||||
"@0x/contracts-utils": "^4.6.4",
|
||||
"@0x/contracts-zero-ex": "^0.15.0",
|
||||
"@0x/mesh-rpc-client": "^9.4.2",
|
||||
"@0x/migrations": "^6.5.4",
|
||||
"@0x/migrations": "^6.5.7",
|
||||
"@0x/sol-compiler": "^4.4.1",
|
||||
"@0x/subproviders": "^6.2.3",
|
||||
"@0x/ts-doc-gen": "^0.0.28",
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { getContractAddressesForChainOrThrow } from '@0x/contract-addresses';
|
||||
import { ChainId, getContractAddressesForChainOrThrow } from '@0x/contract-addresses';
|
||||
import { DevUtilsContract } from '@0x/contract-wrappers';
|
||||
import { schemas } from '@0x/json-schemas';
|
||||
import { assetDataUtils, SignedOrder } from '@0x/order-utils';
|
||||
@@ -26,6 +26,7 @@ import {
|
||||
import { assert } from './utils/assert';
|
||||
import { calculateLiquidity } from './utils/calculate_liquidity';
|
||||
import { MarketOperationUtils } from './utils/market_operation_utils';
|
||||
import { BancorService } from './utils/market_operation_utils/bancor_service';
|
||||
import { createDummyOrderForSampler } from './utils/market_operation_utils/orders';
|
||||
import { DexOrderSampler } from './utils/market_operation_utils/sampler';
|
||||
import { SourceFilters } from './utils/market_operation_utils/source_filters';
|
||||
@@ -208,16 +209,18 @@ export class SwapQuoter {
|
||||
gas: samplerGasLimit,
|
||||
},
|
||||
);
|
||||
|
||||
this._marketOperationUtils = new MarketOperationUtils(
|
||||
new DexOrderSampler(
|
||||
samplerContract,
|
||||
samplerOverrides,
|
||||
provider,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined, // balancer pool cache
|
||||
undefined, // cream pool cache
|
||||
tokenAdjacencyGraph,
|
||||
liquidityProviderRegistry,
|
||||
this.chainId === ChainId.Mainnet // Enable Bancor only on Mainnet
|
||||
? async () => BancorService.createAsync(provider)
|
||||
: async () => undefined,
|
||||
),
|
||||
this._contractAddresses,
|
||||
{
|
||||
|
@@ -1,26 +1,17 @@
|
||||
import { SupportedProvider } from '@0x/dev-utils';
|
||||
import { BigNumber } from '@0x/utils';
|
||||
import { SDK } from '@bancor/sdk';
|
||||
import { Ethereum, getDecimals } from '@bancor/sdk/dist/blockchains/ethereum';
|
||||
import { fromWei, toWei } from '@bancor/sdk/dist/helpers';
|
||||
import { BlockchainType, Token } from '@bancor/sdk/dist/types';
|
||||
import { Ethereum } from '@bancor/sdk/dist/blockchains/ethereum';
|
||||
import { BlockchainType } from '@bancor/sdk/dist/types';
|
||||
|
||||
import { BancorFillData, Quote } from './types';
|
||||
import { TOKENS } from './constants';
|
||||
|
||||
/**
|
||||
* Converts an address to a Bancor Token type
|
||||
*/
|
||||
export function token(address: string, blockchainType: BlockchainType = BlockchainType.Ethereum): Token {
|
||||
return {
|
||||
blockchainType,
|
||||
blockchainId: address,
|
||||
};
|
||||
}
|
||||
const findToken = (tokenAddress: string, graph: object): string =>
|
||||
// If we're looking for WETH it is stored by Bancor as the 0xeee address
|
||||
tokenAddress.toLowerCase() === TOKENS.WETH.toLowerCase()
|
||||
? '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE'
|
||||
: Object.keys(graph).filter(k => k.toLowerCase() === tokenAddress.toLowerCase())[0];
|
||||
|
||||
export class BancorService {
|
||||
// Bancor recommends setting this value to 2% under the expected return amount
|
||||
public minReturnAmountBufferPercentage = 0.99;
|
||||
|
||||
public static async createAsync(provider: SupportedProvider): Promise<BancorService> {
|
||||
const sdk = await SDK.create({ ethereumNodeEndpoint: provider });
|
||||
const service = new BancorService(sdk);
|
||||
@@ -28,38 +19,16 @@ export class BancorService {
|
||||
}
|
||||
|
||||
constructor(public sdk: SDK) {}
|
||||
|
||||
public async getQuotesAsync(
|
||||
fromToken: string,
|
||||
toToken: string,
|
||||
amounts: BigNumber[],
|
||||
): Promise<Array<Quote<BancorFillData>>> {
|
||||
const sdk = this.sdk;
|
||||
const blockchain = sdk._core.blockchains[BlockchainType.Ethereum] as Ethereum;
|
||||
const sourceDecimals = await getDecimals(blockchain, fromToken);
|
||||
const quotes = await sdk.pricing.getPathAndRates(
|
||||
token(fromToken),
|
||||
token(toToken),
|
||||
amounts.map(amt => fromWei(amt.toString(), sourceDecimals)),
|
||||
);
|
||||
const targetDecimals = await getDecimals(blockchain, toToken);
|
||||
const networkAddress = this.getBancorNetworkAddress();
|
||||
|
||||
return quotes.map(quote => {
|
||||
const { path, rate } = quote;
|
||||
const output = toWei(rate, targetDecimals);
|
||||
return {
|
||||
amount: new BigNumber(output).multipliedBy(this.minReturnAmountBufferPercentage).dp(0),
|
||||
fillData: {
|
||||
path: path.map(p => p.blockchainId),
|
||||
networkAddress,
|
||||
},
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
public getBancorNetworkAddress(): string {
|
||||
const blockchain = this.sdk._core.blockchains[BlockchainType.Ethereum] as Ethereum;
|
||||
return blockchain.bancorNetwork._address;
|
||||
public getPaths(_fromToken: string, _toToken: string): string[][] {
|
||||
// HACK: We reach into the blockchain object and pull in it's cache of tokens
|
||||
// and we use it's internal non-async getPathsFunc
|
||||
try {
|
||||
const blockchain = this.sdk._core.blockchains[BlockchainType.Ethereum] as Ethereum;
|
||||
const fromToken = findToken(_fromToken, blockchain.graph);
|
||||
const toToken = findToken(_toToken, blockchain.graph);
|
||||
return blockchain.getPathsFunc.bind(blockchain)(fromToken, toToken);
|
||||
} catch (e) {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -5,6 +5,7 @@ import { BridgeContractAddresses } from '../../types';
|
||||
|
||||
import { SourceFilters } from './source_filters';
|
||||
import {
|
||||
BancorFillData,
|
||||
CurveFillData,
|
||||
CurveFunctionSelectors,
|
||||
CurveInfo,
|
||||
@@ -34,8 +35,7 @@ export const SELL_SOURCE_FILTER = new SourceFilters([
|
||||
ERC20BridgeSource.Kyber,
|
||||
ERC20BridgeSource.Curve,
|
||||
ERC20BridgeSource.Balancer,
|
||||
// Bancor is sampled off-chain, but this list should only include on-chain sources (used in ERC20BridgeSampler)
|
||||
// ERC20BridgeSource.Bancor,
|
||||
ERC20BridgeSource.Bancor,
|
||||
ERC20BridgeSource.MStable,
|
||||
ERC20BridgeSource.Mooniswap,
|
||||
ERC20BridgeSource.Swerve,
|
||||
@@ -60,7 +60,7 @@ export const BUY_SOURCE_FILTER = new SourceFilters([
|
||||
ERC20BridgeSource.Kyber,
|
||||
ERC20BridgeSource.Curve,
|
||||
ERC20BridgeSource.Balancer,
|
||||
// ERC20BridgeSource.Bancor, // FIXME: Disabled until Bancor SDK supports buy quotes
|
||||
// ERC20BridgeSource.Bancor, // FIXME: Bancor Buys not implemented in Sampler
|
||||
ERC20BridgeSource.MStable,
|
||||
ERC20BridgeSource.Mooniswap,
|
||||
ERC20BridgeSource.Shell,
|
||||
@@ -410,7 +410,7 @@ export const BRIDGE_ADDRESSES_BY_CHAIN: { [chainId in ChainId]: BridgeContractAd
|
||||
curveBridge: '0x1796cd592d19e3bcd744fbb025bb61a6d8cb2c09',
|
||||
multiBridge: '0xc03117a8c9bde203f70aa911cb64a7a0df5ba1e1',
|
||||
balancerBridge: '0xfe01821ca163844203220cd08e4f2b2fb43ae4e4',
|
||||
bancorBridge: '0x259897d9699553edbdf8538599242354e957fb94',
|
||||
bancorBridge: '0xc880c252db7c51f74161633338a3bdafa8e65276',
|
||||
mStableBridge: '0x2bf04fcea05f0989a14d9afa37aa376baca6b2b3',
|
||||
mooniswapBridge: '0x02b7eca484ad960fca3f7709e0b2ac81eec3069c',
|
||||
sushiswapBridge: '0x47ed0262a0b688dcb836d254c6a2e96b6c48a9f5',
|
||||
@@ -539,7 +539,14 @@ export const DEFAULT_GAS_SCHEDULE: Required<FeeSchedule> = {
|
||||
throw new Error('Unrecognized SnowSwap address');
|
||||
}
|
||||
},
|
||||
[ERC20BridgeSource.Bancor]: () => 300e3,
|
||||
[ERC20BridgeSource.Bancor]: (fillData?: FillData) => {
|
||||
let gas = 200e3;
|
||||
const path = (fillData as BancorFillData).path;
|
||||
if (path.length > 2) {
|
||||
gas += (path.length - 2) * 60e3; // +60k for each hop.
|
||||
}
|
||||
return gas;
|
||||
},
|
||||
};
|
||||
|
||||
export const DEFAULT_FEE_SCHEDULE: Required<FeeSchedule> = Object.assign(
|
||||
|
@@ -81,13 +81,12 @@ export class MarketOperationUtils {
|
||||
private readonly _feeSources = new SourceFilters(FEE_QUOTE_SOURCES);
|
||||
|
||||
private static _computeQuoteReport(
|
||||
nativeOrders: SignedOrder[],
|
||||
quoteRequestor: QuoteRequestor | undefined,
|
||||
marketSideLiquidity: MarketSideLiquidity,
|
||||
optimizerResult: OptimizerResult,
|
||||
comparisonPrice?: BigNumber | undefined,
|
||||
): QuoteReport {
|
||||
const { side, dexQuotes, twoHopQuotes, orderFillableAmounts } = marketSideLiquidity;
|
||||
const { side, dexQuotes, twoHopQuotes, orderFillableAmounts, nativeOrders } = marketSideLiquidity;
|
||||
const { liquidityDelivered } = optimizerResult;
|
||||
return generateQuoteReport(
|
||||
side,
|
||||
@@ -204,23 +203,12 @@ export class MarketOperationUtils {
|
||||
? this._sampler.getCreamSellQuotesOffChainAsync(makerToken, takerToken, sampleAmounts)
|
||||
: Promise.resolve([]);
|
||||
|
||||
const offChainBancorPromise = quoteSourceFilters.isAllowed(ERC20BridgeSource.Bancor)
|
||||
? this._sampler.getBancorSellQuotesOffChainAsync(makerToken, takerToken, [takerAmount])
|
||||
: Promise.resolve([]);
|
||||
|
||||
const [
|
||||
[tokenDecimals, orderFillableAmounts, ethToMakerAssetRate, ethToTakerAssetRate, dexQuotes, twoHopQuotes],
|
||||
rfqtIndicativeQuotes,
|
||||
offChainBalancerQuotes,
|
||||
offChainCreamQuotes,
|
||||
offChainBancorQuotes,
|
||||
] = await Promise.all([
|
||||
samplerPromise,
|
||||
rfqtPromise,
|
||||
offChainBalancerPromise,
|
||||
offChainCreamPromise,
|
||||
offChainBancorPromise,
|
||||
]);
|
||||
] = await Promise.all([samplerPromise, rfqtPromise, offChainBalancerPromise, offChainCreamPromise]);
|
||||
|
||||
const [makerTokenDecimals, takerTokenDecimals] = tokenDecimals;
|
||||
return {
|
||||
@@ -228,7 +216,7 @@ export class MarketOperationUtils {
|
||||
inputAmount: takerAmount,
|
||||
inputToken: takerToken,
|
||||
outputToken: makerToken,
|
||||
dexQuotes: dexQuotes.concat([...offChainBalancerQuotes, ...offChainCreamQuotes, offChainBancorQuotes]),
|
||||
dexQuotes: dexQuotes.concat([...offChainBalancerQuotes, ...offChainCreamQuotes]),
|
||||
nativeOrders,
|
||||
orderFillableAmounts,
|
||||
ethToOutputRate: ethToMakerAssetRate,
|
||||
@@ -630,7 +618,7 @@ export class MarketOperationUtils {
|
||||
side === MarketOperation.Sell
|
||||
? this.getMarketSellLiquidityAsync.bind(this)
|
||||
: this.getMarketBuyLiquidityAsync.bind(this);
|
||||
const marketSideLiquidity: MarketSideLiquidity = await marketLiquidityFnAsync(nativeOrders, amount, _opts);
|
||||
let marketSideLiquidity: MarketSideLiquidity = await marketLiquidityFnAsync(nativeOrders, amount, _opts);
|
||||
let optimizerResult: OptimizerResult | undefined;
|
||||
try {
|
||||
optimizerResult = await this._generateOptimizedOrdersAsync(marketSideLiquidity, optimizerOpts);
|
||||
@@ -673,13 +661,11 @@ export class MarketOperationUtils {
|
||||
);
|
||||
// Re-run optimizer with the new indicative quote
|
||||
if (indicativeQuotes.length > 0) {
|
||||
optimizerResult = await this._generateOptimizedOrdersAsync(
|
||||
{
|
||||
...marketSideLiquidity,
|
||||
rfqtIndicativeQuotes: indicativeQuotes,
|
||||
},
|
||||
optimizerOpts,
|
||||
);
|
||||
marketSideLiquidity = {
|
||||
...marketSideLiquidity,
|
||||
rfqtIndicativeQuotes: indicativeQuotes,
|
||||
};
|
||||
optimizerResult = await this._generateOptimizedOrdersAsync(marketSideLiquidity, optimizerOpts);
|
||||
}
|
||||
} else if (!rfqt.isIndicative && isFirmPriceAwareEnabled) {
|
||||
// A firm quote is being requested, and firm quotes price-aware enabled. Ensure that `intentOnFilling` is enabled.
|
||||
@@ -707,19 +693,18 @@ export class MarketOperationUtils {
|
||||
? firmQuoteSignedOrders.map(signedOrder => signedOrder.takerAssetAmount)
|
||||
: await rfqt.firmQuoteValidator.getRfqtTakerFillableAmountsAsync(firmQuoteSignedOrders);
|
||||
|
||||
marketSideLiquidity = {
|
||||
...marketSideLiquidity,
|
||||
nativeOrders: marketSideLiquidity.nativeOrders.concat(firmQuoteSignedOrders),
|
||||
orderFillableAmounts: marketSideLiquidity.orderFillableAmounts.concat(
|
||||
rfqOrderFillableAmounts,
|
||||
),
|
||||
};
|
||||
|
||||
// Re-run optimizer with the new firm quote. This is the second and last time
|
||||
// we run the optimized in a block of code. In this case, we don't catch a potential `NoOptimalPath` exception
|
||||
// and we let it bubble up if it happens.
|
||||
optimizerResult = await this._generateOptimizedOrdersAsync(
|
||||
{
|
||||
...marketSideLiquidity,
|
||||
nativeOrders: marketSideLiquidity.nativeOrders.concat(firmQuoteSignedOrders),
|
||||
orderFillableAmounts: marketSideLiquidity.orderFillableAmounts.concat(
|
||||
rfqOrderFillableAmounts,
|
||||
),
|
||||
},
|
||||
optimizerOpts,
|
||||
);
|
||||
optimizerResult = await this._generateOptimizedOrdersAsync(marketSideLiquidity, optimizerOpts);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -735,7 +720,6 @@ export class MarketOperationUtils {
|
||||
let quoteReport: QuoteReport | undefined;
|
||||
if (_opts.shouldGenerateQuoteReport) {
|
||||
quoteReport = MarketOperationUtils._computeQuoteReport(
|
||||
nativeOrders,
|
||||
_opts.rfqt ? _opts.rfqt.quoteRequestor : undefined,
|
||||
marketSideLiquidity,
|
||||
optimizerResult,
|
||||
|
@@ -1,4 +1,3 @@
|
||||
import { SupportedProvider } from '@0x/dev-utils';
|
||||
import { BigNumber, NULL_BYTES } from '@0x/utils';
|
||||
|
||||
import { SamplerOverrides } from '../../types';
|
||||
@@ -36,21 +35,19 @@ export class DexOrderSampler extends SamplerOperations {
|
||||
constructor(
|
||||
_samplerContract: ERC20BridgeSamplerContract,
|
||||
private readonly _samplerOverrides?: SamplerOverrides,
|
||||
provider?: SupportedProvider,
|
||||
balancerPoolsCache?: BalancerPoolsCache,
|
||||
creamPoolsCache?: CreamPoolsCache,
|
||||
getBancorServiceFn?: () => BancorService,
|
||||
tokenAdjacencyGraph?: TokenAdjacencyGraph,
|
||||
liquidityProviderRegistry?: LiquidityProviderRegistry,
|
||||
bancorServiceFn: () => Promise<BancorService | undefined> = async () => undefined,
|
||||
) {
|
||||
super(
|
||||
_samplerContract,
|
||||
provider,
|
||||
balancerPoolsCache,
|
||||
creamPoolsCache,
|
||||
getBancorServiceFn,
|
||||
tokenAdjacencyGraph,
|
||||
liquidityProviderRegistry,
|
||||
bancorServiceFn,
|
||||
);
|
||||
}
|
||||
|
||||
|
@@ -1,4 +1,3 @@
|
||||
import { SupportedProvider } from '@0x/dev-utils';
|
||||
import { SignedOrder } from '@0x/types';
|
||||
import { BigNumber } from '@0x/utils';
|
||||
import * as _ from 'lodash';
|
||||
@@ -81,25 +80,16 @@ export class SamplerOperations {
|
||||
|
||||
constructor(
|
||||
protected readonly _samplerContract: ERC20BridgeSamplerContract,
|
||||
public readonly provider?: SupportedProvider,
|
||||
public readonly balancerPoolsCache: BalancerPoolsCache = new BalancerPoolsCache(),
|
||||
public readonly creamPoolsCache: CreamPoolsCache = new CreamPoolsCache(),
|
||||
protected readonly getBancorServiceFn?: () => BancorService, // for dependency injection in tests
|
||||
protected readonly tokenAdjacencyGraph: TokenAdjacencyGraph = { default: [] },
|
||||
public readonly liquidityProviderRegistry: LiquidityProviderRegistry = LIQUIDITY_PROVIDER_REGISTRY,
|
||||
) {}
|
||||
|
||||
public async getBancorServiceAsync(): Promise<BancorService> {
|
||||
if (this.getBancorServiceFn !== undefined) {
|
||||
return this.getBancorServiceFn();
|
||||
}
|
||||
if (this.provider === undefined) {
|
||||
throw new Error('Cannot sample liquidity from Bancor; no provider supplied.');
|
||||
}
|
||||
if (this._bancorService === undefined) {
|
||||
this._bancorService = await BancorService.createAsync(this.provider);
|
||||
}
|
||||
return this._bancorService;
|
||||
bancorServiceFn: () => Promise<BancorService | undefined> = async () => undefined,
|
||||
) {
|
||||
// Initialize the Bancor service, fetching paths in the background
|
||||
bancorServiceFn()
|
||||
.then(service => (this._bancorService = service))
|
||||
.catch(/* do nothing */);
|
||||
}
|
||||
|
||||
public getTokenDecimals(makerTokenAddress: string, takerTokenAddress: string): BatchedOperation<BigNumber[]> {
|
||||
@@ -588,28 +578,48 @@ export class SamplerOperations {
|
||||
});
|
||||
}
|
||||
|
||||
public async getBancorSellQuotesOffChainAsync(
|
||||
public getBancorSellQuotes(
|
||||
makerToken: string,
|
||||
takerToken: string,
|
||||
takerFillAmounts: BigNumber[],
|
||||
): Promise<Array<DexSample<BancorFillData>>> {
|
||||
const bancorService = await this.getBancorServiceAsync();
|
||||
try {
|
||||
const quotes = await bancorService.getQuotesAsync(takerToken, makerToken, takerFillAmounts);
|
||||
return quotes.map((quote, i) => ({
|
||||
source: ERC20BridgeSource.Bancor,
|
||||
output: quote.amount,
|
||||
input: takerFillAmounts[i],
|
||||
fillData: quote.fillData,
|
||||
}));
|
||||
} catch (e) {
|
||||
return takerFillAmounts.map(input => ({
|
||||
source: ERC20BridgeSource.Bancor,
|
||||
output: ZERO_AMOUNT,
|
||||
input,
|
||||
fillData: { path: [], networkAddress: '' },
|
||||
}));
|
||||
}
|
||||
): SourceQuoteOperation<BancorFillData> {
|
||||
const paths = this._bancorService ? this._bancorService.getPaths(takerToken, makerToken) : [];
|
||||
return new SamplerContractOperation({
|
||||
source: ERC20BridgeSource.Bancor,
|
||||
contract: this._samplerContract,
|
||||
function: this._samplerContract.sampleSellsFromBancor,
|
||||
params: [paths, takerToken, makerToken, takerFillAmounts],
|
||||
callback: (callResults: string, fillData: BancorFillData): BigNumber[] => {
|
||||
const [networkAddress, path, samples] = this._samplerContract.getABIDecodedReturnData<
|
||||
[string, string[], BigNumber[]]
|
||||
>('sampleSellsFromBancor', callResults);
|
||||
fillData.networkAddress = networkAddress;
|
||||
fillData.path = path;
|
||||
return samples;
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// Unimplemented
|
||||
public getBancorBuyQuotes(
|
||||
makerToken: string,
|
||||
takerToken: string,
|
||||
makerFillAmounts: BigNumber[],
|
||||
): SourceQuoteOperation<BancorFillData> {
|
||||
return new SamplerContractOperation({
|
||||
source: ERC20BridgeSource.Bancor,
|
||||
contract: this._samplerContract,
|
||||
function: this._samplerContract.sampleBuysFromBancor,
|
||||
params: [[], takerToken, makerToken, makerFillAmounts],
|
||||
callback: (callResults: string, fillData: BancorFillData): BigNumber[] => {
|
||||
const [networkAddress, path, samples] = this._samplerContract.getABIDecodedReturnData<
|
||||
[string, string[], BigNumber[]]
|
||||
>('sampleSellsFromBancor', callResults);
|
||||
fillData.networkAddress = networkAddress;
|
||||
fillData.path = path;
|
||||
return samples;
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
public getMooniswapSellQuotes(
|
||||
@@ -1114,6 +1124,8 @@ export class SamplerOperations {
|
||||
);
|
||||
case ERC20BridgeSource.Dodo:
|
||||
return this.getDODOSellQuotes(makerToken, takerToken, takerFillAmounts);
|
||||
case ERC20BridgeSource.Bancor:
|
||||
return this.getBancorSellQuotes(makerToken, takerToken, takerFillAmounts);
|
||||
default:
|
||||
throw new Error(`Unsupported sell sample source: ${source}`);
|
||||
}
|
||||
@@ -1237,6 +1249,8 @@ export class SamplerOperations {
|
||||
);
|
||||
case ERC20BridgeSource.Dodo:
|
||||
return this.getDODOBuyQuotes(makerToken, takerToken, makerFillAmounts);
|
||||
case ERC20BridgeSource.Bancor:
|
||||
return this.getBancorBuyQuotes(makerToken, takerToken, makerFillAmounts);
|
||||
default:
|
||||
throw new Error(`Unsupported buy sample source: ${source}`);
|
||||
}
|
||||
|
@@ -8,6 +8,7 @@ import { ContractArtifact } from 'ethereum-types';
|
||||
import * as ApproximateBuys from '../test/generated-artifacts/ApproximateBuys.json';
|
||||
import * as BalanceChecker from '../test/generated-artifacts/BalanceChecker.json';
|
||||
import * as BalancerSampler from '../test/generated-artifacts/BalancerSampler.json';
|
||||
import * as BancorSampler from '../test/generated-artifacts/BancorSampler.json';
|
||||
import * as CurveSampler from '../test/generated-artifacts/CurveSampler.json';
|
||||
import * as DeploymentConstants from '../test/generated-artifacts/DeploymentConstants.json';
|
||||
import * as DODOSampler from '../test/generated-artifacts/DODOSampler.json';
|
||||
@@ -15,6 +16,7 @@ import * as DummyLiquidityProvider from '../test/generated-artifacts/DummyLiquid
|
||||
import * as ERC20BridgeSampler from '../test/generated-artifacts/ERC20BridgeSampler.json';
|
||||
import * as Eth2DaiSampler from '../test/generated-artifacts/Eth2DaiSampler.json';
|
||||
import * as IBalancer from '../test/generated-artifacts/IBalancer.json';
|
||||
import * as IBancor from '../test/generated-artifacts/IBancor.json';
|
||||
import * as ICurve from '../test/generated-artifacts/ICurve.json';
|
||||
import * as IEth2Dai from '../test/generated-artifacts/IEth2Dai.json';
|
||||
import * as IKyberNetwork from '../test/generated-artifacts/IKyberNetwork.json';
|
||||
@@ -42,6 +44,7 @@ export const artifacts = {
|
||||
ApproximateBuys: ApproximateBuys as ContractArtifact,
|
||||
BalanceChecker: BalanceChecker as ContractArtifact,
|
||||
BalancerSampler: BalancerSampler as ContractArtifact,
|
||||
BancorSampler: BancorSampler as ContractArtifact,
|
||||
CurveSampler: CurveSampler as ContractArtifact,
|
||||
DODOSampler: DODOSampler as ContractArtifact,
|
||||
DeploymentConstants: DeploymentConstants as ContractArtifact,
|
||||
@@ -60,6 +63,7 @@ export const artifacts = {
|
||||
UniswapSampler: UniswapSampler as ContractArtifact,
|
||||
UniswapV2Sampler: UniswapV2Sampler as ContractArtifact,
|
||||
IBalancer: IBalancer as ContractArtifact,
|
||||
IBancor: IBancor as ContractArtifact,
|
||||
ICurve: ICurve as ContractArtifact,
|
||||
IEth2Dai: IEth2Dai as ContractArtifact,
|
||||
IKyberNetwork: IKyberNetwork as ContractArtifact,
|
||||
|
@@ -1,72 +0,0 @@
|
||||
import { web3Factory, Web3ProviderEngine } from '@0x/dev-utils';
|
||||
import { Ethereum, getDecimals } from '@bancor/sdk/dist/blockchains/ethereum';
|
||||
import { fromWei, toWei } from '@bancor/sdk/dist/helpers';
|
||||
import { BlockchainType } from '@bancor/sdk/dist/types';
|
||||
import * as chai from 'chai';
|
||||
import * as _ from 'lodash';
|
||||
import 'mocha';
|
||||
|
||||
import { BancorFillData, BigNumber } from '../src';
|
||||
import { BancorService, token } from '../src/utils/market_operation_utils/bancor_service';
|
||||
|
||||
import { chaiSetup } from './utils/chai_setup';
|
||||
|
||||
chaiSetup.configure();
|
||||
const expect = chai.expect;
|
||||
|
||||
const ADDRESS_REGEX = /^(0x)?[0-9a-f]{40}$/i;
|
||||
const RPC_URL = `https://mainnet.infura.io/v3/${process.env.INFURA_PROJECT_ID}`;
|
||||
|
||||
const provider: Web3ProviderEngine = web3Factory.getRpcProvider({ rpcUrl: RPC_URL });
|
||||
// tslint:disable:custom-no-magic-numbers
|
||||
|
||||
let bancorService: BancorService;
|
||||
|
||||
// These tests test the bancor SDK against mainnet
|
||||
// TODO (xianny): After we move asset-swapper out of the monorepo, we should add an env variable to circle CI to run this test
|
||||
describe.skip('Bancor Service', () => {
|
||||
const eth = '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee';
|
||||
const bnt = '0x1f573d6fb3f13d689ff844b4ce37794d79a7ff1c';
|
||||
it('should retrieve the bancor network address', async () => {
|
||||
bancorService = await BancorService.createAsync(provider);
|
||||
const networkAddress = bancorService.getBancorNetworkAddress();
|
||||
expect(networkAddress).to.match(ADDRESS_REGEX);
|
||||
});
|
||||
it('should retrieve a quote', async () => {
|
||||
const amt = new BigNumber(10e18);
|
||||
const quotes = await bancorService.getQuotesAsync(eth, bnt, [amt]);
|
||||
const fillData = quotes[0].fillData as BancorFillData;
|
||||
|
||||
// get rate from the bancor sdk
|
||||
const blockchain = bancorService.sdk._core.blockchains[BlockchainType.Ethereum] as Ethereum;
|
||||
const sourceDecimals = await getDecimals(blockchain, token(eth));
|
||||
const rate = await bancorService.sdk.pricing.getRateByPath(
|
||||
fillData.path.map(p => token(p)),
|
||||
fromWei(amt.toString(), sourceDecimals),
|
||||
);
|
||||
const expectedRate = toWei(rate, await getDecimals(blockchain, token(bnt)));
|
||||
|
||||
expect(fillData.networkAddress).to.match(ADDRESS_REGEX);
|
||||
expect(fillData.path[0].toLowerCase()).to.eq(eth);
|
||||
expect(fillData.path[2].toLowerCase()).to.eq(bnt);
|
||||
expect(fillData.path.length).to.eq(3); // eth -> bnt should be single hop!
|
||||
expect(quotes[0].amount.dp(0)).to.bignumber.eq(
|
||||
new BigNumber(expectedRate).multipliedBy(bancorService.minReturnAmountBufferPercentage).dp(0),
|
||||
);
|
||||
});
|
||||
// HACK (xianny): for exploring SDK results
|
||||
it('should retrieve multiple quotes', async () => {
|
||||
const amts = [1, 10, 100, 1000].map(a => new BigNumber(a).multipliedBy(10e18));
|
||||
const quotes = await bancorService.getQuotesAsync(eth, bnt, amts);
|
||||
quotes.map((q, i) => {
|
||||
// tslint:disable:no-console
|
||||
const fillData = q.fillData as BancorFillData;
|
||||
console.log(
|
||||
`Input ${amts[i].toExponential()}; Output: ${q.amount}; Ratio: ${q.amount.dividedBy(amts[i])}, Path: ${
|
||||
fillData.path.length
|
||||
}\nPath: ${JSON.stringify(fillData.path)}`,
|
||||
);
|
||||
// tslint:enable:no-console
|
||||
});
|
||||
});
|
||||
});
|
@@ -17,9 +17,7 @@ import { DexOrderSampler, getSampleAmounts } from '../src/utils/market_operation
|
||||
import { ERC20BridgeSource, TokenAdjacencyGraph } from '../src/utils/market_operation_utils/types';
|
||||
|
||||
import { MockBalancerPoolsCache } from './utils/mock_balancer_pools_cache';
|
||||
import { MockBancorService } from './utils/mock_bancor_service';
|
||||
import { MockSamplerContract } from './utils/mock_sampler_contract';
|
||||
import { provider } from './utils/web3_wrapper';
|
||||
|
||||
const CHAIN_ID = 1;
|
||||
// tslint:disable: custom-no-magic-numbers
|
||||
@@ -104,7 +102,15 @@ describe('DexSampler tests', () => {
|
||||
return expectedFillableAmounts;
|
||||
},
|
||||
});
|
||||
const dexOrderSampler = new DexOrderSampler(sampler);
|
||||
const dexOrderSampler = new DexOrderSampler(
|
||||
sampler,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
async () => undefined,
|
||||
);
|
||||
const [fillableAmounts] = await dexOrderSampler.executeAsync(
|
||||
dexOrderSampler.getOrderFillableMakerAmounts(ORDERS, exchangeAddress),
|
||||
);
|
||||
@@ -120,7 +126,15 @@ describe('DexSampler tests', () => {
|
||||
return expectedFillableAmounts;
|
||||
},
|
||||
});
|
||||
const dexOrderSampler = new DexOrderSampler(sampler);
|
||||
const dexOrderSampler = new DexOrderSampler(
|
||||
sampler,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
async () => undefined,
|
||||
);
|
||||
const [fillableAmounts] = await dexOrderSampler.executeAsync(
|
||||
dexOrderSampler.getOrderFillableTakerAmounts(ORDERS, exchangeAddress),
|
||||
);
|
||||
@@ -140,7 +154,15 @@ describe('DexSampler tests', () => {
|
||||
return ['0x', expectedMakerFillAmounts];
|
||||
},
|
||||
});
|
||||
const dexOrderSampler = new DexOrderSampler(sampler);
|
||||
const dexOrderSampler = new DexOrderSampler(
|
||||
sampler,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
async () => undefined,
|
||||
);
|
||||
const [fillableAmounts] = await dexOrderSampler.executeAsync(
|
||||
dexOrderSampler.getKyberSellQuotes(
|
||||
'0x',
|
||||
@@ -171,9 +193,10 @@ describe('DexSampler tests', () => {
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
{ [poolAddress]: { tokens: [expectedMakerToken, expectedTakerToken], gasCost } },
|
||||
{
|
||||
[poolAddress]: { tokens: [expectedMakerToken, expectedTakerToken], gasCost },
|
||||
},
|
||||
async () => undefined,
|
||||
);
|
||||
const [result] = await dexOrderSampler.executeAsync(
|
||||
dexOrderSampler.getSellQuotes(
|
||||
@@ -214,9 +237,10 @@ describe('DexSampler tests', () => {
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
{ [poolAddress]: { tokens: [expectedMakerToken, expectedTakerToken], gasCost } },
|
||||
{
|
||||
[poolAddress]: { tokens: [expectedMakerToken, expectedTakerToken], gasCost },
|
||||
},
|
||||
async () => undefined,
|
||||
);
|
||||
const [result] = await dexOrderSampler.executeAsync(
|
||||
dexOrderSampler.getBuyQuotes(
|
||||
@@ -251,7 +275,15 @@ describe('DexSampler tests', () => {
|
||||
return expectedMakerFillAmounts;
|
||||
},
|
||||
});
|
||||
const dexOrderSampler = new DexOrderSampler(sampler);
|
||||
const dexOrderSampler = new DexOrderSampler(
|
||||
sampler,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
async () => undefined,
|
||||
);
|
||||
const [fillableAmounts] = await dexOrderSampler.executeAsync(
|
||||
dexOrderSampler.getEth2DaiSellQuotes(expectedMakerToken, expectedTakerToken, expectedTakerFillAmounts),
|
||||
);
|
||||
@@ -271,7 +303,15 @@ describe('DexSampler tests', () => {
|
||||
return expectedMakerFillAmounts;
|
||||
},
|
||||
});
|
||||
const dexOrderSampler = new DexOrderSampler(sampler);
|
||||
const dexOrderSampler = new DexOrderSampler(
|
||||
sampler,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
async () => undefined,
|
||||
);
|
||||
const [fillableAmounts] = await dexOrderSampler.executeAsync(
|
||||
dexOrderSampler.getUniswapSellQuotes(expectedMakerToken, expectedTakerToken, expectedTakerFillAmounts),
|
||||
);
|
||||
@@ -290,7 +330,15 @@ describe('DexSampler tests', () => {
|
||||
return expectedMakerFillAmounts;
|
||||
},
|
||||
});
|
||||
const dexOrderSampler = new DexOrderSampler(sampler);
|
||||
const dexOrderSampler = new DexOrderSampler(
|
||||
sampler,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
async () => undefined,
|
||||
);
|
||||
const [fillableAmounts] = await dexOrderSampler.executeAsync(
|
||||
dexOrderSampler.getUniswapV2SellQuotes(
|
||||
[expectedMakerToken, expectedTakerToken],
|
||||
@@ -313,7 +361,15 @@ describe('DexSampler tests', () => {
|
||||
return expectedTakerFillAmounts;
|
||||
},
|
||||
});
|
||||
const dexOrderSampler = new DexOrderSampler(sampler);
|
||||
const dexOrderSampler = new DexOrderSampler(
|
||||
sampler,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
async () => undefined,
|
||||
);
|
||||
const [fillableAmounts] = await dexOrderSampler.executeAsync(
|
||||
dexOrderSampler.getEth2DaiBuyQuotes(expectedMakerToken, expectedTakerToken, expectedMakerFillAmounts),
|
||||
);
|
||||
@@ -333,7 +389,15 @@ describe('DexSampler tests', () => {
|
||||
return expectedTakerFillAmounts;
|
||||
},
|
||||
});
|
||||
const dexOrderSampler = new DexOrderSampler(sampler);
|
||||
const dexOrderSampler = new DexOrderSampler(
|
||||
sampler,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
async () => undefined,
|
||||
);
|
||||
const [fillableAmounts] = await dexOrderSampler.executeAsync(
|
||||
dexOrderSampler.getUniswapBuyQuotes(expectedMakerToken, expectedTakerToken, expectedMakerFillAmounts),
|
||||
);
|
||||
@@ -385,9 +449,9 @@ describe('DexSampler tests', () => {
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
tokenAdjacencyGraph,
|
||||
undefined,
|
||||
async () => undefined,
|
||||
);
|
||||
const [quotes] = await dexOrderSampler.executeAsync(
|
||||
dexOrderSampler.getSellQuotes(
|
||||
@@ -441,8 +505,11 @@ describe('DexSampler tests', () => {
|
||||
const dexOrderSampler = new DexOrderSampler(
|
||||
new MockSamplerContract({}),
|
||||
undefined,
|
||||
undefined,
|
||||
balancerPoolsCache,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
async () => undefined,
|
||||
);
|
||||
const quotes = await dexOrderSampler.getBalancerSellQuotesOffChainAsync(
|
||||
expectedMakerToken,
|
||||
@@ -451,45 +518,6 @@ describe('DexSampler tests', () => {
|
||||
);
|
||||
expect(quotes).to.have.lengthOf(0);
|
||||
});
|
||||
it('getSellQuotes() uses samples from Bancor', async () => {
|
||||
const expectedTakerToken = randomAddress();
|
||||
const expectedMakerToken = randomAddress();
|
||||
const networkAddress = randomAddress();
|
||||
const expectedTakerFillAmounts = getSampleAmounts(new BigNumber(100e18), 3);
|
||||
const rate = getRandomFloat(0, 100);
|
||||
const bancorService = await MockBancorService.createMockAsync({
|
||||
getQuotesAsync: async (fromToken: string, toToken: string, amounts: BigNumber[]) => {
|
||||
expect(fromToken).equal(expectedTakerToken);
|
||||
expect(toToken).equal(expectedMakerToken);
|
||||
return Promise.resolve(
|
||||
amounts.map(a => ({
|
||||
fillData: { path: [fromToken, toToken], networkAddress },
|
||||
amount: a.multipliedBy(rate),
|
||||
})),
|
||||
);
|
||||
},
|
||||
});
|
||||
const dexOrderSampler = new DexOrderSampler(
|
||||
new MockSamplerContract({}),
|
||||
undefined, // sampler overrides
|
||||
provider,
|
||||
undefined, // balancer cache
|
||||
undefined, // cream cache
|
||||
() => bancorService,
|
||||
);
|
||||
const quotes = await dexOrderSampler.getBancorSellQuotesOffChainAsync(
|
||||
expectedMakerToken,
|
||||
expectedTakerToken,
|
||||
expectedTakerFillAmounts,
|
||||
);
|
||||
const expectedQuotes = expectedTakerFillAmounts.map(a => ({
|
||||
source: ERC20BridgeSource.Bancor,
|
||||
input: a,
|
||||
output: a.multipliedBy(rate),
|
||||
fillData: { path: [expectedTakerToken, expectedMakerToken], networkAddress },
|
||||
}));
|
||||
expect(quotes).to.deep.eq(expectedQuotes);
|
||||
});
|
||||
it('getBuyQuotes()', async () => {
|
||||
const expectedTakerToken = randomAddress();
|
||||
const expectedMakerToken = randomAddress();
|
||||
@@ -530,9 +558,9 @@ describe('DexSampler tests', () => {
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
tokenAdjacencyGraph,
|
||||
undefined,
|
||||
async () => undefined,
|
||||
);
|
||||
const [quotes] = await dexOrderSampler.executeAsync(
|
||||
dexOrderSampler.getBuyQuotes(sources, expectedMakerToken, expectedTakerToken, expectedMakerFillAmounts),
|
||||
@@ -577,8 +605,11 @@ describe('DexSampler tests', () => {
|
||||
const dexOrderSampler = new DexOrderSampler(
|
||||
new MockSamplerContract({}),
|
||||
undefined,
|
||||
undefined,
|
||||
balancerPoolsCache,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
async () => undefined,
|
||||
);
|
||||
const quotes = await dexOrderSampler.getBalancerBuyQuotesOffChainAsync(
|
||||
expectedMakerToken,
|
||||
@@ -605,7 +636,15 @@ describe('DexSampler tests', () => {
|
||||
return expectedFillableTakerAmounts;
|
||||
},
|
||||
});
|
||||
const dexOrderSampler = new DexOrderSampler(sampler);
|
||||
const dexOrderSampler = new DexOrderSampler(
|
||||
sampler,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
async () => undefined,
|
||||
);
|
||||
const [fillableMakerAmounts, fillableTakerAmounts] = await dexOrderSampler.executeAsync(
|
||||
dexOrderSampler.getOrderFillableMakerAmounts(ORDERS, exchangeAddress),
|
||||
dexOrderSampler.getOrderFillableTakerAmounts(ORDERS, exchangeAddress),
|
||||
|
@@ -1,33 +0,0 @@
|
||||
import { BigNumber } from '@0x/utils';
|
||||
import { SDK } from '@bancor/sdk';
|
||||
|
||||
import { BancorService } from '../../src/utils/market_operation_utils/bancor_service';
|
||||
import { BancorFillData, Quote } from '../../src/utils/market_operation_utils/types';
|
||||
|
||||
export interface Handlers {
|
||||
getQuotesAsync: (fromToken: string, toToken: string, amount: BigNumber[]) => Promise<Array<Quote<BancorFillData>>>;
|
||||
}
|
||||
|
||||
export class MockBancorService extends BancorService {
|
||||
// Bancor recommends setting this value to 2% under the expected return amount
|
||||
public minReturnAmountBufferPercentage = 0.98;
|
||||
|
||||
public static async createMockAsync(handlers: Partial<Handlers>): Promise<MockBancorService> {
|
||||
const sdk = new SDK();
|
||||
return new MockBancorService(sdk, handlers);
|
||||
}
|
||||
|
||||
constructor(sdk: SDK, public handlers: Partial<Handlers>) {
|
||||
super(sdk);
|
||||
}
|
||||
|
||||
public async getQuotesAsync(
|
||||
fromToken: string,
|
||||
toToken: string,
|
||||
amounts: BigNumber[],
|
||||
): Promise<Array<Quote<BancorFillData>>> {
|
||||
return this.handlers.getQuotesAsync
|
||||
? this.handlers.getQuotesAsync(fromToken, toToken, amounts)
|
||||
: super.getQuotesAsync(fromToken, toToken, amounts);
|
||||
}
|
||||
}
|
@@ -6,6 +6,7 @@
|
||||
export * from '../test/generated-wrappers/approximate_buys';
|
||||
export * from '../test/generated-wrappers/balance_checker';
|
||||
export * from '../test/generated-wrappers/balancer_sampler';
|
||||
export * from '../test/generated-wrappers/bancor_sampler';
|
||||
export * from '../test/generated-wrappers/curve_sampler';
|
||||
export * from '../test/generated-wrappers/d_o_d_o_sampler';
|
||||
export * from '../test/generated-wrappers/deployment_constants';
|
||||
@@ -13,6 +14,7 @@ export * from '../test/generated-wrappers/dummy_liquidity_provider';
|
||||
export * from '../test/generated-wrappers/erc20_bridge_sampler';
|
||||
export * from '../test/generated-wrappers/eth2_dai_sampler';
|
||||
export * from '../test/generated-wrappers/i_balancer';
|
||||
export * from '../test/generated-wrappers/i_bancor';
|
||||
export * from '../test/generated-wrappers/i_curve';
|
||||
export * from '../test/generated-wrappers/i_eth2_dai';
|
||||
export * from '../test/generated-wrappers/i_kyber_network';
|
||||
|
@@ -8,6 +8,7 @@
|
||||
"test/generated-artifacts/ApproximateBuys.json",
|
||||
"test/generated-artifacts/BalanceChecker.json",
|
||||
"test/generated-artifacts/BalancerSampler.json",
|
||||
"test/generated-artifacts/BancorSampler.json",
|
||||
"test/generated-artifacts/CurveSampler.json",
|
||||
"test/generated-artifacts/DODOSampler.json",
|
||||
"test/generated-artifacts/DeploymentConstants.json",
|
||||
@@ -15,6 +16,7 @@
|
||||
"test/generated-artifacts/ERC20BridgeSampler.json",
|
||||
"test/generated-artifacts/Eth2DaiSampler.json",
|
||||
"test/generated-artifacts/IBalancer.json",
|
||||
"test/generated-artifacts/IBancor.json",
|
||||
"test/generated-artifacts/ICurve.json",
|
||||
"test/generated-artifacts/IEth2Dai.json",
|
||||
"test/generated-artifacts/IKyberNetwork.json",
|
||||
|
@@ -1,4 +1,14 @@
|
||||
[
|
||||
{
|
||||
"version": "5.7.0",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Redeploy FQT",
|
||||
"pr": 91
|
||||
}
|
||||
],
|
||||
"timestamp": 1608245516
|
||||
},
|
||||
{
|
||||
"version": "5.6.0",
|
||||
"changes": [
|
||||
|
@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
CHANGELOG
|
||||
|
||||
## v5.7.0 - _December 17, 2020_
|
||||
|
||||
* Redeploy FQT (#91)
|
||||
|
||||
## v5.6.0 - _December 7, 2020_
|
||||
|
||||
* Update mainnet and ropsten transformer addresses for hot-pants release (#70)
|
||||
|
@@ -37,7 +37,7 @@
|
||||
"wethTransformer": "0xb2bc06a4efb20fc6553a69dbfa49b7be938034a7",
|
||||
"payTakerTransformer": "0x4638a7ebe75b911b995d0ec73a81e4f85f41f24e",
|
||||
"affiliateFeeTransformer": "0xda6d9fc5998f550a094585cf9171f0e8ee3ac59f",
|
||||
"fillQuoteTransformer": "0x74c35f17a19d4ee0ddd65cc21c671806913f9176"
|
||||
"fillQuoteTransformer": "0xab6959d63bf6557d4bc2a0fc5265f5a6851e33f3"
|
||||
}
|
||||
},
|
||||
"3": {
|
||||
@@ -78,7 +78,7 @@
|
||||
"wethTransformer": "0x05ad19aa3826e0609a19568ffbd1dfe86c6c7184",
|
||||
"payTakerTransformer": "0x6d0ebf2bcd9cc93ec553b60ad201943dcca4e291",
|
||||
"affiliateFeeTransformer": "0x6588256778ca4432fa43983ac685c45efb2379e2",
|
||||
"fillQuoteTransformer": "0x5ec162400ec00f0f3ef1d8aae1fed37742d5dc81"
|
||||
"fillQuoteTransformer": "0x5cd9164c9352ff95e3b6fa7bb9ac89a102c9d109"
|
||||
}
|
||||
},
|
||||
"4": {
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@0x/contract-addresses",
|
||||
"version": "5.6.0",
|
||||
"version": "5.7.0",
|
||||
"engines": {
|
||||
"node": ">=6.12"
|
||||
},
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@0x/contract-wrappers-test",
|
||||
"version": "12.2.28",
|
||||
"version": "12.2.31",
|
||||
"engines": {
|
||||
"node": ">=6.12"
|
||||
},
|
||||
@@ -31,11 +31,11 @@
|
||||
},
|
||||
"homepage": "https://github.com/0xProject/protocol/tree/main/packages/contract-wrappers-test",
|
||||
"devDependencies": {
|
||||
"@0x/contract-wrappers": "^13.11.0",
|
||||
"@0x/contracts-test-utils": "^5.3.15",
|
||||
"@0x/contract-wrappers": "^13.11.1",
|
||||
"@0x/contracts-test-utils": "^5.3.16",
|
||||
"@0x/dev-utils": "^4.1.3",
|
||||
"@0x/migrations": "^6.5.4",
|
||||
"@0x/order-utils": "^10.4.10",
|
||||
"@0x/migrations": "^6.5.7",
|
||||
"@0x/order-utils": "^10.4.11",
|
||||
"@0x/subproviders": "^6.2.3",
|
||||
"@0x/ts-doc-gen": "^0.0.28",
|
||||
"@0x/tslint-config": "^4.1.3",
|
||||
|
@@ -1,4 +1,13 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1608245516,
|
||||
"version": "13.11.1",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "13.11.0",
|
||||
"changes": [
|
||||
|
@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
CHANGELOG
|
||||
|
||||
## v13.11.1 - _December 17, 2020_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v13.11.0 - _December 9, 2020_
|
||||
|
||||
* Regenerate wrappers (#76)
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@0x/contract-wrappers",
|
||||
"version": "13.11.0",
|
||||
"version": "13.11.1",
|
||||
"engines": {
|
||||
"node": ">=6.12"
|
||||
},
|
||||
@@ -57,7 +57,7 @@
|
||||
"dependencies": {
|
||||
"@0x/assert": "^3.0.19",
|
||||
"@0x/base-contract": "^6.2.14",
|
||||
"@0x/contract-addresses": "^5.6.0",
|
||||
"@0x/contract-addresses": "^5.7.0",
|
||||
"@0x/json-schemas": "^5.3.4",
|
||||
"@0x/types": "^3.3.1",
|
||||
"@0x/utils": "^6.1.1",
|
||||
|
@@ -1,4 +1,31 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1608245516,
|
||||
"version": "6.5.7",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1608149382,
|
||||
"version": "6.5.6",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1608105788,
|
||||
"version": "6.5.5",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1607485227,
|
||||
"version": "6.5.4",
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user