0

Getting this error when attempting to deploy a contract that reads in three addresses and two tuples

creation of PairFlash errored: Error encoding arguments: Error: types/values length mismatch (count={"types":5,"values":11}, value={"types":["address","address","address","tuple(address,address,uint24,uint256,uint256)","tuple(address,address,uint24,uint256,uint256)"],"values":["0xE592427A0AEce92De3Edee1F18E0157C05861564","0x1F98431c8aD98523631AE4a59f267346ea31F984","0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270","",",0x9c2C5fd7b07E95EE044DDeba0E97a665F142394f,",",10,","","",",0x85955046DF4668e1DD369D2DE9f3AEB98DD2A369,",",22875,",""]}, code=INVALID_ARGUMENT, version=abi/5.7.0)

The tuple reads as: 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2,0x9c2C5fd7b07E95EE044DDeba0E97a665F142394f,3000,10,22875

Are the commas not supposed to be added?

Code below:

pragma solidity >=0.7.6 <=0.8.18;
pragma abicoder v2;
pragma experimental ABIEncoderV2;

import '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3FlashCallback.sol';
import '@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol';

import '@uniswap/v3-periphery/contracts/base/PeripheryPayments.sol';
import '@uniswap/v3-periphery/contracts/base/PeripheryImmutableState.sol';
import '@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol';
import '@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol';
import '@uniswap/v3-periphery/contracts/libraries/TransferHelper.sol';
import '@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol';

/// @title Flash contract implementation
/// @notice An example contract using the Uniswap V3 flash function
contract PairFlash is IUniswapV3FlashCallback, PeripheryImmutableState, PeripheryPayments {
    using LowGasSafeMath for uint256;
    using LowGasSafeMath for int256;

    ISwapRouter public immutable swapRouter;
    
    constructor(
        ISwapRouter _swapRouter,
        address _factory,
        address _WETH9,
        FlashParams memory flashParams,
        FlashParams2 memory flashParams2
    ) PeripheryImmutableState(_factory, _WETH9) {
        swapRouter = _swapRouter;
        flashParams.token0;
        flashParams2.token1;
        flashParams2.token2;       
    }

    /// @param fee0 The fee from calling flash for token0
    /// @param fee1 The fee from calling flash for token1
    /// @param data The data needed in the callback passed as FlashCallbackData from `initFlash`
    /// @notice implements the callback called from flash
    /// @dev fails if the flash is not profitable, meaning the amountOut from the flash is less than the amount borrowed
    function uniswapV3FlashCallback(
        uint256 fee0,
        uint256 fee1,
        bytes calldata data
    ) external override {
        FlashCallbackData memory decoded = abi.decode(data, (FlashCallbackData));
        CallbackValidation.verifyCallback(factory, decoded.poolKey);

        FlashCallbackData2 memory decoded2 = abi.decode(data, (FlashCallbackData2));
        CallbackValidation.verifyCallback(factory, decoded2.poolKey2);

        FlashCallbackData3 memory decoded3 = abi.decode(data, (FlashCallbackData3));
        CallbackValidation.verifyCallback(factory, decoded3.poolKey3);

        //address token0 = decoded.poolKey.token0;
        //address token1 = decoded.poolKey.token1;
        //address token2 = decoded2.poolKey2.token1;
        //address token3 = decoded3.poolKey3.token0;

        //uint24 poolfee0 = decoded.poolKey.fee;
        //uint24 poolfee1 = decoded2.poolKey2.fee;
        //uint24 poolfee2 = decoded3.poolKey3.fee;

        //uint256 amount0 = decoded.amount0;
        //uint256 amount1 = decoded.amount1;

        //uint256 amount1a = decoded2.amount1;
        //uint256 amount2 = decoded2.amount2;

        //uint256 amount2a = decoded3.amount2;
        //uint256 amount0a = decoded3.amount0;

        TransferHelper.safeApprove(decoded.poolKey.token0, address(swapRouter), decoded.amount0);
        TransferHelper.safeApprove(decoded.poolKey.token1, address(swapRouter), decoded.amount1);
        TransferHelper.safeApprove(decoded2.poolKey2.token1, address(swapRouter), decoded2.amount2);


        // profitable check
        // exactInputSingle will fail if this amount not met
        //uint256 amount1Min = LowGasSafeMath.add(amount1, poolfee1);
        uint256 amount0Min = LowGasSafeMath.add(decoded.amount0, decoded.poolKey.fee);

        uint256 amount0aMin = LowGasSafeMath.add(decoded3.amount0, decoded3.poolKey3.fee);


        //multihop swap from WETH to token1 to token2
        swapRouter.exactInput(
            ISwapRouter.ExactInputParams({
                path: abi.encodePacked(decoded.poolKey.token0, decoded.poolKey.fee, decoded.poolKey.token1, decoded2.poolKey2.fee, decoded2.poolKey2.token1),
                recipient: address(this),
                deadline: block.timestamp,
                amountIn: decoded.amount1,
                amountOutMinimum: amount0Min               
            })
        );

        //single swap from token2 back to WETH

       uint256 amountOut0 =
            swapRouter.exactInputSingle(
                ISwapRouter.ExactInputSingleParams({
                    tokenIn: decoded3.poolKey3.token0,
                    tokenOut: decoded3.poolKey3.token1,
                    fee: decoded3.poolKey3.fee,
                    recipient: address(this),
                    deadline: block.timestamp,
                    amountIn: decoded3.amount2,
                    amountOutMinimum: amount0aMin,
                    sqrtPriceLimitX96: 0
                })
            );
        
        /*
        // call exactInputSingle for swapping token1 for token0 in pool w/fee2
        uint256 amountOut0 =
            swapRouter.exactInputSingle(
                ISwapRouter.ExactInputSingleParams({
                    tokenIn: decoded.poolKey.token1,
                    tokenOut: decoded.poolKey.token0,
                    fee: poolfee0,
                    recipient: address(this),
                    deadline: block.timestamp,
                    amountIn: amount1,
                    amountOutMinimum: amount0,
                    sqrtPriceLimitX96: 0
                })
            );

        // call exactInputSingle for swapping token2 for token 1 in pool 
 

        //last call to return to WETH

        uint256 amountOut2 =
            swapRouter.exactInputSingle(
                ISwapRouter.ExactInputSingleParams({
                    tokenIn: token3,
                    tokenOut: token2,
                    fee: poolfee2,
                    recipient: address(this),
                    deadline: block.timestamp,
                    amountIn: amount2a,
                    amountOutMinimum: amount0a,
                    sqrtPriceLimitX96: 0
                })
            );       
        */
        // end up with amountOut0 of token0 from first swap and amountOut1 of token1 from second swap
        uint256 amount0Owed = LowGasSafeMath.add(amountOut0, decoded3.poolKey3.fee);
       // uint256 amount1Owed = LowGasSafeMath.add(decoded.amount1, poolfee1);

        TransferHelper.safeApprove(decoded3.poolKey3.token1, address(this), amount0Owed);
        //TransferHelper.safeApprove(token1, address(this), amount1Owed);

        if (amount0Owed > 0) pay(decoded3.poolKey3.token1, address(this), msg.sender, amount0Owed);
        //if (amount1Owed > 0) pay(token1, address(this), msg.sender, amount1Owed);

        // if profitable pay profits to payer
        if (amountOut0 > amount0Owed) {
            uint256 profit0 = LowGasSafeMath.sub(amountOut0, amount0Owed);

            TransferHelper.safeApprove(decoded3.poolKey3.token1, address(this), profit0);
            pay(decoded3.poolKey3.token1, address(this), decoded.payer, profit0);
        }


        /*
        if (amount1a > amount1Owed) {
            uint256 profit1 = LowGasSafeMath.sub(amount1a, amount1Owed);
            TransferHelper.safeApprove(token0, address(this), profit1);
            pay(token1, address(this), decoded.payer, profit1);
        }
        */
    }

    //fee1 is the fee of the pool from the initial borrow
    //fee2 is the fee of the first pool to arb from
    //fee3 is the fee of the second pool to arb from
    struct FlashParams {
        address token0;
        address token1;
        uint24 fee1;
        uint256 amount0;
        uint256 amount1;
    }

    struct FlashParams2 {
        address token1;
        address token2;
        uint24 fee4;
        uint256 amount1;
        uint256 amount2;
    }


    struct FlashParams3 {
        address token2;
        address token0;
        uint24 fee7;
        uint256 amount2;
        uint256 amount0;
    }

    // fee2 and fee3 are the two other fees associated with the two other pools of token0 and token1
    struct FlashCallbackData {
        uint256 amount0;
        uint256 amount1;
        address payer;
        PoolAddress.PoolKey poolKey;
    }

    struct FlashCallbackData2 {
        uint256 amount1;
        uint256 amount2;
        address payer;
        PoolAddress.PoolKey poolKey2;
    }

    struct FlashCallbackData3 {
        uint256 amount2;
        uint256 amount0;
        address payer;
        PoolAddress.PoolKey poolKey3;
    }

    /// @param params The parameters necessary for flash and the callback, passed in as FlashParams
    /// @notice Calls the pools flash function with data needed in `uniswapV3FlashCallback`
    function initFlash(FlashParams memory params, FlashParams2 memory params2, FlashParams3 memory params3) external {
        PoolAddress.PoolKey memory poolKey =
            PoolAddress.PoolKey({token0: params.token0, token1: params.token1, fee: params.fee1});
        PoolAddress.PoolKey memory poolKey2 =
            PoolAddress.PoolKey({token0: params2.token1, token1: params2.token2, fee: params2.fee4});
        PoolAddress.PoolKey memory poolKey3 =
            PoolAddress.PoolKey({token0: params3.token2, token1: params3.token0, fee: params3.fee7});


        IUniswapV3Pool pool = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey));
        IUniswapV3Pool pool2 = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey2));
        IUniswapV3Pool pool3 = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey3));
        // recipient of borrowed amounts
        // amount of token0 requested to borrow
        // amount of token1 requested to borrow
        // need amount 0 and amount1 in callback to pay back pool
        // recipient of flash should be THIS contract
        pool.flash(
            address(this),
            params.amount0,
            params.amount1,
            abi.encode(
                FlashCallbackData({
                    amount0: params.amount0,
                    amount1: params.amount1,
                    payer: msg.sender,
                    poolKey: poolKey
                })
            )
        );

       pool2.flash(
            address(this),
            params2.amount1,
            params2.amount2,
            abi.encode(
                FlashCallbackData2({
                    amount1: params2.amount1,
                    amount2: params2.amount2,
                    payer: msg.sender,
                    poolKey2: poolKey2
                })
            )
        ); 

       pool3.flash(
            address(this),
            params3.amount2,
            params3.amount0,
            abi.encode(
                FlashCallbackData3({
                    amount2: params3.amount2,
                    amount0: params3.amount0,
                    payer: msg.sender,
                    poolKey3: poolKey3
                })
            )
        );      


    }
}```
2
  • Hi Manny! We will need you to provide the code used to make the deployment transaction.
    – Ismael
    Commented Oct 2, 2023 at 4:48
  • Hi Ismael, I have added the contract code!
    – user126715
    Commented Oct 6, 2023 at 15:53

0

Your Answer

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