creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "@gammaswap/v1-core/contracts/base/GammaPool.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity >=0.8.13;\n\nimport \"../libraries/GammaSwapLibrary.sol\";\nimport \"../interfaces/IGammaPool.sol\";\nimport \"../interfaces/IGammaPoolFactory.sol\";\nimport \"../interfaces/strategies/lending/IBorrowStrategy.sol\";\nimport \"../interfaces/strategies/lending/IRepayStrategy.sol\";\nimport \"../interfaces/strategies/rebalance/IRebalanceStrategy.sol\";\nimport \"../interfaces/strategies/base/ILongStrategy.sol\";\nimport \"../interfaces/strategies/base/ILiquidationStrategy.sol\";\nimport \"../interfaces/strategies/liquidation/ISingleLiquidationStrategy.sol\";\nimport \"../interfaces/strategies/liquidation/IBatchLiquidationStrategy.sol\";\nimport \"../interfaces/IPoolViewer.sol\";\nimport \"./GammaPoolERC4626.sol\";\n\n/// @title Basic GammaPool smart contract\n/// @author Daniel D. Alcarraz (https://github.com/0xDanr)\n/// @dev Used as template for building other GammaPool contract implementations for other CFMMs\nabstract contract GammaPool is IGammaPool, GammaPoolERC4626 {\n\n    using LibStorage for LibStorage.Storage;\n\n    error Forbidden();\n    error ZeroFeeDivisor();\n    error LiquidationFeeGtLTVThreshold();\n    error InvalidMinBorrow();\n\n    /// @dev See {IGammaPool-protocolId}\n    uint16 immutable public override protocolId;\n\n    /// @dev See {IGammaPool-factory}\n    address immutable public override factory;\n\n    /// @dev See {IGammaPool-borrowStrategy}\n    address immutable public override borrowStrategy;\n\n    /// @dev See {IGammaPool-repayStrategy}\n    address immutable public override repayStrategy;\n\n    /// @dev See {IGammaPool-rebalanceStrategy}\n    address immutable public override rebalanceStrategy;\n\n    /// @dev See {IGammaPool-shortStrategy}\n    address immutable public override shortStrategy;\n\n    /// @dev See {IGammaPool-singleLiquidationStrategy}\n    address immutable public override singleLiquidationStrategy;\n\n    /// @dev See {IGammaPool-batchLiquidationStrategy}\n    address immutable public override batchLiquidationStrategy;\n\n    /// @dev See {IGammaPool-viewer}\n    address immutable public override viewer;\n\n    /// @dev Initializes the contract by setting `protocolId`, `factory`, `borrowStrategy`, `repayStrategy`, `rebalanceStrategy`,\n    /// @dev shortStrategy`, `singleLiquidationStrategy`, `batchLiquidationStrategy`, and `viewer`.\n    constructor(uint16 protocolId_, address factory_,  address borrowStrategy_, address repayStrategy_, address rebalanceStrategy_,\n        address shortStrategy_, address singleLiquidationStrategy_, address batchLiquidationStrategy_, address viewer_) {\n        protocolId = protocolId_;\n        factory = factory_;\n        borrowStrategy = borrowStrategy_;\n        repayStrategy = repayStrategy_;\n        rebalanceStrategy = rebalanceStrategy_;\n        shortStrategy = shortStrategy_;\n        singleLiquidationStrategy = singleLiquidationStrategy_;\n        batchLiquidationStrategy = batchLiquidationStrategy_;\n        viewer = viewer_;\n    }\n\n    /// @dev See {IGammaPool-initialize}\n    function initialize(address _cfmm, address[] calldata _tokens, uint8[] calldata _decimals, uint72 _minBorrow, bytes calldata) external virtual override {\n        if(msg.sender != factory) revert Forbidden(); // only factory is allowed to initialize\n        s.initialize(factory, _cfmm, protocolId, _tokens, _decimals, _minBorrow);\n    }\n\n    /// @dev See {IGammaPool-setPoolParams}\n    function setPoolParams(uint16 origFee, uint8 extSwapFee, uint8 emaMultiplier, uint8 minUtilRate1, uint8 minUtilRate2, uint16 feeDivisor, uint8 liquidationFee, uint8 ltvThreshold, uint72 minBorrow) external virtual override {\n        if(msg.sender != factory) revert Forbidden(); // only factory is allowed to update dynamic fee parameters\n\n        if(feeDivisor == 0) revert ZeroFeeDivisor();\n        if(liquidationFee > uint256(ltvThreshold) * 10) revert LiquidationFeeGtLTVThreshold();\n        if(minBorrow < 1e3) revert InvalidMinBorrow();\n\n        s.ltvThreshold = ltvThreshold;\n        s.liquidationFee = liquidationFee;\n        s.origFee = origFee;\n        s.extSwapFee = extSwapFee;\n        s.emaMultiplier = emaMultiplier;\n        s.minUtilRate1 = minUtilRate1;\n        s.minUtilRate2 = minUtilRate2;\n        s.feeDivisor = feeDivisor;\n        s.minBorrow = minBorrow;\n    }\n\n    /// @dev See {IGammaPool-cfmm}\n    function cfmm() external virtual override view returns(address) {\n        return s.cfmm;\n    }\n\n    /// @dev See {IGammaPool-tokens}\n    function tokens() external virtual override view returns(address[] memory) {\n        return s.tokens;\n    }\n\n    /// @dev See {IGammaPool-vaultImplementation}\n    function vaultImplementation() internal virtual override view returns(address) {\n        return shortStrategy;\n    }\n\n    /// @dev See {IRateModel-validateParameters}\n    function validateParameters(bytes calldata _data) external view returns(bool) {\n        return IRateModel(borrowStrategy).validateParameters(_data);\n    }\n\n    /// @dev See {IRateModel-rateParamsStore}\n    function rateParamsStore() external view returns(address) {\n        return s.factory;\n    }\n\n    /***** CFMM Data *****/\n\n    /// @dev See {GammaPoolERC4626-_getLatestCFMMReserves}\n    function _getLatestCFMMReserves() internal virtual override view returns(uint128[] memory cfmmReserves) {\n        return IShortStrategy(shortStrategy)._getLatestCFMMReserves(abi.encode(s.cfmm));\n    }\n\n    /// @dev See {GammaPoolERC4626-_getLatestCFMMInvariant}\n    function _getLatestCFMMInvariant() internal virtual override view returns(uint256 lastCFMMInvariant) {\n        return IShortStrategy(shortStrategy)._getLatestCFMMInvariant(abi.encode(s.cfmm));\n    }\n\n    /// @dev See {GammaPoolERC4626-_getLatestCFMMTotalSupply}\n    function _getLatestCFMMTotalSupply() internal virtual override view returns(uint256 lastCFMMTotalSupply) {\n        return GammaSwapLibrary.totalSupply(s.cfmm);\n    }\n\n    /// @dev See {IGammaPool-getLatestCFMMReserves}\n    function getLatestCFMMReserves() external virtual override view returns(uint128[] memory cfmmReserves) {\n        return _getLatestCFMMReserves();\n    }\n\n    /// @dev See {IGammaPool-getCFMMBalances}\n    function getLatestCFMMBalances() external virtual override view returns(uint128[] memory cfmmReserves, uint256 cfmmInvariant, uint256 cfmmTotalSupply) {\n        return(_getLatestCFMMReserves(), _getLatestCFMMInvariant(), _getLatestCFMMTotalSupply());\n    }\n\n    /// @dev See {IGammaPool.getLastCFMMPrice}.\n    function getLastCFMMPrice() external virtual override view returns(uint256) {\n        return _getLastCFMMPrice();\n    }\n\n    /***** GammaPool Data *****/\n\n    /// @dev See {IGammaPool-getPoolBalances}\n    function getPoolBalances() external virtual override view returns(uint128[] memory tokenBalances, uint256 lpTokenBalance, uint256 lpTokenBorrowed,\n        uint256 lpTokenBorrowedPlusInterest, uint256 borrowedInvariant, uint256 lpInvariant) {\n        return(s.TOKEN_BALANCE, s.LP_TOKEN_BALANCE, s.LP_TOKEN_BORROWED, s.LP_TOKEN_BORROWED_PLUS_INTEREST, s.BORROWED_INVARIANT, s.LP_INVARIANT);\n    }\n\n    /// @dev See {IGammaPool-getCFMMBalances}\n    function getCFMMBalances() external virtual override view returns(uint128[] memory cfmmReserves, uint256 cfmmInvariant, uint256 cfmmTotalSupply) {\n        return(s.CFMM_RESERVES, s.lastCFMMInvariant, s.lastCFMMTotalSupply);\n    }\n\n    /// @dev See {IGammaPool-getRates}\n    function getRates() external virtual override view returns(uint256 accFeeIndex, uint256 lastCFMMFeeIndex, uint256 lastBlockNumber) {\n        return(s.accFeeIndex, s.lastCFMMFeeIndex, s.LAST_BLOCK_NUMBER);\n    }\n\n    /// @dev See {IGammaPool-getPoolData}\n    function getPoolData() external virtual override view returns(PoolData memory data) {\n        data.poolId = address(this);\n        data.protocolId = protocolId;\n        data.borrowStrategy = borrowStrategy;\n        data.repayStrategy = repayStrategy;\n        data.rebalanceStrategy = rebalanceStrategy;\n        data.shortStrategy = shortStrategy;\n        data.singleLiquidationStrategy = singleLiquidationStrategy;\n        data.batchLiquidationStrategy = batchLiquidationStrategy;\n        data.cfmm = s.cfmm;\n        data.currBlockNumber = uint40(block.number);\n        data.LAST_BLOCK_NUMBER = s.LAST_BLOCK_NUMBER;\n        data.factory = s.factory;\n        data.paramsStore = s.factory;\n        data.LP_TOKEN_BALANCE = s.LP_TOKEN_BALANCE;\n        data.LP_TOKEN_BORROWED = s.LP_TOKEN_BORROWED;\n        data.totalSupply = s.totalSupply;\n        data.TOKEN_BALANCE = s.TOKEN_BALANCE;\n        data.tokens = s.tokens;\n        data.decimals = s.decimals;\n        data.LP_TOKEN_BORROWED_PLUS_INTEREST = s.LP_TOKEN_BORROWED_PLUS_INTEREST;\n        data.BORROWED_INVARIANT = s.BORROWED_INVARIANT;\n        data.LP_INVARIANT = s.LP_INVARIANT;\n        data.accFeeIndex = s.accFeeIndex;\n        data.ltvThreshold = s.ltvThreshold;\n        data.liquidationFee = s.liquidationFee;\n        data.origFee = s.origFee;\n        data.extSwapFee = s.extSwapFee;\n        data.lastCFMMFeeIndex = s.lastCFMMFeeIndex;\n        data.lastCFMMInvariant = s.lastCFMMInvariant;\n        data.lastCFMMTotalSupply = s.lastCFMMTotalSupply;\n        data.CFMM_RESERVES = s.CFMM_RESERVES;\n        data.emaUtilRate = s.emaUtilRate;\n        data.emaMultiplier = s.emaMultiplier;\n        data.minUtilRate1 = s.minUtilRate1;\n        data.minUtilRate2 = s.minUtilRate2;\n        data.feeDivisor = s.feeDivisor;\n        data.minBorrow = s.minBorrow;\n    }\n\n    /***** SHORT *****/\n\n    /// @dev See {IGammaPool-depositNoPull}\n    function depositNoPull(address to) external virtual override whenNotPaused(5) returns(uint256 shares) {\n        return abi.decode(callStrategy(shortStrategy, abi.encodeCall(IShortStrategy._depositNoPull, to)), (uint256));\n    }\n\n    /// @dev See {IGammaPool-withdrawNoPull}\n    function withdrawNoPull(address to) external virtual override whenNotPaused(6) returns(uint256 assets) {\n        return abi.decode(callStrategy(shortStrategy, abi.encodeCall(IShortStrategy._withdrawNoPull, to)), (uint256));\n    }\n\n    /// @dev See {IGammaPool-depositReserves}\n    function depositReserves(address to, uint256[] calldata amountsDesired, uint256[] calldata amountsMin, bytes calldata data) external virtual override whenNotPaused(7) returns(uint256[] memory reserves, uint256 shares){\n        return abi.decode(callStrategy(shortStrategy, abi.encodeCall(IShortStrategy._depositReserves, (to, amountsDesired, amountsMin, data))), (uint256[],uint256));\n    }\n\n    /// @dev See {IGammaPool-withdrawReserves}\n    function withdrawReserves(address to) external virtual override whenNotPaused(8) returns (uint256[] memory reserves, uint256 assets) {\n        return abi.decode(callStrategy(shortStrategy, abi.encodeCall(IShortStrategy._withdrawReserves, to)), (uint256[],uint256));\n    }\n\n    /***** LONG *****/\n\n    /// @dev See {IGammaPool-createLoan}\n    function createLoan(uint16 refId) external lock virtual override whenNotPaused(9) returns(uint256 tokenId) {\n        tokenId = s.createLoan(s.tokens.length, refId);\n        emit LoanCreated(msg.sender, tokenId, refId);\n    }\n\n    /// @dev See {IGammaPool-loan}\n    function loan(uint256 tokenId) external virtual override view returns(LoanData memory _loanData) {\n        _loanData = _getLoanData(tokenId);\n    }\n\n    /// @dev Get loan and convert to LoanData struct\n    /// @param _tokenId - tokenId of loan to convert\n    /// @return _loanData - loan data struct (same as Loan + tokenId)\n    function _getLoanData(uint256 _tokenId) internal virtual view returns(LoanData memory _loanData) {\n        LibStorage.Loan memory _loan = s.loans[_tokenId];\n        _loanData.tokenId = _tokenId;\n        _loanData.id = _loan.id;\n        _loanData.poolId = _loan.poolId;\n        _loanData.tokensHeld = _loan.tokensHeld;\n        _loanData.initLiquidity = _loan.initLiquidity;\n        _loanData.lastLiquidity = _loan.liquidity;\n        _loanData.liquidity = _loan.liquidity;\n        _loanData.lpTokens = _loan.lpTokens;\n        _loanData.rateIndex = _loan.rateIndex;\n        _loanData.px = _loan.px;\n        _loanData.refAddr = _loan.refAddr;\n        _loanData.refFee = _loan.refFee;\n        _loanData.refType = _loan.refType;\n    }\n\n    /// @dev Get loan and convert to LoanData struct\n    /// @param _tokenId - tokenId of loan to convert\n    /// @return _loanData - loan data struct (same as Loan + tokenId)\n    function getLoanData(uint256 _tokenId) public virtual override view returns(LoanData memory _loanData) {\n        _loanData = _getLoanData(_tokenId);\n        _loanData.tokens = s.tokens;\n        _loanData.decimals = s.decimals;\n        _loanData.paramsStore = s.factory;\n        _loanData.shortStrategy = shortStrategy;\n        _loanData.accFeeIndex = s.accFeeIndex;\n        _loanData.LAST_BLOCK_NUMBER = s.LAST_BLOCK_NUMBER;\n        _loanData.BORROWED_INVARIANT = s.BORROWED_INVARIANT;\n        _loanData.LP_INVARIANT = s.LP_INVARIANT;\n        _loanData.LP_TOKEN_BALANCE = s.LP_TOKEN_BALANCE;\n        _loanData.lastCFMMInvariant = s.lastCFMMInvariant;\n        _loanData.lastCFMMTotalSupply = s.lastCFMMTotalSupply;\n        _loanData.ltvThreshold = s.ltvThreshold;\n        _loanData.liquidationFee = s.liquidationFee;\n        _loanData.lastCFMMFeeIndex = s.lastCFMMFeeIndex;\n    }\n\n    /// @dev See {IGammaPool-getLoans}\n    function getLoans(uint256 start, uint256 end, bool active) external virtual override view returns(LoanData[] memory _loans) {\n        uint256[] storage _tokenIds = s.tokenIds;\n        if(start > end || _tokenIds.length == 0) {\n            return _loans;\n        }\n        uint256 lastIdx;\n        unchecked {\n            lastIdx = _tokenIds.length - 1;\n        }\n        end = lastIdx < end ? lastIdx : end; // end = min(lastIdx,end) <= min(type(uint256).max-1,end)\n        if(start <= end) {\n            unchecked {\n                _loans = new LoanData[](1 + end - start);\n            }\n            LoanData memory _loan;\n            uint256 k = 0;\n            for(uint256 i = start; i <= end;) {\n                _loan = _getLoanData(_tokenIds[i]);\n                if(!active || _loan.initLiquidity > 0) {\n                    _loans[k] = _loan;\n                    unchecked {\n                        ++k;\n                    }\n                }\n                unchecked {\n                    ++i;\n                }\n            }\n        }\n        return _loans;\n    }\n\n    /// @dev See {IGammaPool-getLoansById}\n    function getLoansById(uint256[] calldata tokenIds, bool active) external virtual override view returns(LoanData[] memory _loans) {\n        uint256 _size = tokenIds.length;\n        _loans = new LoanData[](_size);\n        LoanData memory _loan;\n        uint256 k = 0;\n        for(uint256 i = 0; i < _size;) {\n            _loan = _getLoanData(tokenIds[i]);\n            if(_loan.id > 0 && (!active || _loan.initLiquidity > 0)) {\n                _loans[k] = _loan;\n                unchecked {\n                    ++k;\n                }\n            }\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    /// @dev calculate liquidity invariant from collateral tokens\n    /// @param tokensHeld - loan's collateral tokens\n    /// @return collateralInvariant - invariant calculated from loan's collateral tokens\n    function _calcInvariant(uint128[] memory tokensHeld) internal virtual view returns(uint256);\n\n    /// @dev See {IGammaPool-calcInvariant}\n    function calcInvariant(uint128[] memory tokensHeld) external virtual override view returns(uint256) {\n        return _calcInvariant(tokensHeld);\n    }\n\n    /// @dev See {IGammaPool-getLoanCount}\n    function getLoanCount() external virtual override view returns(uint256) {\n        return s.tokenIds.length;\n    }\n\n    /// @dev See {IGammaPool-increaseCollateral}\n    function increaseCollateral(uint256 tokenId, uint256[] calldata ratio) external virtual override whenNotPaused(10) returns(uint128[] memory tokensHeld) {\n        return abi.decode(callStrategy(borrowStrategy, abi.encodeCall(IBorrowStrategy._increaseCollateral, (tokenId, ratio))), (uint128[]));\n    }\n\n    /// @dev See {IGammaPool-decreaseCollateral}\n    function decreaseCollateral(uint256 tokenId, uint128[] memory amounts, address to, uint256[] calldata ratio) external virtual override whenNotPaused(11) returns(uint128[] memory tokensHeld) {\n        return abi.decode(callStrategy(borrowStrategy, abi.encodeCall(IBorrowStrategy._decreaseCollateral, (tokenId, amounts, to, ratio))), (uint128[]));\n    }\n\n    /// @dev See {IGammaPool-borrowLiquidity}\n    function borrowLiquidity(uint256 tokenId, uint256 lpTokens, uint256[] calldata ratio) external virtual override whenNotPaused(12) returns(uint256 liquidityBorrowed, uint256[] memory amounts, uint128[] memory tokensHeld) {\n        return abi.decode(callStrategy(borrowStrategy, abi.encodeCall(IBorrowStrategy._borrowLiquidity, (tokenId, lpTokens, ratio))), (uint256, uint256[], uint128[]));\n    }\n\n    /// @dev See {IGammaPool-repayLiquidity}\n    function repayLiquidity(uint256 tokenId, uint256 liquidity, uint256 collateralId, address to) external virtual override whenNotPaused(13) returns(uint256 liquidityPaid, uint256[] memory amounts) {\n        return abi.decode(callStrategy(repayStrategy, abi.encodeCall(IRepayStrategy._repayLiquidity, (tokenId, liquidity, collateralId, to))), (uint256, uint256[]));\n    }\n\n    /// @dev See {IGammaPool-repayLiquiditySetRatio}\n    function repayLiquiditySetRatio(uint256 tokenId, uint256 liquidity, uint256[] calldata ratio) external virtual override whenNotPaused(14) returns(uint256 liquidityPaid, uint256[] memory amounts) {\n        return abi.decode(callStrategy(repayStrategy, abi.encodeCall(IRepayStrategy._repayLiquiditySetRatio, (tokenId, liquidity, ratio))), (uint256, uint256[]));\n    }\n\n    /// @dev See {IGammaPool-repayLiquidityWithLP}\n    function repayLiquidityWithLP(uint256 tokenId, uint256 collateralId, address to) external virtual override whenNotPaused(15) returns(uint256 liquidityPaid, uint128[] memory tokensHeld) {\n        return abi.decode(callStrategy(repayStrategy, abi.encodeCall(IRepayStrategy._repayLiquidityWithLP, (tokenId, collateralId, to))), (uint256, uint128[]));\n    }\n\n    /// @dev See {IGammaPool-rebalanceCollateral}\n    function rebalanceCollateral(uint256 tokenId, int256[] memory deltas, uint256[] calldata ratio) external virtual override whenNotPaused(16) returns(uint128[] memory tokensHeld) {\n        return abi.decode(callStrategy(rebalanceStrategy, abi.encodeCall(IRebalanceStrategy._rebalanceCollateral, (tokenId, deltas, ratio))), (uint128[]));\n    }\n\n    /// @dev See {IGammaPool-updatePool}\n    function updatePool(uint256 tokenId) external virtual override whenNotPaused(17) returns(uint256 loanLiquidityDebt, uint256 poolLiquidityDebt) {\n        return abi.decode(callStrategy(rebalanceStrategy, abi.encodeCall(IRebalanceStrategy._updatePool, tokenId)), (uint256, uint256));\n    }\n\n    /// @dev See {IGammaPool-liquidate}\n    function liquidate(uint256 tokenId) external virtual override whenNotPaused(18) returns(uint256 loanLiquidity, uint256 refund) {\n        return abi.decode(callStrategy(singleLiquidationStrategy, abi.encodeCall(ISingleLiquidationStrategy._liquidate, tokenId)), (uint256, uint256));\n    }\n\n    /// @dev See {IGammaPool-liquidateWithLP}\n    function liquidateWithLP(uint256 tokenId) external virtual override whenNotPaused(19) returns(uint256 loanLiquidity, uint256[] memory refund) {\n        return abi.decode(callStrategy(singleLiquidationStrategy, abi.encodeCall(ISingleLiquidationStrategy._liquidateWithLP, tokenId)), (uint256, uint256[]));\n    }\n\n    /// @dev See {IGammaPool-batchLiquidations}\n    function batchLiquidations(uint256[] calldata tokenIds) external virtual override whenNotPaused(20) returns(uint256 totalLoanLiquidity, uint256[] memory refund) {\n        return abi.decode(callStrategy(batchLiquidationStrategy, abi.encodeCall(IBatchLiquidationStrategy._batchLiquidations, tokenIds)), (uint256, uint256[]));\n    }\n\n    /***** SYNC POOL *****/\n\n    /// @dev See {IGammaPool-sync}\n    function sync() external virtual override whenNotPaused(21) {\n        callStrategy(shortStrategy, abi.encodeCall(IShortStrategy._sync, ()));\n    }\n\n    /// @dev See {IGammaPool-skim}\n    function skim(address to) external virtual override lock whenNotPaused(22) {\n        address[] memory _tokens = s.tokens; // gas savings\n        uint128[] memory _tokenBalances = s.TOKEN_BALANCE;\n        for(uint256 i; i < _tokens.length;) {\n            skim(_tokens[i], _tokenBalances[i], to); // skim collateral tokens\n            unchecked {\n                ++i;\n            }\n        }\n        skim(s.cfmm, s.LP_TOKEN_BALANCE, to); // skim cfmm LP tokens\n    }\n\n    /// @dev See {ITransfers-clearToken}\n    function clearToken(address token, address to, uint256 minAmt) external override virtual lock whenNotPaused(23) {\n        // Can't clear CFMM LP tokens or collateral tokens\n        if(isCFMMToken(token) || isCollateralToken(token)) revert RestrictedToken();\n\n        uint256 tokenBal = IERC20(token).balanceOf(address(this));\n        if(tokenBal < minAmt) revert NotEnoughTokens(); // Only clear if past threshold\n\n        // If not CFMM LP token or collateral token send entire amount\n        if (tokenBal > 0) GammaSwapLibrary.safeTransfer(token, to, tokenBal);\n    }\n\n    /// @dev See {Transfers-isCFMMToken}\n    function isCFMMToken(address token) internal virtual override view returns(bool) {\n        return token == s.cfmm;\n    }\n\n    /// @dev See {Transfers-isCollateralToken}\n    function isCollateralToken(address token) internal virtual override view returns(bool) {\n        address[] memory _tokens = s.tokens; // gas savings\n        for(uint256 i; i < _tokens.length;) {\n            if(token == _tokens[i]) {\n                return true;\n            }\n            unchecked {\n                ++i;\n            }\n        }\n        return false;\n    }\n}\n"
      },
      "@gammaswap/v1-core/contracts/base/GammaPoolERC20.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity >=0.8.4;\n\nimport \"../storage/AppStorage.sol\";\nimport \"../interfaces/strategies/events/IGammaPoolERC20Events.sol\";\n\n/// @title ERC20 (GS LP) implementation of GammaPool\n/// @author Daniel D. Alcarraz (https://github.com/0xDanr)\n/// @dev The root contract in GammaPool inheritance hierarchy. Inherits AppStorage contract to implement App Storage pattern\nabstract contract GammaPoolERC20 is IGammaPoolERC20Events, AppStorage {\n\n    error ERC20Transfer();\n    error ERC20Allowance();\n\n    /// @return name - name of the token.\n    string public constant name = 'GammaSwap V1';\n\n    /// @return symbol - token symbol\n    string public constant symbol = 'GS-V1';\n\n    /// @return decimals - number of decimals used to get the user representation of GS LP token numbers.\n    uint8 public constant decimals = 18;\n\n    /// @return totalSupply - amount of GS LP tokens in existence.\n    function totalSupply() public virtual view returns (uint256) {\n        return s.totalSupply;\n    }\n\n    /// @dev Returns the amount of GS LP tokens owned by `account`.\n    /// @param account - address whose GS LP token balance is being checked\n    /// @return balance - amount of GS LP tokens held by account address\n    function balanceOf(address account) external virtual view returns (uint256) {\n        return s.balanceOf[account];\n    }\n\n    /// @dev Returns the remaining number of GS LP tokens that `spender` will be allowed to spend on behalf of `owner` through a transferFrom function call. Zero by default.\n    /// @param owner - address which owns the GS LP tokens spender is being given permission to spend\n    /// @param spender - address given permission to spend owner's GS LP tokens\n    /// @return allowance - amount of GS LP tokens belonging to owner that spender is allowed to spend, changes with transferFrom or approve function calls\n    function allowance(address owner, address spender) external virtual view returns (uint256) {\n        return s.allowance[owner][spender];\n    }\n\n    /// @dev Moves `amount` of GS LP tokens from `from` to `to`.\n    /// @param from - address sending GS LP tokens\n    /// @param to - address receiving GS LP tokens\n    /// @param amount - amount of GS LP tokens being sent\n    function _transfer(address from, address to, uint256 amount) internal virtual {\n        uint256 currentBalance = s.balanceOf[from];\n        if(currentBalance < amount) revert ERC20Transfer(); // insufficient balance\n\n        unchecked{\n            s.balanceOf[from] = currentBalance - amount;\n        }\n        s.balanceOf[to] = s.balanceOf[to] + amount;\n        emit Transfer(from, to, amount);\n    }\n\n    /// @dev Sets `amount` as the allowance of `spender` over the caller's GS LP tokens.\n    /// @param spender - address given permission to spend caller's GS LP tokens\n    /// @param amount - amount of GS LP tokens spender is given permission to spend\n    /// @return bool - true if operation succeeded\n    function approve(address spender, uint256 amount) external virtual returns (bool) {\n        s.allowance[msg.sender][spender] = amount;\n        emit Approval(msg.sender, spender, amount);\n        return true;\n    }\n\n    /// @dev Moves `amount` GS LP tokens from the caller's account to `to`.\n    /// @param to - address receiving caller's GS LP tokens\n    /// @param amount - amount of GS LP tokens caller is sending\n    /// @return bool - true if operation succeeded\n    function transfer(address to, uint256 amount) external virtual returns (bool) {\n        _transfer(msg.sender, to, amount);\n        return true;\n    }\n\n    /// @dev Moves `amount` GS LP tokens from `from` to `to` using the allowance mechanism. `amount` is then deducted from the caller's allowance.\n    /// @param from - address sending GS LP tokens (not necessarily caller's address)\n    /// @param to - address receiving GS LP tokens\n    /// @param amount - amount of GS LP tokens being sent\n    /// @return bool - true if operation succeeded\n    function transferFrom(address from, address to, uint256 amount) external virtual returns (bool) {\n        uint256 currentAllowance = s.allowance[from][msg.sender];\n        if (currentAllowance != type(uint256).max) { // is allowance set to max uint256, then never decrease allowance\n            if(currentAllowance < amount) revert ERC20Allowance(); // revert if trying to send more than allowance\n\n            unchecked {\n                s.allowance[from][msg.sender] = currentAllowance - amount;\n            }\n        }\n        _transfer(from, to, amount);\n        return true;\n    }\n\n}\n"
      },
      "@gammaswap/v1-core/contracts/base/GammaPoolERC4626.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity >=0.8.13;\n\nimport \"../interfaces/strategies/base/IShortStrategy.sol\";\nimport \"../rates/AbstractRateModel.sol\";\nimport \"../utils/DelegateCaller.sol\";\nimport \"../utils/Pausable.sol\";\nimport \"./Refunds.sol\";\nimport \"./GammaPoolERC20.sol\";\n\n/// @title ERC4626 (GS LP) implementation of GammaPool\n/// @author Daniel D. Alcarraz (https://github.com/0xDanr)\n/// @dev Vault implementation of GammaPool, assets are CFMM LP tokens, shares are GS LP tokens\nabstract contract GammaPoolERC4626 is GammaPoolERC20, DelegateCaller, Refunds, Pausable {\n\n    error MinShares();\n\n    /// @dev Minimum number of shares issued on first deposit to avoid rounding issues\n    uint256 public constant MIN_SHARES = 1e3;\n\n    /// @return address - implementation contract that implements vault logic (e.g. ShortStrategy)\n    function vaultImplementation() internal virtual view returns(address);\n\n    /// @return cfmmTotalSupply - latest total supply of LP tokens from CFMM\n    function _getLatestCFMMTotalSupply() internal virtual view returns(uint256 cfmmTotalSupply);\n\n    /// @return cfmmInvariant - latest invariant in CFMM\n    function _getLatestCFMMInvariant() internal virtual view returns(uint256 cfmmInvariant);\n\n    /// @return cfmmReserves - latest token reserves in the CFMM\n    function _getLatestCFMMReserves() internal virtual view returns(uint128[] memory cfmmReserves);\n\n    /// @return lastPrice - latest token reserves in the CFMM\n    function _getLastCFMMPrice() internal virtual view returns(uint256 lastPrice);\n\n    // @dev See {Pausable-_pauser}\n    function _pauser() internal override virtual view returns(address) {\n        return s.factory;\n    }\n\n    /// @dev See {Pausable-_functionIds}\n    function _functionIds() internal override virtual view returns(uint256) {\n        return s.funcIds;\n    }\n\n    /// @dev See {Pausable-_setFunctionIds}\n    function _setFunctionIds(uint256 _funcIds) internal override virtual {\n        s.funcIds = _funcIds;\n    }\n\n    /// @return address - CFMM LP token address used for the Vault for accounting, depositing, and withdrawing.\n    function asset() external virtual view returns(address) {\n        return s.cfmm;\n    }\n\n    /// @dev Deposit CFMM LP token and get GS LP token, does a transferFrom according to ERC4626 implementation\n    /// @param assets - CFMM LP tokens deposited in exchange for GS LP tokens\n    /// @param to - address receiving GS LP tokens\n    /// @return shares - quantity of GS LP tokens sent to receiver address (`to`) for CFMM LP tokens\n    function deposit(uint256 assets, address to) external virtual whenNotPaused(1) returns (uint256 shares) {\n        return abi.decode(callStrategy(vaultImplementation(), abi.encodeCall(IShortStrategy._deposit, (assets, to))), (uint256));\n    }\n\n    /// @dev Mint GS LP token in exchange for CFMM LP token deposits, does a transferFrom according to ERC4626 implementation\n    /// @param shares - GS LP tokens minted from CFMM LP token deposits\n    /// @param to - address receiving GS LP tokens\n    /// @return assets - quantity of CFMM LP tokens sent to receiver address (`to`)\n    function mint(uint256 shares, address to) external virtual whenNotPaused(2) returns (uint256 assets) {\n        return abi.decode(callStrategy(vaultImplementation(), abi.encodeCall(IShortStrategy._mint, (shares, to))), (uint256));\n    }\n\n    /// @dev Withdraw CFMM LP token by burning GS LP tokens\n    /// @param assets - amount of CFMM LP tokens requested to withdraw in exchange for GS LP tokens\n    /// @param to - address receiving CFMM LP tokens\n    /// @param from - address burning its GS LP tokens\n    /// @return shares - quantity of GS LP tokens burned\n    function withdraw(uint256 assets, address to, address from) external virtual whenNotPaused(3) returns (uint256 shares) {\n        return abi.decode(callStrategy(vaultImplementation(), abi.encodeCall(IShortStrategy._withdraw, (assets, to, from))), (uint256));\n    }\n\n    /// @dev Redeem GS LP tokens and get CFMM LP token\n    /// @param shares - GS LP tokens requested to redeem in exchange for GS LP tokens\n    /// @param to - address receiving CFMM LP tokens\n    /// @param from - address redeeming GS LP tokens\n    /// @return assets - quantity of CFMM LP tokens sent to receiver address (`to`) for GS LP tokens redeemed\n    function redeem(uint256 shares, address to, address from) external virtual whenNotPaused(4) returns (uint256 assets) {\n        return abi.decode(callStrategy(vaultImplementation(), abi.encodeCall(IShortStrategy._redeem, (shares, to, from))), (uint256));\n    }\n\n    /// @dev Calculates and returns total CFMM LP tokens belonging to liquidity providers using state global variables. It does not update the GammaPool\n    /// @return assets - current total CFMM LP tokens (real and virtual) in existence in the GammaPool, including accrued interest\n    function totalAssets() public view virtual returns(uint256 assets) {\n        (assets,) = _totalAssetsAndSupply();\n    }\n\n    /// @dev Get total supply of GS LP tokens, takes into account dilution through protocol revenue\n    /// @return supply - total supply of GS LP tokens after taking protocol revenue dilution into account\n    function totalSupply() public virtual override view returns(uint256 supply){\n        (, supply) = _totalAssetsAndSupply();\n    }\n\n    /// @dev Convert CFMM LP tokens to GS LP tokens\n    /// @param assets - CFMM LP tokens\n    /// @return shares - GS LP tokens quantity that corresponds to assets quantity provided as a parameter (CFMM LP tokens)\n    function convertToShares(uint256 assets) public view virtual returns (uint256) {\n        if(assets == 0) {\n            return 0;\n        }\n        (uint256 _totalAssets, uint256 supply) = _totalAssetsAndSupply();\n\n        if(supply == 0 || _totalAssets == 0) {\n            if(assets <= MIN_SHARES) revert MinShares();\n\n            unchecked {\n                return assets - MIN_SHARES;\n            }\n        }\n        return (assets * supply) / _totalAssets;\n    }\n\n    /// @dev Convert GS LP tokens to GS LP tokens\n    /// @param shares - GS LP tokens\n    /// @return assets - CFMM LP tokens quantity that corresponds to shares quantity provided as a parameter (GS LP tokens)\n    function convertToAssets(uint256 shares) public view virtual returns (uint256) {\n        if(shares == 0) {\n            return 0;\n        }\n        (uint256 assets, uint256 supply) = _totalAssetsAndSupply();\n        if(supply == 0) {\n            if(shares <= MIN_SHARES) revert MinShares();\n\n            unchecked {\n                return shares - MIN_SHARES;\n            }\n        }\n        // totalAssets is total CFMM LP tokens, including accrued interest, calculated using state variables\n        return (shares * assets) / supply;\n    }\n\n    /// @dev Allows an on-chain or off-chain user to simulate the effects of their deposit at the current block, given current on-chain conditions.\n    /// @param assets - CFMM LP tokens\n    /// @return shares - expected GS LP tokens to get from assets (CFMM LP tokens) deposited\n    function previewDeposit(uint256 assets) public view virtual returns (uint256) {\n        return convertToShares(assets);\n    }\n\n    /// @dev Allows an on-chain or off-chain user to simulate the effects of their mint at the current block, given current on-chain conditions.\n    /// @param shares - GS LP tokens\n    /// @return assets - CFMM LP tokens needed to deposit to get the desired shares (GS LP tokens)\n    function previewMint(uint256 shares) public view virtual returns (uint256) {\n        return convertToAssets(shares);\n    }\n\n    /// @dev Allows an on-chain or off-chain user to simulate the effects of their withdrawal at the current block, given current on-chain conditions.\n    /// @param assets - CFMM LP tokens\n    /// @return shares - expected GS LP tokens needed to burn to withdraw desired assets (CFMM LP tokens)\n    function previewWithdraw(uint256 assets) public view virtual returns (uint256) {\n        return convertToShares(assets);\n    }\n\n    /// @dev Allows an on-chain or off-chain user to simulate the effects of their redemption at the current block, given current on-chain conditions.\n    /// @param shares - GS LP tokens\n    /// @return assets - expected CFMM LP tokens withdrawn if shares (GS LP tokens) burned\n    function previewRedeem(uint256 shares) public view virtual returns (uint256) {\n        return convertToAssets(shares);\n    }\n\n    /// @dev Returns the maximum amount of CFMM LP tokens that can be deposited into the Vault for the receiver, through a deposit call. Ignores address parameter\n    /// @return maxAssets - maximum amount of CFMM LP tokens that can be deposited\n    function maxDeposit(address) public view virtual returns (uint256) {\n        (uint256 assets, uint256 supply) = _totalAssetsAndSupply();\n        return assets > 0 || supply == 0 ? type(uint256).max : 0; // no limits on deposits unless pool is a bad state\n    }\n\n    /// @dev Returns the maximum amount of the GS LP tokens that can be minted for the receiver, through a mint call. Ignores address parameter\n    /// @return maxShares - maximum amount of GS LP tokens that can be minted\n    function maxMint(address) public view virtual returns (uint256) {\n        return type(uint256).max;\n    }\n\n    /// @dev Calculate max CFMM LP tokens available for withdrawal by checking against CFMM LP tokens not borrowed\n    /// @param assets - CFMM LP tokens to withdraw\n    /// @return maxAssets - maximum CFMM LP tokens available for withdrawal\n    function maxAssets(uint256 assets) internal view virtual returns(uint256) {\n        uint256 lpTokenBalance = s.LP_TOKEN_BALANCE; // CFMM LP tokens in GammaPool that have not been borrowed\n        if(assets < lpTokenBalance){ // limit assets available to withdraw to what has not been borrowed\n            return assets;\n        }\n        return lpTokenBalance;\n    }\n\n    /// @dev Returns the maximum amount of CFMM LP tokens that can be withdrawn from the owner balance in the Vault, through a withdraw call.\n    /// @param owner - address that owns GS LP tokens\n    /// @return maxAssets - maximum amount of CFMM LP tokens that can be withdrawn by owner address\n    function maxWithdraw(address owner) public view virtual returns (uint256) {\n        return maxAssets(convertToAssets(s.balanceOf[owner])); // convert owner GS LP tokens to equivalent CFMM LP tokens and check if available to withdraw\n    }\n\n    /// @dev Returns the maximum amount of GS LP tokens that can be redeemed from the owner balance in the Vault, through a redeem call.\n    /// @param owner - address that owns GS LP tokens\n    /// @return maxShares - maximum amount of GS LP tokens that can be redeemed by owner address\n    function maxRedeem(address owner) public view virtual returns (uint256) {\n        return convertToShares(maxWithdraw(owner)); // get maximum amount of CFMM LP tokens that can be withdrawn and convert to equivalent GS LP token amount\n    }\n\n    /// @dev Calculate and return total CFMM LP tokens belonging to GammaPool liquidity providers using state global variables.\n    /// @dev And calculate and return total supply of GS LP tokens taking into account dilution through protocol revenue.\n    /// @dev This function does not update the GammaPool\n    /// @return assets - current total CFMM LP tokens (real and virtual) in existence in the GammaPool, including accrued interest\n    /// @return supply - total supply of GS LP tokens after taking protocol revenue dilution into account\n    function _totalAssetsAndSupply() internal view virtual returns (uint256 assets, uint256 supply) {\n        IShortStrategy.VaultBalancesParams memory _params;\n        _params.factory = s.factory;\n        _params.pool = address(this);\n        _params.paramsStore = _params.factory;\n        _params.BORROWED_INVARIANT = s.BORROWED_INVARIANT;\n        _params.latestCfmmInvariant = _getLatestCFMMInvariant();\n        _params.latestCfmmTotalSupply = _getLatestCFMMTotalSupply();\n        _params.LAST_BLOCK_NUMBER = s.LAST_BLOCK_NUMBER;\n        _params.lastCFMMInvariant = s.lastCFMMInvariant;\n        _params.lastCFMMTotalSupply = s.lastCFMMTotalSupply;\n        _params.lastCFMMFeeIndex = s.lastCFMMFeeIndex;\n        _params.totalSupply = s.totalSupply;\n        _params.LP_TOKEN_BALANCE = s.LP_TOKEN_BALANCE;\n        _params.LP_INVARIANT = s.LP_INVARIANT;\n\n        (assets, supply) = IShortStrategy(vaultImplementation()).totalAssetsAndSupply(_params);\n    }\n}"
      },
      "@gammaswap/v1-core/contracts/base/GammaPoolExternal.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity >=0.8.13;\n\nimport \"../interfaces/IGammaPoolExternal.sol\";\nimport \"../interfaces/strategies/rebalance/IExternalRebalanceStrategy.sol\";\nimport \"../interfaces/strategies/liquidation/IExternalLiquidationStrategy.sol\";\nimport \"../utils/DelegateCaller.sol\";\nimport \"../utils/Pausable.sol\";\n\n/// @title Basic GammaPool smart contract with flash loan functionality\n/// @author Daniel D. Alcarraz (https://github.com/0xDanr)\n/// @dev Used as template for building other GammaPool contract implementations with flash loan functionality for other CFMMs\nabstract contract GammaPoolExternal is IGammaPoolExternal, DelegateCaller, Pausable {\n\n    /// @dev See {IGammaPool-externalRebalanceStrategy}\n    address immutable public override externalRebalanceStrategy;\n\n    /// @dev See {IGammaPool-externalLiquidationStrategy}\n    address immutable public override externalLiquidationStrategy;\n\n    /// @dev Initializes the contract by setting `externalRebalanceStrategy`, and `externalLiquidationStrategy`\n    constructor(address externalRebalanceStrategy_, address externalLiquidationStrategy_) {\n        externalRebalanceStrategy = externalRebalanceStrategy_;\n        externalLiquidationStrategy = externalLiquidationStrategy_;\n    }\n\n    /// @dev See {IGammaPoolExternal-rebalanceExternally}\n    function rebalanceExternally(uint256 tokenId, uint128[] calldata amounts, uint256 lpTokens, address to, bytes calldata data) external override virtual whenNotPaused(24) returns(uint256 loanLiquidity, uint128[] memory tokensHeld) {\n        return abi.decode(callStrategy(externalRebalanceStrategy, abi.encodeCall(IExternalRebalanceStrategy._rebalanceExternally, (tokenId, amounts, lpTokens, to, data))), (uint256, uint128[]));\n    }\n\n    /// @dev See {IGammaPoolExternal-liquidateExternally}\n    function liquidateExternally(uint256 tokenId, uint128[] calldata amounts, uint256 lpTokens, address to, bytes calldata data) external override virtual whenNotPaused(25) returns(uint256 loanLiquidity, uint256[] memory refund) {\n        return abi.decode(callStrategy(externalLiquidationStrategy, abi.encodeCall(IExternalLiquidationStrategy._liquidateExternally, (tokenId, amounts, lpTokens, to, data))), (uint256, uint256[]));\n    }\n}\n"
      },
      "@gammaswap/v1-core/contracts/base/Refunds.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity >=0.8.4;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"../interfaces/IRefunds.sol\";\nimport \"../libraries/GammaSwapLibrary.sol\";\n\n/// @title Contract used to handle token transfers by the GammaPool\n/// @author Daniel D. Alcarraz (https://github.com/0xDanr)\n/// @dev Abstract contract meant to be inherited by the GammaPool abstract contract to handle token transfers and clearing\nabstract contract Refunds is IRefunds {\n\n    error RestrictedToken();\n    error NotEnoughTokens();\n\n    /// @dev Remove excess quantities of ERC20 token\n    /// @param token - address of ERC20 token that will be transferred\n    /// @param balance - quantity of ERC20 token to be expected to remain in GammaPool, excess will be withdrawn\n    /// @param to - destination address where ERC20 token will be sent to\n    function skim(address token, uint256 balance, address to) internal virtual {\n        uint256 newBalance = IERC20(token).balanceOf(address(this));\n        if(newBalance > balance) {\n            uint256 excessBalance;\n            unchecked {\n                excessBalance = newBalance - balance;\n            }\n            GammaSwapLibrary.safeTransfer(token, to, excessBalance);\n        }\n    }\n\n    /// @dev See {ITransfers-clearToken}\n    function clearToken(address token, address to, uint256 minAmt) external override virtual {\n        // Can't clear CFMM LP tokens or collateral tokens\n        if(isCFMMToken(token) || isCollateralToken(token)) revert RestrictedToken();\n\n        uint256 tokenBal = IERC20(token).balanceOf(address(this));\n        if(tokenBal < minAmt) revert NotEnoughTokens(); // Only clear if past threshold\n\n        // If not CFMM LP token or collateral token send entire amount\n        if (tokenBal > 0) GammaSwapLibrary.safeTransfer(token, to, tokenBal);\n    }\n\n    /// @dev Check if ERC20 token is LP token of the CFMM the GammaPool is made for\n    /// @param token - address of ERC20 token that will be checked\n    /// @return bool - true if it is LP token of the CFMM the GammaPool is made for, false otherwise\n    function isCFMMToken(address token) internal virtual view returns(bool);\n\n    /// @dev Check if ERC20 token is a collateral token of the GammaPool\n    /// @param token - address of ERC20 token that will be checked\n    /// @return bool - true if it is a collateral token of the GammaPool, false otherwise\n    function isCollateralToken(address token) internal virtual view returns(bool);\n}\n"
      },
      "@gammaswap/v1-core/contracts/interfaces/IGammaPool.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity >=0.8.0;\n\nimport \"./IGammaPoolEvents.sol\";\nimport \"./IProtocol.sol\";\nimport \"./strategies/events/IGammaPoolERC20Events.sol\";\nimport \"./rates/IRateModel.sol\";\n\n/// @title Interface for GammaPool\n/// @author Daniel D. Alcarraz (https://github.com/0xDanr)\n/// @dev Interface used for GammaPool implementations\ninterface IGammaPool is IProtocol, IGammaPoolEvents, IGammaPoolERC20Events, IRateModel {\n    /// @dev Struct containing Loan data plus tokenId\n    struct LoanData {\n        /// @dev Loan counter, used to generate unique tokenId which indentifies the loan in the GammaPool\n        uint256 id;\n\n        /// @dev Loan tokenId\n        uint256 tokenId;\n\n        // 1x256 bits\n        /// @dev GammaPool address loan belongs to\n        address poolId; // 160 bits\n        /// @dev Index of GammaPool interest rate at time loan is created/updated, max 7.9% trillion\n        uint96 rateIndex; // 96 bits\n\n        // 1x256 bits\n        /// @dev Initial loan debt in liquidity invariant units. Only increase when more liquidity is borrowed, decreases when liquidity is paid\n        uint128 initLiquidity; // 128 bits\n        /// @dev Loan debt in liquidity invariant units in last update\n        uint128 lastLiquidity; // 128 bits\n        /// @dev Loan debt in liquidity invariant units, increases with every update according to how many blocks have passed\n        uint128 liquidity; // 128 bits\n        /// @dev Collateral in terms of liquidity invariant units, increases with every update according to how many blocks have passed\n        uint256 collateral;\n\n        /// @dev Initial loan debt in terms of LP tokens at time liquidity was borrowed, updates along with initLiquidity\n        uint256 lpTokens;\n        /// @dev Reserve tokens held as collateral for the liquidity debt, indices match GammaPool's tokens[] array indices\n        uint128[] tokensHeld; // array of 128 bit numbers\n\n        /// @dev reference address of contract holding additional collateral for loan (e.g. CollateralManager)\n        address refAddr;\n        /// @dev reference fee of contract holding additional collateral for loan (e.g. CollateralManager)\n        uint16 refFee;\n        /// @dev reference type of contract holding additional collateral for loan (e.g. CollateralManager)\n        uint8 refType;\n\n        /// @dev price at which loan was opened\n        uint256 px;\n        /// @dev if true loan can be liquidated\n        bool canLiquidate;\n\n        /// @dev names of ERC20 tokens of CFMM\n        uint256 accFeeIndex;\n        /// @dev Percent accrual in CFMM invariant since last update\n        uint256 lastCFMMFeeIndex;\n        /// @dev names of ERC20 tokens of CFMM\n        uint256 LAST_BLOCK_NUMBER;\n\n        /// @dev ERC20 tokens of CFMM\n        address[] tokens;\n        /// @dev decimals of ERC20 tokens of CFMM\n        uint8[] decimals;\n        /// @dev symbols of ERC20 tokens of CFMM\n        string[] symbols;\n        /// @dev names of ERC20 tokens of CFMM\n        string[] names;\n\n        /// @dev interest rate model parameter store\n        address paramsStore;\n        /// @dev address of short strategy\n        address shortStrategy;\n\n        /// @dev borrowed liquidity invariant of the pool\n        uint256 BORROWED_INVARIANT;\n        /// @dev Quantity of CFMM's liquidity invariant held in GammaPool as LP tokens\n        uint256 LP_INVARIANT;\n        /// @dev balance of CFMM LP tokens in the pool\n        uint256 LP_TOKEN_BALANCE;\n        /// @dev last CFMM liquidity invariant\n        uint256 lastCFMMInvariant;\n        /// @dev last CFMM total supply of LP tokens\n        uint256 lastCFMMTotalSupply;\n        /// @dev LTV liquidation threshold\n        uint256 ltvThreshold;\n        /// @dev Liquidation fee\n        uint256 liquidationFee;\n    }\n\n    /// @dev Struct returned in getLatestRates function. Contains all relevant global state variables\n    struct RateData {\n        /// @dev GammaPool's ever increasing interest rate index, tracks interest accrued through CFMM and liquidity loans, max 7.9% trillion\n        uint256 accFeeIndex;\n        /// @dev Percent accrual in CFMM invariant since last update\n        uint256 lastCFMMFeeIndex;\n        /// @dev Percent accrual in CFMM invariant and GammaPool interest since last update\n        uint256 lastFeeIndex;\n        /// @dev Borrow APR of LP tokens in GammaPool\n        uint256 borrowRate;\n        /// @dev Utilization rate of GammaPool\n        uint256 utilizationRate;\n        /// @dev last block an update to the GammaPool's global storage variables happened\n        uint256 lastBlockNumber;\n        /// @dev Current block number when requesting pool data\n        uint256 currBlockNumber;\n        /// @dev Last Price in CFMM\n        uint256 lastPrice;\n        /// @dev Supply APR of LP tokens in GammaPool\n        uint256 supplyRate;\n        /// @dev names of ERC20 tokens of CFMM\n        uint256 BORROWED_INVARIANT;\n        /// @dev Quantity of CFMM's liquidity invariant held in GammaPool as LP tokens\n        uint256 LP_INVARIANT;\n        /// @dev EMA of utilization Rate\n        uint256 emaUtilRate;\n        /// @dev Minimum Utilization Rate 1\n        uint256 minUtilRate1;\n        /// @dev Minimum Utilization Rate 2\n        uint256 minUtilRate2;\n        /// @dev Dynamic origination fee divisor\n        uint256 feeDivisor;\n        /// @dev Loan opening origination fee in basis points\n        uint256 origFee; // 16 bits\n        /// @dev LTV liquidation threshold\n        uint256 ltvThreshold;\n        /// @dev Liquidation fee\n        uint256 liquidationFee;\n        /// @dev Short Strategy implementation address\n        address shortStrategy;\n        /// @dev Interest Rate Parameters Store contract\n        address paramsStore;\n    }\n\n    /// @dev Struct returned in getPoolData function. Contains all relevant global state variables\n    struct PoolData {\n        /// @dev GammaPool address\n        address poolId;\n        /// @dev Protocol id of the implementation contract for this GammaPool\n        uint16 protocolId;\n        /// @dev Borrow Strategy implementation contract for this GammaPool\n        address borrowStrategy;\n        /// @dev Repay Strategy implementation contract for this GammaPool\n        address repayStrategy;\n        /// @dev Rebalance Strategy implementation contract for this GammaPool\n        address rebalanceStrategy;\n        /// @dev Short Strategy implementation contract for this GammaPool\n        address shortStrategy;\n        /// @dev Single Liquidation Strategy implementation contract for this GammaPool\n        address singleLiquidationStrategy;\n        /// @dev Batch Liquidation Strategy implementation contract for this GammaPool\n        address batchLiquidationStrategy;\n\n        /// @dev factory - address of factory contract that instantiated this GammaPool\n        address factory;\n        /// @dev paramsStore - interest rate model parameters store contract\n        address paramsStore;\n\n        // LP Tokens\n        /// @dev Quantity of CFMM's LP tokens deposited in GammaPool by liquidity providers\n        uint256 LP_TOKEN_BALANCE;// LP Tokens in GS, LP_TOKEN_TOTAL = LP_TOKEN_BALANCE + LP_TOKEN_BORROWED_PLUS_INTEREST\n        /// @dev Quantity of CFMM's LP tokens that have been borrowed by liquidity borrowers excluding accrued interest (principal)\n        uint256 LP_TOKEN_BORROWED;//LP Tokens that have been borrowed (Principal)\n        /// @dev Quantity of CFMM's LP tokens that have been borrowed by liquidity borrowers including accrued interest\n        uint256 LP_TOKEN_BORROWED_PLUS_INTEREST;//LP Tokens that have been borrowed (principal) plus interest in LP Tokens\n\n        // Invariants\n        /// @dev Quantity of CFMM's liquidity invariant that has been borrowed including accrued interest, maps to LP_TOKEN_BORROWED_PLUS_INTEREST\n        uint128 BORROWED_INVARIANT;\n        /// @dev Quantity of CFMM's liquidity invariant held in GammaPool as LP tokens, maps to LP_TOKEN_BALANCE\n        uint128 LP_INVARIANT;//Invariant from LP Tokens, TOTAL_INVARIANT = BORROWED_INVARIANT + LP_INVARIANT\n\n        // Rates\n        /// @dev cfmm - address of CFMM this GammaPool is for\n        address cfmm;\n        /// @dev GammaPool's ever increasing interest rate index, tracks interest accrued through CFMM and liquidity loans, max 30.9% billion\n        uint80 accFeeIndex;\n        /// @dev External swap fee in basis points, max 255 basis points = 2.55%\n        uint8 extSwapFee; // 8 bits\n        /// @dev Loan opening origination fee in basis points\n        uint16 origFee; // 16 bits\n        /// @dev LAST_BLOCK_NUMBER - last block an update to the GammaPool's global storage variables happened\n        uint40 LAST_BLOCK_NUMBER;\n        /// @dev Percent accrual in CFMM invariant since last update\n        uint64 lastCFMMFeeIndex; // 64 bits\n        /// @dev Total liquidity invariant amount in CFMM (from GammaPool and others), read in last update to GammaPool's storage variables\n        uint128 lastCFMMInvariant;\n        /// @dev Total LP token supply from CFMM (belonging to GammaPool and others), read in last update to GammaPool's storage variables\n        uint256 lastCFMMTotalSupply;\n\n        // ERC20 fields\n        /// @dev Total supply of GammaPool's own ERC20 token representing the liquidity of depositors to the CFMM through the GammaPool\n        uint256 totalSupply;\n\n        // tokens and balances\n        /// @dev ERC20 tokens of CFMM\n        address[] tokens;\n        /// @dev symbols of ERC20 tokens of CFMM\n        string[] symbols;\n        /// @dev names of ERC20 tokens of CFMM\n        string[] names;\n        /// @dev Decimals of CFMM tokens, indices match tokens[] array\n        uint8[] decimals;\n        /// @dev Amounts of ERC20 tokens from the CFMM held as collateral in the GammaPool. Equals to the sum of all tokensHeld[] quantities in all loans\n        uint128[] TOKEN_BALANCE;\n        /// @dev Amounts of ERC20 tokens from the CFMM held in the CFMM as reserve quantities. Used to log prices in the CFMM during updates to the GammaPool\n        uint128[] CFMM_RESERVES; //keeps track of price of CFMM at time of update\n\n        /// @dev Last Price in CFMM\n        uint256 lastPrice;\n        /// @dev Percent accrual in CFMM invariant and GammaPool interest since last update\n        uint256 lastFeeIndex;\n        /// @dev Borrow rate of LP tokens in GammaPool\n        uint256 borrowRate;\n        /// @dev Utilization rate of GammaPool\n        uint256 utilizationRate;\n        /// @dev Current block number when requesting pool data\n        uint40 currBlockNumber;\n        /// @dev LTV liquidation threshold\n        uint8 ltvThreshold;\n        /// @dev Liquidation fee\n        uint8 liquidationFee;\n        /// @dev Supply APR of LP tokens in GammaPool\n        uint256 supplyRate;\n        /// @dev EMA of utilization Rate\n        uint40 emaUtilRate;\n        /// @dev Multiplier of EMA Utilization Rate\n        uint8 emaMultiplier;\n        /// @dev Minimum Utilization Rate 1\n        uint8 minUtilRate1;\n        /// @dev Minimum Utilization Rate 2\n        uint8 minUtilRate2;\n        /// @dev Dynamic origination fee divisor\n        uint16 feeDivisor;\n        /// @dev Minimum liquidity amount that can be borrowed\n        uint72 minBorrow;\n    }\n\n    /// @dev cfmm - address of CFMM this GammaPool is for\n    function cfmm() external view returns(address);\n\n    /// @dev ERC20 tokens of CFMM\n    function tokens() external view returns(address[] memory);\n\n    /// @dev address of factory contract that instantiated this GammaPool\n    function factory() external view returns(address);\n\n    /// @dev viewer contract to implement complex view functions for data in this GammaPool\n    function viewer() external view returns(address);\n\n    /// @dev Borrow Strategy implementation contract for this GammaPool\n    function borrowStrategy() external view returns(address);\n\n    /// @dev Repay Strategy implementation contract for this GammaPool\n    function repayStrategy() external view returns(address);\n\n    /// @dev Rebalance Strategy implementation contract for this GammaPool\n    function rebalanceStrategy() external view returns(address);\n\n    /// @dev Short Strategy implementation contract for this GammaPool\n    function shortStrategy() external view returns(address);\n\n    /// @dev Single Loan Liquidation Strategy implementation contract for this GammaPool\n    function singleLiquidationStrategy() external view returns(address);\n\n    /// @dev Batch Liquidations Strategy implementation contract for this GammaPool\n    function batchLiquidationStrategy() external view returns(address);\n\n    /// @dev Set parameters to calculate origination fee, liquidation fee, and ltv threshold\n    /// @param origFee - loan opening origination fee in basis points\n    /// @param extSwapFee - external swap fee in basis points, max 255 basis points = 2.55%\n    /// @param emaMultiplier - multiplier used in EMA calculation of utilization rate\n    /// @param minUtilRate1 - minimum utilization rate to calculate dynamic origination fee in exponential model\n    /// @param minUtilRate2 - minimum utilization rate to calculate dynamic origination fee in linear model\n    /// @param feeDivisor - fee divisor for calculating origination fee, based on 2^(maxUtilRate - minUtilRate1)\n    /// @param liquidationFee - liquidation fee to charge during liquidations in basis points (1 - 255 => 0.01% to 2.55%)\n    /// @param ltvThreshold - ltv threshold (1 - 255 => 0.1% to 25.5%)\n    /// @param minBorrow - minimum liquidity amount that can be borrowed or left unpaid in a loan\n    function setPoolParams(uint16 origFee, uint8 extSwapFee, uint8 emaMultiplier, uint8 minUtilRate1, uint8 minUtilRate2, uint16 feeDivisor, uint8 liquidationFee, uint8 ltvThreshold, uint72 minBorrow) external;\n\n    /// @dev Balances in the GammaPool of collateral tokens, CFMM LP tokens, and invariant amounts at last update\n    /// @return tokenBalances - balances of collateral tokens in GammaPool\n    /// @return lpTokenBalance - CFMM LP token balance of GammaPool\n    /// @return lpTokenBorrowed - CFMM LP token principal amounts borrowed from GammaPool\n    /// @return lpTokenBorrowedPlusInterest - CFMM LP token amounts borrowed from GammaPool including accrued interest\n    /// @return borrowedInvariant - invariant amount borrowed from GammaPool including accrued interest, maps to lpTokenBorrowedPlusInterest\n    /// @return lpInvariant - invariant of CFMM LP tokens in GammaPool not borrowed, maps to lpTokenBalance\n    function getPoolBalances() external view returns(uint128[] memory tokenBalances, uint256 lpTokenBalance, uint256 lpTokenBorrowed,\n        uint256 lpTokenBorrowedPlusInterest, uint256 borrowedInvariant, uint256 lpInvariant);\n\n    /// @dev Balances in CFMM at last update of GammaPool\n    /// @return cfmmReserves - total reserve tokens in CFMM last time GammaPool was updated\n    /// @return cfmmInvariant - total liquidity invariant of CFMM last time GammaPool was updated\n    /// @return cfmmTotalSupply - total CFMM LP tokens in existence last time GammaPool was updated\n    function getCFMMBalances() external view returns(uint128[] memory cfmmReserves, uint256 cfmmInvariant, uint256 cfmmTotalSupply);\n\n    /// @dev Interest rate information in GammaPool at last update\n    /// @return accFeeIndex - total accrued interest in GammaPool at last update\n    /// @return lastCFMMFeeIndex - total accrued CFMM fee since last update\n    /// @return lastBlockNumber - last block GammaPool was updated\n    function getRates() external view returns(uint256 accFeeIndex, uint256 lastCFMMFeeIndex, uint256 lastBlockNumber);\n\n    /// @return data - struct containing all relevant global state variables and descriptive information of GammaPool. Used to avoid making multiple calls\n    function getPoolData() external view returns(PoolData memory data);\n\n    // Short Gamma\n\n    /// @dev Deposit CFMM LP token and get GS LP token, without doing a transferFrom transaction. Must have sent CFMM LP token first\n    /// @param to - address of receiver of GS LP token\n    /// @return shares - quantity of GS LP tokens received for CFMM LP tokens\n    function depositNoPull(address to) external returns(uint256 shares);\n\n    /// @dev Withdraw CFMM LP token, by burning GS LP token, without doing a transferFrom transaction. Must have sent GS LP token first\n    /// @param to - address of receiver of CFMM LP tokens\n    /// @return assets - quantity of CFMM LP tokens received for GS LP tokens\n    function withdrawNoPull(address to) external returns(uint256 assets);\n\n    /// @dev Withdraw reserve token quantities of CFMM (instead of CFMM LP tokens), by burning GS LP token\n    /// @param to - address of receiver of reserve token quantities\n    /// @return reserves - quantity of reserve tokens withdrawn from CFMM and sent to receiver\n    /// @return assets - quantity of CFMM LP tokens representing reserve tokens withdrawn\n    function withdrawReserves(address to) external returns (uint256[] memory reserves, uint256 assets);\n\n    /// @dev Deposit reserve token quantities to CFMM (instead of CFMM LP tokens) to get CFMM LP tokens, store them in GammaPool and receive GS LP tokens\n    /// @param to - address of receiver of GS LP tokens\n    /// @param amountsDesired - desired amounts of reserve tokens to deposit\n    /// @param amountsMin - minimum amounts of reserve tokens to deposit\n    /// @param data - information identifying request to deposit\n    /// @return reserves - quantity of actual reserve tokens deposited in CFMM\n    /// @return shares - quantity of GS LP tokens received for reserve tokens deposited\n    function depositReserves(address to, uint256[] calldata amountsDesired, uint256[] calldata amountsMin, bytes calldata data) external returns(uint256[] memory reserves, uint256 shares);\n\n    /// @return cfmmReserves - latest token reserves in the CFMM\n    function getLatestCFMMReserves() external view returns(uint128[] memory cfmmReserves);\n\n    /// @return cfmmReserves - latest token reserves in the CFMM\n    /// @return cfmmInvariant - latest total invariant in the CFMM\n    /// @return cfmmTotalSupply - latest total supply of LP tokens in CFMM\n    function getLatestCFMMBalances() external view returns(uint128[] memory cfmmReserves, uint256 cfmmInvariant, uint256 cfmmTotalSupply);\n\n    /// @return lastPrice - calculates and gets current price at CFMM\n    function getLastCFMMPrice() external view returns(uint256);\n\n    // Long Gamma\n\n    /// @dev Create a new Loan struct\n    /// @param refId - Reference id of post transaction activities attached to this loan\n    /// @return tokenId - unique id of loan struct created\n    function createLoan(uint16 refId) external returns(uint256 tokenId);\n\n    /// @dev Get loan from storage and convert to LoanData struct\n    /// @param _tokenId - tokenId of loan to convert\n    /// @return _loanData - loan data struct (same as Loan + tokenId)\n    function getLoanData(uint256 _tokenId) external view returns(LoanData memory _loanData);\n\n    /// @dev Get loan with its most updated information\n    /// @param _tokenId - unique id of loan, used to look up loan in GammaPool\n    /// @return _loanData - loan data struct (same as Loan + tokenId)\n    function loan(uint256 _tokenId) external view returns(LoanData memory _loanData);\n\n    /// @dev Get list of loans and their corresponding tokenIds created in GammaPool. Capped at s.tokenIds.length.\n    /// @param start - index from where to start getting tokenIds from array\n    /// @param end - end index of array wishing to get tokenIds. If end > s.tokenIds.length, end is s.tokenIds.length\n    /// @param active - if true, return loans that have an outstanding liquidity debt\n    /// @return _loans - list of loans created in GammaPool\n    function getLoans(uint256 start, uint256 end, bool active) external view returns(LoanData[] memory _loans);\n\n    /// @dev calculate liquidity invariant from collateral tokens\n    /// @param tokensHeld - loan's collateral tokens\n    /// @return collateralInvariant - invariant calculated from loan's collateral tokens\n    function calcInvariant(uint128[] memory tokensHeld) external view returns(uint256);\n\n    /// @dev Get list of loans mapped to tokenIds in array `tokenIds`\n    /// @param tokenIds - list of loan tokenIds\n    /// @param active - if true, return loans that have an outstanding liquidity debt\n    /// @return _loans - list of loans created in GammaPool\n    function getLoansById(uint256[] calldata tokenIds, bool active) external view returns(LoanData[] memory _loans);\n\n    /// @return loanCount - total number of loans opened\n    function getLoanCount() external view returns(uint256);\n\n    /// @dev Deposit more collateral in loan identified by tokenId\n    /// @param tokenId - unique id identifying loan\n    /// @param ratio - ratio to rebalance collateral after increasing collateral\n    /// @return tokensHeld - updated collateral token amounts backing loan\n    function increaseCollateral(uint256 tokenId, uint256[] calldata ratio) external returns(uint128[] memory tokensHeld);\n\n    /// @dev Withdraw collateral from loan identified by tokenId\n    /// @param tokenId - unique id identifying loan\n    /// @param amounts - amounts of collateral tokens requested to withdraw\n    /// @param to - destination address of receiver of collateral withdrawn\n    /// @param ratio - ratio to rebalance collateral after withdrawing collateral\n    /// @return tokensHeld - updated collateral token amounts backing loan\n    function decreaseCollateral(uint256 tokenId, uint128[] memory amounts, address to, uint256[] calldata ratio) external returns(uint128[] memory tokensHeld);\n\n    /// @dev Borrow liquidity from the CFMM and add it to the debt and collateral of loan identified by tokenId\n    /// @param tokenId - unique id identifying loan\n    /// @param lpTokens - quantity of CFMM LP tokens requested to short\n    /// @param ratio - ratio to rebalance collateral after borrowing\n    /// @return liquidityBorrowed - liquidity amount that has been borrowed\n    /// @return amounts - reserves quantities withdrawn from CFMM that correspond to the LP tokens shorted, now used as collateral\n    /// @return tokensHeld - updated collateral token amounts backing loan\n    function borrowLiquidity(uint256 tokenId, uint256 lpTokens, uint256[] calldata ratio) external returns(uint256 liquidityBorrowed, uint256[] memory amounts, uint128[] memory tokensHeld);\n\n    /// @dev Repay liquidity debt of loan identified by tokenId, debt is repaid using available collateral in loan\n    /// @param tokenId - unique id identifying loan\n    /// @param liquidity - liquidity debt being repaid, capped at actual liquidity owed. Can't repay more than you owe\n    /// @param collateralId - index of collateral token + 1\n    /// @param to - if repayment type requires withdrawal, the address that will receive the funds. Otherwise can be zero address\n    /// @return liquidityPaid - liquidity amount that has been repaid\n    /// @return amounts - collateral amounts consumed in repaying liquidity debt\n    function repayLiquidity(uint256 tokenId, uint256 liquidity, uint256 collateralId, address to) external returns(uint256 liquidityPaid, uint256[] memory amounts);\n\n    /// @dev Repay liquidity debt of loan identified by tokenId, debt is repaid using available collateral in loan\n    /// @param tokenId - unique id identifying loan\n    /// @param liquidity - liquidity debt being repaid, capped at actual liquidity owed. Can't repay more than you owe\n    /// @param ratio - weights of collateral after repaying liquidity\n    /// @return liquidityPaid - liquidity amount that has been repaid\n    /// @return amounts - collateral amounts consumed in repaying liquidity debt\n    function repayLiquiditySetRatio(uint256 tokenId, uint256 liquidity, uint256[] calldata ratio) external returns(uint256 liquidityPaid, uint256[] memory amounts);\n\n    /// @dev Repay liquidity debt of loan identified by tokenId, using CFMM LP token\n    /// @param tokenId - unique id identifying loan\n    /// @param collateralId - index of collateral token to rebalance to + 1\n    /// @param to - if repayment type requires withdrawal, the address that will receive the funds. Otherwise can be zero address\n    /// @return liquidityPaid - liquidity amount that has been repaid\n    /// @return tokensHeld - remaining token amounts collateralizing loan\n    function repayLiquidityWithLP(uint256 tokenId, uint256 collateralId, address to) external returns(uint256 liquidityPaid, uint128[] memory tokensHeld);\n\n    /// @dev Rebalance collateral amounts of loan identified by tokenId by purchasing or selling some of the collateral\n    /// @param tokenId - unique id identifying loan\n    /// @param deltas - collateral amounts being bought or sold (>0 buy, <0 sell), index matches tokensHeld[] index. Only n-1 tokens can be traded\n    /// @param ratio - ratio to rebalance collateral\n    /// @return tokensHeld - updated collateral token amounts backing loan\n    function rebalanceCollateral(uint256 tokenId, int256[] memory deltas, uint256[] calldata ratio) external returns(uint128[] memory tokensHeld);\n\n    /// @dev Update pool liquidity debt and optinally also loan liquidity debt\n    /// @param tokenId - (optional) unique ids identifying loan, pass zero to ignore this parameter\n    /// @return loanLiquidityDebt - updated liquidity debt amount of loan\n    /// @return poolLiquidityDebt - updated liquidity debt amount of pool\n    function updatePool(uint256 tokenId) external returns(uint256 loanLiquidityDebt, uint256 poolLiquidityDebt);\n\n    /// @notice When calling this function and adding additional collateral it is assumed that you have sent the collateral first\n    /// @dev Function to liquidate a loan using its own collateral or depositing additional tokens. Seeks full liquidation\n    /// @param tokenId - tokenId of loan being liquidated\n    /// @return loanLiquidity - loan liquidity liquidated (after write down)\n    /// @return refund - amount of CFMM LP tokens being refunded to liquidator\n    function liquidate(uint256 tokenId) external returns(uint256 loanLiquidity, uint256 refund);\n\n    /// @dev Function to liquidate a loan using external LP tokens. Allows partial liquidation\n    /// @param tokenId - tokenId of loan being liquidated\n    /// @return loanLiquidity - loan liquidity liquidated (after write down)\n    /// @return refund - amounts from collateral tokens being refunded to liquidator\n    function liquidateWithLP(uint256 tokenId) external returns(uint256 loanLiquidity, uint256[] memory refund);\n\n    /// @dev Function to liquidate multiple loans in batch.\n    /// @param tokenIds - list of tokenIds of loans to liquidate\n    /// @return totalLoanLiquidity - total loan liquidity liquidated (after write down)\n    /// @return refund - amounts from collateral tokens being refunded to liquidator\n    function batchLiquidations(uint256[] calldata tokenIds) external returns(uint256 totalLoanLiquidity, uint256[] memory refund);\n\n    // Sync functions\n\n    /// @dev Skim excess collateral tokens or CFMM LP tokens from GammaPool and send them to receiver (`to`) address\n    /// @param to - address receiving excess tokens\n    function skim(address to) external;\n\n    /// @dev Synchronize LP_TOKEN_BALANCE with actual CFMM LP tokens deposited in GammaPool\n    function sync() external;\n}\n"
      },
      "@gammaswap/v1-core/contracts/interfaces/IGammaPoolEvents.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity >=0.8.0;\n\nimport \"./strategies/events/ILiquidationStrategyEvents.sol\";\nimport \"./strategies/events/IShortStrategyEvents.sol\";\nimport \"./strategies/events/IExternalStrategyEvents.sol\";\n\n/// @title GammaPool Events Interface\n/// @author Daniel D. Alcarraz (https://github.com/0xDanr)\n/// @dev Events emitted by all GammaPool implementations (contains all strategy events)\ninterface IGammaPoolEvents is IShortStrategyEvents, ILiquidationStrategyEvents, IExternalStrategyEvents {\n    /// @dev Event emitted when a Loan is created\n    /// @param caller - address that created the loan\n    /// @param tokenId - unique id that identifies the loan in question\n    /// @param refId - Reference id of post transaction activities attached to this loan\n    event LoanCreated(address indexed caller, uint256 tokenId, uint16 refId);\n}\n"
      },
      "@gammaswap/v1-core/contracts/interfaces/IGammaPoolExternal.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity >=0.8.0;\n\nimport \"./IGammaPool.sol\";\n\n/// @title Interface for GammaPoolExternal\n/// @author Daniel D. Alcarraz (https://github.com/0xDanr)\n/// @dev Interface used for GammaPool implementations that have flash loan functionality\ninterface IGammaPoolExternal {\n\n    /// @dev External Rebalance Strategy implementation contract for this GammaPool\n    function externalRebalanceStrategy() external view returns(address);\n\n    /// @dev External Liquidation Strategy implementation contract for this GammaPool\n    function externalLiquidationStrategy() external view returns(address);\n\n    /// @dev Flash loan pool's collateral and/or lp tokens to external address. Rebalanced loan collateral is acceptable in  repayment of flash loan\n    /// @param tokenId - unique id identifying loan\n    /// @param amounts - collateral amounts being flash loaned\n    /// @param lpTokens - amount of CFMM LP tokens being flash loaned\n    /// @param to - address that will receive flash loan swaps and potentially rebalance loan's collateral\n    /// @param data - optional bytes parameter for custom user defined data\n    /// @return loanLiquidity - updated loan liquidity, includes flash loan fees\n    /// @return tokensHeld - updated collateral token amounts backing loan\n    function rebalanceExternally(uint256 tokenId, uint128[] calldata amounts, uint256 lpTokens, address to, bytes calldata data) external returns(uint256 loanLiquidity, uint128[] memory tokensHeld);\n\n    /// @notice The entire pool's collateral is available in the flash loan. Flash loan must result in a net CFMM LP token deposit that repays loan's liquidity debt\n    /// @dev Function to liquidate a loan using using a flash loan of collateral tokens from the pool and/or CFMM LP tokens. Seeks full liquidation\n    /// @param tokenId - tokenId of loan being liquidated\n    /// @param amounts - amount collateral tokens from the pool to flash loan\n    /// @param lpTokens - amount of CFMM LP tokens being flash loaned\n    /// @param to - address that will receive the collateral tokens and/or lpTokens in flash loan\n    /// @param data - optional bytes parameter for custom user defined data\n    /// @return loanLiquidity - loan liquidity liquidated (after write down if there's bad debt), flash loan fees added after write down\n    /// @return refund - amounts from collateral tokens being refunded to liquidator\n    function liquidateExternally(uint256 tokenId, uint128[] calldata amounts, uint256 lpTokens, address to, bytes calldata data) external returns(uint256 loanLiquidity, uint256[] memory refund);\n\n}\n"
      },
      "@gammaswap/v1-core/contracts/interfaces/IGammaPoolFactory.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity >=0.8.0;\n\n/// @title Interface for factory contract to create more GammaPool contracts.\n/// @author Daniel D. Alcarraz (https://github.com/0xDanr)\n/// @dev All instantiated GammaPoolFactory contracts must implement this interface\ninterface IGammaPoolFactory {\n    /// @dev Event emitted when a new GammaPool is instantiated\n    /// @param pool - address of new pool that is created\n    /// @param cfmm - address of CFMM the GammaPool is created for\n    /// @param protocolId - id identifier of GammaPool protocol (can be thought of as version)\n    /// @param implementation - implementation address of GammaPool proxy contract. Because all GammaPools are created as proxy contracts\n    /// @param tokens - ERC20 tokens of CFMM\n    /// @param count - number of GammaPools instantiated including this contract\n    event PoolCreated(address indexed pool, address indexed cfmm, uint16 indexed protocolId, address implementation, address[] tokens, uint256 count);\n\n    /// @dev Event emitted when a GammaPool fee is updated\n    /// @param pool - address of new pool whose fee is updated (zero address is default params)\n    /// @param to - receiving address of protocol fees\n    /// @param protocolFee - protocol fee share charged from interest rate accruals\n    /// @param origFeeShare - protocol fee share charged on origination fees\n    /// @param isSet - bool flag, true use fee information, false use GammaSwap default fees\n    event FeeUpdate(address indexed pool, address indexed to, uint16 protocolFee, uint16 origFeeShare, bool isSet);\n\n    /// @dev Event emitted when a GammaPool parameters are updated\n    /// @param pool - address of GammaPool whose origination fee parameters will be updated\n    /// @param origFee - loan opening origination fee in basis points\n    /// @param extSwapFee - external swap fee in basis points, max 255 basis points = 2.55%\n    /// @param emaMultiplier - multiplier used in EMA calculation of utilization rate\n    /// @param minUtilRate1 - minimum utilization rate to calculate dynamic origination fee using exponential model\n    /// @param minUtilRate2 - minimum utilization rate to calculate dynamic origination fee using linear model\n    /// @param feeDivisor - fee divisor for calculating origination fee, based on 2^(maxUtilRate - minUtilRate1)\n    /// @param liquidationFee - liquidation fee to charge during liquidations in basis points (1 - 255 => 0.01% to 2.55%)\n    /// @param ltvThreshold - ltv threshold (1 - 255 => 0.1% to 25.5%)\n    /// @param minBorrow - minimum liquidity amount that can be borrowed or left unpaid in a loan\n    event PoolParamsUpdate(address indexed pool, uint16 origFee, uint8 extSwapFee, uint8 emaMultiplier, uint8 minUtilRate1, uint8 minUtilRate2, uint16 feeDivisor, uint8 liquidationFee, uint8 ltvThreshold, uint72 minBorrow);\n\n    /// @dev Check if protocol is restricted. Which means only owner of GammaPoolFactory is allowed to instantiate GammaPools using this protocol\n    /// @param _protocolId - id identifier of GammaPool protocol (can be thought of as version) that is being checked\n    /// @return _isRestricted - true if protocol is restricted, false otherwise\n    function isProtocolRestricted(uint16 _protocolId) external view returns(bool);\n\n    /// @dev Set a protocol to be restricted or unrestricted. That means only owner of GammaPoolFactory is allowed to instantiate GammaPools using this protocol\n    /// @param _protocolId - id identifier of GammaPool protocol (can be thought of as version) that is being restricted\n    /// @param _isRestricted - set to true for restricted, set to false for unrestricted\n    function setIsProtocolRestricted(uint16 _protocolId, bool _isRestricted) external;\n\n    /// @notice Only owner of GammaPoolFactory can call this function\n    /// @dev Add a protocol implementation to GammaPoolFactory contract. Which means GammaPoolFactory can create GammaPools with this implementation (protocol)\n    /// @param _implementation - implementation address of GammaPool proxy contract. Because all GammaPools are created as proxy contracts\n    function addProtocol(address _implementation) external;\n\n    /// @notice Only owner of GammaPoolFactory can call this function\n    /// @dev Update protocol implementation for a protocol.\n    /// @param _protocolId - id identifier of GammaPool implementation\n    /// @param _newImplementation - implementation address of GammaPool proxy contract. Because all GammaPools are created as proxy contracts\n    function updateProtocol(uint16 _protocolId, address _newImplementation) external;\n\n    /// @notice Only owner of GammaPoolFactory can call this function\n    /// @dev Locks protocol implementation for upgradable protocols (<10000) so GammaPoolFactory can no longer update the implementation contract for this upgradable protocol\n    /// @param _protocolId - id identifier of GammaPool implementation\n    function lockProtocol(uint16 _protocolId) external;\n\n    /// @dev Get implementation address that maps to protocolId. This is the actual implementation code that a GammaPool implements for a protocolId\n    /// @param _protocolId - id identifier of GammaPool implementation (can be thought of as version)\n    /// @return _address - implementation address of GammaPool proxy contract. Because all GammaPools are created as proxy contracts\n    function getProtocol(uint16 _protocolId) external view returns (address);\n\n    /// @dev Get beacon address that maps to protocolId. This beacon contract contains the implementation address of the GammaPool proxy\n    /// @param _protocolId - id identifier of GammaPool implementation (can be thought of as version)\n    /// @return _address - address of beacon of GammaPool proxy contract. Because all GammaPools are created as proxy contracts if there is one\n    function getProtocolBeacon(uint16 _protocolId) external view returns (address);\n\n    /// @dev Instantiate a new GammaPool for a CFMM based on an existing implementation (protocolId)\n    /// @param _protocolId - id identifier of GammaPool protocol (can be thought of as version)\n    /// @param _cfmm - address of CFMM the GammaPool is created for\n    /// @param _tokens - addresses of ERC20 tokens in CFMM, used for validation during runtime of function\n    /// @param _data - custom struct containing additional information used to verify the `_cfmm`\n    /// @return _address - address of new GammaPool proxy contract that was instantiated\n    function createPool(uint16 _protocolId, address _cfmm, address[] calldata _tokens, bytes calldata _data) external returns(address);\n\n    /// @dev Mapping of bytes32 salts (key) to GammaPool addresses. The salt is predetermined and used to instantiate a GammaPool with a unique address\n    /// @param _salt - the bytes32 key that is unique to the GammaPool and therefore also used as a unique identifier of the GammaPool\n    /// @return _address - address of GammaPool that maps to bytes32 salt (key)\n    function getPool(bytes32 _salt) external view returns(address);\n\n    /// @dev Mapping of bytes32 salts (key) to GammaPool addresses. The salt is predetermined and used to instantiate a GammaPool with a unique address\n    /// @param _pool - address of GammaPool that maps to bytes32 salt (key)\n    /// @return _salt - the bytes32 key that is unique to the GammaPool and therefore also used as a unique identifier of the GammaPool\n    function getKey(address _pool) external view returns(bytes32);\n\n    /// @return count - number of GammaPools that have been instantiated through this GammaPoolFactory contract\n    function allPoolsLength() external view returns (uint256);\n\n    /// @dev Get pool fee parameters used to calculate protocol fees\n    /// @param _pool - pool address identifier\n    /// @return _to - address receiving fee\n    /// @return _protocolFee - protocol fee share charged from interest rate accruals\n    /// @return _origFeeShare - protocol fee share charged on origination fees\n    /// @return _isSet - bool flag, true use fee information, false use GammaSwap default fees\n    function getPoolFee(address _pool) external view returns (address _to, uint256 _protocolFee, uint256 _origFeeShare, bool _isSet);\n\n    /// @dev Set pool fee parameters used to calculate protocol fees\n    /// @param _pool - id identifier of GammaPool protocol (can be thought of as version)\n    /// @param _to - address receiving fee\n    /// @param _protocolFee - protocol fee share charged from interest rate accruals\n    /// @param _origFeeShare - protocol fee share charged on origination fees\n    /// @param _isSet - bool flag, true use fee information, false use GammaSwap default fees\n    function setPoolFee(address _pool, address _to, uint16 _protocolFee, uint16 _origFeeShare, bool _isSet) external;\n\n    /// @dev Call admin function in GammaPool contract\n    /// @param _pool - address of GammaPool whose admin function will be called\n    /// @param _data - custom struct containing information to execute in pool contract\n    function execute(address _pool, bytes calldata _data) external;\n\n    /// @dev Pause a GammaPool's function identified by a `_functionId`\n    /// @param _pool - address of GammaPool whose functions we will pause\n    /// @param _functionId - id of function in GammaPool we want to pause\n    /// @return _functionIds - uint256 number containing all turned on (paused) function ids\n    function pausePoolFunction(address _pool, uint8 _functionId) external returns(uint256 _functionIds) ;\n\n    /// @dev Unpause a GammaPool's function identified by a `_functionId`\n    /// @param _pool - address of GammaPool whose functions we will unpause\n    /// @param _functionId - id of function in GammaPool we want to unpause\n    /// @return _functionIds - uint256 number containing all turned on (paused) function ids\n    function unpausePoolFunction(address _pool, uint8 _functionId) external returns(uint256 _functionIds) ;\n\n    /// @return fee - protocol fee charged by GammaPool to liquidity borrowers in terms of basis points\n    function fee() external view returns(uint16);\n\n    /// @return origFeeShare - protocol fee share charged on origination fees\n    function origFeeShare() external view returns(uint16);\n\n    /// @return feeTo - address that receives protocol fees\n    function feeTo() external view returns(address);\n\n    /// @return feeToSetter - address that has the power to set protocol fees\n    function feeToSetter() external view returns(address);\n\n    /// @return feeTo - address that receives protocol fees\n    /// @return fee - protocol fee charged by GammaPool to liquidity borrowers in terms of basis points\n    /// @return origFeeShare - protocol fee share charged on origination fees\n    function feeInfo() external view returns(address,uint256,uint256);\n\n    /// @dev Get list of pools from start index to end index. If it goes over index it returns up to the max size of allPools array\n    /// @param start - start index of pools to search\n    /// @param end - end index of pools to search\n    /// @return _pools - all pools requested\n    function getPools(uint256 start, uint256 end) external view returns(address[] memory _pools);\n\n    /// @dev See {IGammaPoolFactory-setFee}\n    function setFee(uint16 _fee) external;\n\n    /// @dev See {IGammaPoolFactory-setFeeTo}\n    function setFeeTo(address _feeTo) external;\n\n    /// @dev See {IGammaPoolFactory-setOrigFeeShare}\n    function setOrigFeeShare(uint16 _origFeeShare) external;\n\n    /// @dev See {IGammaPoolFactory-setFeeToSetter}\n    function setFeeToSetter(address _feeToSetter) external;\n\n}"
      },
      "@gammaswap/v1-core/contracts/interfaces/IPausable.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity >=0.8.0;\n\n/// @title Interface for Pausable contract\n/// @author Daniel D. Alcarraz (https://github.com/0xDanr)\n/// @dev All instantiated Pausable contracts must implement this interface so that they can pause individual functions\ninterface IPausable {\n\n    error ForbiddenPauser();\n    error Paused(uint8 _functionId);\n    error NotPaused(uint8 _functionId);\n\n    /// @dev Emitted when the pause is triggered by `account`.\n    event Pause(address account, uint8 _functionId);\n\n    /// @dev Emitted when the unpause is triggered by `account`.\n    event Unpause(address account, uint8 _functionId);\n\n    /// @dev Get uint256 number containing all function id bits at their current state\n    /// @return functionIds - uint256 number containing all turned on (paused) function ids\n    function functionIds() external view returns(uint256);\n\n    /// @dev Pause a GammaPool's function identified by a `_functionId`\n    /// @param _functionId - id of function in GammaPool we want to pause\n    /// @return isPaused - true if function identified by `_functionId` is paused\n    function isPaused(uint8 _functionId) external view returns (bool);\n\n    /// @dev Pause a GammaPool's function identified by a `_functionId`\n    /// @param _functionId - id of function in GammaPool we want to pause\n    /// @return _functionIds - uint256 number containing all turned on (paused) function ids\n    function pause(uint8 _functionId) external returns (uint256);\n\n    /// @dev Unpause a GammaPool's function identified by a `_functionId`\n    /// @param _functionId - id of function in GammaPool we want to unpause\n    /// @return _functionIds - uint256 number containing all turned on (paused) function ids\n    function unpause(uint8 _functionId) external returns (uint256);\n}\n"
      },
      "@gammaswap/v1-core/contracts/interfaces/IPoolViewer.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity >=0.8.0;\n\nimport \"./IGammaPool.sol\";\n\n/// @title Interface for Viewer Contract for GammaPool\n/// @author Daniel D. Alcarraz (https://github.com/0xDanr)\n/// @dev Viewer makes complex view function calls from GammaPool's storage data (e.g. updated loan and pool debt)\ninterface IPoolViewer {\n\n    /// @dev Check if can liquidate loan identified by `tokenId`\n    /// @param pool - address of pool loans belong to\n    /// @param tokenId - unique id of loan, used to look up loan in GammaPool\n    /// @return canLiquidate - true if loan can be liquidated, false otherwise\n    function canLiquidate(address pool, uint256 tokenId) external view returns(bool);\n\n    /// @dev Get latest rate information from GammaPool\n    /// @param pool - address of pool to request latest rates for\n    /// @return data - RateData struct containing latest rate information\n    function getLatestRates(address pool) external view returns(IGammaPool.RateData memory data);\n\n    /// @dev Get list of loans and their corresponding tokenIds created in GammaPool. Capped at s.tokenIds.length.\n    /// @param pool - address of pool loans belong to\n    /// @param start - index from where to start getting tokenIds from array\n    /// @param end - end index of array wishing to get tokenIds. If end > s.tokenIds.length, end is s.tokenIds.length\n    /// @param active - if true, return loans that have an outstanding liquidity debt\n    /// @return _loans - list of loans created in GammaPool\n    function getLoans(address pool, uint256 start, uint256 end, bool active) external view returns(IGammaPool.LoanData[] memory _loans);\n\n    /// @dev Get list of loans mapped to tokenIds in array `tokenIds`\n    /// @param pool - address of pool loans belong to\n    /// @param tokenIds - list of loan tokenIds\n    /// @param active - if true, return loans that have an outstanding liquidity debt\n    /// @return _loans - list of loans created in GammaPool\n    function getLoansById(address pool, uint256[] calldata tokenIds, bool active) external view returns(IGammaPool.LoanData[] memory _loans);\n\n    /// @dev Get loan with its most updated information\n    /// @param pool - address of pool loan belongs to\n    /// @param tokenId - unique id of loan, used to look up loan in GammaPool\n    /// @return loanData - loan data struct (same as Loan + tokenId)\n    function loan(address pool, uint256 tokenId) external view returns(IGammaPool.LoanData memory loanData);\n\n    /// @dev Returns pool storage data updated to their latest values\n    /// @notice Difference with getPoolData() is this struct is what PoolData would return if an update of the GammaPool were to occur at the current block\n    /// @param pool - address of pool to get pool data for\n    /// @return data - struct containing all relevant global state variables and descriptive information of GammaPool. Used to avoid making multiple calls\n    function getLatestPoolData(address pool) external view returns(IGammaPool.PoolData memory data);\n\n    /// @dev Returns same information as getLatestPoolData plus symbol and name of tokens of pool\n    /// @param pool - address of pool to get pool data for\n    /// @return data - struct containing all relevant global state variables and descriptive information of GammaPool. Used to avoid making multiple calls\n    function getLatestPoolDataWithMetaData(address pool) external view returns(IGammaPool.PoolData memory data);\n\n    /// @dev Calculate origination fee that will be charged if borrowing liquidity amount\n    /// @param pool - address of GammaPool to calculate origination fee for\n    /// @param liquidity - liquidity to borrow\n    /// @return origFee - calculated origination fee, without any discounts\n    function calcDynamicOriginationFee(address pool, uint256 liquidity) external view returns(uint256 origFee);\n\n    /// @dev Return pool storage data\n    /// @param pool - address of pool to get pool data for\n    /// @return data - struct containing all relevant global state variables and descriptive information of GammaPool. Used to avoid making multiple calls\n    function getPoolData(address pool) external view returns(IGammaPool.PoolData memory data);\n\n    /// @dev Get CFMM tokens meta data\n    /// @param _tokens - array of token address of ERC20 tokens of CFMM\n    /// @return _symbols - array of symbols of ERC20 tokens of CFMM\n    /// @return _names - array of names of ERC20 tokens of CFMM\n    /// @return _decimals - array of decimals of ERC20 tokens of CFMM\n    function getTokensMetaData(address[] memory _tokens) external view returns(string[] memory _symbols, string[] memory _names, uint8[] memory _decimals);\n\n}\n"
      },
      "@gammaswap/v1-core/contracts/interfaces/IProtocol.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity >=0.8.0;\n\n/// @title Interface for Protocol\n/// @author Daniel D. Alcarraz (https://github.com/0xDanr)\n/// @dev Interface used to add protocols and initialize them in GammaPoolFactory\ninterface IProtocol {\n    /// @dev Protocol id of the implementation contract for this GammaPool\n    function protocolId() external view returns(uint16);\n\n    /// @dev Check GammaPool for CFMM and tokens can be created with this implementation\n    /// @param _tokens - assumed tokens of CFMM, validate function should check CFMM is indeed for these tokens\n    /// @param _cfmm - address of CFMM GammaPool will be for\n    /// @param _data - custom struct containing additional information used to verify the `_cfmm`\n    /// @return _tokensOrdered - tokens ordered to match the same order as in CFMM\n    function validateCFMM(address[] calldata _tokens, address _cfmm, bytes calldata _data) external view returns(address[] memory _tokensOrdered);\n\n    /// @dev Function to initialize state variables GammaPool, called usually from GammaPoolFactory contract right after GammaPool instantiation\n    /// @param _cfmm - address of CFMM GammaPool is for\n    /// @param _tokens - ERC20 tokens of CFMM\n    /// @param _decimals - decimals of CFMM tokens, indices must match _tokens[] array\n    /// @param _data - custom struct containing additional information used to verify the `_cfmm`\n    /// @param _minBorrow - minimum amount of liquidity that can be borrowed or left unpaid in a loan\n    function initialize(address _cfmm, address[] calldata _tokens, uint8[] calldata _decimals, uint72 _minBorrow, bytes calldata _data) external;\n}\n"
      },
      "@gammaswap/v1-core/contracts/interfaces/IRefunds.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity >=0.8.0;\n\n/// @title Interface for Refunds abstract contract\n/// @author Daniel D. Alcarraz (https://github.com/0xDanr)\n/// @dev Interface used to clear tokens from a contract\ninterface IRefunds {\n    /// @dev Withdraw ERC20 tokens from contract\n    /// @param token - address of ERC20 token that will be withdrawn\n    /// @param to - destination address where withdrawn quantity will be sent to\n    /// @param minAmt - threshold balance before token can be withdrawn\n    function clearToken(address token, address to, uint256 minAmt) external;\n}\n"
      },
      "@gammaswap/v1-core/contracts/interfaces/observer/ILoanObserverStore.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity >=0.8.0;\n\n/// @title Interface for Loan Observer Store\n/// @author Daniel D. Alcarraz (https://github.com/0xDanr)\n/// @dev Interface used for Loan Observer Store implementations\ninterface ILoanObserverStore {\n\n    /// @dev Get external collateral reference for a new position being opened\n    /// @param refId - address of GammaPool we're setting an external reference for\n    /// @param refAddr - address asking collateral reference for (if not permissioned, it should revert. Normally a PositionManager)\n    /// @param refFee - discount on origination fee to be applied to loans using collateral reference address\n    /// @param refType - discount on origination fee to be applied to loans using collateral reference address\n    /// @param active - discount on origination fee to be applied to loans using collateral reference address\n    /// @param restricted - discount on origination fee to be applied to loans using collateral reference address\n    function setLoanObserver(uint256 refId, address refAddr, uint16 refFee, uint8 refType, bool active, bool restricted) external;\n\n    /// @dev Allow users to create loans in pool that will be observed by observer with reference id `refId`\n    /// @param refId - reference id of observer\n    /// @param pool - address of GammaPool we are requesting information for\n    function setPoolObserved(uint256 refId, address pool) external;\n\n    /// @dev Prohibit users to create loans in pool that will be observed by observer with reference id `refId`\n    /// @param refId - reference id of observer\n    /// @param pool - address of GammaPool we are requesting information for\n    function unsetPoolObserved(uint256 refId, address pool) external;\n\n    /// @dev Check if a pool can use observer\n    /// @param refId - reference id of observer\n    /// @param pool - address of GammaPool we are requesting information for\n    /// @return observed - if true observer can observe loans from pool\n    function isPoolObserved(uint256 refId, address pool) external view returns(bool);\n\n    /// @dev Allow a user address to open loans that can be observed by observer\n    /// @param refId - reference id of observer\n    /// @param user - address that can open loans that use observer\n    /// @param isAllowed - if true observer can observe loans created by user\n    function allowToBeObserved(uint256 refId, address user, bool isAllowed) external;\n\n    /// @dev Check if a user can open loans that are observed by observer\n    /// @param refId - reference id of observer\n    /// @param user - address that can open loans that use observer\n    /// @return allowed - if true observer can observe loans created by user\n    function isAllowedToBeObserved(uint256 refId, address user) external view returns(bool);\n\n    /// @dev Get observer identified with reference id `refId`\n    /// @param refId - reference id of information containing collateral reference\n    /// @return refAddr - address of ICollateralManager contract. Provides external collateral information\n    /// @return refFee - discount for loan associated with this reference id\n    /// @return refType - discount for loan associated with this reference id\n    /// @return active - discount on origination fee to be applied to loans using collateral reference address\n    /// @return restricted - discount on origination fee to be applied to loans using collateral reference address\n    function getLoanObserver(uint256 refId) external view returns(address, uint16, uint8, bool, bool);\n\n    /// @dev Get observer for a new loan being opened if the observer exists, the pool is registered with the observer,\n    /// @dev and the user is allowed to create loans observed by observer identified by `refId`\n    /// @param refId - reference id of information containing collateral reference\n    /// @param pool - address asking collateral reference for (if not permissioned, it should revert. Normally a PositionManager)\n    /// @param user - address asking collateral reference for\n    /// @return refAddr - address of ICollateralManager contract. Provides external collateral information\n    /// @return refFee - discount for loan associated with this reference id\n    /// @return refType - discount for loan associated with this reference id\n    function getPoolObserverByUser(uint16 refId, address pool, address user) external view returns(address, uint16, uint8);\n}\n"
      },
      "@gammaswap/v1-core/contracts/interfaces/rates/IRateModel.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity >=0.8.0;\n\n/// @title Interface of Interest Rate Model Store\n/// @author Daniel D. Alcarraz (https://github.com/0xDanr)\n/// @notice Interface of contract that saves and retrieves interest rate model parameters\ninterface IRateModel {\n    /// @dev Function to validate interest rate model parameters\n    /// @param _data - bytes parameters containing interest rate model parameters\n    /// @return validation - true if parameters passed validation\n    function validateParameters(bytes calldata _data) external view returns(bool);\n\n    /// @dev Gets address of contract containing parameters for interest rate model\n    /// @return address - address of smart contract that stores interest rate parameters\n    function rateParamsStore() external view returns(address);\n}\n"
      },
      "@gammaswap/v1-core/contracts/interfaces/strategies/base/ILiquidationStrategy.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity >=0.8.0;\n\nimport \"../events/ILiquidationStrategyEvents.sol\";\n\n/// @title Interface for Liquidation Strategy contracts\n/// @author Daniel D. Alcarraz (https://github.com/0xDanr)\n/// @dev Parent interface of every Liquidation strategy\ninterface ILiquidationStrategy is ILiquidationStrategyEvents {\n    /// @return minimum liquidation fee charged during liquidation of a loan\n    function liquidationFee() external view returns(uint256);\n\n    /// @dev Check if can liquidate loan based on liquidity debt and collateral\n    /// @param liquidity - liquidity debt of loan\n    /// @param collateral - liquidity invariant calculated from collateral tokens (`tokensHeld`)\n    /// @return canLiquidate - true if loan can be liquidated, false otherwise\n    function canLiquidate(uint256 liquidity, uint256 collateral) external view returns(bool);\n}\n"
      },
      "@gammaswap/v1-core/contracts/interfaces/strategies/base/ILongStrategy.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity >=0.8.0;\n\nimport \"../events/ILongStrategyEvents.sol\";\n\n/// @title Interface for Long Strategy\n/// @author Daniel D. Alcarraz (https://github.com/0xDanr)\n/// @dev Used in strategies that borrow and repay liquidity loans\ninterface ILongStrategy is ILongStrategyEvents {\n    /// @return loan to value threshold over which a loan is eligible for liquidation\n    function ltvThreshold() external view returns(uint256);\n}\n"
      },
      "@gammaswap/v1-core/contracts/interfaces/strategies/base/IShortStrategy.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity >=0.8.0;\n\nimport \"../events/IShortStrategyEvents.sol\";\n\n/// @title Interface for Short Strategy\n/// @author Daniel D. Alcarraz (https://github.com/0xDanr)\n/// @dev Used in strategies that deposit and withdraw liquidity from CFMM for liquidity providers\ninterface IShortStrategy is IShortStrategyEvents {\n\n    /// @dev Parameters used to calculate the GS LP tokens and CFMM LP tokens in the GammaPool after protocol fees and accrued interest\n    struct VaultBalancesParams {\n        /// @dev address of factory contract of GammaPool\n        address factory;\n        /// @dev address of GammaPool\n        address pool;\n        /// @dev address of contract holding rate parameters for pool\n        address paramsStore;\n        /// @dev storage number of borrowed liquidity invariant in GammaPool\n        uint256 BORROWED_INVARIANT;\n        /// @dev current liquidity invariant in CFMM\n        uint256 latestCfmmInvariant;\n        /// @dev current total supply of CFMM LP tokens in existence\n        uint256 latestCfmmTotalSupply;\n        /// @dev last block number GammaPool was updated\n        uint256 LAST_BLOCK_NUMBER;\n        /// @dev CFMM liquidity invariant at time of last update of GammaPool\n        uint256 lastCFMMInvariant;\n        /// @dev CFMM LP Token supply at time of last update of GammaPool\n        uint256 lastCFMMTotalSupply;\n        /// @dev CFMM Fee Index at time of last update of GammaPool\n        uint256 lastCFMMFeeIndex;\n        /// @dev current total supply of GS LP tokens\n        uint256 totalSupply;\n        /// @dev current LP Tokens in GammaPool counted at time of last update\n        uint256 LP_TOKEN_BALANCE;\n        /// @dev liquidity invariant of LP tokens in GammaPool at time of last update\n        uint256 LP_INVARIANT;\n    }\n\n\n    /// @dev Deposit CFMM LP tokens and get GS LP tokens, without doing a transferFrom transaction. Must have sent CFMM LP tokens first\n    /// @param to - address of receiver of GS LP token\n    /// @return shares - quantity of GS LP tokens received for CFMM LP tokens\n    function _depositNoPull(address to) external returns(uint256 shares);\n\n    /// @dev Withdraw CFMM LP tokens, by burning GS LP tokens, without doing a transferFrom transaction. Must have sent GS LP tokens first\n    /// @param to - address of receiver of CFMM LP tokens\n    /// @return assets - quantity of CFMM LP tokens received for GS LP tokens\n    function _withdrawNoPull(address to) external returns(uint256 assets);\n\n    /// @dev Withdraw reserve token quantities of CFMM (instead of CFMM LP tokens), by burning GS LP tokens\n    /// @param to - address of receiver of reserve token quantities\n    /// @return reserves - quantity of reserve tokens withdrawn from CFMM and sent to receiver\n    /// @return assets - quantity of CFMM LP tokens representing reserve tokens withdrawn\n    function _withdrawReserves(address to) external returns(uint256[] memory reserves, uint256 assets);\n\n    /// @dev Deposit reserve token quantities to CFMM (instead of CFMM LP tokens) to get CFMM LP tokens, store them in GammaPool and receive GS LP tokens\n    /// @param to - address of receiver of GS LP tokens\n    /// @param amountsDesired - desired amounts of reserve tokens to deposit\n    /// @param amountsMin - minimum amounts of reserve tokens to deposit\n    /// @param data - information identifying request to deposit\n    /// @return reserves - quantity of actual reserve tokens deposited in CFMM\n    /// @return shares - quantity of GS LP tokens received for reserve tokens deposited\n    function _depositReserves(address to, uint256[] calldata amountsDesired, uint256[] calldata amountsMin, bytes calldata data) external returns(uint256[] memory reserves, uint256 shares);\n\n    /// @dev Get latest reserves in the CFMM, which can be used for pricing\n    /// @param cfmmData - bytes data for calculating CFMM reserves\n    /// @return cfmmReserves - reserves in the CFMM\n    function _getLatestCFMMReserves(bytes memory cfmmData) external view returns(uint128[] memory cfmmReserves);\n\n    /// @dev Get latest invariant from CFMM\n    /// @param cfmmData - bytes data for calculating CFMM invariant\n    /// @return cfmmInvariant - reserves in the CFMM\n    function _getLatestCFMMInvariant(bytes memory cfmmData) external view returns(uint256 cfmmInvariant);\n\n    /// @dev Calculate current total CFMM LP tokens (real and virtual) in existence in the GammaPool, including accrued interest\n    /// @param borrowedInvariant - invariant amount borrowed in GammaPool including accrued interest calculated in last update to GammaPool\n    /// @param lpBalance - amount of LP tokens deposited in GammaPool\n    /// @param lastCFMMInvariant - invariant amount in CFMM\n    /// @param lastCFMMTotalSupply - total supply in CFMM\n    /// @param lastFeeIndex - last fees charged by GammaPool since last update\n    /// @return totalAssets - total CFMM LP tokens in existence in the pool (real and virtual) including accrued interest\n    function totalAssets(uint256 borrowedInvariant, uint256 lpBalance, uint256 lastCFMMInvariant, uint256 lastCFMMTotalSupply, uint256 lastFeeIndex) external view returns(uint256);\n\n    /// @dev Calculate current total GS LP tokens in the GammaPool after dilution from protocol fees\n    /// @param factory - address of factory contract that created GammaPool\n    /// @param pool - address of pool to get interest rate calculations for\n    /// @param lastCFMMFeeIndex - accrued CFMM Fees in storage\n    /// @param lastFeeIndex - last fees charged by GammaPool since last update\n    /// @param utilizationRate - current utilization rate of GammaPool\n    /// @param supply - actual GS LP total supply available in the pool\n    /// @return totalSupply - total GS LP tokens in the pool including accrued interest\n    function totalSupply(address factory, address pool, uint256 lastCFMMFeeIndex, uint256 lastFeeIndex, uint256 utilizationRate, uint256 supply) external view returns (uint256);\n\n    /// @dev Calculate fees charged by GammaPool since last update to liquidity loans and current borrow rate\n    /// @param borrowRate - current borrow rate of GammaPool\n    /// @param borrowedInvariant - invariant amount borrowed in GammaPool including accrued interest calculated in last update to GammaPool\n    /// @param lastCFMMInvariant - current invariant amount of CFMM in GammaPool\n    /// @param lastCFMMTotalSupply - current total supply of CFMM LP shares in GammaPool\n    /// @param prevCFMMInvariant - invariant amount in CFMM in last update to GammaPool\n    /// @param prevCFMMTotalSupply - total supply in CFMM in last update to GammaPool\n    /// @param lastBlockNum - last block GammaPool was updated\n    /// @param lastCFMMFeeIndex - last fees accrued by CFMM since last update\n    /// @param maxCFMMFeeLeverage - max leverage of CFMM yield\n    /// @param spread - spread to add to cfmmFeeIndex\n    /// @return lastFeeIndex - last fees charged by GammaPool since last update\n    /// @return updLastCFMMFeeIndex - updated fees accrued by CFMM till current block\n    function getLastFees(uint256 borrowRate, uint256 borrowedInvariant, uint256 lastCFMMInvariant, uint256 lastCFMMTotalSupply,\n        uint256 prevCFMMInvariant, uint256 prevCFMMTotalSupply, uint256 lastBlockNum, uint256 lastCFMMFeeIndex,\n        uint256 maxCFMMFeeLeverage, uint256 spread) external view returns(uint256 lastFeeIndex, uint256 updLastCFMMFeeIndex);\n\n    /// @dev Calculate current total GS LP tokens after protocol fees and total CFMM LP tokens (real and virtual) in\n    /// @dev existence in the GammaPool after accrued interest. The total assets and supply numbers returned by this\n    /// @dev function are used in the ERC4626 implementation of the GammaPool\n    /// @param vaultBalanceParams - parameters from GammaPool to calculate current total GS LP Tokens and CFMM LP Tokens after fees and interest\n    /// @return assets - total CFMM LP tokens in existence in the pool (real and virtual) including accrued interest\n    /// @return supply - total GS LP tokens in the pool including accrued interest\n    function totalAssetsAndSupply(VaultBalancesParams memory vaultBalanceParams) external view returns(uint256 assets, uint256 supply);\n\n    /// @dev Calculate balances updated by fees charged since last update\n    /// @param lastFeeIndex - last fees charged by GammaPool since last update\n    /// @param borrowedInvariant - invariant amount borrowed in GammaPool including accrued interest calculated in last update to GammaPool\n    /// @param lpBalance - amount of LP tokens deposited in GammaPool\n    /// @param lastCFMMInvariant - invariant amount in CFMM\n    /// @param lastCFMMTotalSupply - total supply in CFMM\n    /// @return lastLPBalance - last fees accrued by CFMM since last update\n    /// @return lastBorrowedLPBalance - last fees charged by GammaPool since last update\n    /// @return lastBorrowedInvariant - current borrow rate of GammaPool\n    function getLatestBalances(uint256 lastFeeIndex, uint256 borrowedInvariant, uint256 lpBalance, uint256 lastCFMMInvariant,\n        uint256 lastCFMMTotalSupply) external view returns(uint256 lastLPBalance, uint256 lastBorrowedLPBalance, uint256 lastBorrowedInvariant);\n\n    /// @dev Update pool invariant, LP tokens borrowed plus interest, interest rate index, and last block update\n    /// @param utilizationRate - interest accrued to loans in GammaPool\n    /// @param emaUtilRateLast - interest accrued to loans in GammaPool\n    /// @param emaMultiplier - interest accrued to loans in GammaPool\n    /// @return emaUtilRate - interest accrued to loans in GammaPool\n    function calcUtilRateEma(uint256 utilizationRate, uint256 emaUtilRateLast, uint256 emaMultiplier) external view returns(uint256 emaUtilRate);\n\n    /// @dev Synchronize LP_TOKEN_BALANCE with actual CFMM LP tokens deposited in GammaPool\n    function _sync() external;\n\n    /***** ERC4626 Functions *****/\n\n    /// @dev Deposit CFMM LP tokens and get GS LP tokens, does a transferFrom according to ERC4626 implementation\n    /// @param assets - CFMM LP tokens deposited in exchange for GS LP tokens\n    /// @param to - address receiving GS LP tokens\n    /// @return shares - quantity of GS LP tokens sent to receiver address (`to`) for CFMM LP tokens\n    function _deposit(uint256 assets, address to) external returns (uint256 shares);\n\n    /// @dev Mint GS LP token in exchange for CFMM LP token deposits, does a transferFrom according to ERC4626 implementation\n    /// @param shares - GS LP tokens minted from CFMM LP token deposits\n    /// @param to - address receiving GS LP tokens\n    /// @return assets - quantity of CFMM LP tokens sent to receiver address (`to`)\n    function _mint(uint256 shares, address to) external returns (uint256 assets);\n\n    /// @dev Withdraw CFMM LP token by burning GS LP tokens\n    /// @param assets - amount of CFMM LP tokens requested to withdraw in exchange for GS LP tokens\n    /// @param to - address receiving CFMM LP tokens\n    /// @param from - address burning its GS LP tokens\n    /// @return shares - quantity of GS LP tokens burned\n    function _withdraw(uint256 assets, address to, address from) external returns (uint256 shares);\n\n    /// @dev Redeem GS LP tokens and get CFMM LP token\n    /// @param shares - GS LP tokens requested to redeem in exchange for GS LP tokens\n    /// @param to - address receiving CFMM LP tokens\n    /// @param from - address redeeming GS LP tokens\n    /// @return assets - quantity of CFMM LP tokens sent to receiver address (`to`) for GS LP tokens redeemed\n    function _redeem(uint256 shares, address to, address from) external returns (uint256 assets);\n}"
      },
      "@gammaswap/v1-core/contracts/interfaces/strategies/events/IExternalStrategyEvents.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity >=0.8.0;\n\nimport \"./IStrategyEvents.sol\";\n\n/// @title External Strategy Events Interface\n/// @author Daniel D. Alcarraz (https://github.com/0xDanr)\n/// @dev Events emitted by external strategy (flash loans) implementations\ninterface IExternalStrategyEvents is IStrategyEvents {\n    /// @dev Event emitted when a flash loan is made. Purpose of flash loan is for external swaps/rebalance of loan collateral\n    /// @param tokenId - unique id that identifies the loan in question\n    /// @param amounts - amounts of tokens held as collateral in pool that were swapped\n    /// @param lpTokens - LP tokens swapped externally\n    /// @param liquidity - total liquidity externally swapped in flash loan (amounts + lpTokens)\n    /// @param txType - transaction type. Possible values come from enum TX_TYPE\n    event ExternalSwap(uint256 indexed tokenId, uint128[] amounts, uint256 lpTokens, uint128 liquidity, TX_TYPE indexed txType);\n}\n"
      },
      "@gammaswap/v1-core/contracts/interfaces/strategies/events/IGammaPoolERC20Events.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity >=0.8.0;\n\n/// @title GammaPool ERC20 Events\n/// @author Daniel D. Alcarraz (https://github.com/0xDanr)\n/// @dev Events that should be emitted by all strategy implementations (root of all strategy events interfaces)\ninterface IGammaPoolERC20Events {\n    /// @dev Emitted when `amount` GS LP tokens are moved from account `from` to account `to`.\n    /// @param from - address sending GS LP tokens\n    /// @param to - address receiving GS LP tokens\n    /// @param amount - amount of GS LP tokens being sent\n    event Transfer(address indexed from, address indexed to, uint256 amount);\n\n    /// @dev Emitted when the allowance of a `spender` for an `owner` is set by a call to approve function. `amount` is the new allowance.\n    /// @param owner - address which owns the GS LP tokens spender is being given permission to spend\n    /// @param spender - address given permission to spend owner's GS LP tokens\n    /// @param amount - amount of GS LP tokens spender is given permission to spend\n    event Approval(address indexed owner, address indexed spender, uint256 amount);\n}\n"
      },
      "@gammaswap/v1-core/contracts/interfaces/strategies/events/ILiquidationStrategyEvents.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity >=0.8.0;\n\nimport \"./ILongStrategyEvents.sol\";\n\n/// @title Liquidation Strategy Events Interface\n/// @author Daniel D. Alcarraz (https://github.com/0xDanr)\n/// @dev Events emitted by all liquidation strategy implementations\ninterface ILiquidationStrategyEvents is ILongStrategyEvents {\n    /// @dev Event emitted when liquidating through _liquidate or _liquidateWithLP functions\n    /// @param tokenId - id identifier of loan being liquidated\n    /// @param collateral - collateral of loan being liquidated\n    /// @param liquidity - liquidity debt being repaid\n    /// @param writeDownAmt - amount of liquidity invariant being written down\n    /// @param fee - liquidation fee paid to liquidator in liquidity invariant units\n    /// @param txType - type of liquidation. Possible values come from enum TX_TYPE\n    event Liquidation(uint256 indexed tokenId, uint128 collateral, uint128 liquidity, uint128 writeDownAmt, uint128 fee, TX_TYPE txType);\n}"
      },
      "@gammaswap/v1-core/contracts/interfaces/strategies/events/ILongStrategyEvents.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity >=0.8.0;\n\nimport \"./IStrategyEvents.sol\";\n\n/// @title Long Strategy Events Interface\n/// @author Daniel D. Alcarraz (https://github.com/0xDanr)\n/// @dev Events emitted by all long strategy implementations\ninterface ILongStrategyEvents is IStrategyEvents {\n    /// @dev Event emitted when a Loan is updated\n    /// @param tokenId - unique id that identifies the loan in question\n    /// @param tokensHeld - amounts of tokens held as collateral against the loan\n    /// @param liquidity - liquidity invariant that was borrowed including accrued interest\n    /// @param initLiquidity - initial liquidity borrowed excluding interest (principal)\n    /// @param lpTokens - LP tokens borrowed excluding interest (principal)\n    /// @param rateIndex - interest rate index of GammaPool at time loan is updated\n    /// @param txType - transaction type. Possible values come from enum TX_TYPE\n    event LoanUpdated(uint256 indexed tokenId, uint128[] tokensHeld, uint128 liquidity, uint128 initLiquidity, uint256 lpTokens, uint96 rateIndex, TX_TYPE indexed txType);\n}\n"
      },
      "@gammaswap/v1-core/contracts/interfaces/strategies/events/IShortStrategyEvents.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity >=0.8.0;\n\nimport \"./IStrategyEvents.sol\";\n\n/// @title Short Strategy Events Interface\n/// @author Daniel D. Alcarraz (https://github.com/0xDanr)\n/// @dev Events emitted by all short strategy implementations\ninterface IShortStrategyEvents is IStrategyEvents {\n    /// @dev Event emitted when a deposit of CFMM LP tokens in exchange of GS LP tokens happens (e.g. _deposit, _mint, _depositReserves, _depositNoPull)\n    /// @param caller - address calling the function to deposit CFMM LP tokens\n    /// @param to - address receiving GS LP tokens\n    /// @param assets - amount CFMM LP tokens deposited\n    /// @param shares - amount GS LP tokens minted\n    event Deposit(address indexed caller, address indexed to, uint256 assets, uint256 shares);\n\n    /// @dev Event emitted when a withdrawal of CFMM LP tokens happens (e.g. _withdraw, _redeem, _withdrawReserves, _withdrawNoPull)\n    /// @param caller - address calling the function to withdraw CFMM LP tokens\n    /// @param to - address receiving CFMM LP tokens\n    /// @param from - address redeeming/burning GS LP tokens\n    /// @param assets - amount of CFMM LP tokens withdrawn\n    /// @param shares - amount of GS LP tokens redeemed\n    event Withdraw(address indexed caller, address indexed to, address indexed from, uint256 assets, uint256 shares);\n}\n"
      },
      "@gammaswap/v1-core/contracts/interfaces/strategies/events/IStrategyEvents.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity >=0.8.0;\n\n/// @title Strategy Events interface\n/// @author Daniel D. Alcarraz (https://github.com/0xDanr)\n/// @dev Events that should be emitted by all strategy implementations (root of all strategy events interfaces)\ninterface IStrategyEvents {\n    enum TX_TYPE {\n        DEPOSIT_LIQUIDITY,      // 0\n        WITHDRAW_LIQUIDITY,     // 1\n        DEPOSIT_RESERVES,       // 2\n        WITHDRAW_RESERVES,      // 3\n        INCREASE_COLLATERAL,    // 4\n        DECREASE_COLLATERAL,    // 5\n        REBALANCE_COLLATERAL,   // 6\n        BORROW_LIQUIDITY,       // 7\n        REPAY_LIQUIDITY,        // 8\n        REPAY_LIQUIDITY_SET_RATIO,// 9\n        REPAY_LIQUIDITY_WITH_LP,// 10\n        LIQUIDATE,              // 11\n        LIQUIDATE_WITH_LP,      // 12\n        BATCH_LIQUIDATION,      // 13\n        SYNC,                   // 14\n        EXTERNAL_REBALANCE,     // 15\n        EXTERNAL_LIQUIDATION,   // 16\n        UPDATE_POOL }           // 17\n\n    /// @dev Event emitted when the Pool's global state variables is updated\n    /// @param lpTokenBalance - quantity of CFMM LP tokens deposited in the pool\n    /// @param lpTokenBorrowed - quantity of CFMM LP tokens that have been borrowed from the pool (principal)\n    /// @param lastBlockNumber - last block the Pool's where updated\n    /// @param accFeeIndex - interest of total accrued interest in the GammaPool until current update\n    /// @param lpTokenBorrowedPlusInterest - quantity of CFMM LP tokens that have been borrowed from the pool including interest\n    /// @param lpInvariant - lpTokenBalance as invariant units\n    /// @param borrowedInvariant - lpTokenBorrowedPlusInterest as invariant units\n    /// @param cfmmReserves - reserves in CFMM. Used to track price\n    /// @param txType - transaction type. Possible values come from enum TX_TYPE\n    event PoolUpdated(uint256 lpTokenBalance, uint256 lpTokenBorrowed, uint40 lastBlockNumber, uint80 accFeeIndex,\n        uint256 lpTokenBorrowedPlusInterest, uint128 lpInvariant, uint128 borrowedInvariant, uint128[] cfmmReserves, TX_TYPE indexed txType);\n}"
      },
      "@gammaswap/v1-core/contracts/interfaces/strategies/lending/IBorrowStrategy.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity >=0.8.0;\n\nimport \"../base/ILongStrategy.sol\";\n\n/// @title Interface for Borrow Strategy\n/// @author Daniel D. Alcarraz (https://github.com/0xDanr)\n/// @dev Used in strategies that borrow liquidity\ninterface IBorrowStrategy is ILongStrategy {\n    /// @dev Calculate and return dynamic origination fee in basis points\n    /// @param baseOrigFee - base origination fee charge\n    /// @param utilRate - current utilization rate of GammaPool\n    /// @param lowUtilRate - low utilization rate threshold, used as a lower bound for the utilization rate\n    /// @param minUtilRate1 - minimum utilization rate after which origination fee will start increasing exponentially\n    /// @param minUtilRate2 - minimum utilization rate after which origination fee will start increasing linearly\n    /// @param feeDivisor - fee divisor of formula for dynamic origination fee\n    /// @return origFee - origination fee that will be applied to loan\n    function calcDynamicOriginationFee(uint256 baseOrigFee, uint256 utilRate, uint256 lowUtilRate, uint256 minUtilRate1, uint256 minUtilRate2, uint256 feeDivisor) external view returns(uint256 origFee);\n\n    /// @dev Deposit more collateral in loan identified by tokenId\n    /// @param tokenId - unique id identifying loan\n    /// @param ratio - ratio to rebalance collateral after increasing collateral\n    /// @return tokensHeld - updated collateral token amounts backing loan\n    function _increaseCollateral(uint256 tokenId, uint256[] calldata ratio) external returns(uint128[] memory tokensHeld);\n\n    /// @dev Withdraw collateral from loan identified by tokenId\n    /// @param tokenId - unique id identifying loan\n    /// @param amounts - amounts of collateral tokens requested to withdraw\n    /// @param to - destination address of receiver of collateral withdrawn\n    /// @param ratio - ratio to rebalance collateral after withdrawing collateral\n    /// @return tokensHeld - updated collateral token amounts backing loan\n    function _decreaseCollateral(uint256 tokenId, uint128[] memory amounts, address to, uint256[] calldata ratio) external returns(uint128[] memory tokensHeld);\n\n    /// @dev Borrow liquidity from the CFMM and add it to the debt and collateral of loan identified by tokenId\n    /// @param tokenId - unique id identifying loan\n    /// @param lpTokens - amount of CFMM LP tokens requested to short\n    /// @param ratio - weights of collateral after borrowing liquidity\n    /// @return liquidityBorrowed - liquidity amount that has been borrowed\n    /// @return amounts - reserves quantities withdrawn from CFMM that correspond to the LP tokens shorted, now used as collateral\n    /// @return tokensHeld - updated collateral token amounts backing loan\n    function _borrowLiquidity(uint256 tokenId, uint256 lpTokens, uint256[] calldata ratio) external returns(uint256 liquidityBorrowed, uint256[] memory amounts, uint128[] memory tokensHeld);\n}\n"
      },
      "@gammaswap/v1-core/contracts/interfaces/strategies/lending/IRepayStrategy.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity >=0.8.0;\n\nimport \"../base/ILongStrategy.sol\";\n\n/// @title Interface for Repay Strategy\n/// @author Daniel D. Alcarraz (https://github.com/0xDanr)\n/// @dev Used in strategies that repay liquidity loans\ninterface IRepayStrategy is ILongStrategy {\n\n    /// @dev Repay liquidity debt of loan identified by tokenId, using CFMM LP token\n    /// @param tokenId - unique id identifying loan\n    /// @param collateralId - index of collateral token to rebalance to + 1\n    /// @param to - if repayment type requires withdrawal, the address that will receive the funds. Otherwise can be zero address\n    /// @return liquidityPaid - liquidity amount that has been repaid\n    /// @return tokensHeld - remaining token amounts collateralizing loan\n    function _repayLiquidityWithLP(uint256 tokenId, uint256 collateralId, address to) external returns(uint256 liquidityPaid, uint128[] memory tokensHeld);\n\n    /// @dev Repay liquidity debt of loan identified by tokenId, debt is repaid using available collateral in loan\n    /// @param tokenId - unique id identifying loan\n    /// @param liquidity - liquidity debt being repaid, capped at actual liquidity owed. Can't repay more than you owe\n    /// @param collateralId - index of collateral token to rebalance to + 1\n    /// @param to - if repayment type requires withdrawal, the address that will receive the funds. Otherwise can be zero address\n    /// @return liquidityPaid - liquidity amount that has been repaid\n    /// @return amounts - collateral amounts consumed in repaying liquidity debt\n    function _repayLiquidity(uint256 tokenId, uint256 liquidity, uint256 collateralId, address to) external returns(uint256 liquidityPaid, uint256[] memory amounts);\n\n    /// @dev Repay liquidity debt of loan identified by tokenId, debt is repaid using available collateral in loan\n    /// @param tokenId - unique id identifying loan\n    /// @param liquidity - liquidity debt being repaid, capped at actual liquidity owed. Can't repay more than you owe\n    /// @param ratio - weights of collateral after repaying liquidity\n    /// @return liquidityPaid - liquidity amount that has been repaid\n    /// @return amounts - collateral amounts consumed in repaying liquidity debt\n    function _repayLiquiditySetRatio(uint256 tokenId, uint256 liquidity, uint256[] calldata ratio) external returns(uint256 liquidityPaid, uint256[] memory amounts);\n}\n"
      },
      "@gammaswap/v1-core/contracts/interfaces/strategies/liquidation/IBatchLiquidationStrategy.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity >=0.8.0;\n\nimport \"../base/ILiquidationStrategy.sol\";\n\n/// @title Interface for Batch Liquidation Strategy contracts\n/// @author Daniel D. Alcarraz (https://github.com/0xDanr)\n/// @dev Defines function to liquidate loans in batch\ninterface IBatchLiquidationStrategy is ILiquidationStrategy {\n    /// @dev Function to liquidate multiple loans in batch.\n    /// @param tokenIds - list of tokenIds of loans to liquidate\n    /// @return totalLoanLiquidity - total loan liquidity liquidated (after write down)\n    /// @return refund - amounts from collateral tokens being refunded to liquidator\n    function _batchLiquidations(uint256[] calldata tokenIds) external returns(uint256 totalLoanLiquidity, uint128[] memory refund);\n}\n"
      },
      "@gammaswap/v1-core/contracts/interfaces/strategies/liquidation/IExternalLiquidationStrategy.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity >=0.8.0;\n\nimport \"../base/ILiquidationStrategy.sol\";\nimport \"../events/IExternalStrategyEvents.sol\";\n\n/// @title Interface for External Liquidation Strategy contracts\n/// @author Daniel D. Alcarraz (https://github.com/0xDanr)\n/// @dev Used to liquidate loans using a flash loan. Purpose of flash loan is for external swaps/rebalance of loan collateral\ninterface IExternalLiquidationStrategy is ILiquidationStrategy, IExternalStrategyEvents {\n    /// @notice The entire pool's collateral is available in the flash loan. Flash loan must result in a net CFMM LP token deposit that repays loan's liquidity debt\n    /// @dev Function to liquidate a loan using using a flash loan of collateral tokens from the pool and/or CFMM LP tokens. Seeks full liquidation\n    /// @param tokenId - tokenId of loan being liquidated\n    /// @param amounts - amount collateral tokens from the pool to flash loan\n    /// @param lpTokens - amount of CFMM LP tokens being flash loaned\n    /// @param to - address that will receive the collateral tokens and/or lpTokens in flash loan\n    /// @param data - optional bytes parameter for custom user defined data\n    /// @return loanLiquidity - loan liquidity liquidated (after write down if there's bad debt), flash loan fees added after write down\n    /// @return refund - amounts from collateral tokens being refunded to liquidator\n    function _liquidateExternally(uint256 tokenId, uint128[] calldata amounts, uint256 lpTokens, address to, bytes calldata data) external returns(uint256 loanLiquidity, uint128[] memory refund);\n}\n"
      },
      "@gammaswap/v1-core/contracts/interfaces/strategies/liquidation/ISingleLiquidationStrategy.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity >=0.8.0;\n\nimport \"../base/ILiquidationStrategy.sol\";\n\n/// @title Interface for Liquidation Strategy contract used in all strategies\n/// @author Daniel D. Alcarraz (https://github.com/0xDanr)\n/// @dev Used in liquidation strategie sthat liquidate individual loans using its own collateral, or externa CFMM LP deposits\ninterface ISingleLiquidationStrategy is ILiquidationStrategy {\n    /// @notice When calling this function and adding additional collateral it is assumed that you have sent the collateral first\n    /// @dev Function to liquidate a loan using its own collateral or depositing additional tokens. Seeks full liquidation\n    /// @param tokenId - tokenId of loan being liquidated\n    /// @return loanLiquidity - loan liquidity liquidated (after write down)\n    /// @return refund - amount of CFMM LP tokens being refunded to liquidator\n    function _liquidate(uint256 tokenId) external returns(uint256 loanLiquidity, uint256 refund);\n\n    /// @dev Function to liquidate a loan using external LP tokens. Allows partial liquidation\n    /// @param tokenId - tokenId of loan being liquidated\n    /// @return loanLiquidity - loan liquidity liquidated (after write down)\n    /// @return refund - amounts from collateral tokens being refunded to liquidator\n    function _liquidateWithLP(uint256 tokenId) external returns(uint256 loanLiquidity, uint128[] memory refund);\n}\n"
      },
      "@gammaswap/v1-core/contracts/interfaces/strategies/rebalance/IExternalRebalanceStrategy.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity >=0.8.0;\n\nimport \"../base/ILongStrategy.sol\";\nimport \"../events/IExternalStrategyEvents.sol\";\n\n/// @title Interface for External Rebalance Strategy\n/// @author Daniel D. Alcarraz (https://github.com/0xDanr)\n/// @dev Used to rebalance loan's collateral using a flash loan.\ninterface IExternalRebalanceStrategy is ILongStrategy, IExternalStrategyEvents {\n    /// @dev Flash loan pool's collateral and/or lp tokens to external address. Rebalanced loan collateral is acceptable in  repayment of flash loan\n    /// @param tokenId - unique id identifying loan\n    /// @param amounts - collateral amounts being flash loaned\n    /// @param lpTokens - amount of CFMM LP tokens being flash loaned\n    /// @param to - address that will receive flash loan swaps and potentially rebalance loan's collateral\n    /// @param data - optional bytes parameter for custom user defined data\n    /// @return loanLiquidity - updated loan liquidity, includes flash loan fees\n    /// @return tokensHeld - updated collateral token amounts backing loan\n    function _rebalanceExternally(uint256 tokenId, uint128[] calldata amounts, uint256 lpTokens, address to, bytes calldata data) external returns(uint256 loanLiquidity, uint128[] memory tokensHeld);\n}\n"
      },
      "@gammaswap/v1-core/contracts/interfaces/strategies/rebalance/IRebalanceStrategy.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity >=0.8.0;\n\nimport \"../base/ILongStrategy.sol\";\n\n/// @title Interface for Rebalance Strategy\n/// @author Daniel D. Alcarraz (https://github.com/0xDanr)\n/// @dev Used in strategies that rebalance collateral from liquidity loans\ninterface IRebalanceStrategy is ILongStrategy {\n\n    /// @dev Rebalance collateral amounts of loan identified by tokenId by purchasing or selling some of the collateral\n    /// @param tokenId - unique id identifying loan\n    /// @param deltas - collateral amounts being bought or sold (>0 buy, <0 sell), index matches tokensHeld[] index. Only n-1 tokens can be traded\n    /// @param ratio - weights of collateral after borrowing liquidity\n    /// @return tokensHeld - updated collateral token amounts backing loan\n    function _rebalanceCollateral(uint256 tokenId, int256[] memory deltas, uint256[] calldata ratio) external returns(uint128[] memory tokensHeld);\n\n    /// @dev Update pool liquidity debt and loan liquidity debt\n    /// @param tokenId - (optional) unique id identifying loan\n    /// @return loanLiquidityDebt - updated liquidity debt amount of loan\n    /// @return poolLiquidityDebt - updated liquidity debt amount of pool\n    function _updatePool(uint256 tokenId) external returns(uint256 loanLiquidityDebt, uint256 poolLiquidityDebt);\n\n    /// @dev Calculate quantities to trade to rebalance collateral to desired `ratio`\n    /// @param tokensHeld - loan collateral to rebalance\n    /// @param reserves - reserve token quantities in CFMM\n    /// @param ratio - desired ratio of collateral\n    /// @return deltas - amount of collateral to trade to achieve desired `ratio`\n    function calcDeltasForRatio(uint128[] memory tokensHeld, uint128[] memory reserves, uint256[] calldata ratio) external view returns(int256[] memory deltas);\n\n    /// @dev Calculate quantities to trade to be able to close the `liquidity` amount\n    /// @param tokensHeld - tokens held as collateral for liquidity to pay\n    /// @param reserves - reserve token quantities in CFMM\n    /// @param liquidity - amount of liquidity to pay\n    /// @param collateralId - index of tokensHeld array to rebalance to (e.g. the collateral of the chosen index will be completely used up in repayment)\n    /// @return deltas - amounts of collateral to trade to be able to repay `liquidity`\n    function calcDeltasToClose(uint128[] memory tokensHeld, uint128[] memory reserves, uint256 liquidity, uint256 collateralId) external view returns(int256[] memory deltas);\n\n    /// @dev Calculate quantities to trade to rebalance collateral so that after withdrawing `amounts` we achieve desired `ratio`\n    /// @param amounts - amounts that will be withdrawn from collateral\n    /// @param tokensHeld - loan collateral to rebalance\n    /// @param reserves - reserve token quantities in CFMM\n    /// @param ratio - desired ratio of collateral after withdrawing `amounts`\n    /// @return deltas - amount of collateral to trade to achieve desired `ratio`\n    function calcDeltasForWithdrawal(uint128[] memory amounts, uint128[] memory tokensHeld, uint128[] memory reserves, uint256[] calldata ratio) external view returns(int256[] memory deltas);\n}\n"
      },
      "@gammaswap/v1-core/contracts/libraries/AddressCalculator.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity >=0.8.0;\n\nimport \"../interfaces/IGammaPoolFactory.sol\";\n\n/// @title Library used calculate the deterministic addresses used to instantiate GammaPools\n/// @author Daniel D. Alcarraz (https://github.com/0xDanr)\n/// @dev These algorithms are based on EIP-1014 (https://eips.ethereum.org/EIPS/eip-1014)\nlibrary AddressCalculator {\n\n    /// @dev calculate salt used to create deterministic address, the salt is also used as unique key identifier for the GammaPool\n    /// @param cfmm - address of CFMM the GammaPool is for\n    /// @param protocolId - protocol id of instance address the GammaPool will use (version of GammaPool for this CFMM)\n    /// @return key - key/salt used as unique identifier of GammaPool\n    function getGammaPoolKey(address cfmm, uint16 protocolId) internal pure returns(bytes32) {\n        return keccak256(abi.encode(cfmm, protocolId)); // key is hash of CFMM address and protocolId\n    }\n\n    /// @dev calculate deterministic address to instantiate GammaPool minimal beacon proxy or minimal proxy contract\n    /// @param factory - address of factory that will instantiate GammaPool proxy contract\n    /// @param protocolId - protocol id of instance address the GammaPool will use (version of this GammaPool)\n    /// @param key - salt used in address generation to assure its uniqueness\n    /// @return _address - address of GammaPool that maps to protocolId and key\n    function calcAddress(address factory, uint16 protocolId, bytes32 key) internal view returns (address) {\n        if (protocolId < 10000) {\n            return predictDeterministicAddress(IGammaPoolFactory(factory).getProtocolBeacon(protocolId), protocolId, key, factory);\n        } else {\n            return predictDeterministicAddress2(IGammaPoolFactory(factory).getProtocol(protocolId), key, factory);\n        }\n    }\n\n    /// @dev calculate a deterministic address based on init code hash\n    /// @param factory - address of factory that instantiated or will instantiate this contract\n    /// @param salt - salt used in address generation to assure its uniqueness\n    /// @param initCodeHash - init code hash of template contract which will be used to instantiate contract with deterministic address\n    /// @return _address - address of contract that maps to salt and init code hash that is created by factory contract\n    function calcAddress(address factory, bytes32 salt, bytes32 initCodeHash) internal pure returns (address) {\n        return address(uint160(uint256(keccak256(abi.encodePacked(hex\"ff\",factory,salt,initCodeHash)))));\n    }\n\n    /// @dev Compute bytecode of a minimal beacon proxy contract, excluding bytecode metadata hash\n    /// @param beacon - address of beacon of minimal beacon proxy\n    /// @param protocolId - id of protocol\n    /// @param factory - address of factory that instantiated or will instantiate this contract\n    /// @return bytecode - the calculated bytecode for minimal beacon proxy contract\n    function calcMinimalBeaconProxyBytecode(\n        address beacon,\n        uint16 protocolId,\n        address factory\n    ) internal pure returns(bytes memory) {\n        return abi.encodePacked(\n            hex\"608060405234801561001057600080fd5b5073\",\n            beacon,\n            hex\"7f\",\n            hex\"a3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50\",\n            hex\"5560\",\n            protocolId < 256 ? hex\"6c\" : hex\"6d\",\n            hex\"806100566000396000f3fe\",\n            hex\"608060408190526334b1f0a960e21b8152\",\n            protocolId < 256 ? hex\"60\" : hex\"61\",\n            protocolId < 256 ? abi.encodePacked(uint8(protocolId)) : abi.encodePacked(protocolId),\n            hex\"60845260208160248173\",\n            factory,\n            hex\"5afa60\",\n            protocolId < 256 ? hex\"3a\" : hex\"3b\",\n            hex\"573d6000fd5b5060805160003681823780813683855af491503d81823e81801560\",\n            protocolId < 256 ? hex\"5b\" : hex\"5c\",\n            hex\"573d82f35b3d82fdfea164736f6c6343000815000a\"\n        );\n    }\n\n    /// @dev Computes the address of a minimal beacon proxy contract\n    /// @param protocolId - id of protocol\n    /// @param salt - salt used in address generation to assure its uniqueness\n    /// @param factory - address of factory that instantiated or will instantiate this contract\n    /// @return predicted - the calculated address\n    function predictDeterministicAddress(\n        address beacon,\n        uint16 protocolId,\n        bytes32 salt,\n        address factory\n    ) internal pure returns (address) {\n        bytes memory bytecode = calcMinimalBeaconProxyBytecode(beacon, protocolId, factory);\n\n        // Compute the hash of the initialization code.\n        bytes32 bytecodeHash = keccak256(bytecode);\n\n        // Compute the final CREATE2 address\n        bytes32 data = keccak256(abi.encodePacked(bytes1(0xff), factory, salt, bytecodeHash));\n        return address(uint160(uint256(data)));\n    }\n\n    /// @dev Computes the address of a minimal proxy contract\n    /// @param implementation - address of implementation contract of this minimal proxy contract\n    /// @param salt - salt used in address generation to assure its uniqueness\n    /// @param factory - address of factory that instantiated or will instantiate this contract\n    /// @return predicted - the calculated address\n    function predictDeterministicAddress2(\n        address implementation,\n        bytes32 salt,\n        address factory\n    ) internal pure returns (address predicted) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let ptr := mload(0x40)\n            mstore(add(ptr, 0x38), factory)\n            mstore(add(ptr, 0x24), 0x5af43d82803e903d91602b57fd5bf3ff)\n            mstore(add(ptr, 0x14), implementation)\n            mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73)\n            mstore(add(ptr, 0x58), salt)\n            mstore(add(ptr, 0x78), keccak256(add(ptr, 0x0c), 0x37))\n            predicted := keccak256(add(ptr, 0x43), 0x55)\n        }\n    }\n}"
      },
      "@gammaswap/v1-core/contracts/libraries/GammaSwapLibrary.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity >=0.8.13;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\n/// @title Library used to perform common ERC20 transactions\n/// @author Daniel D. Alcarraz (https://github.com/0xDanr)\n/// @dev Library performs approvals, transfers and views ERC20 state fields\nlibrary GammaSwapLibrary {\n\n    error ST_Fail();\n    error STF_Fail();\n    error SA_Fail();\n    error STE_Fail();\n\n    /// @dev Check the ERC20 balance of an address\n    /// @param _token - address of ERC20 token we're checking the balance of\n    /// @param _address - Ethereum address we're checking for balance of ERC20 token\n    /// @return balanceOf - amount of _token held in _address\n    function balanceOf(address _token, address _address) internal view returns (uint256) {\n        (bool success, bytes memory data) = _token.staticcall(abi.encodeCall(IERC20.balanceOf, _address));\n\n        require(success && data.length >= 32);\n\n        return abi.decode(data, (uint256));\n    }\n\n    /// @dev Get how much of an ERC20 token is in existence (minted)\n    /// @param _token - address of ERC20 token we're checking the total minted amount of\n    /// @return totalSupply - total amount of _token that is in existence (minted and not burned)\n    function totalSupply(address _token) internal view returns (uint256) {\n        (bool success, bytes memory data) = _token.staticcall(abi.encodeCall(IERC20.totalSupply,()));\n\n        require(success && data.length >= 32);\n\n        return abi.decode(data, (uint256));\n    }\n\n    /// @dev Get decimals of ERC20 token\n    /// @param _token - address of ERC20 token we are getting the decimal information from\n    /// @return decimals - decimals of ERC20 token\n    function decimals(address _token) internal view returns (uint8) {\n        (bool success, bytes memory data) = _token.staticcall(abi.encodeWithSignature(\"decimals()\")); // requesting via ERC20 decimals implementation\n\n        require(success && data.length >= 1);\n\n        return abi.decode(data, (uint8));\n    }\n\n    /// @dev Get symbol of ERC20 token\n    /// @param _token - address of ERC20 token we are getting the symbol information from\n    /// @return symbol - symbol of ERC20 token\n    function symbol(address _token) internal view returns (string memory) {\n        (bool success, bytes memory data) = _token.staticcall(abi.encodeWithSignature(\"symbol()\")); // requesting via ERC20 symbol implementation\n\n        require(success && data.length >= 1);\n\n        return abi.decode(data, (string));\n    }\n\n    /// @dev Get name of ERC20 token\n    /// @param _token - address of ERC20 token we are getting the name information from\n    /// @return name - name of ERC20 token\n    function name(address _token) internal view returns (string memory) {\n        (bool success, bytes memory data) = _token.staticcall(abi.encodeWithSignature(\"name()\")); // requesting via ERC20 name implementation\n\n        require(success && data.length >= 1);\n\n        return abi.decode(data, (string));\n    }\n\n    /// @dev Safe transfer any ERC20 token, only used internally\n    /// @param _token - address of ERC20 token that will be transferred\n    /// @param _to - destination address where ERC20 token will be sent to\n    /// @param _amount - quantity of ERC20 token to be transferred\n    function safeTransfer(address _token, address _to, uint256 _amount) internal {\n        (bool success, bytes memory data) = _token.call(abi.encodeCall(IERC20.transfer, (_to, _amount)));\n\n        if(!(success && (data.length == 0 || abi.decode(data, (bool))))) revert ST_Fail();\n    }\n\n    /// @dev Moves `amount` of ERC20 token `_token` from `_from` to `_to` using the allowance mechanism. `_amount` is then deducted from the caller's allowance.\n    /// @param _token - address of ERC20 token that will be transferred\n    /// @param _from - address sending _token (not necessarily caller's address)\n    /// @param _to - address receiving _token\n    /// @param _amount - amount of _token being sent\n    function safeTransferFrom(address _token, address _from, address _to, uint256 _amount) internal {\n        (bool success, bytes memory data) = _token.call(abi.encodeCall(IERC20.transferFrom, (_from, _to, _amount)));\n\n        if(!(success && (data.length == 0 || abi.decode(data, (bool))))) revert STF_Fail();\n    }\n\n    /// @dev Safe approve any ERC20 token to be spent by another address (`_spender`), only used internally\n    /// @param _token - address of ERC20 token that will be approved\n    /// @param _spender - address that will be granted approval to spend msg.sender tokens\n    /// @param _amount - quantity of ERC20 token that `_spender` will be approved to spend\n    function safeApprove(address _token, address _spender, uint256 _amount) internal {\n        (bool success, bytes memory data) = _token.call(abi.encodeCall(IERC20.approve, (_spender, _amount)));\n\n        if(!(success && (data.length == 0 || abi.decode(data, (bool))))) revert SA_Fail();\n    }\n\n    /// @dev Safe transfer any ERC20 token, only used internally\n    /// @param _to - destination address where ETH will be sent to\n    /// @param _amount - quantity of ERC20 token to be transferred\n    function safeTransferETH(address _to, uint256 _amount) internal {\n        (bool success, ) = _to.call{value: _amount}(\"\");\n\n        if(!success) revert STE_Fail();\n    }\n\n    /// @dev Check if `account` is a smart contract's address and it has been instantiated (has code)\n    /// @param account - Ethereum address to check if it's a smart contract address\n    /// @return bool - true if it is a smart contract address\n    function isContract(address account) internal view returns (bool) {\n        return account.code.length > 0;\n    }\n\n    function convertUint128ToUint256Array(uint128[] memory arr) internal pure returns(uint256[] memory res) {\n        res = new uint256[](arr.length);\n        for(uint256 i = 0; i < arr.length;) {\n            res[i] = uint256(arr[i]);\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    function convertUint128ToRatio(uint128[] memory arr) internal pure returns(uint256[] memory res) {\n        res = new uint256[](arr.length);\n        for(uint256 i = 0; i < arr.length;) {\n            res[i] = uint256(arr[i]) * 1000;\n            unchecked {\n                ++i;\n            }\n        }\n    }\n}"
      },
      "@gammaswap/v1-core/contracts/libraries/GSMath.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity >=0.8.0;\n\n/// @title Math Library\n/// @author Daniel D. Alcarraz (https://github.com/0xDanr)\n/// @dev Library for performing various math operations\nlibrary GSMath {\n    function max(uint256 x, uint256 y) internal pure returns (uint256 z) {\n        z = x > y ? x : y;\n    }\n\n    function min(uint256 x, uint256 y) internal pure returns (uint256 z) {\n        z = x < y ? x : y;\n    }\n\n    /// @dev Returns the square root of `a`.\n    /// @param a number to square root\n    /// @return z square root of a\n    function sqrt(uint256 a) internal pure returns (uint256 z) {\n        if (a == 0) return 0;\n\n        assembly {\n            z := 181 // Should be 1, but this saves a multiplication later.\n\n            let r := shl(7, lt(0xffffffffffffffffffffffffffffffffff, a))\n            r := or(shl(6, lt(0xffffffffffffffffff, shr(r, a))), r)\n            r := or(shl(5, lt(0xffffffffff, shr(r, a))), r)\n            r := or(shl(4, lt(0xffffff, shr(r, a))), r)\n            z := shl(shr(1, r), z)\n\n            // Doesn't overflow since y < 2**136 after above.\n            z := shr(18, mul(z, add(shr(r, a), 65536))) // A mul() saved from z = 181.\n\n            // Given worst case multiplicative error of 2.84 above, 7 iterations should be enough.\n            z := shr(1, add(div(a, z), z))\n            z := shr(1, add(div(a, z), z))\n            z := shr(1, add(div(a, z), z))\n            z := shr(1, add(div(a, z), z))\n            z := shr(1, add(div(a, z), z))\n            z := shr(1, add(div(a, z), z))\n            z := shr(1, add(div(a, z), z))\n\n            // If x+1 is a perfect square, the Babylonian method cycles between floor(sqrt(x)) and ceil(sqrt(x)).\n            // We always return floor. Source https://en.wikipedia.org/wiki/Integer_square_root#Using_only_integer_division\n            z := sub(z, lt(div(a, z), z))\n        }\n    }\n}\n"
      },
      "@gammaswap/v1-core/contracts/libraries/LibStorage.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity >=0.8.4;\n\nimport \"../interfaces/observer/ILoanObserverStore.sol\";\nimport \"../interfaces/IGammaPoolFactory.sol\";\n\n/// @title Library containing global storage variables for GammaPools according to App Storage pattern\n/// @author Daniel D. Alcarraz (https://github.com/0xDanr)\n/// @dev Structs are packed to minimize storage size\nlibrary LibStorage {\n\n    /// @dev Loan struct used to track relevant liquidity loan information\n    struct Loan {\n        /// @dev Loan counter, used to generate unique tokenId which indentifies the loan in the GammaPool\n        uint256 id;\n\n        // 1x256 bits\n        /// @dev GammaPool address loan belongs to\n        address poolId; // 160 bits\n        /// @dev Index of GammaPool interest rate at time loan is created/updated, max 7.9% trillion\n        uint96 rateIndex; // 96 bits\n\n        // 1x256 bits\n        /// @dev Initial loan debt in liquidity invariant units. Only increase when more liquidity is borrowed, decreases when liquidity is paid\n        uint128 initLiquidity; // 128 bits\n        /// @dev Loan debt in liquidity invariant units, increases with every update according to how many blocks have passed\n        uint128 liquidity; // 128 bits\n\n        /// @dev Initial loan debt in terms of LP tokens at time liquidity was borrowed, updates along with initLiquidity\n        uint256 lpTokens;\n        /// @dev Reserve tokens held as collateral for the liquidity debt, indices match GammaPool's tokens[] array indices\n        uint128[] tokensHeld; // array of 128 bit numbers\n\n        /// @dev price at which loan was opened\n        uint256 px;\n\n        /// @dev reference address holding additional collateral information for the loan\n        address refAddr;\n        /// @dev reference fee, typically used for loans using a collateral reference addresses\n        uint16 refFee;\n        /// @dev reference type, typically used for loans using a collateral reference addresses\n        uint8 refType;\n    }\n\n    /// @dev Storage struct used to track GammaPool's state variables\n    /// @notice `LP_TOKEN_TOTAL = LP_TOKEN_BALANCE + LP_TOKEN_BORROWED_PLUS_INTEREST` and `TOTAL_INVARIANT = BORROWED_INVARIANT + LP_INVARIANT`\n    struct Storage {\n        // 1x256 bits\n        /// @dev factory - address of factory contract that instantiated this GammaPool\n        address factory; // 160 bits\n        /// @dev Protocol id of the implementation contract for this GammaPool\n        uint16 protocolId; // 16 bits\n        /// @dev unlocked - flag used in mutex implementation (1 = unlocked, 0 = locked). Initialized at 1\n        uint8 unlocked; // 8 bits\n        /// @dev EMA of utilization rate\n        uint32 emaUtilRate; // 32 bits, 6 decimal number\n        /// @dev Multiplier of EMA used to calculate emaUtilRate\n        uint8 emaMultiplier; // 8 bits, 1 decimals (0 = 0%, 1 = 0.1%, max 255 = 25.5%)\n        /// @dev Minimum utilization rate at which point we start using the dynamic fee\n        uint8 minUtilRate1; // 8 bits, 0 decimals (0 = 0%, 100 = 100%), default is 85. If set to 100, dynamic orig fee is disabled\n        /// @dev Minimum utilization rate at which point we start using the dynamic fee\n        uint8 minUtilRate2; // 8 bits, 0 decimals (0 = 0%, 100 = 100%), default is 65. If set to 100, dynamic orig fee is disabled\n        /// @dev Dynamic origination fee divisor, to cap at 99% use 16384 = 2^(99-85)\n        uint16 feeDivisor; // 16 bits, 0 decimals, max is 5 digit integer 65535, formula is 2^(maxUtilRate - minUtilRate1)\n\n        // 3x256 bits, LP Tokens\n        /// @dev Quantity of CFMM's LP tokens deposited in GammaPool by liquidity providers\n        uint256 LP_TOKEN_BALANCE;\n        /// @dev Quantity of CFMM's LP tokens that have been borrowed by liquidity borrowers excluding accrued interest (principal)\n        uint256 LP_TOKEN_BORROWED;\n        /// @dev Quantity of CFMM's LP tokens that have been borrowed by liquidity borrowers including accrued interest\n        uint256 LP_TOKEN_BORROWED_PLUS_INTEREST;\n\n        // 1x256 bits, Invariants\n        /// @dev Quantity of CFMM's liquidity invariant that has been borrowed including accrued interest, maps to LP_TOKEN_BORROWED_PLUS_INTEREST\n        uint128 BORROWED_INVARIANT; // 128 bits\n        /// @dev Quantity of CFMM's liquidity invariant held in GammaPool as LP tokens, maps to LP_TOKEN_BALANCE\n        uint128 LP_INVARIANT; // 128 bits\n\n        // 3x256 bits, Rates & CFMM\n        /// @dev cfmm - address of CFMM this GammaPool is for\n        address cfmm; // 160 bits\n        /// @dev GammaPool's ever increasing interest rate index, tracks interest accrued through CFMM and liquidity loans, max 120.8% million\n        uint80 accFeeIndex; // 80 bits\n        /// @dev GammaPool's Margin threshold (1 - 255 => 0.1% to 25.5%) LTV = 1 - ltvThreshold\n        uint8 ltvThreshold; // 8 bits\n        /// @dev GammaPool's liquidation fee in basis points (1 - 255 => 0.01% to 2.55%)\n        uint8 liquidationFee; // 8 bits\n        /// @dev External swap fee in basis points, max 255 basis points = 2.55%\n        uint8 extSwapFee; // 8 bits\n        /// @dev Loan opening origination fee in basis points\n        uint16 origFee; // 16 bits\n        /// @dev LAST_BLOCK_NUMBER - last block an update to the GammaPool's global storage variables happened\n        uint40 LAST_BLOCK_NUMBER; // 40 bits\n        /// @dev Percent accrual in CFMM invariant since last update in a different block, max 1,844.67%\n        uint64 lastCFMMFeeIndex; // 64 bits\n        /// @dev Total liquidity invariant amount in CFMM (from GammaPool and others), read in last update to GammaPool's storage variables\n        uint128 lastCFMMInvariant; // 128 bits\n        /// @dev Total LP token supply from CFMM (belonging to GammaPool and others), read in last update to GammaPool's storage variables\n        uint256 lastCFMMTotalSupply;\n\n        /// @dev The ID of the next loan that will be minted. Initialized at 1\n        uint256 nextId;\n\n        /// @dev Function IDs so that we can pause individual functions\n        uint256 funcIds;\n\n        // ERC20 fields\n        /// @dev Total supply of GammaPool's own ERC20 token representing the liquidity of depositors to the CFMM through the GammaPool\n        uint256 totalSupply;\n        /// @dev Balance of GammaPool's ERC20 token, this is used to keep track of the balances of different addresses as defined in the ERC20 standard\n        mapping(address => uint256) balanceOf;\n        /// @dev Spending allowance of GammaPool's ERC20 token, this is used to keep track of the spending allowance of different addresses as defined in the ERC20 standard\n        mapping(address => mapping(address => uint256)) allowance;\n\n        /// @dev Mapping of all loans issued by the GammaPool, the key is the tokenId (unique identifier) of the loan\n        mapping(uint256 => Loan) loans;\n\n        /// @dev Minimum liquidity that can be borrowed or remain for a loan\n        uint72 minBorrow;\n\n        // tokens and balances\n        /// @dev ERC20 tokens of CFMM\n        address[] tokens;\n        /// @dev Decimals of tokens in CFMM, indices match tokens[] array\n        uint8[] decimals;\n        /// @dev Amounts of ERC20 tokens from the CFMM held as collateral in the GammaPool. Equals to the sum of all tokensHeld[] quantities in all loans\n        uint128[] TOKEN_BALANCE;\n        /// @dev Amounts of ERC20 tokens from the CFMM held in the CFMM as reserve quantities. Used to log prices quoted by the CFMM during updates to the GammaPool\n        uint128[] CFMM_RESERVES;\n        /// @dev List of all tokenIds created in GammaPool\n        uint256[] tokenIds;\n\n        // Custom parameters\n        /// @dev Custom fields\n        mapping(uint256 => bytes32) fields;\n        /// @dev Custom object (e.g. struct)\n        bytes obj;\n    }\n\n    error Initialized();\n\n    /// @dev Initializes global storage variables of GammaPool, must be called right after instantiating GammaPool\n    /// @param self - pointer to storage variables (doesn't need to be passed)\n    /// @param _factory - address of factory that created this GammaPool\n    /// @param _cfmm - address of CFMM this GammaPool is for\n    /// @param _protocolId - protocol id of the implementation contract for this GammaPool\n    /// @param _tokens - tokens of CFMM this GammaPool is for\n    /// @param _decimals -decimals of the tokens of the CFMM the GammaPool is for, indices must match tokens array\n    /// @param _minBorrow - minimum amount of liquidity that can be borrowed or left unpaid in a loan\n    function initialize(Storage storage self, address _factory, address _cfmm, uint16 _protocolId, address[] calldata _tokens, uint8[] calldata _decimals, uint72 _minBorrow) internal {\n        if(self.factory != address(0)) revert Initialized();// cannot initialize twice\n\n        self.factory = _factory;\n        self.protocolId = _protocolId;\n        self.cfmm = _cfmm;\n        self.tokens = _tokens;\n        self.decimals = _decimals;\n        self.minBorrow =_minBorrow;\n\n        self.lastCFMMFeeIndex = 1e18;\n        self.accFeeIndex = 1e18; // initialized as 1 with 18 decimal places\n        self.LAST_BLOCK_NUMBER = uint40(block.number); // first block update number is block at initialization\n\n        self.nextId = 1; // loan counter starts at 1\n        self.unlocked = 1; // mutex initialized as unlocked\n\n        self.ltvThreshold = 5; // 50 basis points\n        self.liquidationFee = 25; // 25 basis points\n        self.origFee = 2;\n        self.extSwapFee = 10;\n\n        self.emaMultiplier = 10; // ema smoothing factor is 10/1000 = 1%\n        self.minUtilRate1 = 92; // min util rate 1 is 92%\n        self.minUtilRate2 = 80; // min util rate 2 is 80%\n        self.feeDivisor = 2048; // 25% orig fee at 99% util rate\n\n        self.TOKEN_BALANCE = new uint128[](_tokens.length);\n        self.CFMM_RESERVES = new uint128[](_tokens.length);\n    }\n\n    /// @dev Creates an empty loan struct in the GammaPool and initializes it to start tracking borrowed liquidity\n    /// @param self - pointer to storage variables (doesn't need to be passed)\n    /// @param _tokenCount - number of tokens in the CFMM the loan is for\n    /// @param refId - reference id of CollateralManager set up in CollateralReferenceStore (e.g. GammaPoolFactory)\n    /// @return _tokenId - unique tokenId used to get and update loan\n    function createLoan(Storage storage self, uint256 _tokenCount, uint16 refId) internal returns(uint256 _tokenId) {\n        // get loan counter for GammaPool and increase it by 1 for the next loan\n        uint256 id = self.nextId++;\n\n        // create unique tokenId to identify loan across all GammaPools. _tokenId is hash of GammaPool address, sender address, and loan counter\n        _tokenId = uint256(keccak256(abi.encode(msg.sender, address(this), id)));\n\n        address refAddr;\n        uint16 refFee;\n        uint8 refType;\n        if(refId > 0 ) {\n            (refAddr, refFee, refType) = ILoanObserverStore(self.factory).getPoolObserverByUser(refId, address(this), msg.sender);\n        }\n\n        // instantiate Loan struct and store it mapped to _tokenId\n        self.loans[_tokenId] = Loan({\n            id: id, // loan counter\n            poolId: address(this), // GammaPool address loan belongs to\n            rateIndex: self.accFeeIndex, // initialized as current interest rate index\n            initLiquidity: 0,\n            liquidity: 0,\n            lpTokens: 0,\n            tokensHeld: new uint128[](_tokenCount),\n            px: 0,\n            refAddr: refAddr,\n            refFee: refFee,\n            refType: refType\n        });\n\n        self.tokenIds.push(_tokenId);\n    }\n\n    /// @dev Get custom field as uint256\n    /// @param self - pointer to storage variables (doesn't need to be passed)\n    /// @param idx - index of mapping of uint256 field\n    /// @return field - value of custom field from storage as uint256\n    function getUint256(Storage storage self, uint256 idx) internal view returns(uint256) {\n        return uint256(self.fields[idx]);\n    }\n\n    /// @dev Set custom field as uint256\n    /// @param self - pointer to storage variables (doesn't need to be passed)\n    /// @param idx - index of mapping of uint256 field\n    /// @param val - value of custom field to store in storage as uint256\n    function setUint256(Storage storage self, uint256 idx, uint256 val) internal {\n        self.fields[idx] = bytes32(val);\n    }\n\n    /// @dev Get custom field as int256\n    /// @param self - pointer to storage variables (doesn't need to be passed)\n    /// @param idx - index of mapping of int256 field\n    /// @return field - value of custom field from storage as int256\n    function getInt256(Storage storage self, uint256 idx) internal view returns(int256) {\n        return int256(uint256(self.fields[idx]));\n    }\n\n    /// @dev Set custom field as int256\n    /// @param self - pointer to storage variables (doesn't need to be passed)\n    /// @param idx - index of mapping of int256 field\n    /// @param val - value of custom field to store in storage as int256\n    function setInt256(Storage storage self, uint256 idx, int256 val) internal {\n        self.fields[idx] = bytes32(uint256(val));\n    }\n\n    /// @dev Get custom field as bytes32\n    /// @param self - pointer to storage variables (doesn't need to be passed)\n    /// @param idx - index of mapping of bytes32 field\n    /// @return field - value of custom field from storage as bytes32\n    function getBytes32(Storage storage self, uint256 idx) internal view returns(bytes32) {\n        return self.fields[idx];\n    }\n\n    /// @dev Set custom field as bytes32\n    /// @param self - pointer to storage variables (doesn't need to be passed)\n    /// @param idx - index of mapping of bytes32 field\n    /// @param val - value of custom field to store in storage as bytes32\n    function setBytes32(Storage storage self, uint256 idx, bytes32 val) internal {\n        self.fields[idx] = val;\n    }\n\n    /// @dev Get custom field as address\n    /// @param self - pointer to storage variables (doesn't need to be passed)\n    /// @param idx - index of mapping of address field\n    /// @return field - value of custom field from storage as address\n    function getAddress(Storage storage self, uint256 idx) internal view returns(address) {\n        return address(uint160(uint256(self.fields[idx])));\n    }\n\n    /// @dev Set custom field as address\n    /// @param self - pointer to storage variables (doesn't need to be passed)\n    /// @param idx - index of mapping of address field\n    /// @param val - value of custom field to store in storage as address\n    function setAddress(Storage storage self, uint256 idx, address val) internal {\n        self.fields[idx] = bytes32(uint256(uint160(val)));\n    }\n}\n"
      },
      "@gammaswap/v1-core/contracts/rates/AbstractRateModel.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity >=0.8.4;\n\nimport \"../interfaces/rates/IRateModel.sol\";\n\n/// @title Abstract contract to calculate the utilization rate of the GammaPool.\n/// @author Daniel D. Alcarraz (https://github.com/0xDanr)\n/// @notice All rate models inherit this contract since all rate models depend on utilization rate\n/// @dev All strategies inherit a rate model in its base and therefore all strategies inherit this contract.\nabstract contract AbstractRateModel is IRateModel {\n    /// @notice Calculates the utilization rate of the pool. How much borrowed out of how much liquidity is in the AMM through GammaSwap\n    /// @dev The utilization rate always has 18 decimal places, even if the reserve tokens do not. Everything is adjusted to 18 decimal points\n    /// @param lpInvariant - invariant amount available to be borrowed from LP tokens deposited in GammaSwap\n    /// @param borrowedInvariant - invariant amount borrowed from GammaSwap\n    /// @return utilizationRate - borrowedInvariant / (lpInvariant + borrowedInvairant)\n    function calcUtilizationRate(uint256 lpInvariant, uint256 borrowedInvariant) internal virtual view returns(uint256) {\n        uint256 totalInvariant = lpInvariant + borrowedInvariant; // total invariant belonging to liquidity depositors in GammaSwap\n        if(totalInvariant == 0) // avoid division by zero\n            return 0;\n\n        return borrowedInvariant * 1e18 / totalInvariant; // utilization rate will always have 18 decimals\n    }\n\n    /// @notice Calculates the borrow rate according to an implementation formula\n    /// @dev The borrow rate is expected to always have 18 decimal places\n    /// @param lpInvariant - invariant amount available to be borrowed from LP tokens deposited in GammaSwap\n    /// @param borrowedInvariant - invariant amount borrowed from GammaSwap\n    /// @param paramsStore - address of rate params store, to get overriding parameter values\n    /// @param pool - address of pool asking for rate calculation\n    /// @return borrowRate - rate that will be charged to liquidity borrowers\n    /// @return utilizationRate - utilization rate used to calculate the borrow rate\n    /// @return maxCFMMFeeLeverage - maxLeverage number with 3 decimals. E.g. 5000 = 5\n    /// @return spread - additional fee to add to cfmmFeeIndex to create spread\n    function calcBorrowRate(uint256 lpInvariant, uint256 borrowedInvariant, address paramsStore, address pool) public virtual view returns(uint256, uint256, uint256, uint256);\n\n    /// @dev See {IRateModel-rateParamsStore}\n    function rateParamsStore() public override virtual view returns(address) {\n        return _rateParamsStore();\n    }\n\n    /// @dev Return contract holding rate parameters\n    function _rateParamsStore() internal virtual view returns(address);\n}\n"
      },
      "@gammaswap/v1-core/contracts/storage/AppStorage.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity >=0.8.4;\n\nimport \"../libraries/LibStorage.sol\";\n\n/// @title Contract that implements App Storage pattern in GammaPool contracts\n/// @author Daniel D. Alcarraz (https://github.com/0xDanr)\n/// @notice This pattern is based on Nick Mudge's App Storage implementation (https://dev.to/mudgen/appstorage-pattern-for-state-variables-in-solidity-3lki)\n/// @dev This contract has to be inherited as the root contract in an inheritance hierarchy\nabstract contract AppStorage {\n\n    /// @notice Global storage variables of GammaPool according to App Storage pattern\n    /// @dev No other state variable should be defined before this state variable\n    LibStorage.Storage internal s;\n\n    error Locked();\n\n    /// @dev Mutex implementation to prevent a contract from calling itself, directly or indirectly.\n    modifier lock() {\n        _lock();\n        _;\n        _unlock();\n    }\n\n    function _lock() internal {\n        if(s.unlocked != 1) revert Locked();\n        s.unlocked = 0;\n    }\n\n    function _unlock() internal {\n        s.unlocked = 1;\n    }\n}\n"
      },
      "@gammaswap/v1-core/contracts/utils/DelegateCaller.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity >=0.8.4;\n\n/// @title Abstract DelegateCaller contract.\n/// @author Daniel D. Alcarraz (https://github.com/0xDanr)\n/// @dev Parent contract to contracts that perform delegate calls. All delegate call logic handled here\nabstract contract DelegateCaller {\n\n    /// @dev Implement contract logic via delegate calls of implementation contracts\n    /// @param strategy - address of implementation contract\n    /// @param data - bytes containing function call and parameters at implementation (`strategy`) contract\n    /// @return result - returned data from delegate function call\n    function callStrategy(address strategy, bytes memory data) internal virtual returns(bytes memory result) {\n        bool success;\n        (success, result) = strategy.delegatecall(data);\n        if (!success) {\n            if (result.length == 0) revert();\n            assembly {\n                revert(add(32, result), mload(result))\n            }\n        }\n        return result;\n    }\n\n}\n"
      },
      "@gammaswap/v1-core/contracts/utils/Pausable.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity >=0.8.4;\n\nimport \"../interfaces/IPausable.sol\";\n\n/// @title Abstract Pausable contract.\n/// @author Daniel D. Alcarraz (https://github.com/0xDanr)\n/// @notice Abstract implementation of IPausable interface.\n/// @dev Pauses individual functions in inherited contract through bit manipulation of a 256 bit number\n/// @dev The 256 bit number means there are at most 255 functions that can be paused by turning on the respective bit index that identifies that function\n/// @dev If the zeroth bit is turned on, then all pausable functions are paused\nabstract contract Pausable is IPausable {\n\n    /// @dev Modifier to make a function callable only when the contract is not paused.\n    modifier whenNotPaused(uint8 _functionId) {\n        _requireNotPaused(_functionId);\n        _;\n    }\n\n    /// @dev Modifier to make a function callable only when the contract is paused. The contract must be paused.\n    modifier whenPaused(uint8 _functionId) {\n        _requirePaused(_functionId);\n        _;\n    }\n\n    /// @dev address allowed to pause functions\n    function _pauser() internal virtual view returns(address);\n\n    /// @dev 256 bit number whose indices represent the ids of pausable functions\n    function _functionIds() internal virtual view returns(uint256);\n\n    /// @dev Update 256 bit number whose indices represent the ids of pausable functions\n    function _setFunctionIds(uint256 _funcIds) internal virtual;\n\n    /// @dev See {IPausable-functionIds}\n    function functionIds() external override virtual view returns(uint256) {\n        return _functionIds();\n    }\n\n    // @dev Throws if the contract is paused.\n    function _requireNotPaused(uint8 _functionId) internal view virtual {\n        if(isPaused(_functionId)) revert Paused(_functionId);\n    }\n\n    /// @dev Throws if the contract is not paused.\n    function _requirePaused(uint8 _functionId) internal view virtual {\n        if(!isPaused(_functionId)) revert NotPaused(_functionId);\n    }\n\n    /// @dev See {IPausable-isPaused}\n    function isPaused(uint8 _functionId) public override virtual view returns (bool) {\n        uint256 funcIds = _functionIds();\n        uint256 mask = uint256(1) << _functionId;\n        return funcIds == 1 || (funcIds & mask) != 0;\n    }\n\n    /// @dev See {IPausable-pause}\n    function pause(uint8 _functionId) external override virtual returns (uint256) {\n        if(msg.sender != _pauser()) revert ForbiddenPauser();\n\n        uint256 mask = uint256(1) << _functionId;\n        uint256 funcIds = _functionIds() | mask;\n\n        _setFunctionIds(funcIds);\n\n        emit Pause(msg.sender, _functionId);\n\n        return funcIds;\n    }\n\n    /// @dev See {IPausable-unpause}\n    function unpause(uint8 _functionId) external override virtual returns (uint256) {\n        if(msg.sender != _pauser()) revert ForbiddenPauser();\n\n        uint256 mask = ~(uint256(1) << _functionId);\n        uint256 funcIds = _functionIds() & mask;\n\n        _setFunctionIds(funcIds);\n\n        emit Unpause(msg.sender, _functionId);\n\n        return funcIds;\n    }\n}\n"
      },
      "@gammaswap/v1-implementations/contracts/pools/CPMMGammaPool.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport \"@gammaswap/v1-core/contracts/base/GammaPool.sol\";\nimport \"@gammaswap/v1-core/contracts/base/GammaPoolExternal.sol\";\nimport \"@gammaswap/v1-core/contracts/libraries/AddressCalculator.sol\";\nimport \"@gammaswap/v1-core/contracts/libraries/GammaSwapLibrary.sol\";\nimport \"@gammaswap/v1-core/contracts/libraries/GSMath.sol\";\n\n/// @title GammaPool implementation for Constant Product Market Maker\n/// @author Daniel D. Alcarraz (https://github.com/0xDanr)\n/// @dev This implementation is specifically for validating UniswapV2Pair and clone contracts\ncontract CPMMGammaPool is GammaPool, GammaPoolExternal {\n\n    error NotContract();\n    error BadProtocol();\n    error InvalidTokensLength();\n\n    using LibStorage for LibStorage.Storage;\n\n    /// @return cfmmFactory - factory contract that created CFMM\n    address immutable public cfmmFactory;\n\n    /// @return cfmmInitCodeHash - init code hash of CFMM\n    bytes32 immutable public cfmmInitCodeHash;\n\n    /// @dev Initializes the contract by setting `protocolId`, `factory`, `borrowStrategy`, `repayStrategy`,\n    /// @dev `shortStrategy`, `liquidationStrategy`, `batchLiquidationStrategy`, `cfmmFactory`, and `cfmmInitCodeHash`.\n    constructor(uint16 _protocolId, address _factory, address _borrowStrategy, address _repayStrategy,\n        address _shortStrategy, address _liquidationStrategy, address _batchLiquidationStrategy, address _viewer,\n        address _externalRebalanceStrategy, address _externalLiquidationStrategy, address _cfmmFactory, bytes32 _cfmmInitCodeHash)\n        GammaPool(_protocolId, _factory, _borrowStrategy, _repayStrategy, _borrowStrategy, _shortStrategy,\n        _liquidationStrategy, _batchLiquidationStrategy, _viewer)\n        GammaPoolExternal(_externalRebalanceStrategy, _externalLiquidationStrategy) {\n        cfmmFactory = _cfmmFactory;\n        cfmmInitCodeHash = _cfmmInitCodeHash;\n    }\n\n    /// @dev See {IGammaPool-createLoan}\n    function createLoan(uint16 refId) external lock virtual override whenNotPaused(9) returns(uint256 tokenId) {\n        tokenId = s.createLoan(2, refId); // only 2 token pair\n        emit LoanCreated(msg.sender, tokenId, refId);\n    }\n\n    /// @dev See {GammaPoolERC4626._calcInvariant}.\n    function _calcInvariant(uint128[] memory tokensHeld) internal virtual override view returns(uint256) {\n        return GSMath.sqrt(uint256(tokensHeld[0]) * tokensHeld[1]);\n    }\n\n    /// @dev See {GammaPoolERC4626._getLastCFMMPrice}.\n    function _getLastCFMMPrice() internal virtual override view returns(uint256) {\n        uint128[] memory _reserves = _getLatestCFMMReserves();\n        if(_reserves[0] == 0) {\n            return 0;\n        }\n        return _reserves[1] * (10 ** s.decimals[0]) / _reserves[0];\n    }\n\n    /// @dev See {IGammaPool-validateCFMM}\n    function validateCFMM(address[] calldata _tokens, address _cfmm, bytes calldata) external virtual override view returns(address[] memory _tokensOrdered) {\n        if(!GammaSwapLibrary.isContract(_cfmm)) revert NotContract(); // Not a smart contract (hence not a CFMM) or not instantiated yet\n        if(_tokens.length != 2) revert InvalidTokensLength();\n\n        // Order tokens to match order of tokens in CFMM\n        _tokensOrdered = new address[](2);\n        (_tokensOrdered[0], _tokensOrdered[1]) = _tokens[0] < _tokens[1] ? (_tokens[0], _tokens[1]) : (_tokens[1], _tokens[0]);\n\n        // Verify CFMM was created by CFMM's factory contract\n        if(_cfmm != AddressCalculator.calcAddress(cfmmFactory,keccak256(abi.encodePacked(_tokensOrdered[0], _tokensOrdered[1])),cfmmInitCodeHash)) {\n            revert BadProtocol();\n        }\n    }\n}\n"
      },
      "@gammaswap/v1-implementations/contracts/pools/CPMMGammaPoolMain.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport \"./CPMMGammaPool.sol\";\n\n/// @title GammaPool implementation for Constant Product Market Maker in mainnet Ethereum\n/// @author Daniel D. Alcarraz (https://github.com/0xDanr)\n/// @dev This implementation is specifically for validating UniswapV2Pair and clone contracts\n/// @dev Overrides the initialize function to set params for higher network costs in mainnet Ethereum\ncontract CPMMGammaPoolMain is CPMMGammaPool {\n\n    using LibStorage for LibStorage.Storage;\n\n    /// @dev Initializes the contract by setting `protocolId`, `factory`, `borrowStrategy`, `repayStrategy`,\n    /// @dev `shortStrategy`, `liquidationStrategy`, `batchLiquidationStrategy`, `cfmmFactory`, and `cfmmInitCodeHash`.\n    constructor(uint16 _protocolId, address _factory, address _borrowStrategy, address _repayStrategy,\n        address _shortStrategy, address _liquidationStrategy, address _batchLiquidationStrategy, address _viewer,\n        address _externalRebalanceStrategy, address _externalLiquidationStrategy, address _cfmmFactory, bytes32 _cfmmInitCodeHash)\n        CPMMGammaPool(_protocolId, _factory, _borrowStrategy, _repayStrategy, _shortStrategy, _liquidationStrategy,\n        _batchLiquidationStrategy, _viewer, _externalRebalanceStrategy, _externalLiquidationStrategy, _cfmmFactory, _cfmmInitCodeHash) {\n    }\n\n    /// @dev See {IGammaPool-initialize}\n    function initialize(address _cfmm, address[] calldata _tokens, uint8[] calldata _decimals, uint72 _minBorrow, bytes calldata) external virtual override {\n        if(msg.sender != factory) revert Forbidden(); // only factory is allowed to initialize\n        s.initialize(factory, _cfmm, protocolId, _tokens, _decimals, _minBorrow);\n        s.ltvThreshold = 15; // 150 basis points\n        s.liquidationFee = 125; // 125 basis points\n    }\n}\n"
      },
      "@openzeppelin/contracts/token/ERC20/IERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.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(\n        address from,\n        address to,\n        uint256 amount\n    ) external returns (bool);\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": {}
    }
  }}