1

I am simply trying to call a method in Uniswap QuoterV2 and keep getting errors that the arguments aren't correct. This is my relevant code:

import QuoterABI from '@uniswap/v3-periphery/artifacts/contracts/interfaces/IQuoterV2.sol/IQuoterV2.json'
const UNISWAP_QUOTER_ADDRESS = '0x3d4e44Eb1374240CE5F1B871ab261CD16335B76a'
const quoterContract = new ethers.Contract(UNISWAP_QUOTER_ADDRESS, QuoterABI.abi, provider);

const quotedAmountOut = await quoterContract.callStatic.quoteExactInputSingle(
    tokenIn.address,
    tokenOut.address,
    pool.fee,
    amountIn,
    0
);

This returns an error:

reason: 'too many arguments: passed to contract',
code: 'UNEXPECTED_ARGUMENT',
count: 5,
expectedCount: 1

While all the examples I found online pass in 5 parameters, why is it that I need to turn the parameters into a single parameter like this:

const quotedAmountOut = await quoterContract.callStatic.quoteExactInputSingle(
    [
        tokenIn.address,
        tokenOut.address,
        pool.fee,
        amountIn,
        0
    ]
);          

Sure, now it doesn't complain about the wrong number of parameters but instead now it complains about value out of bounds:

reason: 'value out-of-bounds',
code: 'INVALID_ARGUMENT',
argument: 'fee',
value: BigNumber { _hex: '0x5af3107a4000', _isBigNumber: true }

I took a look at the ABI I'm using here: https://www.npmjs.com/package/@uniswap/v3-periphery?activeTab=code

Relevant function is here:

{
    "inputs": [
        {
            "components": [
                {
                    "internalType": "address",
                    "name": "tokenIn",
                    "type": "address"
                },
                {
                    "internalType": "address",
                    "name": "tokenOut",
                    "type": "address"
                },
                {
                    "internalType": "uint256",
                    "name": "amountIn",
                    "type": "uint256"
                },
                {
                    "internalType": "uint24",
                    "name": "fee",
                    "type": "uint24"
                },
                {
                    "internalType": "uint160",
                    "name": "sqrtPriceLimitX96",
                    "type": "uint160"
                }
            ],
            "internalType": "struct IQuoterV2.QuoteExactInputSingleParams",
            "name": "params",
            "type": "tuple"
        }
    ],
    "name": "quoteExactInputSingle",
    "outputs": [
        {
            "internalType": "uint256",
            "name": "amountOut",
            "type": "uint256"
        },
        {
            "internalType": "uint160",
            "name": "sqrtPriceX96After",
            "type": "uint160"
        },
        {
            "internalType": "uint32",
            "name": "initializedTicksCrossed",
            "type": "uint32"
        },
        {
            "internalType": "uint256",
            "name": "gasEstimate",
            "type": "uint256"
        }
    ],
    "stateMutability": "nonpayable",
    "type": "function"
}

It says that it takes in a tuple? But why does every example pass in 5 separate parameters. Also, the order of the parameters shows amountIn should be the 3rd parameter not the 4th, even if I update that I still get the same error. I'm really frusturated here spent the whole day debugging and keep running into various errors with this, any help is appreciated.

EDIT: Thank you for your help, I've tried again and still having these issues. This is my code:

const UNISWAP_QUOTER_ADDRESS = '0x3d4e44Eb1374240CE5F1B871ab261CD16335B76a';
const QUOTERv2_ABI = '[{"inputs":[{"internalType":"address","name":"_factory","type":"address"},{"internalType":"address","name":"_WETH9","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"WETH9","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"factory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"path","type":"bytes"},{"internalType":"uint256","name":"amountIn","type":"uint256"}],"name":"quoteExactInput","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint160[]","name":"sqrtPriceX96AfterList","type":"uint160[]"},{"internalType":"uint32[]","name":"initializedTicksCrossedList","type":"uint32[]"},{"internalType":"uint256","name":"gasEstimate","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint24","name":"fee","type":"uint24"},{"internalType":"uint160","name":"sqrtPriceLimitX96","type":"uint160"}],"internalType":"struct IQuoterV2.QuoteExactInputSingleParams","name":"params","type":"tuple"}],"name":"quoteExactInputSingle","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint160","name":"sqrtPriceX96After","type":"uint160"},{"internalType":"uint32","name":"initializedTicksCrossed","type":"uint32"},{"internalType":"uint256","name":"gasEstimate","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"path","type":"bytes"},{"internalType":"uint256","name":"amountOut","type":"uint256"}],"name":"quoteExactOutput","outputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint160[]","name":"sqrtPriceX96AfterList","type":"uint160[]"},{"internalType":"uint32[]","name":"initializedTicksCrossedList","type":"uint32[]"},{"internalType":"uint256","name":"gasEstimate","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint24","name":"fee","type":"uint24"},{"internalType":"uint160","name":"sqrtPriceLimitX96","type":"uint160"}],"internalType":"struct IQuoterV2.QuoteExactOutputSingleParams","name":"params","type":"tuple"}],"name":"quoteExactOutputSingle","outputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint160","name":"sqrtPriceX96After","type":"uint160"},{"internalType":"uint32","name":"initializedTicksCrossed","type":"uint32"},{"internalType":"uint256","name":"gasEstimate","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"int256","name":"amount0Delta","type":"int256"},{"internalType":"int256","name":"amount1Delta","type":"int256"},{"internalType":"bytes","name":"path","type":"bytes"}],"name":"uniswapV3SwapCallback","outputs":[],"stateMutability":"view","type":"function"}]';

const quoterContract = new ethers.Contract(UNISWAP_QUOTER_ADDRESS, QUOTERv2_ABI, provider);

console.log(tokenIn.address);
console.log(tokenOut.address);
console.log(amountIn);
console.log(pool.fee);

        const params = {
            tokenIn: tokenIn.address,
            tokenOut: tokenOut.address,
            amountIn: amountIn,
            fee: pool.fee,
            sqrtPriceLimitX96: 0,
        };


    const quotedAmountOut = await quoterContract.callStatic.quoteExactInputSingle(
        params
    );

Console.log shows that the tokenIn and tokenOut are just public addresses, the amountIn is a BigNum and pool.fee is 3000. I'm getting this error when I run it:

Error: invalid BigNumber value (argument="value", value=[{"type":"BigNumber","hex":"0x12c5e263a5dadc1d6466cad1"},{"type":"BigNumber","hex":"0xaba3e92070893071a033a27bfddb"},0,{"type":"BigNumber","hex":"0x017b5c"}], code=INVALID_ARGUMENT, version=bignumber/5.7.0)

As you see it's still complaining about a wrong BigNumber value, but I'm not sure where it's coming from because the only BigNumber I'm passing in is the amountIn and that number is: BigNumber { _hex: '0x0de0b6b3a7640000', _isBigNumber: true } according to console.log.

EDIT3: Nevermind, actually the call to Quoter 2 was correct and I was getting the error above further down in my code where I was trying to print the output of quoter, but because my console.log statements were for the old quoter the output couldn't be parsed and gave me an error. So happy to solve this and have to pay more attention to where the errors are coming from.

3
  • Can you please provide the chain/network name on which you're interacting with Uniswap QuoterV2? Commented Apr 3 at 19:04
  • The updated quoter takes a tuple with the arguments in, and switches positions of two of the values. amoutIn and fee. Switch to the old abi if calling the old quoter.
    – Maka
    Commented Apr 3 at 19:05
  • I'm trying to run it on the Base network, which is why I'm using Uniswap's QuoterV2 since it's the only one available on Base. Commented Apr 4 at 7:29

1 Answer 1

0

Sounds like you are using the updated ABI on the first iteration of the quoter contract.

The updated quoter takes a tuple with the arguments in, and switches positions of two of the values. amountIn and fee. Switch to the old ABI if calling the old quoter.

Here are examples calling each with their respective ABI.

>>> w3 = con('POLYGON')
>>> quoter = w3.eth.contract(address=QUOTER_ADDRESS, abi=QUOTER_ABI)
>>> quoterv2 = w3.eth.contract(address=QUOTERv2_ADDRESS, abi=QUOTERv2_ABI)
>>>
>>> AMOUNT_IN = 1*10**18
>>> SQRT_PRICE_LIMIT = 0
>>> FEE = 500
>>>
>>> amount_out  = quoter.functions.quoteExactInputSingle(WMATIC_ADDRESS, USDC_ADDRESS, FEE, AMOUNT_IN, SQRT_PRICE_LIMIT).call()
>>> amount_outv2 = quoterv2.functions.quoteExactInputSingle((WMATIC_ADDRESS, USDC_ADDRESS, AMOUNT_IN, FEE, SQRT_PRICE_LIMIT)).call()
>>>
>>> amount_out
888809
>>> amount_outv2
[888809, 74712374439444685749537, 1, 86403]
QUOTER_ABI = '''
[{"inputs":[{"internalType":"address","name":"_factory","type":"address"},{"internalType":"address","name":"_WETH9","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"WETH9","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"factory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"path","type":"bytes"},{"internalType":"uint256","name":"amountIn","type":"uint256"}],"name":"quoteExactInput","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"uint24","name":"fee","type":"uint24"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint160","name":"sqrtPriceLimitX96","type":"uint160"}],"name":"quoteExactInputSingle","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"path","type":"bytes"},{"internalType":"uint256","name":"amountOut","type":"uint256"}],"name":"quoteExactOutput","outputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"uint24","name":"fee","type":"uint24"},{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint160","name":"sqrtPriceLimitX96","type":"uint160"}],"name":"quoteExactOutputSingle","outputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"int256","name":"amount0Delta","type":"int256"},{"internalType":"int256","name":"amount1Delta","type":"int256"},{"internalType":"bytes","name":"path","type":"bytes"}],"name":"uniswapV3SwapCallback","outputs":[],"stateMutability":"view","type":"function"}]
'''
QUOTERv2_ABI = '''
[{"inputs":[{"internalType":"address","name":"_factory","type":"address"},{"internalType":"address","name":"_WETH9","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"WETH9","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"factory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"path","type":"bytes"},{"internalType":"uint256","name":"amountIn","type":"uint256"}],"name":"quoteExactInput","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint160[]","name":"sqrtPriceX96AfterList","type":"uint160[]"},{"internalType":"uint32[]","name":"initializedTicksCrossedList","type":"uint32[]"},{"internalType":"uint256","name":"gasEstimate","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint24","name":"fee","type":"uint24"},{"internalType":"uint160","name":"sqrtPriceLimitX96","type":"uint160"}],"internalType":"struct IQuoterV2.QuoteExactInputSingleParams","name":"params","type":"tuple"}],"name":"quoteExactInputSingle","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint160","name":"sqrtPriceX96After","type":"uint160"},{"internalType":"uint32","name":"initializedTicksCrossed","type":"uint32"},{"internalType":"uint256","name":"gasEstimate","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"path","type":"bytes"},{"internalType":"uint256","name":"amountOut","type":"uint256"}],"name":"quoteExactOutput","outputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint160[]","name":"sqrtPriceX96AfterList","type":"uint160[]"},{"internalType":"uint32[]","name":"initializedTicksCrossedList","type":"uint32[]"},{"internalType":"uint256","name":"gasEstimate","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint24","name":"fee","type":"uint24"},{"internalType":"uint160","name":"sqrtPriceLimitX96","type":"uint160"}],"internalType":"struct IQuoterV2.QuoteExactOutputSingleParams","name":"params","type":"tuple"}],"name":"quoteExactOutputSingle","outputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint160","name":"sqrtPriceX96After","type":"uint160"},{"internalType":"uint32","name":"initializedTicksCrossed","type":"uint32"},{"internalType":"uint256","name":"gasEstimate","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"int256","name":"amount0Delta","type":"int256"},{"internalType":"int256","name":"amount1Delta","type":"int256"},{"internalType":"bytes","name":"path","type":"bytes"}],"name":"uniswapV3SwapCallback","outputs":[],"stateMutability":"view","type":"function"}]
'''

For the pool fee you are passing too large a number for the type. You are passing 100000000000000 When the type is uint24, and the values that can be for any given pool are:

100, 500, 3000 10000 
for 
0.01, 0.05, 0.3, or 1%
3
  • Thank you for the reply but I'm still getting the same error. The fee I'm passing is 3000 and all the other fields are correct. The only BigNumber I have is the amountIn. I've updated my question with the additional code. Thank you! Commented Apr 4 at 7:37
  • Thank you, actually this helped narrow down the issue, the call to the quoter was correct. Commented Apr 4 at 7:49
  • Brilliant, well done.
    – Maka
    Commented Apr 4 at 7:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.