feat: Improve Uniswap V3 gas schedule (#397)
* feat: UniswapV3Sampler use QuoterV2 for sells WIP * feat: UniswapV3Sampler for QuoterV2 buys WIP * refactor: separate logic to remove stack too deep issue * feat: Use initializedTicksCrossed from Uniswap QuoterV2 for gas est. * fix: use Quoter gasUsed instead of estimating gas from pools + ticks * refactor: clean up UniswapV3Sampler & remove old Quoter interface * refactor: unify code for buys and sells while handling stack too deep * fix: use mean gas price from all sample estimating UniV3 gas schedule * fix: fallback to legacy Uniswap V3 gas estimate if we can't get gasUsed * refactor: use named function instead of fat arrow * chore: add asset-swapper changelog entry
This commit is contained in:
parent
25dd6bc79a
commit
84e4819e6e
@ -9,6 +9,10 @@
|
|||||||
{
|
{
|
||||||
"note": "Fix incorrect output scaling when input is less than desired amount, update fast-abi",
|
"note": "Fix incorrect output scaling when input is less than desired amount, update fast-abi",
|
||||||
"pr": 401
|
"pr": 401
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Improve Uniswap V3 gas schedule",
|
||||||
|
"pr": 397
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -22,17 +22,43 @@ pragma experimental ABIEncoderV2;
|
|||||||
|
|
||||||
import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
|
import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
|
||||||
|
|
||||||
interface IUniswapV3Quoter {
|
interface IUniswapV3QuoterV2 {
|
||||||
function factory()
|
function factory()
|
||||||
external
|
external
|
||||||
view
|
view
|
||||||
returns (IUniswapV3Factory factory);
|
returns (IUniswapV3Factory factory);
|
||||||
|
|
||||||
|
// @notice Returns the amount out received for a given exact input swap without executing the swap
|
||||||
|
// @param path The path of the swap, i.e. each token pair and the pool fee
|
||||||
|
// @param amountIn The amount of the first token to swap
|
||||||
|
// @return amountOut The amount of the last token that would be received
|
||||||
|
// @return sqrtPriceX96AfterList List of the sqrt price after the swap for each pool in the path
|
||||||
|
// @return initializedTicksCrossedList List of the initialized ticks that the swap crossed for each pool in the path
|
||||||
|
// @return gasEstimate The estimate of the gas that the swap consumes
|
||||||
function quoteExactInput(bytes memory path, uint256 amountIn)
|
function quoteExactInput(bytes memory path, uint256 amountIn)
|
||||||
external
|
external
|
||||||
returns (uint256 amountOut);
|
returns (
|
||||||
|
uint256 amountOut,
|
||||||
|
uint160[] memory sqrtPriceX96AfterList,
|
||||||
|
uint32[] memory initializedTicksCrossedList,
|
||||||
|
uint256 gasEstimate
|
||||||
|
);
|
||||||
|
|
||||||
|
// @notice Returns the amount in required for a given exact output swap without executing the swap
|
||||||
|
// @param path The path of the swap, i.e. each token pair and the pool fee. Path must be provided in reverse order
|
||||||
|
// @param amountOut The amount of the last token to receive
|
||||||
|
// @return amountIn The amount of first token required to be paid
|
||||||
|
// @return sqrtPriceX96AfterList List of the sqrt price after the swap for each pool in the path
|
||||||
|
// @return initializedTicksCrossedList List of the initialized ticks that the swap crossed for each pool in the path
|
||||||
|
// @return gasEstimate The estimate of the gas that the swap consumes
|
||||||
function quoteExactOutput(bytes memory path, uint256 amountOut)
|
function quoteExactOutput(bytes memory path, uint256 amountOut)
|
||||||
external
|
external
|
||||||
returns (uint256 amountIn);
|
returns (
|
||||||
|
uint256 amountIn,
|
||||||
|
uint160[] memory sqrtPriceX96AfterList,
|
||||||
|
uint32[] memory initializedTicksCrossedList,
|
||||||
|
uint256 gasEstimate
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IUniswapV3Factory {
|
interface IUniswapV3Factory {
|
||||||
@ -61,14 +87,15 @@ contract UniswapV3Sampler
|
|||||||
/// @return makerTokenAmounts Maker amounts bought at each taker token
|
/// @return makerTokenAmounts Maker amounts bought at each taker token
|
||||||
/// amount.
|
/// amount.
|
||||||
function sampleSellsFromUniswapV3(
|
function sampleSellsFromUniswapV3(
|
||||||
IUniswapV3Quoter quoter,
|
IUniswapV3QuoterV2 quoter,
|
||||||
IERC20TokenV06[] memory path,
|
IERC20TokenV06[] memory path,
|
||||||
uint256[] memory takerTokenAmounts
|
uint256[] memory takerTokenAmounts
|
||||||
)
|
)
|
||||||
public
|
public
|
||||||
returns (
|
returns (
|
||||||
bytes[] memory uniswapPaths,
|
bytes[] memory uniswapPaths,
|
||||||
uint256[] memory makerTokenAmounts
|
uint256[] memory makerTokenAmounts,
|
||||||
|
uint256[] memory uniswapGasUsed
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
IUniswapV3Pool[][] memory poolPaths =
|
IUniswapV3Pool[][] memory poolPaths =
|
||||||
@ -76,31 +103,39 @@ contract UniswapV3Sampler
|
|||||||
|
|
||||||
makerTokenAmounts = new uint256[](takerTokenAmounts.length);
|
makerTokenAmounts = new uint256[](takerTokenAmounts.length);
|
||||||
uniswapPaths = new bytes[](takerTokenAmounts.length);
|
uniswapPaths = new bytes[](takerTokenAmounts.length);
|
||||||
|
uniswapGasUsed = new uint256[](takerTokenAmounts.length);
|
||||||
|
|
||||||
for (uint256 i = 0; i < takerTokenAmounts.length; ++i) {
|
for (uint256 i = 0; i < takerTokenAmounts.length; ++i) {
|
||||||
// Pick the best result from all the paths.
|
// Pick the best result from all the paths.
|
||||||
bytes memory topUniswapPath;
|
|
||||||
uint256 topBuyAmount = 0;
|
uint256 topBuyAmount = 0;
|
||||||
for (uint256 j = 0; j < poolPaths.length; ++j) {
|
for (uint256 j = 0; j < poolPaths.length; ++j) {
|
||||||
bytes memory uniswapPath = _toUniswapPath(path, poolPaths[j]);
|
bytes memory uniswapPath = _toUniswapPath(path, poolPaths[j]);
|
||||||
try
|
try quoter.quoteExactInput
|
||||||
quoter.quoteExactInput
|
|
||||||
{ gas: QUOTE_GAS }
|
{ gas: QUOTE_GAS }
|
||||||
(uniswapPath, takerTokenAmounts[i])
|
(uniswapPath, takerTokenAmounts[i])
|
||||||
returns (uint256 buyAmount)
|
returns (
|
||||||
|
uint256 buyAmount,
|
||||||
|
uint160[] memory, /* sqrtPriceX96AfterList */
|
||||||
|
uint32[] memory, /* initializedTicksCrossedList */
|
||||||
|
uint256 gasUsed
|
||||||
|
)
|
||||||
{
|
{
|
||||||
if (topBuyAmount <= buyAmount) {
|
if (topBuyAmount <= buyAmount) {
|
||||||
topBuyAmount = buyAmount;
|
topBuyAmount = buyAmount;
|
||||||
topUniswapPath = uniswapPath;
|
uniswapPaths[i] = uniswapPath;
|
||||||
|
uniswapGasUsed[i] = gasUsed;
|
||||||
}
|
}
|
||||||
} catch { }
|
} catch {}
|
||||||
}
|
}
|
||||||
// Break early if we can't complete the buys.
|
// Break early if we can't complete the sells.
|
||||||
if (topBuyAmount == 0) {
|
if (topBuyAmount == 0) {
|
||||||
|
// HACK(kimpers): To avoid too many local variables, paths and gas used is set directly in the loop
|
||||||
|
// then reset if no valid valid quote was found
|
||||||
|
uniswapPaths[i] = "";
|
||||||
|
uniswapGasUsed[i] = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
makerTokenAmounts[i] = topBuyAmount;
|
makerTokenAmounts[i] = topBuyAmount;
|
||||||
uniswapPaths[i] = topUniswapPath;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,14 +147,15 @@ contract UniswapV3Sampler
|
|||||||
/// @return takerTokenAmounts Taker amounts sold at each maker token
|
/// @return takerTokenAmounts Taker amounts sold at each maker token
|
||||||
/// amount.
|
/// amount.
|
||||||
function sampleBuysFromUniswapV3(
|
function sampleBuysFromUniswapV3(
|
||||||
IUniswapV3Quoter quoter,
|
IUniswapV3QuoterV2 quoter,
|
||||||
IERC20TokenV06[] memory path,
|
IERC20TokenV06[] memory path,
|
||||||
uint256[] memory makerTokenAmounts
|
uint256[] memory makerTokenAmounts
|
||||||
)
|
)
|
||||||
public
|
public
|
||||||
returns (
|
returns (
|
||||||
bytes[] memory uniswapPaths,
|
bytes[] memory uniswapPaths,
|
||||||
uint256[] memory takerTokenAmounts
|
uint256[] memory takerTokenAmounts,
|
||||||
|
uint256[] memory uniswapGasUsed
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
IUniswapV3Pool[][] memory poolPaths =
|
IUniswapV3Pool[][] memory poolPaths =
|
||||||
@ -128,11 +164,12 @@ contract UniswapV3Sampler
|
|||||||
|
|
||||||
takerTokenAmounts = new uint256[](makerTokenAmounts.length);
|
takerTokenAmounts = new uint256[](makerTokenAmounts.length);
|
||||||
uniswapPaths = new bytes[](makerTokenAmounts.length);
|
uniswapPaths = new bytes[](makerTokenAmounts.length);
|
||||||
|
uniswapGasUsed = new uint256[](makerTokenAmounts.length);
|
||||||
|
|
||||||
for (uint256 i = 0; i < makerTokenAmounts.length; ++i) {
|
for (uint256 i = 0; i < makerTokenAmounts.length; ++i) {
|
||||||
|
uint256 topSellAmount;
|
||||||
|
|
||||||
// Pick the best result from all the paths.
|
// Pick the best result from all the paths.
|
||||||
bytes memory topUniswapPath;
|
|
||||||
uint256 topSellAmount = 0;
|
|
||||||
for (uint256 j = 0; j < poolPaths.length; ++j) {
|
for (uint256 j = 0; j < poolPaths.length; ++j) {
|
||||||
// quoter requires path to be reversed for buys.
|
// quoter requires path to be reversed for buys.
|
||||||
bytes memory uniswapPath = _toUniswapPath(
|
bytes memory uniswapPath = _toUniswapPath(
|
||||||
@ -143,21 +180,30 @@ contract UniswapV3Sampler
|
|||||||
quoter.quoteExactOutput
|
quoter.quoteExactOutput
|
||||||
{ gas: QUOTE_GAS }
|
{ gas: QUOTE_GAS }
|
||||||
(uniswapPath, makerTokenAmounts[i])
|
(uniswapPath, makerTokenAmounts[i])
|
||||||
returns (uint256 sellAmount)
|
returns (
|
||||||
|
uint256 sellAmount,
|
||||||
|
uint160[] memory, /* sqrtPriceX96AfterList */
|
||||||
|
uint32[] memory, /* initializedTicksCrossedList */
|
||||||
|
uint256 gasUsed
|
||||||
|
)
|
||||||
{
|
{
|
||||||
if (topSellAmount == 0 || topSellAmount >= sellAmount) {
|
if (topSellAmount == 0 || topSellAmount >= sellAmount) {
|
||||||
topSellAmount = sellAmount;
|
topSellAmount = sellAmount;
|
||||||
// But the output path should still be encoded for sells.
|
// But the output path should still be encoded for sells.
|
||||||
topUniswapPath = _toUniswapPath(path, poolPaths[j]);
|
uniswapPaths[i] = _toUniswapPath(path, poolPaths[j]);
|
||||||
|
uniswapGasUsed[i] = gasUsed;
|
||||||
}
|
}
|
||||||
} catch {}
|
} catch {}
|
||||||
}
|
}
|
||||||
// Break early if we can't complete the buys.
|
// Break early if we can't complete the buys.
|
||||||
if (topSellAmount == 0) {
|
if (topSellAmount == 0) {
|
||||||
|
// HACK(kimpers): To avoid too many local variables, paths and gas used is set directly in the loop
|
||||||
|
// then reset if no valid valid quote was found
|
||||||
|
uniswapPaths[i] = "";
|
||||||
|
uniswapGasUsed[i] = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
takerTokenAmounts[i] = topSellAmount;
|
takerTokenAmounts[i] = topSellAmount;
|
||||||
uniswapPaths[i] = topUniswapPath;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -236,6 +282,7 @@ contract UniswapV3Sampler
|
|||||||
|
|
||||||
function _reverseTokenPath(IERC20TokenV06[] memory tokenPath)
|
function _reverseTokenPath(IERC20TokenV06[] memory tokenPath)
|
||||||
private
|
private
|
||||||
|
pure
|
||||||
returns (IERC20TokenV06[] memory reversed)
|
returns (IERC20TokenV06[] memory reversed)
|
||||||
{
|
{
|
||||||
reversed = new IERC20TokenV06[](tokenPath.length);
|
reversed = new IERC20TokenV06[](tokenPath.length);
|
||||||
@ -246,6 +293,7 @@ contract UniswapV3Sampler
|
|||||||
|
|
||||||
function _reversePoolPath(IUniswapV3Pool[] memory poolPath)
|
function _reversePoolPath(IUniswapV3Pool[] memory poolPath)
|
||||||
private
|
private
|
||||||
|
pure
|
||||||
returns (IUniswapV3Pool[] memory reversed)
|
returns (IUniswapV3Pool[] memory reversed)
|
||||||
{
|
{
|
||||||
reversed = new IUniswapV3Pool[](poolPath.length);
|
reversed = new IUniswapV3Pool[](poolPath.length);
|
||||||
|
@ -2,6 +2,7 @@ import { ChainId, getContractAddressesForChainOrThrow } from '@0x/contract-addre
|
|||||||
import { FillQuoteTransformerOrderType } from '@0x/protocol-utils';
|
import { FillQuoteTransformerOrderType } from '@0x/protocol-utils';
|
||||||
import { BigNumber } from '@0x/utils';
|
import { BigNumber } from '@0x/utils';
|
||||||
import { formatBytes32String } from '@ethersproject/strings';
|
import { formatBytes32String } from '@ethersproject/strings';
|
||||||
|
import * as _ from 'lodash';
|
||||||
|
|
||||||
import { TokenAdjacencyGraphBuilder } from '../token_adjacency_graph_builder';
|
import { TokenAdjacencyGraphBuilder } from '../token_adjacency_graph_builder';
|
||||||
|
|
||||||
@ -17,7 +18,9 @@ import {
|
|||||||
ERC20BridgeSource,
|
ERC20BridgeSource,
|
||||||
FeeSchedule,
|
FeeSchedule,
|
||||||
FillData,
|
FillData,
|
||||||
|
FinalUniswapV3FillData,
|
||||||
GetMarketOrdersOpts,
|
GetMarketOrdersOpts,
|
||||||
|
isFinalUniswapV3FillData,
|
||||||
KyberSamplerOpts,
|
KyberSamplerOpts,
|
||||||
LidoInfo,
|
LidoInfo,
|
||||||
LiquidityProviderFillData,
|
LiquidityProviderFillData,
|
||||||
@ -2039,19 +2042,19 @@ export const BEETHOVEN_X_SUBGRAPH_URL_BY_CHAIN = valueByChainId<string>(
|
|||||||
export const UNISWAPV3_CONFIG_BY_CHAIN_ID = valueByChainId(
|
export const UNISWAPV3_CONFIG_BY_CHAIN_ID = valueByChainId(
|
||||||
{
|
{
|
||||||
[ChainId.Mainnet]: {
|
[ChainId.Mainnet]: {
|
||||||
quoter: '0xb27308f9f90d607463bb33ea1bebb41c27ce5ab6',
|
quoter: '0x61ffe014ba17989e743c5f6cb21bf9697530b21e',
|
||||||
router: '0xe592427a0aece92de3edee1f18e0157c05861564',
|
router: '0xe592427a0aece92de3edee1f18e0157c05861564',
|
||||||
},
|
},
|
||||||
[ChainId.Ropsten]: {
|
[ChainId.Ropsten]: {
|
||||||
quoter: '0x2f9e608fd881861b8916257b76613cb22ee0652c',
|
quoter: '0x61ffe014ba17989e743c5f6cb21bf9697530b21e',
|
||||||
router: '0x03782388516e94fcd4c18666303601a12aa729ea',
|
router: '0x03782388516e94fcd4c18666303601a12aa729ea',
|
||||||
},
|
},
|
||||||
[ChainId.Polygon]: {
|
[ChainId.Polygon]: {
|
||||||
quoter: '0xb27308f9f90d607463bb33ea1bebb41c27ce5ab6',
|
quoter: '0x61ffe014ba17989e743c5f6cb21bf9697530b21e',
|
||||||
router: '0xe592427a0aece92de3edee1f18e0157c05861564',
|
router: '0xe592427a0aece92de3edee1f18e0157c05861564',
|
||||||
},
|
},
|
||||||
[ChainId.Optimism]: {
|
[ChainId.Optimism]: {
|
||||||
quoter: '0xb27308f9f90d607463bb33ea1bebb41c27ce5ab6',
|
quoter: '0x61ffe014ba17989e743c5f6cb21bf9697530b21e',
|
||||||
router: '0xe592427a0aece92de3edee1f18e0157c05861564',
|
router: '0xe592427a0aece92de3edee1f18e0157c05861564',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -2334,11 +2337,33 @@ export const DEFAULT_GAS_SCHEDULE: Required<FeeSchedule> = {
|
|||||||
return gas;
|
return gas;
|
||||||
},
|
},
|
||||||
[ERC20BridgeSource.UniswapV3]: (fillData?: FillData) => {
|
[ERC20BridgeSource.UniswapV3]: (fillData?: FillData) => {
|
||||||
let gas = 100e3;
|
const uniFillData = fillData as UniswapV3FillData | FinalUniswapV3FillData;
|
||||||
const path = (fillData as UniswapV3FillData).tokenAddressPath;
|
// NOTE: This base value was heuristically chosen by looking at how much it generally
|
||||||
|
// underestimated gas usage
|
||||||
|
const base = 34e3; // 34k base
|
||||||
|
let gas = base;
|
||||||
|
if (isFinalUniswapV3FillData(uniFillData)) {
|
||||||
|
gas += uniFillData.gasUsed;
|
||||||
|
} else {
|
||||||
|
// NOTE: We don't actually know which of the paths would be used in the router
|
||||||
|
// therefore we estimate using the mean of gas prices returned from UniswapV3
|
||||||
|
// For the best case scenario (least amount of hops & ticks) this will
|
||||||
|
// over estimate the gas usage
|
||||||
|
const pathAmountsWithGasUsed = uniFillData.pathAmounts.filter(p => p.gasUsed > 0);
|
||||||
|
const meanGasUsedForPath = Math.round(_.meanBy(pathAmountsWithGasUsed, p => p.gasUsed));
|
||||||
|
gas += meanGasUsedForPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we for some reason could not read `gasUsed` when sampling
|
||||||
|
// fall back to legacy gas estimation
|
||||||
|
if (gas === base) {
|
||||||
|
gas = 100e3;
|
||||||
|
const path = uniFillData.tokenAddressPath;
|
||||||
if (path.length > 2) {
|
if (path.length > 2) {
|
||||||
gas += (path.length - 2) * 32e3; // +32k for each hop.
|
gas += (path.length - 2) * 32e3; // +32k for each hop.
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return gas;
|
return gas;
|
||||||
},
|
},
|
||||||
[ERC20BridgeSource.Lido]: () => 226e3,
|
[ERC20BridgeSource.Lido]: () => 226e3,
|
||||||
|
@ -36,6 +36,7 @@ import {
|
|||||||
ShellFillData,
|
ShellFillData,
|
||||||
UniswapV2FillData,
|
UniswapV2FillData,
|
||||||
UniswapV3FillData,
|
UniswapV3FillData,
|
||||||
|
UniswapV3PathAmount,
|
||||||
} from './types';
|
} from './types';
|
||||||
|
|
||||||
// tslint:disable completed-docs
|
// tslint:disable completed-docs
|
||||||
@ -387,11 +388,14 @@ function createFinalBridgeOrderFillDataFromCollapsedFill(fill: CollapsedFill): F
|
|||||||
switch (fill.source) {
|
switch (fill.source) {
|
||||||
case ERC20BridgeSource.UniswapV3: {
|
case ERC20BridgeSource.UniswapV3: {
|
||||||
const fd = fill.fillData as UniswapV3FillData;
|
const fd = fill.fillData as UniswapV3FillData;
|
||||||
return {
|
const { uniswapPath, gasUsed } = getBestUniswapV3PathAmountForInputAmount(fd, fill.input);
|
||||||
|
const finalFillData: FinalUniswapV3FillData = {
|
||||||
router: fd.router,
|
router: fd.router,
|
||||||
tokenAddressPath: fd.tokenAddressPath,
|
tokenAddressPath: fd.tokenAddressPath,
|
||||||
uniswapPath: getBestUniswapV3PathForInputAmount(fd, fill.input),
|
uniswapPath,
|
||||||
|
gasUsed,
|
||||||
};
|
};
|
||||||
|
return finalFillData;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -399,18 +403,21 @@ function createFinalBridgeOrderFillDataFromCollapsedFill(fill: CollapsedFill): F
|
|||||||
return fill.fillData;
|
return fill.fillData;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getBestUniswapV3PathForInputAmount(fillData: UniswapV3FillData, inputAmount: BigNumber): string {
|
function getBestUniswapV3PathAmountForInputAmount(
|
||||||
|
fillData: UniswapV3FillData,
|
||||||
|
inputAmount: BigNumber,
|
||||||
|
): UniswapV3PathAmount {
|
||||||
if (fillData.pathAmounts.length === 0) {
|
if (fillData.pathAmounts.length === 0) {
|
||||||
throw new Error(`No Uniswap V3 paths`);
|
throw new Error(`No Uniswap V3 paths`);
|
||||||
}
|
}
|
||||||
// Find the best path that can satisfy `inputAmount`.
|
// Find the best path that can satisfy `inputAmount`.
|
||||||
// Assumes `fillData.pathAmounts` is sorted ascending.
|
// Assumes `fillData.pathAmounts` is sorted ascending.
|
||||||
for (const { inputAmount: pathInputAmount, uniswapPath } of fillData.pathAmounts) {
|
for (const pathAmount of fillData.pathAmounts) {
|
||||||
if (pathInputAmount.gte(inputAmount)) {
|
if (pathAmount.inputAmount.gte(inputAmount)) {
|
||||||
return uniswapPath;
|
return pathAmount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return fillData.pathAmounts[fillData.pathAmounts.length - 1].uniswapPath;
|
return fillData.pathAmounts[fillData.pathAmounts.length - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getMakerTakerTokens(opts: CreateOrderFromPathOpts): [string, string] {
|
export function getMakerTakerTokens(opts: CreateOrderFromPathOpts): [string, string] {
|
||||||
|
@ -767,16 +767,17 @@ export class SamplerOperations {
|
|||||||
function: this._samplerContract.sampleSellsFromUniswapV3,
|
function: this._samplerContract.sampleSellsFromUniswapV3,
|
||||||
params: [quoter, tokenAddressPath, takerFillAmounts],
|
params: [quoter, tokenAddressPath, takerFillAmounts],
|
||||||
callback: (callResults: string, fillData: UniswapV3FillData): BigNumber[] => {
|
callback: (callResults: string, fillData: UniswapV3FillData): BigNumber[] => {
|
||||||
const [paths, samples] = this._samplerContract.getABIDecodedReturnData<[string[], BigNumber[]]>(
|
const [paths, samples, gasUsed] = this._samplerContract.getABIDecodedReturnData<
|
||||||
'sampleSellsFromUniswapV3',
|
[string[], BigNumber[], BigNumber[]]
|
||||||
callResults,
|
>('sampleSellsFromUniswapV3', callResults);
|
||||||
);
|
|
||||||
fillData.router = router;
|
fillData.router = router;
|
||||||
fillData.tokenAddressPath = tokenAddressPath;
|
fillData.tokenAddressPath = tokenAddressPath;
|
||||||
fillData.pathAmounts = paths.map((uniswapPath, i) => ({
|
fillData.pathAmounts = paths.map((uniswapPath, i) => ({
|
||||||
uniswapPath,
|
uniswapPath,
|
||||||
inputAmount: takerFillAmounts[i],
|
inputAmount: takerFillAmounts[i],
|
||||||
|
gasUsed: gasUsed[i].toNumber(),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
return samples;
|
return samples;
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@ -795,15 +796,15 @@ export class SamplerOperations {
|
|||||||
function: this._samplerContract.sampleBuysFromUniswapV3,
|
function: this._samplerContract.sampleBuysFromUniswapV3,
|
||||||
params: [quoter, tokenAddressPath, makerFillAmounts],
|
params: [quoter, tokenAddressPath, makerFillAmounts],
|
||||||
callback: (callResults: string, fillData: UniswapV3FillData): BigNumber[] => {
|
callback: (callResults: string, fillData: UniswapV3FillData): BigNumber[] => {
|
||||||
const [paths, samples] = this._samplerContract.getABIDecodedReturnData<[string[], BigNumber[]]>(
|
const [paths, samples, gasUsed] = this._samplerContract.getABIDecodedReturnData<
|
||||||
'sampleBuysFromUniswapV3',
|
[string[], BigNumber[], BigNumber[]]
|
||||||
callResults,
|
>('sampleBuysFromUniswapV3', callResults);
|
||||||
);
|
|
||||||
fillData.router = router;
|
fillData.router = router;
|
||||||
fillData.tokenAddressPath = tokenAddressPath;
|
fillData.tokenAddressPath = tokenAddressPath;
|
||||||
fillData.pathAmounts = paths.map((uniswapPath, i) => ({
|
fillData.pathAmounts = paths.map((uniswapPath, i) => ({
|
||||||
uniswapPath,
|
uniswapPath,
|
||||||
inputAmount: makerFillAmounts[i],
|
inputAmount: makerFillAmounts[i],
|
||||||
|
gasUsed: gasUsed[i].toNumber(),
|
||||||
}));
|
}));
|
||||||
return samples;
|
return samples;
|
||||||
},
|
},
|
||||||
|
@ -268,19 +268,34 @@ export interface HopInfo {
|
|||||||
returnData: string;
|
returnData: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface UniswapV3PathAmount {
|
||||||
|
uniswapPath: string;
|
||||||
|
inputAmount: BigNumber;
|
||||||
|
gasUsed: number;
|
||||||
|
}
|
||||||
export interface UniswapV3FillData extends FillData {
|
export interface UniswapV3FillData extends FillData {
|
||||||
tokenAddressPath: string[];
|
tokenAddressPath: string[];
|
||||||
router: string;
|
router: string;
|
||||||
pathAmounts: Array<{ uniswapPath: string; inputAmount: BigNumber }>;
|
pathAmounts: UniswapV3PathAmount[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface KyberDmmFillData extends UniswapV2FillData {
|
export interface KyberDmmFillData extends UniswapV2FillData {
|
||||||
poolsPath: string[];
|
poolsPath: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface FinalUniswapV3FillData extends Omit<UniswapV3FillData, 'uniswapPaths'> {
|
/**
|
||||||
|
* Determines whether FillData is UniswapV3FillData or FinalUniswapV3FillData
|
||||||
|
*/
|
||||||
|
export function isFinalUniswapV3FillData(
|
||||||
|
data: UniswapV3FillData | FinalUniswapV3FillData,
|
||||||
|
): data is FinalUniswapV3FillData {
|
||||||
|
return !!(data as FinalUniswapV3FillData).uniswapPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface FinalUniswapV3FillData extends Omit<UniswapV3FillData, 'pathAmounts'> {
|
||||||
// The uniswap-encoded path that can fll the maximum input amount.
|
// The uniswap-encoded path that can fll the maximum input amount.
|
||||||
uniswapPath: string;
|
uniswapPath: string;
|
||||||
|
gasUsed: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface LidoFillData extends FillData {
|
export interface LidoFillData extends FillData {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user