creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "@gammaswap/create-gammapool/contracts/interfaces/IDeltaSwapFactory9.sol": {
        "content": "// SPDX-License-Identifier: GPL-v3\npragma solidity 0.8.21;\n\ninterface IDeltaSwapFactory9 {\n    function getPair(address, address) external returns (address);\n\n    function createPair(address tokenA, address tokenB) external returns (address);\n}"
      },
      "@gammaswap/create-gammapool/contracts/interfaces/IGammaPoolFactory9.sol": {
        "content": "// SPDX-License-Identifier: GPL-v3\npragma solidity 0.8.21;\n\ninterface IGammaPoolFactory9 {\n    function getProtocol(uint16 _protocolId) external view returns (address);\n    function isProtocolRestricted(uint16 _protocolId) external view returns(bool);\n    function createPool(uint16 _protocolId, address _cfmm, address[] calldata _tokens, bytes calldata _data) external returns(address);\n}"
      },
      "@gammaswap/create-gammapool/contracts/interfaces/IPoolZapper.sol": {
        "content": "// SPDX-License-Identifier: GPL-v3\npragma solidity ^0.8.0;\n\n/// @title Interface for Zapper contract to create DS/GS pools\n/// @author Daniel D. Alcarraz (https://github.com/0xDanr)\ninterface IPoolZapper {\n\n    /// @notice Create GammaPool from DeltaSwap pool\n    /// @notice If token pair not found in DS, new DS pair will be created\n    /// @dev Needs tokens approval from user to position manager to add liquidity\n    /// @param token0 Token0 address\n    /// @param token1 Token1 address\n    /// @param amount0 (Optional) Token0 amount to add liquidity\n    /// @param amount1 (Optional) Token1 amount to add liquidity\n    /// @param protocolId GammaPool protocolId\n    /// @param cfmm address of cfmm (if not DeltaSwap)\n    /// @return New GammaPool address\n    function createAndAddLiquidity(address token0, address token1, uint256 amount0, uint256 amount1, uint16 protocolId, address cfmm) external returns (address);\n\n}\n"
      },
      "@gammaswap/create-gammapool/contracts/interfaces/IPositionManager9.sol": {
        "content": "// SPDX-License-Identifier: GPL-v3\npragma solidity 0.8.21;\n\ninterface IPositionManager9 {\n\tstruct DepositReservesParams {\n        uint16 protocolId;\n        address cfmm;\n        address to;\n        uint256 deadline;\n        uint256[] amountsDesired;\n        uint256[] amountsMin;\n    }\n\n\tfunction depositReserves(DepositReservesParams calldata params) external returns (uint256[] memory reserves, uint256 shares);\n}"
      },
      "@gammaswap/create-gammapool/contracts/interfaces/ITransferToken.sol": {
        "content": "// SPDX-License-Identifier: GPL-v3\npragma solidity ^0.8.0;\n\ninterface ITransferToken {\n    function approve(address spender, uint256 amount) external returns (bool);\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\n}\n"
      },
      "@gammaswap/create-gammapool/contracts/PoolZapper.sol": {
        "content": "// SPDX-License-Identifier: GPL-v3\npragma solidity 0.8.21;\n\nimport \"./interfaces/IGammaPoolFactory9.sol\";\nimport \"./interfaces/IDeltaSwapFactory9.sol\";\nimport \"./interfaces/IPositionManager9.sol\";\nimport \"./interfaces/ITransferToken.sol\";\nimport \"./interfaces/IPoolZapper.sol\";\n\n/// @title Zapper contract to create DS/GS pools\n/// @author Simon Mall\ncontract PoolZapper is IPoolZapper {\n    /// @notice GammaPool factory\n    address public gsFactory;\n    /// @notice DeltaSwap factory\n    address public dsFactory;\n    /// @notice DeltaSwapV2 factory\n    address public dsV2Factory;\n    /// @notice UniswapV2 factory\n    address public uniV2Factory;\n    /// @notice Sushiswap factory\n    address public sushiFactory;\n    /// @notice GammaSwap position manager\n    address public positionManager;\n\n    constructor(address _gsFactory, address _dsFactory, address _dsv2Factory, address _univ2Factory, address _sushiFactory, address _positionManager) {\n        gsFactory = _gsFactory;\n        dsFactory = _dsFactory;\n        dsV2Factory = _dsv2Factory;\n        uniV2Factory = _univ2Factory;\n        sushiFactory = _sushiFactory;\n        positionManager = _positionManager;\n    }\n\n    function getOrCreatePool(address factory, address token0, address token1) internal virtual returns(address) {\n        address cfmm;\n        if(factory!=address(0)) {\n            cfmm = IDeltaSwapFactory9(factory).getPair(token0, token1);\n            if (cfmm == address(0)) {\n                cfmm = IDeltaSwapFactory9(factory).createPair(token0, token1);\n            }\n        }\n        return cfmm;\n    }\n\n    /// @dev See {IPoolZapper-createAndAddLiquidity}.\n    function createAndAddLiquidity(address token0, address token1, uint256 amount0, uint256 amount1, uint16 protocolId, address cfmm) external override virtual returns (address) {\n        require(token0 != address(0), \"MISSING_TOKEN0\");\n        require(token1 != address(0), \"MISSING_TOKEN1\");\n\n        require(IGammaPoolFactory9(gsFactory).getProtocol(protocolId) != address(0), \"PROTOCOL_NOT_SET\");\n        require(!IGammaPoolFactory9(gsFactory).isProtocolRestricted(protocolId), \"PROTOCOL_RESTRICTED\");\n\n        if(cfmm == address(0)) {\n            if(protocolId == 1) {\n                cfmm = getOrCreatePool(uniV2Factory, token0, token1);\n            } else if(protocolId == 2) {\n                cfmm = getOrCreatePool(sushiFactory, token0, token1);\n            } else if(protocolId == 3) {\n                cfmm = getOrCreatePool(dsFactory, token0, token1);\n            } else if(protocolId == 4) {\n                cfmm = getOrCreatePool(dsV2Factory, token0, token1);\n            }\n        }\n\n        require(cfmm != address(0), \"MISSING_CFMM\");\n\n        address[] memory tokens = new address[](2);\n        tokens[0] = token0;\n        tokens[1] = token1;\n\n        address gammaPool = IGammaPoolFactory9(gsFactory).createPool(protocolId, cfmm, tokens, \"\");\n\n        // Add liquidity if tokens are provided to set pricing\n        if (amount0 > 0 && amount1 > 0) {\n            ITransferToken(token0).transferFrom(msg.sender, address(this), amount0);\n            ITransferToken(token1).transferFrom(msg.sender, address(this), amount1);\n            ITransferToken(token0).approve(positionManager, amount0);\n            ITransferToken(token1).approve(positionManager, amount1);\n\n            uint256[] memory amounts = new uint256[](2);\n            amounts[0] = token0 < token1 ? amount0 : amount1;\n            amounts[1] = token0 < token1 ? amount1 : amount0;\n            uint256[] memory amountsMin = new uint256[](2);\n            amountsMin[0] = amounts[0] * 99 / 100;\n            amountsMin[1] = amounts[1] * 99 / 100;\n            IPositionManager9.DepositReservesParams memory depositParams = IPositionManager9.DepositReservesParams({\n                protocolId: protocolId,\n                cfmm: cfmm,\n                to: msg.sender,\n                deadline: type(uint256).max,\n                amountsDesired: amounts,\n                amountsMin: amountsMin\n            });\n            (, uint256 shares) = IPositionManager9(positionManager).depositReserves(depositParams);\n\n            require(shares > 0, \"Something went wrong\");\n        }\n\n        return gammaPool;\n    }\n}"
      }
    },
    "settings": {
      "optimizer": {
        "enabled": true,
        "runs": 200
      },
      "evmVersion": "paris",
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "metadata": {
        "useLiteralContent": true
      },
      "remappings": [
        "ds-test/=lib/forge-std/lib/ds-test/src/",
        "forge-std/=lib/forge-std/src/"
      ],
      "libraries": {}
    }
  }}