I am trying to write a smart contract that can facilitate multihop swaps. It is important that I am able to pass in 2 arrays into the swap function: an address[] of the tokens and uint256[] of the pool fees (though they could be 16 bit unsigned/signed ints or whatever it doesn't matter, its just a rough idea as long as they can support the values needed for the pool fees). I have made the assertion that the length of the pool fees is exactly 1 less than the length of the token addresses.

I have looked at Uniswap V3 Path and the Uniswap documentation and have come up with this code so far:

function concatPathParams(bytes[] calldata addresses, bytes[] calldata poolFees) public pure returns (bytes memory) {
    assert(addresses.length == (poolFees.length - 1));

    bytes memory output;

    uint lastIdx = addresses.length - 1;

    for (uint256 i = 0; i < addresses.length; i++) {
        output = abi.encodePacked(output, addresses[i]);

        if (i != lastIdx) {
            output = abi.encodePacked(output, poolFees[i]);

    return output;
function v3MultihopExactInput(uint256 amountIn, bytes[] calldata addresses, bytes[] calldata poolFees) external returns (uint256 amountOut) {
    TransferHelper.safeTransferFrom(address(uint160(bytes20(addresses[0]))), msg.sender, address(this), amountIn);
    TransferHelper.safeApprove(address(uint160(bytes20(addresses[0]))), address(swapRouter), amountIn);

    bytes memory path = concatPathParams(bytes[](addresses), poolFees);

    ISwapRouter.ExactInputParams memory params =
            path: path,
            recipient: msg.sender,
            deadline: block.timestamp,
            amountIn: amountIn,
            amountOutMinimum: 0

    amountOut = swapRouter.exactInput(params);

The TransferHelper is coming from Uniswap's transfer helper.

I can't seem to figure out what I'm doing wrong here. If someone can point me to the appropriate documentation then that would be beyond helpful. I've tried to decode a uniswap swap to see if my issue isn't actually with the path however I have been unsuccesful.

Helpful info:

The concatPathParams with the inputs ["0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", "0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984"] (WETH, UNI) and ["0x01F4"] (pool fee of 500) returns 0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc201f41f9840a85d5af5bf1d1762f925bdaddc4201f984 which to my eye looks correct.

I then approve the Uniswap V3 contract (0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45) and set it up with the params:

enter image description here

(path: 0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc201f41f9840a85d5af5bf1d1762f925bdaddc4201f984, recipient: (my address), amount in: 1000000000000 (how much the contract is approved for and my balance or less of WETH), amountOutMinimum: 0)

The amount out minimum is set to 0 for testing purposes because I don't care about being frontrun with that little ether. The transaction will fail if I confirm it.

Can someone offer their advice here? Thanks!


Your Answer

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

Browse other questions tagged or ask your own question.