-
Notifications
You must be signed in to change notification settings - Fork 13
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
patch: Improve autorouter #561
Conversation
collateralAmount: BigNumber, | ||
preloadedPools?: Pool[] | ||
): Promise<BigNumber> { | ||
// convert collateral into DAI | ||
const { route, fees } = await getRouteAndGasQuote(network, collateral.symbol, collateralAmount, marketId); | ||
if (!route) { | ||
throw new Error(`No route found for ${collateral.symbol} to DAI`); | ||
if (!preloadedPools) { | ||
throw new Error(`pools required to get market price for callee type "${marketId}"`); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this intends to address #531 (comment)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, this is possible solution, but it doesn't completely follow the proposal. Maybe I should ask like that:
How do we get pools
for the getMarketPrice
in case of the auto router?
- We first need to call
fetchAutoRouteInformation
in the parent of thegetMarketPrice
- Then we need to pass
pools
here, then to theconvertCollateralToDaiUsingPool
and then based on the supplied pools it will return us the price
But why do we pass pools
to convertCollateralToDaiUsingPool
if we already know it's the price (since it's returned by the fetchAutoRouteInformation
together with pools
)? Or what to do with the cases when we simply want to convert 0.001 ETH
fee to DAI and don't have pools? Ie how do you handle this now?
The suggestion then is to always return price with pools together. In other words, change getMarketPrice
output type to include pools. And replace/remove "enrichment with pools" with "enrichment with market data"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
adjusted code to either use the total price + pools from AlphaRouter (if autorouting worked out) or fallback to the older way (if hardcoded route).
return { price: daiAmount.dividedBy(collateralAmount), pools: generatedPools }; | ||
} | ||
if (totalPrice && pools) { | ||
return { price: totalPrice.dividedBy(collateralAmount), pools: pools }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The only remaining problem I see now is that totalPrice
here is not the adjusted price that takes exchange fees into account (so we can properly compare exchange prices between each other), but the normal one
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i observe that the autorouter returns 2 amounts:
/**
* The quote for the swap.
* For EXACT_IN swaps this will be an amount of token out.
* For EXACT_OUT this will be an amount of token in.
*/
quote: CurrencyAmount;
/**
* The quote adjusted for the estimated gas used by the swap.
* This is computed by estimating the amount of gas used by the swap, converting
* this estimate to be in terms of the quote token, and subtracting that from the quote.
* i.e. quoteGasAdjusted = quote - estimatedGasUsedQuoteToken
*/
quoteGasAdjusted: CurrencyAmount;
My understanding of the above does not combine well with your claim.
The documentation claims that quote is the amount of "token out". If the value does not account for exchange fees, then the amount out is different from quote
and hence the documentation is not valid.
Did you perhaps mean the gas fees? should i use quoteGasAdjusted
value instead of quote
?
const pools = await routeToPool(network, route, collateral.symbol, fees); | ||
const daiAmount = await convertCollateralToDaiUsingPool( | ||
): Promise<{ price: BigNumber; pools: Pool[] }> { | ||
const { route, fees, totalPrice, pools } = await getRouteAndGasQuote( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: I would remove getRouteAndGasQuote
whatsoever and move its logic here, inside getMarketPrice
. Because it's just adds a very strange layer of abstraction which doesn't add any value, but complicates understanding of what's going on
core/src/calleeFunctions/index.ts
Outdated
const { route, fees } = await fetchAutoRouteInformation(network, collateral.symbol, amount.toFixed()); | ||
if (!route) { | ||
throw new Error('No automatic route can be found'); | ||
const { pools } = await fetchAutoRouteInformation(network, collateral.symbol, amount.toFixed()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Where do we still use
getPools
if we the proposal is to never use them separately from the price? - Why do we ever send amount as a string?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where do we still use getPools if we the proposal is to never use them separately from the price?
getCalleeData
for UniswapV3 has 2 use cases:
- autorouter
- the prices and pools are extracted at the same time. No need to perform other actions (
getPools
is not called)
- the prices and pools are extracted at the same time. No need to perform other actions (
- hardcoded
- the route is provided, prices are not extracted with pools (because alpharouter is not called) and we have to do the old fashioned extraction from the hardcoded route. But we also have to unify the format to use pools primarily. So the
getPools
is called for the sake of converting route to pool.
- the route is provided, prices are not extracted with pools (because alpharouter is not called) and we have to do the old fashioned extraction from the hardcoded route. But we also have to unify the format to use pools primarily. So the
I will refactor the code a bit so that getPools
cannot be called for callee configs where autorouter is enabled.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
removed unused arg (amount)
core/src/types.ts
Outdated
@@ -116,7 +116,7 @@ declare interface MarketDataBase extends Partial<ExchangeFees> { | |||
export declare interface Pool { | |||
addresses: string[]; | |||
fee: number; | |||
routes: string[]; | |||
routes: (string | undefined)[]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In which case it can be an array of undefined
? 😓
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
uniswap autorouter does not promise to return the symbol of the token. It's optional there.
will throw if the autorouter does not return symbol in pool
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hard for me to review properly
- don't have a test case where the auto router uses a route with an unknown token
- cannot properly test regeneration of pools
However,
- was able to participate in
goerli
auction via auto router - UI is not broken but experience is quite similar to current state of prod
Hence approving this PR
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Live testing this as we currently have auctions on mainnet. Enabling the auto-router on the
RENBTC-A
auctions results in UI crash (see below)
console error:
auctions.ts?b334:336 Uncaught TypeError: Cannot read properties of undefined (reading 'forEach')
at Store.updateAuctionsPrices (auctions.ts?b334:336:1)
at Array.wrappedActionHandler (vuex.esm.js?2f62:851:1)
at Store.dispatch (vuex.esm.js?2f62:516:1)
at Store.boundDispatch [as dispatch] (vuex.esm.js?2f62:406:1)
at local.dispatch (vuex.esm.js?2f62:779:1)
at eval (auctions.ts?b334:238:1)
fixed the error, the auction seems to be already gone from the mainnet. I used fork on hardhat instead. CI tells that it's not mergable. Idk how so. Any thoughts @valiafetisov ? |
Executing commands on the fresh clone worked for me
So the state of the branch doesn't seem to be a problem. |
As discussed orally, will document the other error experienced during live test yesterday:
|
could you reproduce this on fork? e.g. on block 16176345 i fail to see the same error. |
As discussed verbally, currently there is no chance for me to start simulation with fork at specific block height. Hence created #568 as intermediate issue. |
did #232 ever get completely resolved? might it be the case that the calculation is just still screwed and in some cases the profit is just really not sufficient, but calculated incorrectly? |
Yes, might be the case that profit amount is calculated incorrectly. But this is always about the precise amount and not about it being negative – we did not have internal or external complains about failed transactions (except for one issue which was long time fixed) |
i have just tested this on |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tests conducted:
- on
goerli
: able restart auction, enable auto router, execute swap tx with auto router selected ✔️ (ETH-A
auction) - via simulation on
localhost
: able to simulate auction, enable auto router, execute tx with auto router selected ✔️ (ETH-A
auction)
- Via simulation: For other collateral types like
RENBTC-A
orLINK-A
enabling the auto router via UI resulted in an endless (killed process after 5min) loading state without getting actual prices (no console error thrown).
this is due to alpha router not being able to load in the data and failing. currently the ui does not notify that this happened:
|
Fine for me to scope it out. So for me this results in two follow up issues:
|
Closes #558
Checklist:
#
)