Skip to content
This repository has been archived by the owner on Jul 9, 2021. It is now read-only.

Commit

Permalink
Merge pull request #2595 from 0xProject/feat/erc20-bridge-sampler/uni…
Browse files Browse the repository at this point in the history
…swapv2-tests

Add Uniswap V2 to ERC20BridgeSampler
  • Loading branch information
dorothy-zbornak authored Jun 4, 2020
2 parents 0c6e05d + fbaf55c commit 32793cc
Show file tree
Hide file tree
Showing 18 changed files with 617 additions and 3 deletions.
4 changes: 4 additions & 0 deletions contracts/erc20-bridge-sampler/CHANGELOG.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@
{
"note": "Use `searchBestRate` in Kyber samples. Return 0 when Uniswap/Eth2Dai reserve",
"pr": 2575
},
{
"note": "Add UniswapV2",
"pr": 2595
}
]
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import "./IUniswapExchangeQuotes.sol";
import "./ICurve.sol";
import "./ILiquidityProvider.sol";
import "./ILiquidityProviderRegistry.sol";
import "./IUniswapV2Router01.sol";


contract ERC20BridgeSampler is
Expand All @@ -46,6 +47,8 @@ contract ERC20BridgeSampler is
uint256 constant internal KYBER_CALL_GAS = 1500e3; // 1.5m
/// @dev Gas limit for Uniswap calls.
uint256 constant internal UNISWAP_CALL_GAS = 150e3; // 150k
/// @dev Gas limit for UniswapV2 calls.
uint256 constant internal UNISWAPV2_CALL_GAS = 150e3; // 150k
/// @dev Base gas limit for Eth2Dai calls.
uint256 constant internal ETH2DAI_CALL_GAS = 1000e3; // 1m
/// @dev Base gas limit for Curve calls. Some Curves have multiple tokens
Expand Down Expand Up @@ -645,6 +648,74 @@ contract ERC20BridgeSampler is
}
}

/// @dev Sample sell quotes from UniswapV2.
/// @param path Token route.
/// @param takerTokenAmounts Taker token sell amount for each sample.
/// @return makerTokenAmounts Maker amounts bought at each taker token
/// amount.
function sampleSellsFromUniswapV2(
address[] memory path,
uint256[] memory takerTokenAmounts
)
public
view
returns (uint256[] memory makerTokenAmounts)
{
uint256 numSamples = takerTokenAmounts.length;
makerTokenAmounts = new uint256[](numSamples);
for (uint256 i = 0; i < numSamples; i++) {
(bool didSucceed, bytes memory resultData) =
_getUniswapV2Router01Address().staticcall.gas(UNISWAPV2_CALL_GAS)(
abi.encodeWithSelector(
IUniswapV2Router01(0).getAmountsOut.selector,
takerTokenAmounts[i],
path
));
uint256 buyAmount = 0;
if (didSucceed) {
// solhint-disable-next-line indent
buyAmount = abi.decode(resultData, (uint256[]))[path.length - 1];
} else {
break;
}
makerTokenAmounts[i] = buyAmount;
}
}

/// @dev Sample buy quotes from UniswapV2.
/// @param path Token route.
/// @param makerTokenAmounts Maker token buy amount for each sample.
/// @return takerTokenAmounts Taker amounts sold at each maker token
/// amount.
function sampleBuysFromUniswapV2(
address[] memory path,
uint256[] memory makerTokenAmounts
)
public
view
returns (uint256[] memory takerTokenAmounts)
{
uint256 numSamples = makerTokenAmounts.length;
takerTokenAmounts = new uint256[](numSamples);
for (uint256 i = 0; i < numSamples; i++) {
(bool didSucceed, bytes memory resultData) =
_getUniswapV2Router01Address().staticcall.gas(UNISWAPV2_CALL_GAS)(
abi.encodeWithSelector(
IUniswapV2Router01(0).getAmountsIn.selector,
makerTokenAmounts[i],
path
));
uint256 sellAmount = 0;
if (didSucceed) {
// solhint-disable-next-line indent
sellAmount = abi.decode(resultData, (uint256[]))[path.length - 1];
} else {
break;
}
takerTokenAmounts[i] = sellAmount;
}
}

/// @dev Overridable way to get token decimals.
/// @param tokenAddress Address of the token.
/// @return decimals The decimal places for the token.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -240,4 +240,30 @@ interface IERC20BridgeSampler {
external
view
returns (address providerAddress);

/// @dev Sample sell quotes from UniswapV2.
/// @param path Token route.
/// @param takerTokenAmounts Taker token sell amount for each sample.
/// @return makerTokenAmounts Maker amounts bought at each taker token
/// amount.
function sampleSellsFromUniswapV2(
address[] calldata path,
uint256[] calldata takerTokenAmounts
)
external
view
returns (uint256[] memory makerTokenAmounts);

/// @dev Sample buy quotes from UniswapV2.
/// @param path Token route.
/// @param makerTokenAmounts Maker token buy amount for each sample.
/// @return takerTokenAmounts Taker amounts sold at each maker token
/// amount.
function sampleBuysFromUniswapV2(
address[] calldata path,
uint256[] calldata makerTokenAmounts
)
external
view
returns (uint256[] memory takerTokenAmounts);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
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;


interface IUniswapV2Router01 {

function getAmountsOut(uint256 amountIn, address[] calldata path)
external
view
returns (uint256[] memory amounts);

function getAmountsIn(uint256 amountOut, address[] calldata path)
external
view
returns (uint256[] memory amounts);
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import "../src/ERC20BridgeSampler.sol";
import "../src/IEth2Dai.sol";
import "../src/IDevUtils.sol";
import "../src/IKyberNetworkProxy.sol";
import "../src/IUniswapV2Router01.sol";


library LibDeterministicQuotes {
Expand Down Expand Up @@ -194,6 +195,55 @@ contract TestERC20BridgeSamplerUniswapExchange is
}


contract TestERC20BridgeSamplerUniswapV2Router01 is
IUniswapV2Router01,
DeploymentConstants,
FailTrigger
{
bytes32 constant private SALT = 0xadc7fcb33c735913b8635927e66896b356a53a912ab2ceff929e60a04b53b3c1;

// Deterministic `IUniswapV2Router01.getAmountsOut()`.
function getAmountsOut(uint256 amountIn, address[] calldata path)
external
view
returns (uint256[] memory amounts)
{
require(path.length >= 2, "PATH_TOO_SHORT");
_revertIfShouldFail();
amounts = new uint256[](path.length);
amounts[0] = amountIn;
for (uint256 i = 0; i < path.length - 1; ++i) {
amounts[i + 1] = LibDeterministicQuotes.getDeterministicSellQuote(
SALT,
path[i],
path[i + 1],
amounts[i]
);
}
}

// Deterministic `IUniswapV2Router01.getAmountsInt()`.
function getAmountsIn(uint256 amountOut, address[] calldata path)
external
view
returns (uint256[] memory amounts)
{
require(path.length >= 2, "PATH_TOO_SHORT");
_revertIfShouldFail();
amounts = new uint256[](path.length);
amounts[0] = amountOut;
for (uint256 i = 0; i < path.length - 1; ++i) {
amounts[i + 1] = LibDeterministicQuotes.getDeterministicBuyQuote(
SALT,
path[i],
path[i + 1],
amounts[i]
);
}
}
}


contract TestERC20BridgeSamplerKyberNetwork is
IKyberNetwork,
DeploymentConstants,
Expand Down Expand Up @@ -325,13 +375,15 @@ contract TestERC20BridgeSampler is
FailTrigger
{
TestERC20BridgeSamplerUniswapExchangeFactory public uniswap;
TestERC20BridgeSamplerUniswapV2Router01 public uniswapV2Router;
TestERC20BridgeSamplerEth2Dai public eth2Dai;
TestERC20BridgeSamplerKyberNetwork public kyber;

uint8 private constant MAX_ORDER_STATUS = uint8(LibOrder.OrderStatus.CANCELLED) + 1;

constructor() public ERC20BridgeSampler(address(this)) {
uniswap = new TestERC20BridgeSamplerUniswapExchangeFactory();
uniswapV2Router = new TestERC20BridgeSamplerUniswapV2Router01();
eth2Dai = new TestERC20BridgeSamplerEth2Dai();
kyber = new TestERC20BridgeSamplerKyberNetwork();
}
Expand Down Expand Up @@ -399,6 +451,15 @@ contract TestERC20BridgeSampler is
return address(uniswap);
}

// Overriden to point to a custom contract.
function _getUniswapV2Router01Address()
internal
view
returns (address uniswapV2RouterAddress)
{
return address(uniswapV2Router);
}

// Overriden to point to a custom contract.
function _getKyberNetworkProxyAddress()
internal
Expand Down
2 changes: 1 addition & 1 deletion contracts/erc20-bridge-sampler/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
"config": {
"publicInterfaceContracts": "ERC20BridgeSampler,IERC20BridgeSampler,ILiquidityProvider,ILiquidityProviderRegistry,DummyLiquidityProviderRegistry,DummyLiquidityProvider",
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually.",
"abis": "./test/generated-artifacts/@(DummyLiquidityProvider|DummyLiquidityProviderRegistry|ERC20BridgeSampler|ICurve|IDevUtils|IERC20BridgeSampler|IEth2Dai|IKyberNetwork|IKyberNetworkProxy|ILiquidityProvider|ILiquidityProviderRegistry|IUniswapExchangeQuotes|TestERC20BridgeSampler).json"
"abis": "./test/generated-artifacts/@(DummyLiquidityProvider|DummyLiquidityProviderRegistry|ERC20BridgeSampler|ICurve|IDevUtils|IERC20BridgeSampler|IEth2Dai|IKyberNetwork|IKyberNetworkProxy|ILiquidityProvider|ILiquidityProviderRegistry|IUniswapExchangeQuotes|IUniswapV2Router01|TestERC20BridgeSampler).json"
},
"repository": {
"type": "git",
Expand Down
2 changes: 2 additions & 0 deletions contracts/erc20-bridge-sampler/test/artifacts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import * as IKyberNetworkProxy from '../test/generated-artifacts/IKyberNetworkPr
import * as ILiquidityProvider from '../test/generated-artifacts/ILiquidityProvider.json';
import * as ILiquidityProviderRegistry from '../test/generated-artifacts/ILiquidityProviderRegistry.json';
import * as IUniswapExchangeQuotes from '../test/generated-artifacts/IUniswapExchangeQuotes.json';
import * as IUniswapV2Router01 from '../test/generated-artifacts/IUniswapV2Router01.json';
import * as TestERC20BridgeSampler from '../test/generated-artifacts/TestERC20BridgeSampler.json';
export const artifacts = {
DummyLiquidityProvider: DummyLiquidityProvider as ContractArtifact,
Expand All @@ -31,5 +32,6 @@ export const artifacts = {
ILiquidityProvider: ILiquidityProvider as ContractArtifact,
ILiquidityProviderRegistry: ILiquidityProviderRegistry as ContractArtifact,
IUniswapExchangeQuotes: IUniswapExchangeQuotes as ContractArtifact,
IUniswapV2Router01: IUniswapV2Router01 as ContractArtifact,
TestERC20BridgeSampler: TestERC20BridgeSampler as ContractArtifact,
};
Loading

0 comments on commit 32793cc

Please sign in to comment.