creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "src/adapters/query/BalancerVolatilePoolQuery.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// Cowri Labs Inc.\n\npragma solidity ^0.8.19;\n\nimport { IPoolQuery, SpecifiedToken } from \"../../interfaces/IPoolQuery.sol\";\nimport \"../../interfaces/IBalancerQuery.sol\";\nimport \"../BalancerAdapter.sol\";\n\ncontract BalancerVolatilePoolQuery is IPoolQuery {\n    uint8 public constant NORMALIZED_DECIMALS = 18;\n\n    BalancerAdapter immutable adapter;\n    IBalancerQuery immutable poolQuery;\n    IPool immutable pool;\n\n    uint256 public immutable xToken; // weth\n    uint256 public immutable yToken; // reth\n    uint256 public immutable lpTokenId;\n\n    uint256 public immutable numAssets;\n\n    mapping(uint256 => uint8) public decimals;\n\n    mapping(uint256 => uint256) public indexOf;\n\n    constructor(address payable adapter_, address query_) {\n        adapter = BalancerAdapter(adapter_);\n        poolQuery = IBalancerQuery(query_);\n\n        pool = adapter.pool();\n\n        xToken = adapter.xToken();\n        yToken = adapter.yToken();\n        lpTokenId = adapter.lpTokenId();\n\n        decimals[xToken] = adapter.decimals(xToken);\n        decimals[yToken] = adapter.decimals(yToken);\n        decimals[lpTokenId] = adapter.decimals(lpTokenId);\n\n        (IERC20[] memory tokens,,) = IBalancerVault(adapter.primitive()).getPoolTokens(pool.getPoolId());\n        numAssets = tokens.length;\n\n        uint256 bptIndex = pool.getBptIndex();\n        if (bptIndex == 0) {\n            indexOf[xToken] = 1;\n            indexOf[yToken] = 2;\n        } else if (bptIndex == 1) {\n            indexOf[xToken] = 0;\n            indexOf[yToken] = 2;\n        } else {\n            indexOf[xToken] = 0;\n            indexOf[yToken] = 1;\n        }\n    }\n\n    function swapGivenInputAmount(uint256 inputToken, uint256 inputAmount) external view override returns (uint256) { }\n    function depositGivenInputAmount(uint256 depositToken, uint256 depositAmount) external view override returns (uint256) { }\n    function withdrawGivenInputAmount(uint256 withdrawnToken, uint256 burnAmount) external view override returns (uint256) { }\n\n    function swapGivenInputAmount(uint256 xBalance, uint256 yBalance, uint256 inputAmount, SpecifiedToken inputToken) public view returns (uint256 outputAmount) {\n        bool isX = inputToken == SpecifiedToken.X;\n\n        uint256 rawInputAmount = _convertDecimals(NORMALIZED_DECIMALS, decimals[isX ? xToken : yToken], inputAmount);\n\n        uint256 rawXBalance = _convertDecimals(NORMALIZED_DECIMALS, decimals[xToken], xBalance);\n        uint256 rawYBalance = _convertDecimals(NORMALIZED_DECIMALS, decimals[yToken], yBalance);\n\n        (uint256 amplification,,) = pool.getAmplificationParameter();\n\n        uint256[] memory balances = new uint256[](numAssets);\n        balances[indexOf[xToken]] = rawXBalance;\n        balances[indexOf[yToken]] = rawYBalance;\n        balances[pool.getBptIndex()] = 1e18;\n\n        uint256[] memory scalingFactors = pool.getScalingFactors();\n        _upscaleArray(balances, scalingFactors);\n\n        uint256 rawOutputAmount =\n            poolQuery._onRegularSwap(true, mulDown(rawInputAmount, scalingFactors[isX ? indexOf[xToken] : indexOf[yToken]]), balances, isX ? indexOf[xToken] : indexOf[yToken], isX ? indexOf[yToken] : indexOf[xToken], amplification);\n\n        uint256 feeAmount = mulUp(rawOutputAmount, pool.getSwapFeePercentage());\n        rawOutputAmount = rawOutputAmount - feeAmount;\n\n        rawOutputAmount = divDown(rawOutputAmount, scalingFactors[isX ? indexOf[yToken] : indexOf[xToken]]);\n\n        uint256 outputToken = isX ? yToken : xToken;\n\n        outputAmount = _convertDecimals(decimals[outputToken], NORMALIZED_DECIMALS, rawOutputAmount);\n    }\n\n    function depositGivenInputAmount(uint256 xBalance, uint256 yBalance, uint256 totalSupply, uint256 depositAmount, SpecifiedToken depositToken) public view returns (uint256 mintAmount) {\n        bool isX = depositToken == SpecifiedToken.X;\n\n        uint256 rawInputAmount = _convertDecimals(NORMALIZED_DECIMALS, decimals[isX ? xToken : yToken], depositAmount);\n\n        uint256 rawXBalance = _convertDecimals(NORMALIZED_DECIMALS, decimals[xToken], xBalance);\n        uint256 rawYBalance = _convertDecimals(NORMALIZED_DECIMALS, decimals[yToken], yBalance);\n        uint256 rawTotalSupply = _convertDecimals(NORMALIZED_DECIMALS, decimals[lpTokenId], totalSupply);\n\n        (uint256 amplification,,) = pool.getAmplificationParameter();\n\n        uint256[] memory balances = new uint256[](numAssets);\n        balances[indexOf[xToken]] = rawXBalance;\n        balances[indexOf[yToken]] = rawYBalance;\n        balances[pool.getBptIndex()] = totalSupply;\n\n        uint256[] memory scalingFactors = pool.getScalingFactors();\n\n        _upscaleArray(balances, scalingFactors);\n\n        uint256[] memory updatedBalances = new uint256[](numAssets - 1);\n        updatedBalances[0] = balances[indexOf[xToken]];\n        updatedBalances[1] = balances[indexOf[yToken]];\n\n        (uint256 rawOutputAmount,) = poolQuery._joinSwapExactTokenInForBptOut(mulDown(rawInputAmount, scalingFactors[isX ? indexOf[xToken] : indexOf[yToken]]), updatedBalances, isX ? 0 : 1, amplification, rawTotalSupply, 0);\n\n        rawOutputAmount = divDown(rawOutputAmount, scalingFactors[pool.getBptIndex()]);\n\n        mintAmount = _convertDecimals(decimals[lpTokenId], NORMALIZED_DECIMALS, rawOutputAmount);\n    }\n\n    function withdrawGivenInputAmount(uint256 xBalance, uint256 yBalance, uint256 totalSupply, uint256 burnAmount, SpecifiedToken withdrawnToken) public view returns (uint256 withdrawnAmount) {\n        uint256 rawInputAmount = _convertDecimals(NORMALIZED_DECIMALS, decimals[lpTokenId], burnAmount);\n\n        uint256 rawXBalance = _convertDecimals(NORMALIZED_DECIMALS, decimals[xToken], xBalance);\n        uint256 rawYBalance = _convertDecimals(NORMALIZED_DECIMALS, decimals[yToken], yBalance);\n        uint256 rawTotalSupply = _convertDecimals(NORMALIZED_DECIMALS, decimals[lpTokenId], totalSupply);\n\n        uint256 outputToken = withdrawnToken == SpecifiedToken.X ? xToken : yToken;\n\n        uint256 tokenIndex = indexOf[outputToken] == numAssets - 1 ? indexOf[outputToken] - 1 : indexOf[outputToken];\n\n        (uint256 amplification,,) = pool.getAmplificationParameter();\n\n        uint256[] memory balances = new uint256[](numAssets);\n        balances[indexOf[xToken]] = rawXBalance;\n        balances[indexOf[yToken]] = rawYBalance;\n        balances[pool.getBptIndex()] = totalSupply;\n\n        uint256[] memory scalingFactors = pool.getScalingFactors();\n\n        _upscaleArray(balances, scalingFactors);\n\n        uint256[] memory updatedBalances = new uint256[](numAssets - 1);\n        updatedBalances[0] = balances[indexOf[xToken]];\n        updatedBalances[1] = balances[indexOf[yToken]];\n\n        (uint256 rawOutputAmount,) = poolQuery._exitSwapExactBptInForTokenOut(mulDown(rawInputAmount, scalingFactors[pool.getBptIndex()]), updatedBalances, tokenIndex, amplification, rawTotalSupply, 0);\n\n        rawOutputAmount = divDown(rawOutputAmount, scalingFactors[indexOf[outputToken]]);\n\n        withdrawnAmount = _convertDecimals(decimals[outputToken], NORMALIZED_DECIMALS, rawOutputAmount);\n    }\n\n    /**\n     * @dev convert a uint256 from one fixed point decimal basis to another,\n     *   returning the truncated amount if a truncation occurs.\n     * @dev fn(from, to, a) => b\n     * @dev a = (x * 10**from) => b = (x * 10**to), where x is constant.\n     * @param amountToConvert the amount being converted\n     * @param decimalsFrom the fixed decimal basis of amountToConvert\n     * @param decimalsTo the fixed decimal basis of the returned convertedAmount\n     * @return convertedAmount the amount after conversion\n     */\n    function _convertDecimals(uint8 decimalsFrom, uint8 decimalsTo, uint256 amountToConvert) internal pure returns (uint256 convertedAmount) {\n        if (decimalsFrom == decimalsTo) {\n            // no shift\n            convertedAmount = amountToConvert;\n        } else if (decimalsFrom < decimalsTo) {\n            // Decimal shift left (add precision)\n            uint256 shift = 10 ** (uint256(decimalsTo - decimalsFrom));\n            convertedAmount = amountToConvert * shift;\n        } else {\n            // Decimal shift right (remove precision) -> truncation\n            uint256 shift = 10 ** (uint256(decimalsFrom - decimalsTo));\n            convertedAmount = amountToConvert / shift;\n        }\n    }\n\n    function _upscaleArray(uint256[] memory amounts, uint256[] memory scalingFactors) internal pure {\n        for (uint256 i = 0; i < amounts.length; ++i) {\n            amounts[i] = mulDown(amounts[i], scalingFactors[i]);\n        }\n    }\n\n    function mulDown(uint256 a, uint256 b) internal pure returns (uint256) {\n        uint256 product = a * b;\n        require(a == 0 || product / a == b, \"revert\");\n\n        return product / 1e18;\n    }\n\n    function divDown(uint256 a, uint256 b) internal pure returns (uint256) {\n        require(b != 0, \"revert\");\n\n        uint256 aInflated = a * 1e18;\n        require(a == 0 || aInflated / a == 1e18, \"revert\"); // mul overflow\n\n        return aInflated / b;\n    }\n\n    function mulUp(uint256 a, uint256 b) internal pure returns (uint256 result) {\n        uint256 product = a * b;\n        uint256 ONE = 1e18;\n        require(a == 0 || product / a == b, \"revert\");\n\n        // The traditional divUp formula is:\n        // divUp(x, y) := (x + y - 1) / y\n        // To avoid intermediate overflow in the addition, we distribute the division and get:\n        // divUp(x, y) := (x - 1) / y + 1\n        // Note that this requires x != 0, if x == 0 then the result is zero\n        //\n        // Equivalent to:\n        // result = product == 0 ? 0 : ((product - 1) / FixedPoint.ONE) + 1;\n        assembly {\n            result := mul(iszero(iszero(product)), add(div(sub(product, 1), ONE), 1))\n        }\n    }\n}\n"
      },
      "src/interfaces/IPoolQuery.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// Cowri Labs Inc.\n\npragma solidity ^0.8.19;\n\nenum SpecifiedToken {\n    X,\n    Y\n}\n\ninterface IPoolQuery {\n    function swapGivenInputAmount(uint256 inputToken, uint256 inputAmount) external view returns (uint256);\n    function depositGivenInputAmount(uint256 depositToken, uint256 depositAmount) external view returns (uint256);\n    function withdrawGivenInputAmount(uint256 withdrawnToken, uint256 burnAmount) external view returns (uint256);\n}\n"
      },
      "src/interfaces/IBalancerQuery.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// Cowri Labs Inc.\n\npragma solidity ^0.8.19;\n\nimport { IBalancerVault } from \"./IBalancerVault.sol\";\n\ninterface IBalancerQuery {\n    function _onRegularSwap(bool isGivenIn, uint256 amountGiven, uint256[] memory registeredBalances, uint256 registeredIndexIn, uint256 registeredIndexOut, uint256 currentAmp) external view returns (uint256);\n\n    function _joinSwapExactTokenInForBptOut(uint256 amountIn, uint256[] memory balances, uint256 indexIn, uint256 currentAmp, uint256 actualSupply, uint256 preJoinExitInvariant) external view returns (uint256, uint256);\n\n    function _exitSwapExactBptInForTokenOut(uint256 bptAmount, uint256[] memory balances, uint256 indexOut, uint256 currentAmp, uint256 actualSupply, uint256 preJoinExitInvariant) external view returns (uint256, uint256);\n\n    function getAmplificationParameter() external view returns (uint256 value, bool isUpdating, uint256 precision);\n\n    function getScalingFactors() external view returns (uint256[] memory);\n\n    function getBptIndex() external view returns (uint256);\n\n    function getSwapFeePercentage() external view returns (uint256);\n\n    function getActualSupply() external view returns (uint256);\n}\n"
      },
      "src/adapters/BalancerAdapter.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// Cowri Labs Inc.\n\npragma solidity ^0.8.19;\n\nimport { IERC20Metadata } from \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\";\nimport \"./OceanAdapter.sol\";\nimport \"../interfaces/IBalancerVault.sol\";\n\nenum ComputeType {\n    Deposit,\n    Swap,\n    Withdraw\n}\n\n/**\n * @notice\n *   balancer adapter to do swaps/deposits and withdrawals through balancer\n */\ncontract BalancerAdapter is OceanAdapter {\n    /////////////////////////////////////////////////////////////////////\n    //                             Errors                              //\n    /////////////////////////////////////////////////////////////////////\n    error INVALID_COMPUTE_TYPE();\n    error SLIPPAGE_LIMIT_EXCEEDED();\n\n    /////////////////////////////////////////////////////////////////////\n    //                             Events                              //\n    /////////////////////////////////////////////////////////////////////\n    event Swap(uint256 inputToken, uint256 inputAmount, uint256 outputAmount, bytes32 slippageProtection, address user, bool computeOutput);\n    event Deposit(uint256 inputToken, uint256 inputAmount, uint256 outputAmount, bytes32 slippageProtection, address user, bool computeOutput);\n    event Withdraw(uint256 outputToken, uint256 inputAmount, uint256 outputAmount, bytes32 slippageProtection, address user, bool computeOutput);\n\n    /// @notice x token Ocean ID.\n    uint256 public immutable xToken;\n\n    /// @notice y token Ocean ID.\n    uint256 public immutable yToken;\n\n    /// @notice lp token Ocean ID.\n    uint256 public immutable lpTokenId;\n\n    /// @notice pool address\n    IPool public immutable pool;\n\n    /// @notice pool asset list\n    IAsset[] public assets;\n\n    /// @notice map token Ocean IDs to corresponding Curve pool indices\n    mapping(uint256 => uint256) public indexOf;\n\n    //*********************************************************************//\n    // ---------------------------- constructor -------------------------- //\n    //*********************************************************************//\n\n    /**\n     * @notice only initializing the immutables, mappings & approves tokens\n     */\n    constructor(address ocean_, address primitive_, address underlyingTokenX_, address underlyingTokenY_, uint256 tokenXIndex_, uint256 tokenYIndex_, bytes32 poolId_) OceanAdapter(ocean_, primitive_) {\n        address xTokenAddress = underlyingTokenX_;\n        xToken = _calculateOceanId(xTokenAddress, 0);\n        underlying[xToken] = xTokenAddress;\n        indexOf[xToken] = tokenXIndex_;\n        decimals[xToken] = IERC20Metadata(xTokenAddress).decimals();\n        _approveToken(xTokenAddress);\n\n        address yTokenAddress = underlyingTokenY_;\n        yToken = _calculateOceanId(yTokenAddress, 0);\n        indexOf[yToken] = tokenYIndex_;\n        underlying[yToken] = yTokenAddress;\n        decimals[yToken] = IERC20Metadata(yTokenAddress).decimals();\n        _approveToken(yTokenAddress);\n\n        (address _pool,) = IBalancerVault(primitive).getPool(poolId_);\n        pool = IPool(_pool);\n\n        lpTokenId = _calculateOceanId(_pool, 0);\n        underlying[lpTokenId] = _pool;\n        decimals[lpTokenId] = 18;\n        _approveToken(_pool);\n\n        (IERC20[] memory tokens,,) = IBalancerVault(primitive).getPoolTokens(pool.getPoolId());\n        for (uint256 i; i < tokens.length;) {\n            assets.push(IAsset(address(tokens[i])));\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    /**\n     * @dev wraps the underlying token into the Ocean\n     * @param tokenId Ocean ID of token to wrap\n     * @param amount wrap amount\n     */\n    function wrapToken(uint256 tokenId, uint256 amount, bytes32 metadata) internal override {\n        address tokenAddress = underlying[tokenId];\n\n        Interaction memory interaction = Interaction({ interactionTypeAndAddress: _fetchInteractionId(tokenAddress, uint256(InteractionType.WrapErc20)), inputToken: 0, outputToken: 0, specifiedAmount: amount, metadata: bytes32(0) });\n\n        IOceanInteractions(ocean).doInteraction(interaction);\n    }\n\n    /**\n     * @dev unwraps the underlying token from the Ocean\n     * @param tokenId Ocean ID of token to unwrap\n     * @param amount unwrap amount\n     */\n    function unwrapToken(uint256 tokenId, uint256 amount, bytes32 metadata) internal override returns (uint256 unwrappedAmount) {\n        address tokenAddress = underlying[tokenId];\n\n        Interaction memory interaction = Interaction({ interactionTypeAndAddress: _fetchInteractionId(tokenAddress, uint256(InteractionType.UnwrapErc20)), inputToken: 0, outputToken: 0, specifiedAmount: amount, metadata: bytes32(0) });\n\n        IOceanInteractions(ocean).doInteraction(interaction);\n\n        // handle the unwrap fee scenario\n        uint256 unwrapFee = amount / IOceanInteractions(ocean).unwrapFeeDivisor();\n        (, uint256 truncated) = _convertDecimals(NORMALIZED_DECIMALS, decimals[tokenId], amount - unwrapFee);\n        unwrapFee = unwrapFee + truncated;\n\n        unwrappedAmount = amount - unwrapFee;\n    }\n\n    /**\n     * @dev swaps/add liquidity/remove liquidity from Curve 2pool\n     * @param inputToken The user is giving this token to the pool\n     * @param outputToken The pool is giving this token to the user\n     * @param inputAmount The amount of the inputToken the user is giving to the pool\n     * @param minimumOutputAmount The minimum amount of tokens expected back after the exchange\n     */\n    function primitiveOutputAmount(uint256 inputToken, uint256 outputToken, uint256 inputAmount, bytes32 minimumOutputAmount) internal override returns (uint256 outputAmount) {\n        (uint256 rawInputAmount,) = _convertDecimals(NORMALIZED_DECIMALS, decimals[inputToken], inputAmount);\n\n        ComputeType action = _determineComputeType(inputToken, outputToken);\n\n        uint256 rawOutputAmount;\n\n        // avoid multiple SLOADS\n        uint256 indexOfInputAmount = indexOf[inputToken];\n        uint256 indexOfOutputAmount = indexOf[outputToken];\n        uint256 assetLength = assets.length;\n\n        if (action == ComputeType.Swap) {\n            IBalancerVault.SingleSwap memory singleSwap = IBalancerVault.SingleSwap({\n                poolId: pool.getPoolId(),\n                kind: IBalancerVault.SwapKind.GIVEN_IN,\n                assetIn: IAsset(underlying[inputToken]),\n                assetOut: IAsset(underlying[outputToken]),\n                amount: rawInputAmount,\n                userData: new bytes(0)\n            });\n\n            IBalancerVault.FundManagement memory fundManagement = IBalancerVault.FundManagement({ sender: payable(address(this)), fromInternalBalance: false, recipient: payable(address(this)), toInternalBalance: false });\n            rawOutputAmount = IBalancerVault(primitive).swap(singleSwap, fundManagement, uint256(minimumOutputAmount), block.timestamp + 300);\n        } else if (action == ComputeType.Deposit) {\n            uint256[] memory amounts = new uint256[](assetLength);\n            amounts[indexOfInputAmount] = rawInputAmount;\n\n            uint256[] memory amountsWithoutBpt = new uint256[](amounts.length - 1);\n            for (uint256 i; i < amountsWithoutBpt.length;) {\n                amountsWithoutBpt[i] = amounts[i < pool.getBptIndex() ? i : i + 1];\n                unchecked {\n                    ++i;\n                }\n            }\n\n            IBalancerVault.JoinPoolRequest memory joinPool = IBalancerVault.JoinPoolRequest({ assets: assets, maxAmountsIn: amounts, userData: abi.encode(1, amountsWithoutBpt, uint256(minimumOutputAmount)), fromInternalBalance: false });\n\n            uint256 bptBalanceBeforeDeposit = IERC20Metadata(address(pool)).balanceOf(address(this));\n            IBalancerVault(primitive).joinPool(pool.getPoolId(), address(this), address(this), joinPool);\n            rawOutputAmount = IERC20Metadata(address(pool)).balanceOf(address(this)) - bptBalanceBeforeDeposit;\n        } else {\n            uint256[] memory amounts = new uint256[](assetLength);\n            amounts[indexOfOutputAmount] = uint256(minimumOutputAmount);\n\n            IBalancerVault.ExitPoolRequest memory exitPool = IBalancerVault.ExitPoolRequest({\n                assets: assets,\n                minAmountsOut: amounts,\n                userData: abi.encode(0, rawInputAmount, indexOfOutputAmount < pool.getBptIndex() ? indexOfOutputAmount : indexOfOutputAmount - 1),\n                toInternalBalance: false\n            });\n            address outputTokenAddress = underlying[outputToken];\n            uint256 outputTokenBalanceBeforeWithdraw = IERC20Metadata(outputTokenAddress).balanceOf(address(this));\n\n            IBalancerVault(primitive).exitPool(pool.getPoolId(), address(this), payable(address(this)), exitPool);\n            rawOutputAmount = IERC20Metadata(outputTokenAddress).balanceOf(address(this)) - outputTokenBalanceBeforeWithdraw;\n        }\n\n        (outputAmount,) = _convertDecimals(decimals[outputToken], NORMALIZED_DECIMALS, rawOutputAmount);\n\n        if (uint256(minimumOutputAmount) > outputAmount) revert SLIPPAGE_LIMIT_EXCEEDED();\n\n        if (action == ComputeType.Swap) {\n            emit Swap(inputToken, inputAmount, outputAmount, minimumOutputAmount, primitive, true);\n        } else if (action == ComputeType.Deposit) {\n            emit Deposit(inputToken, inputAmount, outputAmount, minimumOutputAmount, primitive, true);\n        } else {\n            emit Withdraw(outputToken, inputAmount, outputAmount, minimumOutputAmount, primitive, true);\n        }\n    }\n\n    /**\n     * @dev Approves token to be spent by the Ocean and the Curve pool\n     */\n    function _approveToken(address tokenAddress) private {\n        IERC20Metadata(tokenAddress).approve(ocean, type(uint256).max);\n        IERC20Metadata(tokenAddress).approve(primitive, type(uint256).max);\n    }\n\n    /**\n     * @dev Uses the inputToken and outputToken to determine the ComputeType\n     *  (input: xToken, output: yToken) | (input: yToken, output: xToken) => SWAP\n     *  base := xToken | yToken\n     *  (input: base, output: lpToken) => DEPOSIT\n     *  (input: lpToken, output: base) => WITHDRAW\n     */\n    function _determineComputeType(uint256 inputToken, uint256 outputToken) private view returns (ComputeType computeType) {\n        if (((inputToken == xToken) && (outputToken == yToken)) || ((inputToken == yToken) && (outputToken == xToken))) {\n            return ComputeType.Swap;\n        } else if (((inputToken == xToken) || (inputToken == yToken)) && (outputToken == lpTokenId)) {\n            return ComputeType.Deposit;\n        } else if ((inputToken == lpTokenId) && ((outputToken == xToken) || (outputToken == yToken))) {\n            return ComputeType.Withdraw;\n        } else {\n            revert INVALID_COMPUTE_TYPE();\n        }\n    }\n\n    receive() external payable { }\n}\n"
      },
      "src/interfaces/IBalancerVault.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// Cowri Labs Inc.\n\npragma solidity ^0.8.19;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\ninterface IAsset {\n// solhint-disable-previous-line no-empty-blocks\n}\n\ninterface IBalancerQueries {\n    function queryExit(bytes32 poolId, address sender, address recipient, IBalancerVault.ExitPoolRequest memory request) external returns (uint256 bptIn, uint256[] memory amountsOut);\n}\n\ninterface IPool {\n    function getBptIndex() external view returns (uint256);\n\n    function getPoolId() external view returns (bytes32);\n\n    function getAmplificationParameter() external view returns (uint256, bool, uint256);\n\n    function getScalingFactors() external view returns (uint256[] memory);\n\n    function getSwapFeePercentage() external view returns (uint256);\n}\n\ninterface IBalancerVault {\n    enum SwapKind {\n        GIVEN_IN,\n        GIVEN_OUT\n    }\n\n    enum PoolSpecialization {\n        GENERAL,\n        MINIMAL_SWAP_INFO,\n        TWO_TOKEN\n    }\n\n    function getPoolTokens(bytes32 poolId) external view returns (IERC20[] memory tokens, uint256[] memory balances, uint256 lastChangeBlock);\n\n    function getPool(bytes32 poolId) external view returns (address, PoolSpecialization);\n\n    function joinPool(bytes32 poolId, address sender, address recipient, JoinPoolRequest memory request) external payable;\n\n    struct JoinPoolRequest {\n        IAsset[] assets;\n        uint256[] maxAmountsIn;\n        bytes userData;\n        bool fromInternalBalance;\n    }\n\n    function exitPool(bytes32 poolId, address sender, address payable recipient, ExitPoolRequest memory request) external;\n\n    struct ExitPoolRequest {\n        IAsset[] assets;\n        uint256[] minAmountsOut;\n        bytes userData;\n        bool toInternalBalance;\n    }\n\n    function swap(SingleSwap memory singleSwap, FundManagement memory funds, uint256 limit, uint256 deadline) external payable returns (uint256);\n\n    struct SingleSwap {\n        bytes32 poolId;\n        SwapKind kind;\n        IAsset assetIn;\n        IAsset assetOut;\n        uint256 amount;\n        bytes userData;\n    }\n\n    struct FundManagement {\n        address sender;\n        bool fromInternalBalance;\n        address payable recipient;\n        bool toInternalBalance;\n    }\n}\n"
      },
      "node_modules/@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n *\n * _Available since v4.1._\n */\ninterface IERC20Metadata is IERC20 {\n    /**\n     * @dev Returns the name of the token.\n     */\n    function name() external view returns (string memory);\n\n    /**\n     * @dev Returns the symbol of the token.\n     */\n    function symbol() external view returns (string memory);\n\n    /**\n     * @dev Returns the decimals places of the token.\n     */\n    function decimals() external view returns (uint8);\n}\n"
      },
      "src/adapters/OceanAdapter.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// Cowri Labs Inc.\n\npragma solidity ^0.8.19;\n\nimport \"../interfaces/IOceanPrimitive.sol\";\nimport \"../interfaces/Interactions.sol\";\n\n/**\n * @notice\n *   Helper contract for shell adapters\n */\nabstract contract OceanAdapter is IOceanPrimitive {\n    /// @notice normalized decimals to be compatible with the Ocean.\n    uint8 constant NORMALIZED_DECIMALS = 18;\n\n    /// @notice Ocean address.\n    address public immutable ocean;\n\n    /// @notice external primitive address.\n    address public immutable primitive;\n\n    /// @notice The underlying token address corresponding to the Ocean ID.\n    mapping(uint256 => address) public underlying;\n\n    /// @notice The underlying token decimals wrt to the Ocean ID\n    mapping(uint256 => uint8) public decimals;\n\n    //*********************************************************************//\n    // ---------------------------- constructor -------------------------- //\n    //*********************************************************************//\n\n    /// @notice only initializing the immutables\n    constructor(address ocean_, address primitive_) {\n        ocean = ocean_;\n        primitive = primitive_;\n    }\n\n    /// @notice only allow the Ocean to call a method\n    modifier onlyOcean() {\n        require(msg.sender == ocean);\n        _;\n    }\n\n    /**\n     * @dev The Ocean must always know the input and output tokens in order to\n     *  do the accounting.  One of the token amounts is chosen by the user, and\n     *  the other amount is chosen by the primitive.  When computeOutputAmount is\n     *  called, the user provides the inputAmount, and the primitive uses this to\n     *  compute the outputAmount\n     * @param inputToken The user is giving this token to the primitive\n     * @param outputToken The primitive is giving this token to the user\n     * @param inputAmount The amount of the inputToken the user is giving to the primitive\n     * @param metadata a bytes32 value that the user provides the Ocean\n     * @dev the unused param is an address field called userAddress\n     */\n    function computeOutputAmount(uint256 inputToken, uint256 outputToken, uint256 inputAmount, address, bytes32 metadata) external override onlyOcean returns (uint256 outputAmount) {\n        uint256 unwrappedAmount = unwrapToken(inputToken, inputAmount, metadata);\n\n        outputAmount = primitiveOutputAmount(inputToken, outputToken, unwrappedAmount, metadata);\n\n        wrapToken(outputToken, outputAmount, metadata);\n    }\n\n    /**\n     * @notice Not implemented for this primitive\n     */\n    function computeInputAmount(uint256 inputToken, uint256 outputToken, uint256 outputAmount, address userAddress, bytes32 maximumInputAmount) external override onlyOcean returns (uint256 inputAmount) {\n        revert();\n    }\n\n    /**\n     * @notice used to fetch the Ocean interaction ID\n     */\n    function _fetchInteractionId(address token, uint256 interactionType) internal pure returns (bytes32) {\n        uint256 packedValue = uint256(uint160(token));\n        packedValue |= interactionType << 248;\n        return bytes32(abi.encode(packedValue));\n    }\n\n    /**\n     * @notice calculates Ocean ID for a underlying token\n     */\n    function _calculateOceanId(address tokenAddress, uint256 tokenId) internal pure returns (uint256) {\n        return uint256(keccak256(abi.encodePacked(tokenAddress, tokenId)));\n    }\n\n    /**\n     * @dev Handles the receipt of a single ERC1155 token type. This function is\n     * called at the end of a `safeTransferFrom` after the balance has been updated.\n     * @return `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))` if transfer is allowed\n     */\n    function onERC1155Received(address, address, uint256, uint256, bytes memory) public pure returns (bytes4) {\n        return this.onERC1155Received.selector;\n    }\n\n    function onERC721Received(address, address, uint256, bytes calldata) public pure returns (bytes4) {\n        return this.onERC721Received.selector;\n    }\n\n    /**\n     * @notice returning 0 here since this primitive should not have any tokens\n     */\n    function getTokenSupply(uint256 tokenId) external view virtual override returns (uint256) {\n        return 0;\n    }\n\n    /**\n     * @dev convert a uint256 from one fixed point decimal basis to another,\n     *   returning the truncated amount if a truncation occurs.\n     * @dev fn(from, to, a) => b\n     * @dev a = (x * 10**from) => b = (x * 10**to), where x is constant.\n     * @param amountToConvert the amount being converted\n     * @param decimalsFrom the fixed decimal basis of amountToConvert\n     * @param decimalsTo the fixed decimal basis of the returned convertedAmount\n     * @return convertedAmount the amount after conversion\n     * @return truncatedAmount if (from > to), there may be some truncation, it\n     *  is up to the caller to decide what to do with the truncated amount.\n     */\n    function _convertDecimals(uint8 decimalsFrom, uint8 decimalsTo, uint256 amountToConvert) internal pure returns (uint256 convertedAmount, uint256 truncatedAmount) {\n        if (decimalsFrom == decimalsTo) {\n            // no shift\n            convertedAmount = amountToConvert;\n            truncatedAmount = 0;\n        } else if (decimalsFrom < decimalsTo) {\n            // Decimal shift left (add precision)\n            uint256 shift = 10 ** (uint256(decimalsTo - decimalsFrom));\n            convertedAmount = amountToConvert * shift;\n            truncatedAmount = 0;\n        } else {\n            // Decimal shift right (remove precision) -> truncation\n            uint256 shift = 10 ** (uint256(decimalsFrom - decimalsTo));\n            convertedAmount = amountToConvert / shift;\n            truncatedAmount = amountToConvert % shift;\n        }\n    }\n\n    function primitiveOutputAmount(uint256 inputToken, uint256 outputToken, uint256 inputAmount, bytes32 metadata) internal virtual returns (uint256 outputAmount);\n\n    function wrapToken(uint256 tokenId, uint256 amount, bytes32 metadata) internal virtual;\n\n    function unwrapToken(uint256 tokenId, uint256 amount, bytes32 metadata) internal virtual returns (uint256 unwrappedAmount);\n}\n"
      },
      "node_modules/@openzeppelin/contracts/token/ERC20/IERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n    /**\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\n     * another (`to`).\n     *\n     * Note that `value` may be zero.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 value);\n\n    /**\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n     * a call to {approve}. `value` is the new allowance.\n     */\n    event Approval(address indexed owner, address indexed spender, uint256 value);\n\n    /**\n     * @dev Returns the amount of tokens in existence.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns the amount of tokens owned by `account`.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /**\n     * @dev Moves `amount` tokens from the caller's account to `to`.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transfer(address to, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Returns the remaining number of tokens that `spender` will be\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\n     * zero by default.\n     *\n     * This value changes when {approve} or {transferFrom} are called.\n     */\n    function allowance(address owner, address spender) external view returns (uint256);\n\n    /**\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\n     * that someone may use both the old and the new allowance by unfortunate\n     * transaction ordering. One possible solution to mitigate this race\n     * condition is to first reduce the spender's allowance to 0 and set the\n     * desired value afterwards:\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address spender, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Moves `amount` tokens from `from` to `to` using the\n     * allowance mechanism. `amount` is then deducted from the caller's\n     * allowance.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(address from, address to, uint256 amount) external returns (bool);\n}\n"
      },
      "src/interfaces/IOceanPrimitive.sol": {
        "content": "// SPDX-License-Identifier: unlicensed\n// Cowri Labs Inc.\n\npragma solidity ^0.8.19;\n\n/// @notice Implementing this allows a primitive to be called by the Ocean's\n///  defi framework.\ninterface IOceanPrimitive {\n    function computeOutputAmount(uint256 inputToken, uint256 outputToken, uint256 inputAmount, address userAddress, bytes32 metadata) external returns (uint256 outputAmount);\n\n    function computeInputAmount(uint256 inputToken, uint256 outputToken, uint256 outputAmount, address userAddress, bytes32 metadata) external returns (uint256 inputAmount);\n\n    function getTokenSupply(uint256 tokenId) external view returns (uint256 totalSupply);\n}\n"
      },
      "src/interfaces/Interactions.sol": {
        "content": "// SPDX-License-Identifier: unlicensed\n// Cowri Labs Inc.\n\npragma solidity ^0.8.19;\n\n/**\n * @param interactionTypeAndAddress the type of interaction and the external\n *  contract called during this interaction.\n * @param inputToken this field is ignored except when the interaction type\n *  begins with \"Compute\".  During a \"Compute\" interaction, this token is given\n *  to the external contract.\n * @param outputToken this field is ignored except when the interaction type\n *  begins with \"Compute\".  During a \"Compute\" interaction, this token is\n *  received from the external contract.\n * @param specifiedAmount This value is the amount of the specified token.\n *  See the comment above the declaration for InteractionType for information\n *  on specified tokens.  When this value is equal to type(uint256).max, it is\n *  a request by the user to use the intra-transaction delta of the specified\n *  token as the specified amount.  See LibBalanceDelta for more information\n *  about this.  When the Ocean executes an interaction, it resolves the\n *  specifiedAmount before calling the external contract.  During a \"721\"\n *  interaction, the resolved specifiedAmount must be identically \"1\".\n * @param metadata This value is used in two ways.  During \"Compute\"\n *  interactions, it is forwarded to the external contract.  The external\n *  contract can define whatever expectations it wants for these 32 bytes.  The\n *  caller is expected to be aware of the expectations of the external contract\n *  invoked during the interaction.  During 721/1155 and wraps and unwraps,\n *  these bytes are cast to uint256 and used as the external ledger's token ID\n *  for the interaction.\n */\nstruct Interaction {\n    bytes32 interactionTypeAndAddress;\n    uint256 inputToken;\n    uint256 outputToken;\n    uint256 specifiedAmount;\n    bytes32 metadata;\n}\n\n/**\n * InteractionType determines how the properties of Interaction are interpreted\n *\n * The interface implemented by the external contract, the specified token\n *  for the interaction, and what sign (+/-) of delta can be used are\n *  determined by the InteractionType.\n *\n * @param WrapErc20\n *      type(externalContract).interfaceId == IERC20\n *      specifiedToken == calculateOceanId(externalContract, 0)\n *      negative delta can be used as specifiedAmount\n *\n * @param UnwrapErc20\n *      type(externalContract).interfaceId == IERC20\n *      specifiedToken == calculateOceanId(externalContract, 0)\n *      positive delta can be used as specifiedAmount\n *\n * @param WrapErc721\n *      type(externalContract).interfaceId == IERC721\n *      specifiedToken == calculateOceanId(externalContract, metadata)\n *      negative delta can be used as specifiedAmount\n *\n * @param UnwrapErc721\n *      type(externalContract).interfaceId == IERC721\n *      specifiedToken == calculateOceanId(externalContract, metadata)\n *      positive delta can be used as specifiedAmount\n *\n * @param WrapErc1155\n *      type(externalContract).interfaceId == IERC1155\n *      specifiedToken == calculateOceanId(externalContract, metadata)\n *      negative delta can be used as specifiedAmount\n *\n * @param WrapErc1155\n *      type(externalContract).interfaceId == IERC1155\n *      specifiedToken == calculateOceanId(externalContract, metadata)\n *      positive delta can be used as specifiedAmount\n *\n * @param ComputeInputAmount\n *      type(externalContract).interfaceId == IOceanexternalContract\n *      specifiedToken == outputToken\n *      negative delta can be used as specifiedAmount\n *\n * @param ComputeOutputAmount\n *      type(externalContract).interfaceId == IOceanexternalContract\n *      specifiedToken == inputToken\n *      positive delta can be used as specifiedAmount\n */\nenum InteractionType {\n    WrapErc20,\n    UnwrapErc20,\n    WrapErc721,\n    UnwrapErc721,\n    WrapErc1155,\n    UnwrapErc1155,\n    ComputeInputAmount,\n    ComputeOutputAmount,\n    UnwrapEther\n}\n\ninterface IOceanInteractions {\n    function unwrapFeeDivisor() external view returns (uint256);\n\n    function doMultipleInteractions(Interaction[] calldata interactions, uint256[] calldata ids) external payable returns (uint256[] memory burnIds, uint256[] memory burnAmounts, uint256[] memory mintIds, uint256[] memory mintAmounts);\n\n    function forwardedDoMultipleInteractions(\n        Interaction[] calldata interactions,\n        uint256[] calldata ids,\n        address userAddress\n    )\n        external\n        payable\n        returns (uint256[] memory burnIds, uint256[] memory burnAmounts, uint256[] memory mintIds, uint256[] memory mintAmounts);\n\n    function doInteraction(Interaction calldata interaction) external payable returns (uint256 burnId, uint256 burnAmount, uint256 mintId, uint256 mintAmount);\n\n    function forwardedDoInteraction(Interaction calldata interaction, address userAddress) external payable returns (uint256 burnId, uint256 burnAmount, uint256 mintId, uint256 mintAmount);\n}\n"
      }
    },
    "settings": {
      "remappings": [
        "@prb/test/=lib/prb-test/src/",
        "forge-std/=lib/forge-std/src/",
        "@sablier/v2-core/=lib/v2-core/",
        "balancer-v2-monorepo/=lib/balancer-v2-monorepo/",
        "src/=src/",
        "@openzeppelin/=node_modules/@openzeppelin/",
        "@shell-v2-ocean/=node_modules/shell-v2-ocean/",
        "abdk-libraries-solidity/=node_modules/abdk-libraries-solidity/",
        "@balancer-labs/=lib/balancer-v2-monorepo/../../node_modules/@balancer-labs/",
        "ds-test/=lib/forge-std/lib/ds-test/src/",
        "prb-math/=lib/prb-math/src/",
        "prb-test/=lib/prb-test/src/"
      ],
      "optimizer": {
        "enabled": true,
        "runs": 10000
      },
      "metadata": {
        "useLiteralContent": false,
        "bytecodeHash": "none",
        "appendCBOR": false
      },
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "evmVersion": "paris",
      "viaIR": true,
      "libraries": {}
    }
  }}