@0x/contracts-erc20-bridge-sampler: Fix kyber bug and add test contract.

This commit is contained in:
Lawrence Forman 2019-11-15 17:48:52 -05:00
parent a26c3036a7
commit d02db3864e
15 changed files with 592 additions and 94 deletions

View File

@ -67,11 +67,4 @@ interface IUniswapExchange {
)
external
returns (uint256 tokensBought);
/// @dev Retrieves the token that is associated with this exchange.
/// @return tokenAddress The token address.
function toTokenAddress()
external
view
returns (address tokenAddress);
}

View File

@ -0,0 +1,86 @@
/*
Copyright 2019 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.5.9;
pragma experimental ABIEncoderV2;
import "@0x/contracts-asset-proxy/contracts/src/interfaces/IUniswapExchangeFactory.sol";
import "@0x/contracts-exchange/contracts/src/interfaces/IExchange.sol";
import "./IEth2Dai.sol";
import "./IKyberNetwork.sol";
contract DeploymentConstants {
address constant public EXCHANGE_ADDRESS = 0x080bf510FCbF18b91105470639e9561022937712;
address constant public ETH2DAI_ADDRESS = 0x39755357759cE0d7f32dC8dC45414CCa409AE24e;
address constant public UNISWAP_EXCHANGE_FACTORY_ADDRESS = 0xc0a47dFe034B400B47bDaD5FecDa2621de6c4d95;
address constant public KYBER_NETWORK_PROXY_ADDRESS = 0x818E6FECD516Ecc3849DAf6845e3EC868087B755;
address constant public WETH_ADDRESS = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
address constant public KYBER_ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
/// @dev An overridable way to retrieve the 0x Exchange contract.
/// @return zeroex The 0x Exchange contract.
function _getExchangeContract()
internal
view
returns (IExchange zeroex)
{
return IExchange(EXCHANGE_ADDRESS);
}
/// @dev An overridable way to retrieve the Eth2Dai exchange contract.
/// @return eth2dai The Eth2Dai exchange contract.
function _getEth2DaiContract()
internal
view
returns (IEth2Dai eth2dai)
{
return IEth2Dai(ETH2DAI_ADDRESS);
}
/// @dev An overridable way to retrieve the Uniswap exchange factory contract.
/// @return uniswap The UniswapExchangeFactory contract.
function _getUniswapExchangeFactoryContract()
internal
view
returns (IUniswapExchangeFactory uniswap)
{
return IUniswapExchangeFactory(UNISWAP_EXCHANGE_FACTORY_ADDRESS);
}
/// @dev An overridable way to retrieve the Kyber network proxy contract.
/// @return kyber The KyberNeworkProxy contract.
function _getKyberNetworkContract()
internal
view
returns (IKyberNetwork kyber)
{
return IKyberNetwork(KYBER_NETWORK_PROXY_ADDRESS);
}
/// @dev An overridable way to retrieve the WETH contract address.
/// @return weth The WETH contract address.
function _getWETHAddress()
internal
view
returns (address weth)
{
return WETH_ADDRESS;
}
}

View File

@ -1,25 +1,40 @@
/*
Copyright 2019 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.5.9;
pragma experimental ABIEncoderV2;
import "@0x/contracts-asset-proxy/contracts/src/interfaces/IUniswapExchangeFactory.sol";
import "@0x/contracts-erc20/contracts/src/LibERC20Token.sol";
import "@0x/contracts-exchange/contracts/src/interfaces/IExchange.sol";
import "@0x/contracts-exchange-libs/contracts/src/LibOrder.sol";
import "./IERC20BridgeSampler.sol";
import "./IExchange.sol";
import "./IEth2Dai.sol";
import "./IKyberNetwork.sol";
import "./IUniswapExchangeQuotes.sol";
import "./DeploymentConstants.sol";
contract ERC20BridgeSampler is
IERC20BridgeSampler
IERC20BridgeSampler,
DeploymentConstants
{
bytes4 constant internal ERC20_PROXY_ID = bytes4(keccak256("ERC20Token(address)"));
address constant public EXCHANGE_ADDRESS = 0x080bf510FCbF18b91105470639e9561022937712; // V2
address constant public ETH2DAI_ADDRESS = 0x39755357759cE0d7f32dC8dC45414CCa409AE24e;
address constant public UNISWAP_EXCHANGE_FACTORY_ADDRESS = 0xc0a47dFe034B400B47bDaD5FecDa2621de6c4d95;
address constant public KYBER_NETWORK_PROXY_ADDRESS = 0x818E6FECD516Ecc3849DAf6845e3EC868087B755;
address constant public WETH_ADDRESS = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
address constant public KYBER_ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
/// @dev Query native orders and sample sell quotes on multiple DEXes at once.
/// @param orders Native orders to query.
@ -30,14 +45,14 @@ contract ERC20BridgeSampler is
/// each taker token amount. First indexed by source index, then sample
/// index.
function queryOrdersAndSampleSells(
IExchange.Order[] memory orders,
LibOrder.Order[] memory orders,
address[] memory sources,
uint256[] memory takerTokenAmounts
)
public
view
returns (
IExchange.OrderInfo[] memory orderInfos,
LibOrder.OrderInfo[] memory orderInfos,
uint256[][] memory makerTokenAmountsBySource
)
{
@ -60,14 +75,14 @@ contract ERC20BridgeSampler is
/// each maker token amount. First indexed by source index, then sample
/// index.
function queryOrdersAndSampleBuys(
IExchange.Order[] memory orders,
LibOrder.Order[] memory orders,
address[] memory sources,
uint256[] memory makerTokenAmounts
)
public
view
returns (
IExchange.OrderInfo[] memory orderInfos,
LibOrder.OrderInfo[] memory orderInfos,
uint256[][] memory makerTokenAmountsBySource
)
{
@ -83,15 +98,15 @@ contract ERC20BridgeSampler is
/// @dev Queries the status of several native orders.
/// @param orders Native orders to query.
/// @return orderInfos Order info for each respective order.
function queryOrders(IExchange.Order[] memory orders)
function queryOrders(LibOrder.Order[] memory orders)
public
view
returns (IExchange.OrderInfo[] memory orderInfos)
returns (LibOrder.OrderInfo[] memory orderInfos)
{
uint256 numOrders = orders.length;
orderInfos = new IExchange.OrderInfo[](numOrders);
orderInfos = new LibOrder.OrderInfo[](numOrders);
for (uint256 i = 0; i < numOrders; i++) {
orderInfos[i] = IExchange(EXCHANGE_ADDRESS).getOrderInfo(orders[i]);
orderInfos[i] = _getExchangeContract().getOrderInfo(orders[i]);
}
}
@ -170,14 +185,14 @@ contract ERC20BridgeSampler is
view
returns (uint256[] memory makerTokenAmounts)
{
address _takerToken = takerToken == WETH_ADDRESS ? KYBER_ETH_ADDRESS : takerToken;
address _makerToken = makerToken == WETH_ADDRESS ? KYBER_ETH_ADDRESS : makerToken;
address _takerToken = takerToken == _getWETHAddress() ? KYBER_ETH_ADDRESS : takerToken;
address _makerToken = makerToken == _getWETHAddress() ? KYBER_ETH_ADDRESS : makerToken;
uint256 takerTokenDecimals = LibERC20Token.decimals(takerToken);
uint256 makerTokenDecimals = LibERC20Token.decimals(makerToken);
uint256 numSamples = takerTokenAmounts.length;
makerTokenAmounts = new uint256[](numSamples);
for (uint256 i = 0; i < numSamples; i++) {
(uint256 rate,) = IKyberNetwork(KYBER_NETWORK_PROXY_ADDRESS).getExpectedRate(
(uint256 rate,) = _getKyberNetworkContract().getExpectedRate(
_takerToken,
_makerToken,
takerTokenAmounts[i]
@ -185,8 +200,9 @@ contract ERC20BridgeSampler is
makerTokenAmounts[i] =
rate *
takerTokenAmounts[i] *
makerTokenDecimals /
(10 ** 18 * takerTokenDecimals);
10 ** makerTokenDecimals /
10 ** takerTokenDecimals /
10 ** 18;
}
}
@ -208,7 +224,7 @@ contract ERC20BridgeSampler is
uint256 numSamples = takerTokenAmounts.length;
makerTokenAmounts = new uint256[](numSamples);
for (uint256 i = 0; i < numSamples; i++) {
makerTokenAmounts[i] = IEth2Dai(ETH2DAI_ADDRESS).getBuyAmount(
makerTokenAmounts[i] = _getEth2DaiContract().getBuyAmount(
makerToken,
takerToken,
takerTokenAmounts[i]
@ -234,7 +250,7 @@ contract ERC20BridgeSampler is
uint256 numSamples = makerTokenAmounts.length;
takerTokenAmounts = new uint256[](numSamples);
for (uint256 i = 0; i < numSamples; i++) {
takerTokenAmounts[i] = IEth2Dai(ETH2DAI_ADDRESS).getPayAmount(
takerTokenAmounts[i] = _getEth2DaiContract().getPayAmount(
takerToken,
makerToken,
makerTokenAmounts[i]
@ -259,16 +275,16 @@ contract ERC20BridgeSampler is
{
uint256 numSamples = takerTokenAmounts.length;
makerTokenAmounts = new uint256[](numSamples);
IUniswapExchangeQuotes takerTokenExchange = takerToken == WETH_ADDRESS ?
IUniswapExchangeQuotes takerTokenExchange = takerToken == _getWETHAddress() ?
IUniswapExchangeQuotes(0) : _getUniswapExchange(takerToken);
IUniswapExchangeQuotes makerTokenExchange = makerToken == WETH_ADDRESS ?
IUniswapExchangeQuotes makerTokenExchange = makerToken == _getWETHAddress() ?
IUniswapExchangeQuotes(0) : _getUniswapExchange(makerToken);
for (uint256 i = 0; i < numSamples; i++) {
if (makerToken == WETH_ADDRESS) {
if (makerToken == _getWETHAddress()) {
makerTokenAmounts[i] = takerTokenExchange.getTokenToEthInputPrice(
takerTokenAmounts[i]
);
} else if (takerToken == WETH_ADDRESS) {
} else if (takerToken == _getWETHAddress()) {
makerTokenAmounts[i] = makerTokenExchange.getEthToTokenInputPrice(
takerTokenAmounts[i]
);
@ -300,16 +316,16 @@ contract ERC20BridgeSampler is
{
uint256 numSamples = makerTokenAmounts.length;
takerTokenAmounts = new uint256[](numSamples);
IUniswapExchangeQuotes takerTokenExchange = takerToken == WETH_ADDRESS ?
IUniswapExchangeQuotes takerTokenExchange = takerToken == _getWETHAddress() ?
IUniswapExchangeQuotes(0) : _getUniswapExchange(takerToken);
IUniswapExchangeQuotes makerTokenExchange = makerToken == WETH_ADDRESS ?
IUniswapExchangeQuotes makerTokenExchange = makerToken == _getWETHAddress() ?
IUniswapExchangeQuotes(0) : _getUniswapExchange(makerToken);
for (uint256 i = 0; i < numSamples; i++) {
if (makerToken == WETH_ADDRESS) {
if (makerToken == _getWETHAddress()) {
takerTokenAmounts[i] = takerTokenExchange.getTokenToEthOutputPrice(
makerTokenAmounts[i]
);
} else if (takerToken == WETH_ADDRESS) {
} else if (takerToken == _getWETHAddress()) {
takerTokenAmounts[i] = makerTokenExchange.getEthToTokenOutputPrice(
makerTokenAmounts[i]
);
@ -340,13 +356,13 @@ contract ERC20BridgeSampler is
view
returns (uint256[] memory makerTokenAmounts)
{
if (source == ETH2DAI_ADDRESS) {
if (source == address(_getEth2DaiContract())) {
return sampleSellFromEth2Dai(takerToken, makerToken, takerTokenAmounts);
}
if (source == UNISWAP_EXCHANGE_FACTORY_ADDRESS) {
if (source == address(_getUniswapExchangeFactoryContract())) {
return sampleSellFromUniswap(takerToken, makerToken, takerTokenAmounts);
}
if (source == KYBER_NETWORK_PROXY_ADDRESS) {
if (source == address(_getKyberNetworkContract())) {
return sampleSellFromKyberNetwork(takerToken, makerToken, takerTokenAmounts);
}
revert("UNSUPPORTED_SOURCE");
@ -368,10 +384,10 @@ contract ERC20BridgeSampler is
view
returns (uint256[] memory takerTokenAmounts)
{
if (source == ETH2DAI_ADDRESS) {
if (source == address(_getEth2DaiContract())) {
return sampleBuyFromEth2Dai(takerToken, makerToken, makerTokenAmounts);
}
if (source == UNISWAP_EXCHANGE_FACTORY_ADDRESS) {
if (source == address(_getUniswapExchangeFactoryContract())) {
return sampleBuyFromUniswap(takerToken, makerToken, makerTokenAmounts);
}
revert("UNSUPPORTED_SOURCE");
@ -387,10 +403,7 @@ contract ERC20BridgeSampler is
returns (IUniswapExchangeQuotes exchange)
{
exchange = IUniswapExchangeQuotes(
address(
IUniswapExchangeFactory(UNISWAP_EXCHANGE_FACTORY_ADDRESS)
.getExchange(tokenAddress)
)
address(_getUniswapExchangeFactoryContract().getExchange(tokenAddress))
);
require(address(exchange) != address(0), "UNSUPPORTED_UNISWAP_EXCHANGE");
}

View File

@ -1,7 +1,26 @@
/*
Copyright 2019 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.5.9;
pragma experimental ABIEncoderV2;
import "./IExchange.sol";
import "@0x/contracts-exchange/contracts/src/interfaces/IExchange.sol";
import "@0x/contracts-exchange-libs/contracts/src/LibOrder.sol";
interface IERC20BridgeSampler {
@ -15,14 +34,14 @@ interface IERC20BridgeSampler {
/// each taker token amount. First indexed by source index, then sample
/// index.
function queryOrdersAndSampleSells(
IExchange.Order[] calldata orders,
LibOrder.Order[] calldata orders,
address[] calldata sources,
uint256[] calldata takerTokenAmounts
)
external
view
returns (
IExchange.OrderInfo[] memory orderInfos,
LibOrder.OrderInfo[] memory orderInfos,
uint256[][] memory makerTokenAmountsBySource
);
@ -35,24 +54,24 @@ interface IERC20BridgeSampler {
/// each maker token amount. First indexed by source index, then sample
/// index.
function queryOrdersAndSampleBuys(
IExchange.Order[] calldata orders,
LibOrder.Order[] calldata orders,
address[] calldata sources,
uint256[] calldata makerTokenAmounts
)
external
view
returns (
IExchange.OrderInfo[] memory orderInfos,
LibOrder.OrderInfo[] memory orderInfos,
uint256[][] memory makerTokenAmountsBySource
);
/// @dev Queries the status of several native orders.
/// @param orders Native orders to query.
/// @return orderInfos Order info for each respective order.
function queryOrders(IExchange.Order[] calldata orders)
function queryOrders(LibOrder.Order[] calldata orders)
external
view
returns (IExchange.OrderInfo[] memory orderInfos);
returns (LibOrder.OrderInfo[] memory orderInfos);
/// @dev Sample sell quotes on multiple DEXes at once.
/// @param sources Address of each DEX. Passing in an unsupported DEX will throw.

View File

@ -1,3 +1,21 @@
/*
Copyright 2019 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.5.9;

View File

@ -1,34 +0,0 @@
pragma solidity ^0.5.9;
pragma experimental ABIEncoderV2;
interface IExchange {
struct Order {
address makerAddress;
address takerAddress;
address feeRecipientAddress;
address senderAddress;
uint256 makerAssetAmount;
uint256 takerAssetAmount;
uint256 makerFee;
uint256 takerFee;
uint256 expirationTimeSeconds;
uint256 salt;
bytes makerAssetData;
bytes takerAssetData;
// bytes makerFeeAssetData;
// bytes takerFeeAssetData;
}
struct OrderInfo {
uint8 orderStatus;
bytes32 orderHash;
uint256 orderTakerAssetFilledAmount;
}
function getOrderInfo(Order calldata order)
external
view
returns (OrderInfo memory orderInfo);
}

View File

@ -1,3 +1,21 @@
/*
Copyright 2019 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.5.9;

View File

@ -1,3 +1,21 @@
/*
Copyright 2019 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.5.9;

View File

@ -1,3 +1,21 @@
/*
Copyright 2019 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.5.9;

View File

@ -0,0 +1,320 @@
/*
Copyright 2019 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.5.9;
pragma experimental ABIEncoderV2;
import "@0x/contracts-asset-proxy/contracts/src/interfaces/IUniswapExchangeFactory.sol";
import "@0x/contracts-exchange/contracts/src/interfaces/IExchange.sol";
import "@0x/contracts-exchange-libs/contracts/src/LibOrder.sol";
import "../src/ERC20BridgeSampler.sol";
import "../src/IEth2Dai.sol";
import "../src/IKyberNetwork.sol";
library LibDeterministicQuotes {
uint256 private constant MAX_RATE = 10 ** 20;
uint256 private constant MIN_RATE = 10 ** 16;
function getDeterministicSellQuote(
bytes32 salt,
address sellToken,
address buyToken,
uint256 sellAmount
)
internal
pure
returns (uint256 buyAmount)
{
uint256 sellBase = 10 ** getDeterministicTokenDecimals(sellToken);
uint256 buyBase = 10 ** getDeterministicTokenDecimals(buyToken);
uint256 rate = _getDeterministicRate(salt, sellToken, buyToken);
return sellAmount * rate * buyBase / sellBase / 10 ** 18;
}
function getDeterministicBuyQuote(
bytes32 salt,
address sellToken,
address buyToken,
uint256 buyAmount
)
internal
pure
returns (uint256 sellAmount)
{
uint256 sellBase = 10 ** getDeterministicTokenDecimals(sellToken);
uint256 buyBase = 10 ** getDeterministicTokenDecimals(buyToken);
uint256 rate = _getDeterministicRate(salt, sellToken, buyToken);
return buyAmount * 10 ** 18 * sellBase / rate / buyBase;
}
function getDeterministicTokenDecimals(address token)
internal
pure
returns (uint8 decimals)
{
bytes32 seed = keccak256(abi.encodePacked(token));
return uint8(uint256(seed) % 18) + 6;
}
function _getDeterministicRate(bytes32 salt, address sellToken, address buyToken)
private
pure
returns (uint256 rate)
{
bytes32 seed = keccak256(abi.encodePacked(salt, sellToken, buyToken));
return MIN_RATE + uint256(seed) % MAX_RATE;
}
}
contract TestERC20BridgeSamplerUniswapExchange is
IUniswapExchangeQuotes
{
bytes32 constant private BASE_SALT = 0x1d6a6a0506b0b4a554b907a4c29d9f4674e461989d9c1921feb17b26716385ab;
address public tokenAddress;
bytes32 public salt;
address private _wethAddress;
constructor(address _tokenAddress) public {
_wethAddress = msg.sender;
tokenAddress = _tokenAddress;
salt = keccak256(abi.encodePacked(BASE_SALT, _tokenAddress));
}
// Deterministic `IUniswapExchangeQuotes.getEthToTokenInputPrice()`.
function getEthToTokenInputPrice(
uint256 ethSold
)
external
view
returns (uint256 tokensBought)
{
return LibDeterministicQuotes.getDeterministicSellQuote(
salt,
_wethAddress,
tokenAddress,
ethSold
);
}
// Deterministic `IUniswapExchangeQuotes.getEthToTokenOutputPrice()`.
function getEthToTokenOutputPrice(
uint256 tokensBought
)
external
view
returns (uint256 ethSold)
{
return LibDeterministicQuotes.getDeterministicBuyQuote(
salt,
_wethAddress,
tokenAddress,
tokensBought
);
}
// Deterministic `IUniswapExchangeQuotes.getTokenToEthInputPrice()`.
function getTokenToEthInputPrice(
uint256 tokensSold
)
external
view
returns (uint256 ethBought)
{
return LibDeterministicQuotes.getDeterministicSellQuote(
salt,
tokenAddress,
_wethAddress,
tokensSold
);
}
// Deterministic `IUniswapExchangeQuotes.getTokenToEthOutputPrice()`.
function getTokenToEthOutputPrice(
uint256 ethBought
)
external
view
returns (uint256 tokensSold)
{
return LibDeterministicQuotes.getDeterministicBuyQuote(
salt,
tokenAddress,
_wethAddress,
ethBought
);
}
}
contract TestERC20BridgeSampler is
ERC20BridgeSampler
{
bytes32 constant private KYBER_SALT = 0x0ff3ca9d46195c39f9a12afb74207b4970349fb3cfb1e459bbf170298d326bc7;
bytes32 constant private ETH2DAI_SALT = 0xb713b61bb9bb2958a0f5d1534b21e94fc68c4c0c034b0902ed844f2f6cd1b4f7;
mapping (address => IUniswapExchangeQuotes) private _uniswapExchangesByToken;
// Creates Uniswap exchange contracts for tokens.
function createTokenExchanges(address[] calldata tokenAddresses)
external
{
for (uint256 i = 0; i < tokenAddresses.length; i++) {
address tokenAddress = tokenAddresses[i];
_uniswapExchangesByToken[tokenAddress] =
new TestERC20BridgeSamplerUniswapExchange(tokenAddress);
}
}
// `IERC20.decimals()` (for WETH).
function decimals()
external
view
returns (uint8 decimalPlaces)
{
return 18;
}
// Deterministic `IKyberNetwork.getExpectedRate()`.
function getExpectedRate(
address fromToken,
address toToken,
uint256 fromAmount
)
external
view
returns (uint256 expectedRate, uint256 slippageRate)
{
uint256 quote = LibDeterministicQuotes.getDeterministicSellQuote(
KYBER_SALT,
fromToken,
toToken,
fromAmount
);
expectedRate =
10 ** 18 *
(quote / LibDeterministicQuotes.getDeterministicTokenDecimals(toToken)) /
(fromAmount * LibDeterministicQuotes.getDeterministicTokenDecimals(fromToken));
}
// Deterministic `IEth2Dai.getBuyAmount()`.
function getBuyAmount(
address buyToken,
address payToken,
uint256 payAmount
)
external
view
returns (uint256 buyAmount)
{
return LibDeterministicQuotes.getDeterministicSellQuote(
ETH2DAI_SALT,
payToken,
buyToken,
payAmount
);
}
// Deterministic `IEth2Dai.getPayAmount()`.
function getPayAmount(
address payToken,
address buyToken,
uint256 buyAmount
)
external
view
returns (uint256 payAmount)
{
return LibDeterministicQuotes.getDeterministicBuyQuote(
ETH2DAI_SALT,
payToken,
buyToken,
buyAmount
);
}
// `IUniswapExchangeFactory.getExchange()`.
function getExchange(address tokenAddress)
external
view
returns (address)
{
return address(_uniswapExchangesByToken[tokenAddress]);
}
// `IExchange.getOrderInfo()`, overridden to return deterministic order infos.
function getOrderInfo(LibOrder.Order memory order)
public
view
returns (LibOrder.OrderInfo memory orderInfo)
{
// The order hash is just the hash of the salt.
bytes32 orderHash = keccak256(abi.encode(order.salt));
// Everything else is derived from the hash.
orderInfo.orderHash = orderHash;
orderInfo.orderStatus = uint8(uint256(orderHash) % uint8(-1));
orderInfo.orderTakerAssetFilledAmount = uint256(orderHash) % order.takerAssetAmount;
}
// Overriden to point to this contract.
function _getExchangeContract()
internal
view
returns (IExchange zeroex)
{
return IExchange(address(this));
}
// Overriden to point to this contract.
function _getEth2DaiContract()
internal
view
returns (IEth2Dai eth2dai)
{
return IEth2Dai(address(this));
}
// Overriden to point to this contract.
function _getUniswapExchangeFactoryContract()
internal
view
returns (IUniswapExchangeFactory uniswap)
{
return IUniswapExchangeFactory(address(this));
}
// Overriden to point to this contract.
function _getKyberNetworkContract()
internal
view
returns (IKyberNetwork kyber)
{
return IKyberNetwork(address(this));
}
// Overriden to point to this contract.
function _getWETHAddress()
internal
view
returns (address weth)
{
return address(this);
}
}

View File

@ -38,7 +38,7 @@
"config": {
"publicInterfaceContracts": "ERC20BridgeSampler,IERC20BridgeSampler",
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually.",
"abis": "./test/generated-artifacts/@(ERC20BridgeSampler|IERC20BridgeSampler|IEth2Dai|IExchange|IKyberNetwork|IUniswapExchangeQuotes|LibERC20Token).json"
"abis": "./test/generated-artifacts/@(DeploymentConstants|ERC20BridgeSampler|IERC20BridgeSampler|IEth2Dai|IKyberNetwork|IUniswapExchangeQuotes|LibERC20Token|TestERC20BridgeSampler).json"
},
"repository": {
"type": "git",
@ -54,6 +54,7 @@
"@0x/contracts-asset-proxy": "^2.3.0-beta.1",
"@0x/contracts-erc20": "^2.3.0-beta.1",
"@0x/contracts-exchange-libs": "^3.1.0-beta.1",
"@0x/contracts-exchange": "^2.2.0-beta.1",
"@0x/contracts-gen": "^1.1.0-beta.1",
"@0x/contracts-test-utils": "^3.2.0-beta.1",
"@0x/contracts-utils": "^3.3.0-beta.1",

View File

@ -5,19 +5,21 @@
*/
import { ContractArtifact } from 'ethereum-types';
import * as DeploymentConstants from '../test/generated-artifacts/DeploymentConstants.json';
import * as ERC20BridgeSampler from '../test/generated-artifacts/ERC20BridgeSampler.json';
import * as IERC20BridgeSampler from '../test/generated-artifacts/IERC20BridgeSampler.json';
import * as IEth2Dai from '../test/generated-artifacts/IEth2Dai.json';
import * as IExchange from '../test/generated-artifacts/IExchange.json';
import * as IKyberNetwork from '../test/generated-artifacts/IKyberNetwork.json';
import * as IUniswapExchangeQuotes from '../test/generated-artifacts/IUniswapExchangeQuotes.json';
import * as LibERC20Token from '../test/generated-artifacts/LibERC20Token.json';
import * as TestERC20BridgeSampler from '../test/generated-artifacts/TestERC20BridgeSampler.json';
export const artifacts = {
DeploymentConstants: DeploymentConstants as ContractArtifact,
ERC20BridgeSampler: ERC20BridgeSampler as ContractArtifact,
IERC20BridgeSampler: IERC20BridgeSampler as ContractArtifact,
IEth2Dai: IEth2Dai as ContractArtifact,
IExchange: IExchange as ContractArtifact,
IKyberNetwork: IKyberNetwork as ContractArtifact,
IUniswapExchangeQuotes: IUniswapExchangeQuotes as ContractArtifact,
LibERC20Token: LibERC20Token as ContractArtifact,
TestERC20BridgeSampler: TestERC20BridgeSampler as ContractArtifact,
};

View File

@ -0,0 +1,24 @@
import { blockchainTests, expect, getRandomInteger } from '@0x/contracts-test-utils';
import { BigNumber } from '@0x/utils';
import { artifacts } from './artifacts';
import { TestERC20BridgeSamplerContract } from './wrappers';
blockchainTests('erc20-bridge-sampler', env => {
let testContract: TestERC20BridgeSamplerContract;
before(async () => {
testContract = await TestERC20BridgeSamplerContract.deployFrom0xArtifactAsync(
artifacts.TestERC20BridgeSampler,
env.provider,
env.txDefaults,
{},
);
});
describe('queryOrders()', () => {
it('returns the results of `getOrderInfo()` for each order', async () => {
});
});
});

View File

@ -3,10 +3,11 @@
* Warning: This file is auto-generated by contracts-gen. Don't edit manually.
* -----------------------------------------------------------------------------
*/
export * from '../test/generated-wrappers/deployment_constants';
export * from '../test/generated-wrappers/erc20_bridge_sampler';
export * from '../test/generated-wrappers/i_erc20_bridge_sampler';
export * from '../test/generated-wrappers/i_eth2_dai';
export * from '../test/generated-wrappers/i_exchange';
export * from '../test/generated-wrappers/i_kyber_network';
export * from '../test/generated-wrappers/i_uniswap_exchange_quotes';
export * from '../test/generated-wrappers/lib_erc20_token';
export * from '../test/generated-wrappers/test_erc20_bridge_sampler';

View File

@ -5,13 +5,14 @@
"files": [
"generated-artifacts/ERC20BridgeSampler.json",
"generated-artifacts/IERC20BridgeSampler.json",
"test/generated-artifacts/DeploymentConstants.json",
"test/generated-artifacts/ERC20BridgeSampler.json",
"test/generated-artifacts/IERC20BridgeSampler.json",
"test/generated-artifacts/IEth2Dai.json",
"test/generated-artifacts/IExchange.json",
"test/generated-artifacts/IKyberNetwork.json",
"test/generated-artifacts/IUniswapExchangeQuotes.json",
"test/generated-artifacts/LibERC20Token.json"
"test/generated-artifacts/LibERC20Token.json",
"test/generated-artifacts/TestERC20BridgeSampler.json"
],
"exclude": ["./deploy/solc/solc_bin"]
}