Merge pull request #2499 from 0xProject/feature/erc20-bridge-sampler/liquidity-provider-registry

`@0x/contracts-erc20-bridge-sampler`: LiquidityProviderRegistry
This commit is contained in:
Daniel Pyrathon 2020-02-27 12:37:10 -08:00 committed by GitHub
commit 68fb6c2c27
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 136 additions and 14 deletions

View File

@ -5,6 +5,10 @@
{ {
"note": "Add generic liquidity provider sampling", "note": "Add generic liquidity provider sampling",
"pr": 2487 "pr": 2487
},
{
"note": "Use liquidity provider registry in sampler",
"pr": 2499
} }
] ]
}, },

View File

@ -24,6 +24,7 @@ import "@0x/contracts-erc20/contracts/src/LibERC20Token.sol";
import "@0x/contracts-exchange-libs/contracts/src/LibOrder.sol"; import "@0x/contracts-exchange-libs/contracts/src/LibOrder.sol";
import "@0x/contracts-exchange-libs/contracts/src/LibMath.sol"; import "@0x/contracts-exchange-libs/contracts/src/LibMath.sol";
import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol"; import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol";
import "@0x/contracts-utils/contracts/src/LibBytes.sol";
import "./IDevUtils.sol"; import "./IDevUtils.sol";
import "./IERC20BridgeSampler.sol"; import "./IERC20BridgeSampler.sol";
import "./IEth2Dai.sol"; import "./IEth2Dai.sol";
@ -31,6 +32,7 @@ import "./IKyberNetwork.sol";
import "./IUniswapExchangeQuotes.sol"; import "./IUniswapExchangeQuotes.sol";
import "./ICurve.sol"; import "./ICurve.sol";
import "./ILiquidityProvider.sol"; import "./ILiquidityProvider.sol";
import "./ILiquidityProviderRegistry.sol";
contract ERC20BridgeSampler is contract ERC20BridgeSampler is
@ -435,14 +437,14 @@ contract ERC20BridgeSampler is
} }
/// @dev Sample sell quotes from an arbitrary on-chain liquidity provider. /// @dev Sample sell quotes from an arbitrary on-chain liquidity provider.
/// @param providerAddress Address of the liquidity provider contract. /// @param registryAddress Address of the liquidity provider registry contract.
/// @param takerToken Address of the taker token (what to sell). /// @param takerToken Address of the taker token (what to sell).
/// @param makerToken Address of the maker token (what to buy). /// @param makerToken Address of the maker token (what to buy).
/// @param takerTokenAmounts Taker token sell amount for each sample. /// @param takerTokenAmounts Taker token sell amount for each sample.
/// @return makerTokenAmounts Maker amounts bought at each taker token /// @return makerTokenAmounts Maker amounts bought at each taker token
/// amount. /// amount.
function sampleSellsFromLiquidityProvider( function sampleSellsFromLiquidityProviderRegistry(
address providerAddress, address registryAddress,
address takerToken, address takerToken,
address makerToken, address makerToken,
uint256[] memory takerTokenAmounts uint256[] memory takerTokenAmounts
@ -451,8 +453,21 @@ contract ERC20BridgeSampler is
view view
returns (uint256[] memory makerTokenAmounts) returns (uint256[] memory makerTokenAmounts)
{ {
// Initialize array of maker token amounts.
uint256 numSamples = takerTokenAmounts.length; uint256 numSamples = takerTokenAmounts.length;
makerTokenAmounts = new uint256[](numSamples); makerTokenAmounts = new uint256[](numSamples);
// Query registry for provider address.
address providerAddress = getLiquidityProviderFromRegistry(
registryAddress,
takerToken,
makerToken
);
// If provider doesn't exist, return all zeros.
if (providerAddress == address(0)) {
return makerTokenAmounts;
}
for (uint256 i = 0; i < numSamples; i++) { for (uint256 i = 0; i < numSamples; i++) {
(bool didSucceed, bytes memory resultData) = (bool didSucceed, bytes memory resultData) =
providerAddress.staticcall.gas(DEFAULT_CALL_GAS)( providerAddress.staticcall.gas(DEFAULT_CALL_GAS)(
@ -474,14 +489,14 @@ contract ERC20BridgeSampler is
} }
/// @dev Sample buy quotes from an arbitrary on-chain liquidity provider. /// @dev Sample buy quotes from an arbitrary on-chain liquidity provider.
/// @param providerAddress Address of the liquidity provider contract. /// @param registryAddress Address of the liquidity provider registry contract.
/// @param takerToken Address of the taker token (what to sell). /// @param takerToken Address of the taker token (what to sell).
/// @param makerToken Address of the maker token (what to buy). /// @param makerToken Address of the maker token (what to buy).
/// @param makerTokenAmounts Maker token buy amount for each sample. /// @param makerTokenAmounts Maker token buy amount for each sample.
/// @return takerTokenAmounts Taker amounts sold at each maker token /// @return takerTokenAmounts Taker amounts sold at each maker token
/// amount. /// amount.
function sampleBuysFromLiquidityProvider( function sampleBuysFromLiquidityProviderRegistry(
address providerAddress, address registryAddress,
address takerToken, address takerToken,
address makerToken, address makerToken,
uint256[] memory makerTokenAmounts uint256[] memory makerTokenAmounts
@ -490,8 +505,22 @@ contract ERC20BridgeSampler is
view view
returns (uint256[] memory takerTokenAmounts) returns (uint256[] memory takerTokenAmounts)
{ {
// Initialize array of taker token amounts.
uint256 numSamples = makerTokenAmounts.length; uint256 numSamples = makerTokenAmounts.length;
takerTokenAmounts = new uint256[](numSamples); takerTokenAmounts = new uint256[](numSamples);
// Query registry for provider address.
address providerAddress = getLiquidityProviderFromRegistry(
registryAddress,
takerToken,
makerToken
);
// If provider doesn't exist, return all zeros.
if (providerAddress == address(0)) {
return takerTokenAmounts;
}
// Otherwise, query liquidity provider for quotes.
for (uint256 i = 0; i < numSamples; i++) { for (uint256 i = 0; i < numSamples; i++) {
(bool didSucceed, bytes memory resultData) = (bool didSucceed, bytes memory resultData) =
providerAddress.staticcall.gas(DEFAULT_CALL_GAS)( providerAddress.staticcall.gas(DEFAULT_CALL_GAS)(
@ -512,6 +541,32 @@ contract ERC20BridgeSampler is
} }
} }
/// @dev Returns the address of a liquidity provider for the given market
/// (takerToken, makerToken), from a registry of liquidity providers.
/// Returns address(0) if no such provider exists in the registry.
/// @param takerToken Taker asset managed by liquidity provider.
/// @param makerToken Maker asset managed by liquidity provider.
/// @return providerAddress Address of the liquidity provider.
function getLiquidityProviderFromRegistry(
address registryAddress,
address takerToken,
address makerToken
)
public
view
returns (address providerAddress)
{
bytes memory callData = abi.encodeWithSelector(
ILiquidityProviderRegistry(0).getLiquidityProviderForMarket.selector,
takerToken,
makerToken
);
(bool didSucceed, bytes memory returnData) = registryAddress.staticcall(callData);
if (didSucceed) {
return LibBytes.readAddress(returnData, 0);
}
}
/// @dev Overridable way to get token decimals. /// @dev Overridable way to get token decimals.
/// @param tokenAddress Address of the token. /// @param tokenAddress Address of the token.
/// @return decimals The decimal places for the token. /// @return decimals The decimal places for the token.

View File

@ -151,14 +151,14 @@ interface IERC20BridgeSampler {
returns (uint256[] memory makerTokenAmounts); returns (uint256[] memory makerTokenAmounts);
/// @dev Sample sell quotes from an arbitrary on-chain liquidity provider. /// @dev Sample sell quotes from an arbitrary on-chain liquidity provider.
/// @param providerAddress Address of the liquidity provider contract. /// @param registryAddress Address of the liquidity provider registry contract.
/// @param takerToken Address of the taker token (what to sell). /// @param takerToken Address of the taker token (what to sell).
/// @param makerToken Address of the maker token (what to buy). /// @param makerToken Address of the maker token (what to buy).
/// @param takerTokenAmounts Taker token sell amount for each sample. /// @param takerTokenAmounts Taker token sell amount for each sample.
/// @return makerTokenAmounts Maker amounts bought at each taker token /// @return makerTokenAmounts Maker amounts bought at each taker token
/// amount. /// amount.
function sampleSellsFromLiquidityProvider( function sampleSellsFromLiquidityProviderRegistry(
address providerAddress, address registryAddress,
address takerToken, address takerToken,
address makerToken, address makerToken,
uint256[] calldata takerTokenAmounts uint256[] calldata takerTokenAmounts
@ -168,14 +168,14 @@ interface IERC20BridgeSampler {
returns (uint256[] memory makerTokenAmounts); returns (uint256[] memory makerTokenAmounts);
/// @dev Sample buy quotes from an arbitrary on-chain liquidity provider. /// @dev Sample buy quotes from an arbitrary on-chain liquidity provider.
/// @param providerAddress Address of the liquidity provider contract. /// @param registryAddress Address of the liquidity provider registry contract.
/// @param takerToken Address of the taker token (what to sell). /// @param takerToken Address of the taker token (what to sell).
/// @param makerToken Address of the maker token (what to buy). /// @param makerToken Address of the maker token (what to buy).
/// @param makerTokenAmounts Maker token buy amount for each sample. /// @param makerTokenAmounts Maker token buy amount for each sample.
/// @return takerTokenAmounts Taker amounts sold at each maker token /// @return takerTokenAmounts Taker amounts sold at each maker token
/// amount. /// amount.
function sampleBuysFromLiquidityProvider( function sampleBuysFromLiquidityProviderRegistry(
address providerAddress, address registryAddress,
address takerToken, address takerToken,
address makerToken, address makerToken,
uint256[] calldata makerTokenAmounts uint256[] calldata makerTokenAmounts
@ -183,4 +183,19 @@ interface IERC20BridgeSampler {
external external
view view
returns (uint256[] memory takerTokenAmounts); returns (uint256[] memory takerTokenAmounts);
/// @dev Returns the address of a liquidity provider for the given market
/// (takerToken, makerToken), from a registry of liquidity providers.
/// Returns address(0) if no such provider exists in the registry.
/// @param takerToken Taker asset managed by liquidity provider.
/// @param makerToken Maker asset managed by liquidity provider.
/// @return providerAddress Address of the liquidity provider.
function getLiquidityProviderFromRegistry(
address registryAddress,
address takerToken,
address makerToken
)
external
view
returns (address providerAddress);
} }

View File

@ -0,0 +1,36 @@
/*
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 ILiquidityProviderRegistry {
/// @dev Returns the address of a liquidity provider for the given market
/// (takerToken, makerToken), reverting if the pool does not exist.
/// @param takerToken Taker asset managed by liquidity provider.
/// @param makerToken Maker asset managed by liquidity provider.
/// @return Address of the liquidity provider.
function getLiquidityProviderForMarket(
address takerToken,
address makerToken
)
external
view
returns (address providerAddress);
}

View File

@ -36,9 +36,9 @@
"compile:truffle": "truffle compile" "compile:truffle": "truffle compile"
}, },
"config": { "config": {
"publicInterfaceContracts": "ERC20BridgeSampler,IERC20BridgeSampler", "publicInterfaceContracts": "ERC20BridgeSampler,IERC20BridgeSampler,ILiquidityProvider,ILiquidityProviderRegistry",
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually.", "abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually.",
"abis": "./test/generated-artifacts/@(ERC20BridgeSampler|ICurve|IDevUtils|IERC20BridgeSampler|IEth2Dai|IKyberNetwork|ILiquidityProvider|IUniswapExchangeQuotes|TestERC20BridgeSampler).json" "abis": "./test/generated-artifacts/@(ERC20BridgeSampler|ICurve|IDevUtils|IERC20BridgeSampler|IEth2Dai|IKyberNetwork|ILiquidityProvider|ILiquidityProviderRegistry|IUniswapExchangeQuotes|TestERC20BridgeSampler).json"
}, },
"repository": { "repository": {
"type": "git", "type": "git",

View File

@ -7,7 +7,11 @@ import { ContractArtifact } from 'ethereum-types';
import * as ERC20BridgeSampler from '../generated-artifacts/ERC20BridgeSampler.json'; import * as ERC20BridgeSampler from '../generated-artifacts/ERC20BridgeSampler.json';
import * as IERC20BridgeSampler from '../generated-artifacts/IERC20BridgeSampler.json'; import * as IERC20BridgeSampler from '../generated-artifacts/IERC20BridgeSampler.json';
import * as ILiquidityProvider from '../generated-artifacts/ILiquidityProvider.json';
import * as ILiquidityProviderRegistry from '../generated-artifacts/ILiquidityProviderRegistry.json';
export const artifacts = { export const artifacts = {
ERC20BridgeSampler: ERC20BridgeSampler as ContractArtifact, ERC20BridgeSampler: ERC20BridgeSampler as ContractArtifact,
IERC20BridgeSampler: IERC20BridgeSampler as ContractArtifact, IERC20BridgeSampler: IERC20BridgeSampler as ContractArtifact,
ILiquidityProvider: ILiquidityProvider as ContractArtifact,
ILiquidityProviderRegistry: ILiquidityProviderRegistry as ContractArtifact,
}; };

View File

@ -5,3 +5,5 @@
*/ */
export * from '../generated-wrappers/erc20_bridge_sampler'; export * from '../generated-wrappers/erc20_bridge_sampler';
export * from '../generated-wrappers/i_erc20_bridge_sampler'; export * from '../generated-wrappers/i_erc20_bridge_sampler';
export * from '../generated-wrappers/i_liquidity_provider';
export * from '../generated-wrappers/i_liquidity_provider_registry';

View File

@ -12,6 +12,7 @@ import * as IERC20BridgeSampler from '../test/generated-artifacts/IERC20BridgeSa
import * as IEth2Dai from '../test/generated-artifacts/IEth2Dai.json'; import * as IEth2Dai from '../test/generated-artifacts/IEth2Dai.json';
import * as IKyberNetwork from '../test/generated-artifacts/IKyberNetwork.json'; import * as IKyberNetwork from '../test/generated-artifacts/IKyberNetwork.json';
import * as ILiquidityProvider from '../test/generated-artifacts/ILiquidityProvider.json'; 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 IUniswapExchangeQuotes from '../test/generated-artifacts/IUniswapExchangeQuotes.json';
import * as TestERC20BridgeSampler from '../test/generated-artifacts/TestERC20BridgeSampler.json'; import * as TestERC20BridgeSampler from '../test/generated-artifacts/TestERC20BridgeSampler.json';
export const artifacts = { export const artifacts = {
@ -22,6 +23,7 @@ export const artifacts = {
IEth2Dai: IEth2Dai as ContractArtifact, IEth2Dai: IEth2Dai as ContractArtifact,
IKyberNetwork: IKyberNetwork as ContractArtifact, IKyberNetwork: IKyberNetwork as ContractArtifact,
ILiquidityProvider: ILiquidityProvider as ContractArtifact, ILiquidityProvider: ILiquidityProvider as ContractArtifact,
ILiquidityProviderRegistry: ILiquidityProviderRegistry as ContractArtifact,
IUniswapExchangeQuotes: IUniswapExchangeQuotes as ContractArtifact, IUniswapExchangeQuotes: IUniswapExchangeQuotes as ContractArtifact,
TestERC20BridgeSampler: TestERC20BridgeSampler as ContractArtifact, TestERC20BridgeSampler: TestERC20BridgeSampler as ContractArtifact,
}; };

View File

@ -10,5 +10,6 @@ export * from '../test/generated-wrappers/i_erc20_bridge_sampler';
export * from '../test/generated-wrappers/i_eth2_dai'; export * from '../test/generated-wrappers/i_eth2_dai';
export * from '../test/generated-wrappers/i_kyber_network'; export * from '../test/generated-wrappers/i_kyber_network';
export * from '../test/generated-wrappers/i_liquidity_provider'; export * from '../test/generated-wrappers/i_liquidity_provider';
export * from '../test/generated-wrappers/i_liquidity_provider_registry';
export * from '../test/generated-wrappers/i_uniswap_exchange_quotes'; export * from '../test/generated-wrappers/i_uniswap_exchange_quotes';
export * from '../test/generated-wrappers/test_erc20_bridge_sampler'; export * from '../test/generated-wrappers/test_erc20_bridge_sampler';

View File

@ -5,6 +5,8 @@
"files": [ "files": [
"generated-artifacts/ERC20BridgeSampler.json", "generated-artifacts/ERC20BridgeSampler.json",
"generated-artifacts/IERC20BridgeSampler.json", "generated-artifacts/IERC20BridgeSampler.json",
"generated-artifacts/ILiquidityProvider.json",
"generated-artifacts/ILiquidityProviderRegistry.json",
"test/generated-artifacts/ERC20BridgeSampler.json", "test/generated-artifacts/ERC20BridgeSampler.json",
"test/generated-artifacts/ICurve.json", "test/generated-artifacts/ICurve.json",
"test/generated-artifacts/IDevUtils.json", "test/generated-artifacts/IDevUtils.json",
@ -12,6 +14,7 @@
"test/generated-artifacts/IEth2Dai.json", "test/generated-artifacts/IEth2Dai.json",
"test/generated-artifacts/IKyberNetwork.json", "test/generated-artifacts/IKyberNetwork.json",
"test/generated-artifacts/ILiquidityProvider.json", "test/generated-artifacts/ILiquidityProvider.json",
"test/generated-artifacts/ILiquidityProviderRegistry.json",
"test/generated-artifacts/IUniswapExchangeQuotes.json", "test/generated-artifacts/IUniswapExchangeQuotes.json",
"test/generated-artifacts/TestERC20BridgeSampler.json" "test/generated-artifacts/TestERC20BridgeSampler.json"
], ],