{
    "Function": "swapInAMM",
    "File": "contracts/SemiFungiblePositionManager.sol",
    "Parent Contracts": [
        "contracts/multicall/Multicall.sol",
        "contracts/tokens/ERC1155Minimal.sol"
    ],
    "High-Level Calls": [
        "IUniswapV3Pool",
        "LeftRight",
        "PanopticMath",
        "IUniswapV3Pool",
        "IUniswapV3Pool",
        "IUniswapV3Pool",
        "LeftRight",
        "IUniswapV3Pool",
        "IUniswapV3Pool",
        "LeftRight",
        "LeftRight",
        "LeftRight",
        "LeftRight"
    ],
    "Internal Calls": [
        "abi.encode()"
    ],
    "Library Calls": [
        "toInt128",
        "toLeftSlot",
        "rightSlot",
        "leftSlot",
        "toInt128",
        "toRightSlot",
        "convert1to0"
    ],
    "Low-Level Calls": [],
    "Code": "function swapInAMM(\n        IUniswapV3Pool univ3pool,\n        int256 itmAmounts\n    ) internal returns (int256 totalSwapped) {\n        // Initialize variables\n        bool zeroForOne; // The direction of the swap, true for token0 to token1, false for token1 to token0\n        int256 swapAmount; // The amount of token0 or token1 to swap\n        bytes memory data;\n\n        IUniswapV3Pool _univ3pool = univ3pool;\n\n        unchecked {\n            // unpack the in-the-money amounts\n            int128 itm0 = itmAmounts.rightSlot();\n            int128 itm1 = itmAmounts.leftSlot();\n\n            // construct the swap callback struct\n            data = abi.encode(\n                CallbackLib.CallbackData({\n                    poolFeatures: CallbackLib.PoolFeatures({\n                        token0: _univ3pool.token0(),\n                        token1: _univ3pool.token1(),\n                        fee: _univ3pool.fee()\n                    }),\n                    payer: msg.sender\n                })\n            );\n\n            // note: upstream users of this function such as the Panoptic Pool should ensure users always compensate for the ITM amount delta\n            // the netting swap is not perfectly accurate, and it is possible for swaps to run out of liquidity, so we do not want to rely on it\n            // this is simply a convenience feature, and should be treated as such\n            if ((itm0 != 0) && (itm1 != 0)) {\n                (uint160 sqrtPriceX96, , , , , , ) = _univ3pool.slot0();\n\n                // implement a single \"netting\" swap. Thank you @danrobinson for this puzzle/idea\n                // note: negative ITM amounts denote a surplus of tokens (burning liquidity), while positive amounts denote a shortage of tokens (minting liquidity)\n                // compute the approximate delta of token0 that should be resolved in the swap at the current tick\n                // we do this by flipping the signs on the token1 ITM amount converting+deducting it against the token0 ITM amount\n                // couple examples (price = 2 1/0):\n                //  - 100 surplus 0, 100 surplus 1 (itm0 = -100, itm1 = -100)\n                //    normal swap 0: 100 0 => 200 1\n                //    normal swap 1: 100 1 => 50 0\n                //    final swap amounts: 50 0 => 100 1\n                //    netting swap: net0 = -100 - (-100/2) = -50, ZF1 = true, 50 0 => 100 1\n                // - 100 surplus 0, 100 shortage 1 (itm0 = -100, itm1 = 100)\n                //    normal swap 0: 100 0 => 200 1\n                //    normal swap 1: 50 0 => 100 1\n                //    final swap amounts: 150 0 => 300 1\n                //    netting swap: net0 = -100 - (100/2) = -150, ZF1 = true, 150 0 => 300 1\n                // - 100 shortage 0, 100 surplus 1 (itm0 = 100, itm1 = -100)\n                //    normal swap 0: 200 1 => 100 0\n                //    normal swap 1: 100 1 => 50 0\n                //    final swap amounts: 300 1 => 150 0\n                //    netting swap: net0 = 100 - (-100/2) = 150, ZF1 = false, 300 1 => 150 0\n                // - 100 shortage 0, 100 shortage 1 (itm0 = 100, itm1 = 100)\n                //    normal swap 0: 200 1 => 100 0\n                //    normal swap 1: 50 0 => 100 1\n                //    final swap amounts: 100 1 => 50 0\n                //    netting swap: net0 = 100 - (100/2) = 50, ZF1 = false, 100 1 => 50 0\n                // - = Net surplus of token0\n                // + = Net shortage of token0\n                int256 net0 = itm0 - PanopticMath.convert1to0(itm1, sqrtPriceX96);\n\n                zeroForOne = net0 < 0;\n\n                //compute the swap amount, set as positive (exact input)\n                swapAmount = -net0;\n            } else if (itm0 != 0) {\n                zeroForOne = itm0 < 0;\n                swapAmount = -itm0;\n            } else {\n                zeroForOne = itm1 > 0;\n                swapAmount = -itm1;\n            }\n\n            // note - can occur if itm0 and itm1 have the same value\n            // in that case, swapping would be pointless so skip\n            if (swapAmount == 0) return int256(0);\n\n            // swap tokens in the Uniswap pool\n            // @dev note this triggers our swap callback function\n            (int256 swap0, int256 swap1) = _univ3pool.swap(\n                msg.sender,\n                zeroForOne,\n                swapAmount,\n                zeroForOne\n                    ? Constants.MIN_V3POOL_SQRT_RATIO + 1\n                    : Constants.MAX_V3POOL_SQRT_RATIO - 1,\n                data\n            );\n\n            // Add amounts swapped to totalSwapped variable\n            totalSwapped = int256(0).toRightSlot(swap0.toInt128()).toLeftSlot(swap1.toInt128());\n        }\n    }"
}