Error when calling Execute function in Universal Router

Hi,I am trying to swap the two tokens using universal router Address = "0x3fC91A3afd70395Cd496C647d5a6CC9D4B2b7FAD" in Sepolia test Network.
here is the code ,i used

// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.8.17;

// Import the interface of the universal router contract
import 'https://github.com/Uniswap/universal-router/blob/main/contracts/interfaces/IUniversalRouter.sol';
import 'https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/IERC20.sol';
contract SwapDAIUSDC {
    // Define the address of the universal router contract
    address private  UNIVERSAL_ROUTER = 0x3fC91A3afd70395Cd496C647d5a6CC9D4B2b7FAD;
    // Define the address of the DAI token
    address private constant DAI = 0xb1452d2ee842f67a80F7286d5C0636B377D9F1d4;
    // Define the address of the USDC token
    address private constant USDC = 0x3AAe6DC6449AD4603B9fCeD099FA062EdFcE6c1e;

    // Create a variable to store the instance of the universal router contract
    IUniversalRouter public universalRouter;

    constructor() {
        // Initialize the universal router contract
        universalRouter = IUniversalRouter(UNIVERSAL_ROUTER);
    }

    // A function to swap DAI for USDC
    function swapDAIUSDC(uint256 daiAmount, uint256 usdcAmount) external {
        uint256 deadline = block.timestamp + 10;
        // Approve the router contract to spend DAI
        IERC20(DAI).approve(UNIVERSAL_ROUTER, daiAmount);

        // Create an array of commands
        bytes memory commands = new bytes(1);
        // The command is to swap DAI for USDC on Uniswap V2
        commands[0] = 0x09; // The command value for V2_SWAP_EXACT_IN

        // Create an array of inputs
         bytes[] memory inputs = new bytes[](1); 
        // The input for the command is the token amount, the minimum output amount, the path of the token pair, and the recipient address
        inputs[0] = abi.encode(daiAmount, usdcAmount, [DAI, USDC], msg.sender);

        // Call the execute function of the universal router contract
        universalRouter.execute(commands, inputs, deadline);
    }
}

when i tried to call the swapDAIUSDC function ,it throws gas estimation error.
can anyone help me on this.

The comment in your code (above) implies that you are using the wrong command.

Looking into uniswap's code, I see:

uint256 constant V2_SWAP_EXACT_IN = 0x08;
uint256 constant V2_SWAP_EXACT_OUT = 0x09;

And in case you're worried that this is a recent change on GitHub only but not in the deployed contract, you can see these exact same constant values in the contract's verified code on etherscan.

Now,I changed that to

0x08

but again ,i got same gas estimation problem mate

Is there any steps,i missed mate?

Well, conceptually, you should not input usdcAmount from the outside, but rather, calculate that amount internally in your function, by calling the pool contract's getAmountsOut function.

For example:

uint256[] memory amounts = IUniswapV2Router02(POOL).getAmountsOut(daiAmount, [DAI, USDC]);
assert(daiAmount == amounts[0]);
uint256 usdcAmount = amounts[1];

Or simply:

uint256 usdcAmount = IUniswapV2Router02(POOL).getAmountsOut(daiAmount, [DAI, USDC])[1];

So you need to import the IUniswapV2Router02 interface, and hard-code the address of that pool contract just as you do with the other hard-coded addresses.

ok,But i think,in this line only i done some mistake

 inputs[0] = abi.encode(daiAmount, usdcAmount, [DAI, USDC], address(this));

can you check this encoding is correct or not

According to uniswap's code, the order of the encoded parameters should be:

  • address recipient
  • uint256 amountIn
  • uint256 amountOutMin
  • address[] path
  • bool payerIsUser

So you should probably change that line in your code to:

inputs[0] = abi.encode(address(this), daiAmount, usdcAmount, [DAI, USDC], payerIsUser);

I'm not sure if the payer is also the user in your case, so you should fill that up accordingly.

You might also need to replace [DAI, USDC], which is a static array of 2 addresses, with a dynamic array which consists of the same 2 addresses; here is how you can initialize such an array:

address[] path = new address[](2);
path[0] = DAI;
path[1] = USDC;

Thanks mate,I will check and let you know mate

NP, note the additional stuff that I gradually added in the answer above.

Also, keep in mind that the value of usdcAmount specifies the minimum return of USDC.
If the swap returns less than that, then the transaction will revert, hence I have previously pointed out that you should obtain this value internally in your function, rather than receiving it as input in this function.

Thanks mate,But i tried this again i got the gas estimation problem mate,
here is my updated Code

// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.8.17;

// Import the interface of the universal router contract
import 'https://github.com/Uniswap/universal-router/blob/main/contracts/interfaces/IUniversalRouter.sol';
import 'https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/IERC20.sol';
contract SwapDAIUSDC {
    // Define the address of the universal router contract
    address private  UNIVERSAL_ROUTER = 0x3fC91A3afd70395Cd496C647d5a6CC9D4B2b7FAD;
    // Define the address of the DAI token
    address private constant DAI = 0xb1452d2ee842f67a80F7286d5C0636B377D9F1d4;
    // Define the address of the USDC token
    address private constant USDC = 0x3AAe6DC6449AD4603B9fCeD099FA062EdFcE6c1e;

    // Create a variable to store the instance of the universal router contract
    IUniversalRouter public universalRouter;

    constructor() {
        // Initialize the universal router contract
        universalRouter = IUniversalRouter(UNIVERSAL_ROUTER);
    }

    // A function to swap DAI for USDC
    function swapDAIUSDC(uint256 daiAmount, uint256 usdcAmount,bool payerIsUser) external {
        uint256 deadline = block.timestamp + 10;
        // Approve the router contract to spend DAI
        IERC20(DAI).approve(UNIVERSAL_ROUTER, daiAmount);

        // Create an array of commands
        bytes memory commands = new bytes(1);
        // The command is to swap DAI for USDC on Uniswap V3
        commands[0] = 0x00; // The command value for V3_SWAP_EXACT_IN

        // Create an array of inputs
         bytes[] memory inputs = new bytes[](1); 
         address[] memory path = new address[](2);
            path[0] = DAI;
            path[1] = USDC;
        // The input for the command is the token amount, the minimum output amount, the path of the token pair, and the recipient address
        // inputs[0] = abi.encode(daiAmount, usdcAmount, [DAI, USDC], address(this));
        inputs[0] = abi.encode(address(this), daiAmount, usdcAmount, [DAI, USDC], payerIsUser);


        // Call the execute function of the universal router contract
        universalRouter.execute(commands, inputs, deadline);
    }
}

The order of the encoded parameters which I gave you in above was for V2_SWAP_EXACT_IN (0x08), which is what you have originally used, now you're changing it "on the fly" to V3_SWAP_EXACT_IN (0x0)???

And that's coming after you've started with 0x09 instead of 0x08, which is something which you could have easily figured out beforehand!

Dude, please organize your research in a proper manner, and request for help only after you have gathered all the details correctly, WITHOUT changing these details during the session, otherwise the entire effort (of yourself, and more importantly - of the person who's trying to help you out) is wasted!

Sorry Mate, I didn't know this before, As per your guidance I tried 0x8, But I aim to do uniswapV3 after I did some research I got some documentation info, that I got to know for V3 it is 0x00, so only I used that.


after using 0x00, also i got an same error mate.

Have you considered what I explained to you here regarding the minimum-return issue?

Have you tried the suggestion that I gave to you here (which aims to handle this issue)?

yes,i tried that,when i am calling the function ,i gave 1 for USDC value and tried it,
then in second option ,i tried that by writing the test value,


,it shows the error in the universalRouter.execute function.

These are NOT the addresses of DAI and USDC on Sepolia!

They are the addresses of USDT (USDT) and USDTs (USDTs)!

I must note that your process of asking this question has been extremely sloppy; several things which I've pointed out to you throughout this thread were outright obvious mistakes, which you could have easily noticed if you had been even slightly more meticulous!!!

Sorry for the confusion mate,I know this is USDT and USDTs, Actually i deployed two ERC20 token for testing purpose,by using this i created a pair. For name sake only i gave the DAI and USDC in the Smart contract function.But actual name is USDT and USDTs.

What fee value did you use as input when you created that pair?

I've checked it here with various different fee values, and I couldn't find such pair for any of them.

For example, no such pair with fee = 3000:

By giving 500 as fees value,you can get the pool address

Yes, and so can you (using the same link that I gave you in my previous comment).

This pool is deployed at 0xF55EbB3FFa46b6ad127b7bAD88B019C75E09fA1e.

What I suggest, is that instead of trying to execute the swap through the router, which ultimately executes it through the pool, you try to execute it directly through the pool yourself.

If it works, then the problem lies with how you interact with the router (i.e., the problem is in the input that you pass when you call universalRouter.execute).

If it doesn't work, then either there's a problem with the tokens that you've created, or there's a problem with the pool (pair) that you've created, preventing a successful swap.

For example, if there is no liquidity on that pool, then it will not be able to send anything in return.

Or perhaps one of your tokens implement a fee-on-transfer mechanism which causes the pool's swap function to revert upon detecting that fee.

But when i am trying to swap using uniswap exchange,it is working fine