Reenable PLP VIP and add gasCost field to LiquidityProviderRegistry (#65)

This commit is contained in:
mzhu25 2020-12-02 17:26:48 -08:00 committed by GitHub
parent 5f1c139176
commit cc9f43ba3b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 61 additions and 13 deletions

View File

@ -17,6 +17,10 @@
{ {
"note": "Add `unoptimizedPath` to OptimizerResult", "note": "Add `unoptimizedPath` to OptimizerResult",
"pr": 62 "pr": 62
},
{
"note": "Enable PLP VIP feature and add gasCost field to LiquidityProviderRegistry",
"pr": 65
} }
] ]
}, },

View File

@ -34,7 +34,7 @@ import { getSwapMinBuyAmount } from './utils';
// tslint:disable-next-line:custom-no-magic-numbers // tslint:disable-next-line:custom-no-magic-numbers
const MAX_UINT256 = new BigNumber(2).pow(256).minus(1); const MAX_UINT256 = new BigNumber(2).pow(256).minus(1);
const { NULL_ADDRESS, ZERO_AMOUNT } = constants; const { NULL_ADDRESS, NULL_BYTES, ZERO_AMOUNT } = constants;
export class ExchangeProxySwapQuoteConsumer implements SwapQuoteConsumerBase { export class ExchangeProxySwapQuoteConsumer implements SwapQuoteConsumerBase {
public readonly provider: ZeroExProvider; public readonly provider: ZeroExProvider;
@ -131,6 +131,26 @@ export class ExchangeProxySwapQuoteConsumer implements SwapQuoteConsumerBase {
}; };
} }
if (isDirectSwapCompatible(quote, optsWithDefaults, [ERC20BridgeSource.LiquidityProvider])) {
const target = quote.orders[0].makerAddress;
return {
calldataHexString: this._exchangeProxy
.sellToLiquidityProvider(
isFromETH ? ETH_TOKEN_ADDRESS : sellToken,
isToETH ? ETH_TOKEN_ADDRESS : buyToken,
target,
NULL_ADDRESS,
sellAmount,
minBuyAmount,
NULL_BYTES,
)
.getABIEncodedTransactionData(),
ethAmount: isFromETH ? sellAmount : ZERO_AMOUNT,
toAddress: this._exchangeProxy.address,
allowanceTarget: this.contractAddresses.exchangeProxyAllowanceTarget,
};
}
// Build up the transforms. // Build up the transforms.
const transforms = []; const transforms = [];
if (isFromETH) { if (isFromETH) {

View File

@ -13,6 +13,7 @@ import {
FeeSchedule, FeeSchedule,
FillData, FillData,
GetMarketOrdersOpts, GetMarketOrdersOpts,
LiquidityProviderFillData,
LiquidityProviderRegistry, LiquidityProviderRegistry,
MultiHopFillData, MultiHopFillData,
SnowSwapFillData, SnowSwapFillData,
@ -445,7 +446,9 @@ export const BRIDGE_ADDRESSES_BY_CHAIN: { [chainId in ChainId]: BridgeContractAd
export const DEFAULT_GAS_SCHEDULE: Required<FeeSchedule> = { export const DEFAULT_GAS_SCHEDULE: Required<FeeSchedule> = {
[ERC20BridgeSource.Native]: () => 150e3, [ERC20BridgeSource.Native]: () => 150e3,
[ERC20BridgeSource.Uniswap]: () => 90e3, [ERC20BridgeSource.Uniswap]: () => 90e3,
[ERC20BridgeSource.LiquidityProvider]: () => 140e3, [ERC20BridgeSource.LiquidityProvider]: fillData => {
return (fillData as LiquidityProviderFillData).gasCost;
},
[ERC20BridgeSource.Eth2Dai]: () => 400e3, [ERC20BridgeSource.Eth2Dai]: () => 400e3,
[ERC20BridgeSource.Kyber]: () => 450e3, [ERC20BridgeSource.Kyber]: () => 450e3,
[ERC20BridgeSource.Curve]: fillData => { [ERC20BridgeSource.Curve]: fillData => {

View File

@ -7,6 +7,6 @@ export function getLiquidityProvidersForPair(
makerToken: string, makerToken: string,
): string[] { ): string[] {
return Object.entries(registry) return Object.entries(registry)
.filter(([, tokens]) => [makerToken, takerToken].every(t => tokens.includes(t))) .filter(([, plp]) => [makerToken, takerToken].every(t => plp.tokens.includes(t)))
.map(([providerAddress]) => providerAddress); .map(([providerAddress]) => providerAddress);
} }

View File

@ -235,7 +235,10 @@ export class SamplerOperations {
): SourceQuoteOperation<LiquidityProviderFillData> { ): SourceQuoteOperation<LiquidityProviderFillData> {
return new SamplerContractOperation({ return new SamplerContractOperation({
source: ERC20BridgeSource.LiquidityProvider, source: ERC20BridgeSource.LiquidityProvider,
fillData: { poolAddress: providerAddress }, fillData: {
poolAddress: providerAddress,
gasCost: this.liquidityProviderRegistry[providerAddress].gasCost,
},
contract: this._samplerContract, contract: this._samplerContract,
function: this._samplerContract.sampleSellsFromLiquidityProvider, function: this._samplerContract.sampleSellsFromLiquidityProvider,
params: [providerAddress, takerToken, makerToken, takerFillAmounts], params: [providerAddress, takerToken, makerToken, takerFillAmounts],
@ -250,7 +253,10 @@ export class SamplerOperations {
): SourceQuoteOperation<LiquidityProviderFillData> { ): SourceQuoteOperation<LiquidityProviderFillData> {
return new SamplerContractOperation({ return new SamplerContractOperation({
source: ERC20BridgeSource.LiquidityProvider, source: ERC20BridgeSource.LiquidityProvider,
fillData: { poolAddress: providerAddress }, fillData: {
poolAddress: providerAddress,
gasCost: this.liquidityProviderRegistry[providerAddress].gasCost,
},
contract: this._samplerContract, contract: this._samplerContract,
function: this._samplerContract.sampleBuysFromLiquidityProvider, function: this._samplerContract.sampleBuysFromLiquidityProvider,
params: [providerAddress, takerToken, makerToken, makerFillAmounts], params: [providerAddress, takerToken, makerToken, makerFillAmounts],

View File

@ -132,6 +132,7 @@ export interface ShellFillData extends FillData {
export interface LiquidityProviderFillData extends FillData { export interface LiquidityProviderFillData extends FillData {
poolAddress: string; poolAddress: string;
gasCost: number;
} }
export interface BancorFillData extends FillData { export interface BancorFillData extends FillData {
@ -383,7 +384,10 @@ export interface TokenAdjacencyGraph {
} }
export interface LiquidityProviderRegistry { export interface LiquidityProviderRegistry {
[address: string]: [string, string]; [address: string]: {
tokens: string[];
gasCost: number;
};
} }
export interface GenerateOptimizedOrdersOpts { export interface GenerateOptimizedOrdersOpts {

View File

@ -156,6 +156,7 @@ describe('DexSampler tests', () => {
const expectedMakerToken = randomAddress(); const expectedMakerToken = randomAddress();
const expectedTakerToken = randomAddress(); const expectedTakerToken = randomAddress();
const poolAddress = randomAddress(); const poolAddress = randomAddress();
const gasCost = 123;
const sampler = new MockSamplerContract({ const sampler = new MockSamplerContract({
sampleSellsFromLiquidityProvider: (providerAddress, takerToken, makerToken, _fillAmounts) => { sampleSellsFromLiquidityProvider: (providerAddress, takerToken, makerToken, _fillAmounts) => {
expect(providerAddress).to.eq(poolAddress); expect(providerAddress).to.eq(poolAddress);
@ -172,7 +173,7 @@ describe('DexSampler tests', () => {
undefined, undefined,
undefined, undefined,
undefined, undefined,
{ [poolAddress]: [expectedMakerToken, expectedTakerToken] }, { [poolAddress]: { tokens: [expectedMakerToken, expectedTakerToken], gasCost } },
); );
const [result] = await dexOrderSampler.executeAsync( const [result] = await dexOrderSampler.executeAsync(
dexOrderSampler.getSellQuotes( dexOrderSampler.getSellQuotes(
@ -188,7 +189,7 @@ describe('DexSampler tests', () => {
source: 'LiquidityProvider', source: 'LiquidityProvider',
output: toBaseUnitAmount(1001), output: toBaseUnitAmount(1001),
input: toBaseUnitAmount(1000), input: toBaseUnitAmount(1000),
fillData: { poolAddress }, fillData: { poolAddress, gasCost },
}, },
], ],
]); ]);
@ -198,6 +199,7 @@ describe('DexSampler tests', () => {
const expectedMakerToken = randomAddress(); const expectedMakerToken = randomAddress();
const expectedTakerToken = randomAddress(); const expectedTakerToken = randomAddress();
const poolAddress = randomAddress(); const poolAddress = randomAddress();
const gasCost = 321;
const sampler = new MockSamplerContract({ const sampler = new MockSamplerContract({
sampleBuysFromLiquidityProvider: (providerAddress, takerToken, makerToken, _fillAmounts) => { sampleBuysFromLiquidityProvider: (providerAddress, takerToken, makerToken, _fillAmounts) => {
expect(providerAddress).to.eq(poolAddress); expect(providerAddress).to.eq(poolAddress);
@ -214,7 +216,7 @@ describe('DexSampler tests', () => {
undefined, undefined,
undefined, undefined,
undefined, undefined,
{ [poolAddress]: [expectedMakerToken, expectedTakerToken] }, { [poolAddress]: { tokens: [expectedMakerToken, expectedTakerToken], gasCost } },
); );
const [result] = await dexOrderSampler.executeAsync( const [result] = await dexOrderSampler.executeAsync(
dexOrderSampler.getBuyQuotes( dexOrderSampler.getBuyQuotes(
@ -230,7 +232,7 @@ describe('DexSampler tests', () => {
source: 'LiquidityProvider', source: 'LiquidityProvider',
output: toBaseUnitAmount(999), output: toBaseUnitAmount(999),
input: toBaseUnitAmount(1000), input: toBaseUnitAmount(1000),
fillData: { poolAddress }, fillData: { poolAddress, gasCost },
}, },
], ],
]); ]);

View File

@ -1274,7 +1274,10 @@ describe('MarketOperationUtils tests', () => {
.poolAddress; .poolAddress;
const rates: RatesBySource = {}; const rates: RatesBySource = {};
rates[ERC20BridgeSource.LiquidityProvider] = [1, 1, 1, 1]; rates[ERC20BridgeSource.LiquidityProvider] = [1, 1, 1, 1];
MOCK_SAMPLER.liquidityProviderRegistry[liquidityProviderAddress] = [MAKER_TOKEN, TAKER_TOKEN]; MOCK_SAMPLER.liquidityProviderRegistry[liquidityProviderAddress] = {
tokens: [MAKER_TOKEN, TAKER_TOKEN],
gasCost: 0,
};
replaceSamplerOps({ replaceSamplerOps({
getOrderFillableTakerAmounts: () => [constants.ZERO_AMOUNT], getOrderFillableTakerAmounts: () => [constants.ZERO_AMOUNT],
getSellQuotes: createGetMultipleSellQuotesOperationFromRates(rates), getSellQuotes: createGetMultipleSellQuotesOperationFromRates(rates),
@ -1317,7 +1320,10 @@ describe('MarketOperationUtils tests', () => {
[ERC20BridgeSource.Uniswap]: [1, 1, 1, 1], [ERC20BridgeSource.Uniswap]: [1, 1, 1, 1],
[ERC20BridgeSource.LiquidityProvider]: [0.9999, 0.9999, 0.9999, 0.9999], [ERC20BridgeSource.LiquidityProvider]: [0.9999, 0.9999, 0.9999, 0.9999],
}; };
MOCK_SAMPLER.liquidityProviderRegistry[randomAddress()] = [MAKER_TOKEN, TAKER_TOKEN]; MOCK_SAMPLER.liquidityProviderRegistry[randomAddress()] = {
tokens: [MAKER_TOKEN, TAKER_TOKEN],
gasCost: 0,
};
replaceSamplerOps({ replaceSamplerOps({
getSellQuotes: createGetMultipleSellQuotesOperationFromRates(rates), getSellQuotes: createGetMultipleSellQuotesOperationFromRates(rates),
getMedianSellRate: createGetMedianSellRate(ETH_TO_MAKER_RATE), getMedianSellRate: createGetMedianSellRate(ETH_TO_MAKER_RATE),
@ -1736,7 +1742,10 @@ describe('MarketOperationUtils tests', () => {
[ERC20BridgeSource.Uniswap]: [1, 1, 1, 1], [ERC20BridgeSource.Uniswap]: [1, 1, 1, 1],
[ERC20BridgeSource.LiquidityProvider]: [0.9999, 0.9999, 0.9999, 0.9999], [ERC20BridgeSource.LiquidityProvider]: [0.9999, 0.9999, 0.9999, 0.9999],
}; };
MOCK_SAMPLER.liquidityProviderRegistry[randomAddress()] = [MAKER_TOKEN, TAKER_TOKEN]; MOCK_SAMPLER.liquidityProviderRegistry[randomAddress()] = {
tokens: [MAKER_TOKEN, TAKER_TOKEN],
gasCost: 0,
};
replaceSamplerOps({ replaceSamplerOps({
getBuyQuotes: createGetMultipleBuyQuotesOperationFromRates(rates), getBuyQuotes: createGetMultipleBuyQuotesOperationFromRates(rates),
getMedianSellRate: createGetMedianSellRate(ETH_TO_TAKER_RATE), getMedianSellRate: createGetMedianSellRate(ETH_TO_TAKER_RATE),