Feature/liquidity provider sandbox (#16)

* Update liquidity provider feature to use sandbox

* add support for liquidity provider feature in the exchange proxy swap quote consumer

* Move to off-chain liquidity provider registry

* Update ILiquidityProvider interface

* Remove some unused artifacts and wrappers

* Consolidate ILiquidityProvider

* prettier

* lint

* Address PR feedback

* Add failover to sandbox

* Add test for failover behavior in LiquidityProviderSandbox

* Update changelogs

* Emit events for the new LiquidityProvider scenarios

* Fix swap quote consumer bug

* post-rebase fixes

* `@0x/contracts-zero-ex`: bump feature versions

* Add default field to TokenAdjacencyGraph

* update addresses

Co-authored-by: Lawrence Forman <me@merklejerk.com>
This commit is contained in:
mzhu25
2020-11-13 12:22:21 -08:00
committed by GitHub
parent 75dcd687e2
commit 7403c0255a
66 changed files with 1083 additions and 2098 deletions

View File

@@ -20,8 +20,7 @@ pragma solidity ^0.6;
pragma experimental ABIEncoderV2;
import "@0x/contracts-utils/contracts/src/v06/LibBytesV06.sol";
import "./interfaces/ILiquidityProvider.sol";
import "./interfaces/ILiquidityProviderRegistry.sol";
import "@0x/contracts-zero-ex/contracts/src/vendor/ILiquidityProvider.sol";
import "./ApproximateBuys.sol";
import "./SamplerUtils.sol";
@@ -34,37 +33,26 @@ contract LiquidityProviderSampler is
uint256 constant private DEFAULT_CALL_GAS = 400e3; // 400k
/// @dev Sample sell quotes from an arbitrary on-chain liquidity provider.
/// @param registryAddress Address of the liquidity provider registry contract.
/// @param providerAddress Address of the liquidity provider.
/// @param takerToken Address of the taker token (what to sell).
/// @param makerToken Address of the maker token (what to buy).
/// @param takerTokenAmounts Taker token sell amount for each sample.
/// @return makerTokenAmounts Maker amounts bought at each taker token
/// amount.
function sampleSellsFromLiquidityProviderRegistry(
address registryAddress,
function sampleSellsFromLiquidityProvider(
address providerAddress,
address takerToken,
address makerToken,
uint256[] memory takerTokenAmounts
)
public
view
returns (uint256[] memory makerTokenAmounts, address providerAddress)
returns (uint256[] memory makerTokenAmounts)
{
// Initialize array of maker token amounts.
uint256 numSamples = takerTokenAmounts.length;
makerTokenAmounts = new uint256[](numSamples);
// Query registry for provider address.
providerAddress = _getLiquidityProviderFromRegistry(
registryAddress,
takerToken,
makerToken
);
// If provider doesn't exist, return all zeros.
if (providerAddress == address(0)) {
return (makerTokenAmounts, providerAddress);
}
for (uint256 i = 0; i < numSamples; i++) {
try
ILiquidityProvider(providerAddress).getSellQuote
@@ -81,68 +69,33 @@ contract LiquidityProviderSampler is
}
/// @dev Sample buy quotes from an arbitrary on-chain liquidity provider.
/// @param registryAddress Address of the liquidity provider registry contract.
/// @param providerAddress Address of the liquidity provider.
/// @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 takerTokenAmounts Taker amounts sold at each maker token
/// amount.
function sampleBuysFromLiquidityProviderRegistry(
address registryAddress,
function sampleBuysFromLiquidityProvider(
address providerAddress,
address takerToken,
address makerToken,
uint256[] memory makerTokenAmounts
)
public
view
returns (uint256[] memory takerTokenAmounts, address providerAddress)
returns (uint256[] memory takerTokenAmounts)
{
providerAddress = _getLiquidityProviderFromRegistry(
registryAddress,
takerToken,
makerToken
);
takerTokenAmounts = _sampleApproximateBuys(
ApproximateBuyQuoteOpts({
makerTokenData: abi.encode(makerToken, registryAddress),
takerTokenData: abi.encode(takerToken, registryAddress),
getSellQuoteCallback: _sampleSellForApproximateBuyFromLiquidityProviderRegistry
makerTokenData: abi.encode(makerToken, providerAddress),
takerTokenData: abi.encode(takerToken, providerAddress),
getSellQuoteCallback: _sampleSellForApproximateBuyFromLiquidityProvider
}),
makerTokenAmounts
);
}
/// @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
)
private
view
returns (address providerAddress)
{
if (registryAddress == address(0)) {
return address(0);
}
bytes memory callData = abi.encodeWithSelector(
ILiquidityProviderRegistry.getLiquidityProviderForMarket.selector,
takerToken,
makerToken
);
(bool didSucceed, bytes memory returnData) = registryAddress.staticcall(callData);
if (didSucceed && returnData.length == 32) {
return LibBytesV06.readAddress(returnData, 12);
}
}
function _sampleSellForApproximateBuyFromLiquidityProviderRegistry(
function _sampleSellForApproximateBuyFromLiquidityProvider(
bytes memory takerTokenData,
bytes memory makerTokenData,
uint256 sellAmount
@@ -151,15 +104,15 @@ contract LiquidityProviderSampler is
view
returns (uint256 buyAmount)
{
(address takerToken, address plpRegistryAddress) =
(address takerToken, address providerAddress) =
abi.decode(takerTokenData, (address, address));
(address makerToken) =
abi.decode(makerTokenData, (address));
try
this.sampleSellsFromLiquidityProviderRegistry
this.sampleSellsFromLiquidityProvider
{gas: DEFAULT_CALL_GAS}
(plpRegistryAddress, takerToken, makerToken, _toSingleValueArray(sellAmount))
returns (uint256[] memory amounts, address)
(providerAddress, takerToken, makerToken, _toSingleValueArray(sellAmount))
returns (uint256[] memory amounts)
{
return amounts[0];
} catch (bytes memory) {

View File

@@ -1,70 +0,0 @@
/*
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 ILiquidityProvider {
/// @dev Transfers `amount` of the ERC20 `tokenAddress` from `from` to `to`.
/// @param tokenAddress The address of the ERC20 token to transfer.
/// @param from Address to transfer asset from.
/// @param to Address to transfer asset to.
/// @param amount Amount of asset to transfer.
/// @param bridgeData Arbitrary asset data needed by the bridge contract.
/// @return success The magic bytes `0xdc1600f3` if successful.
function bridgeTransferFrom(
address tokenAddress,
address from,
address to,
uint256 amount,
bytes calldata bridgeData
)
external
returns (bytes4 success);
/// @dev Quotes the amount of `makerToken` that would be obtained by
/// selling `sellAmount` of `takerToken`.
/// @param takerToken Address of the taker token (what to sell).
/// @param makerToken Address of the maker token (what to buy).
/// @param sellAmount Amount of `takerToken` to sell.
/// @return makerTokenAmount Amount of `makerToken` that would be obtained.
function getSellQuote(
address takerToken,
address makerToken,
uint256 sellAmount
)
external
view
returns (uint256 makerTokenAmount);
/// @dev Quotes the amount of `takerToken` that would need to be sold in
/// order to obtain `buyAmount` of `makerToken`.
/// @param takerToken Address of the taker token (what to sell).
/// @param makerToken Address of the maker token (what to buy).
/// @param buyAmount Amount of `makerToken` to buy.
/// @return takerTokenAmount Amount of `takerToken` that would need to be sold.
function getBuyQuote(
address takerToken,
address makerToken,
uint256 buyAmount
)
external
view
returns (uint256 takerTokenAmount);
}

View File

@@ -1,36 +0,0 @@
/*
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 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 providerAddress Address of the liquidity provider.
function getLiquidityProviderForMarket(
address takerToken,
address makerToken
)
external
view
returns (address providerAddress);
}