Skip to content
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

Calculation of Quoting for WETH to USDC is Wrong #42

Open
arjunaskykok opened this issue Mar 4, 2023 · 3 comments
Open

Calculation of Quoting for WETH to USDC is Wrong #42

arjunaskykok opened this issue Mar 4, 2023 · 3 comments

Comments

@arjunaskykok
Copy link

Using this configuration in v3-sdk/quoting/config.ts:

  tokens: {
    in: USDC_TOKEN,
    amountIn: 1000,
    out: WETH_TOKEN,
    poolFee: FeeAmount.MEDIUM,
  },

I got this result (which is correct):

Selection_140

On Mar 4th, 2023, 1 ETH is $1570. So with $1000, we would get around 0.63 ETH.

But when I switched the tokens, I got the wrong result. I used this configuration:

  tokens: {
    in: WETH_TOKEN,
    amountIn: 1,
    out: USDC_TOKEN,
    poolFee: FeeAmount.MEDIUM,
  },

Selection_141

The result should be ~1570 USDC.

@balazsotakomaiya
Copy link

Hey @arjunaskykok ,

I've ran into the same problem, and here's what I've found after a bit of debugging:

In the example, you're using the token addresses returned by the poolContract to call the quoteExactInputSingle function.

Like so:

 const [token0, token1, fee] = await Promise.all([
    poolContract.token0(),
    poolContract.token1(),
    poolContract.fee(),
  ])

Whereas, what appears to be the case, is that the order in which the contract returns token0 and token1 isn't guaranteed, in fact it appears to be returning the tokens in alphabetical order. One might call it consistently inconsistent.

The solution is quite simple, albeit, the examples should be updated to reflect this.

Simply don't use the token addresses returned by the pool contract when calling quoteExactInputSingle, as you already know the token addresses anyways.

  const quotedAmountOut = await quoterContract.callStatic.quoteExactInputSingle(
    CurrentConfig.tokens.in.address, // instead of: await poolContract.token0()
    CurrentConfig.tokens.out.address, // instead of: await poolContract.token1()
    poolConstants.fee,
    fromReadableAmount(
      CurrentConfig.tokens.amountIn,
      CurrentConfig.tokens.in.decimals
    ).toString(),
    0
  )

@arjunaskykok
Copy link
Author

@balazsotakomaiya , Thanks for the solution. It works!

@MetaMmodern
Copy link

@balazsotakomaiya fantastic, great investigation and thank you for this. However, I'd like to find out: what are token0() and token1() calls used for then, if we still need to pass them into computePoolAddress call? What's the point of this roundabout?
The documentation says:

This guide fetches this information first in order to show how to fetch any metadata, which will be expanded on in future guides.

But it's weird, what data might me needed that we don't already have? Is it possible to get token address for example without knowing it beforehand?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants