ETH Price: $3,424.04 (-0.43%)

Contract

0xB771f128FD3902a788eF5ef883854a43041380aA

Overview

ETH Balance

0 ETH

ETH Value

$0.00

More Info

Private Name Tags

Multichain Info

No addresses found
Amount:Between 1-1k
Reset Filter

Transaction Hash
Method
Block
From
To

There are no matching entries

Update your filters to view other transactions

Parent Transaction Hash Block From To
View All Internal Transactions

Cross-Chain Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
PositionManagerQueries

Compiler Version
v0.8.21+commit.d9974bed

Optimization Enabled:
Yes with 200 runs

Other Settings:
paris EvmVersion
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity 0.8.21;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@gammaswap/v1-core/contracts/interfaces/IGammaPoolFactory.sol";
import "@gammaswap/v1-core/contracts/interfaces/IPoolViewer.sol";
import "../libraries/QueryUtils.sol";
import "../interfaces/IPositionManagerQueries.sol";
import "../interfaces/IGammaPoolQueryableLoans.sol";
import "./LoanStore.sol";

/// @title Implementation of IPositionManagerQueries
/// @author Daniel D. Alcarraz (https://github.com/0xDanr)
/// @notice Implements external functions used by PositionManager to query pools and loans
/// @dev These are all view functions that read from storage of different GammaPools and GammaPoolFactory
contract PositionManagerQueries is IPositionManagerQueries, LoanStore {

    /// @dev address of GammaPool factory contract
    address private immutable factory;

    /// @dev Initializes the contract by setting `_factory`, and `_owner`.
    constructor(address _factory, address _owner) LoanStore(_owner) {
        factory = _factory;
    }

    /// @dev See {IPositionManagerQueries-getLoansByOwnerAndPool}.
    function getLoansByOwnerAndPool(address owner, address gammaPool, uint256 start, uint256 end) external virtual override view returns(IGammaPool.LoanData[] memory _loans) {
        uint256[] memory _tokenIds = loansByOwnerAndPool[owner][gammaPool];
        (uint256 _start, uint256 _end, uint256 _size) = QueryUtils.getSearchParameters(start, end, _tokenIds.length);
        if(_size > 0) {
            uint256[] memory _tokenIdsReq = new uint256[](_size);
            uint256 k = 0;
            for(uint256 i = _start; i <= _end;) {
                if(_tokenIds[i] > 0) {
                    _tokenIdsReq[k] = _tokenIds[i];
                }
                unchecked {
                    ++k;
                    ++i;
                }
            }
            _loans = IPoolViewer(IGammaPool(gammaPool).viewer()).getLoansById(gammaPool, _tokenIdsReq, false);
        } else {
            _loans = new IGammaPool.LoanData[](0);
        }
    }

    /// @dev See {IPositionManagerQueries-getLoansByOwner}.
    function getLoansByOwner(address owner, uint256 start, uint256 end) external virtual override view returns(IGammaPool.LoanData[] memory _loans) {
        uint256[] memory _loanList = loansByOwner[owner];
        (uint256 _start, uint256 _end, uint256 _size) = QueryUtils.getSearchParameters(start, end, _loanList.length);
        if(_size > 0) {
            _loans = new IGammaPool.LoanData[](_size);
            uint256 k = 0;
            for(uint256 i = _start; i <= _end;) {
                uint256 _tokenId = _loanList[i];
                if(_tokenId > 0) {
                    address pool = loanToInfo[_tokenId].pool;
                    _loans[k] = IPoolViewer(IGammaPool(pool).viewer()).loan(pool, _tokenId);
                }
                unchecked {
                    ++k;
                    ++i;
                }
            }
        } else {
            _loans = new IGammaPool.LoanData[](0);
        }
    }

    /// @dev See {IPositionManagerQueries-getPools}.
    function getPools(uint256 start, uint256 end) external override virtual view returns(IGammaPool.PoolData[] memory _pools) {
        address[] memory poolAddresses = IGammaPoolFactory(factory).getPools(start, end);
        _pools = new IGammaPool.PoolData[](poolAddresses.length);
        for(uint256 i = 0; i < poolAddresses.length;) {
            _pools[i] = IPoolViewer(IGammaPool(poolAddresses[i]).viewer()).getLatestPoolData(poolAddresses[i]);
            unchecked {
                ++i;
            }
        }
    }

    /// @dev See {IPositionManagerQueries-getPoolsByAddresses}.
    function getPoolsByAddresses(address[] calldata poolAddresses) external override virtual view returns(IGammaPool.PoolData[] memory _pools) {
        _pools = new IGammaPool.PoolData[](poolAddresses.length);
        for(uint256 i = 0; i < poolAddresses.length;) {
            _pools[i] = IPoolViewer(IGammaPool(poolAddresses[i]).viewer()).getLatestPoolData(poolAddresses[i]);
            unchecked {
                ++i;
            }
        }
    }

    /// @dev See {IPositionManagerQueries-getPoolsWithOwnerLPBalance}.
    function getPoolsWithOwnerLPBalance(address[] calldata poolAddresses, address owner) external view returns(IGammaPool.PoolData[] memory _pools, uint256[] memory _balances) {
        _pools = new IGammaPool.PoolData[](poolAddresses.length);
        _balances = new uint256[](poolAddresses.length);
        for(uint256 i = 0; i < poolAddresses.length;) {
            _balances[i] = IERC20(poolAddresses[i]).balanceOf(owner);
            _pools[i] = IPoolViewer(IGammaPool(poolAddresses[i]).viewer()).getLatestPoolData(poolAddresses[i]);
            unchecked {
                ++i;
            }
        }
    }
}

File 2 of 20 : IGammaPool.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity >=0.8.0;

import "./IGammaPoolEvents.sol";
import "./IProtocol.sol";
import "./strategies/events/IGammaPoolERC20Events.sol";
import "./rates/IRateModel.sol";

/// @title Interface for GammaPool
/// @author Daniel D. Alcarraz (https://github.com/0xDanr)
/// @dev Interface used for GammaPool implementations
interface IGammaPool is IProtocol, IGammaPoolEvents, IGammaPoolERC20Events, IRateModel {
    /// @dev Struct containing Loan data plus tokenId
    struct LoanData {
        /// @dev Loan counter, used to generate unique tokenId which indentifies the loan in the GammaPool
        uint256 id;

        /// @dev Loan tokenId
        uint256 tokenId;

        // 1x256 bits
        /// @dev GammaPool address loan belongs to
        address poolId; // 160 bits
        /// @dev Index of GammaPool interest rate at time loan is created/updated, max 7.9% trillion
        uint96 rateIndex; // 96 bits

        // 1x256 bits
        /// @dev Initial loan debt in liquidity invariant units. Only increase when more liquidity is borrowed, decreases when liquidity is paid
        uint128 initLiquidity; // 128 bits
        /// @dev Loan debt in liquidity invariant units in last update
        uint128 lastLiquidity; // 128 bits
        /// @dev Loan debt in liquidity invariant units, increases with every update according to how many blocks have passed
        uint128 liquidity; // 128 bits
        /// @dev Collateral in terms of liquidity invariant units, increases with every update according to how many blocks have passed
        uint256 collateral;

        /// @dev Initial loan debt in terms of LP tokens at time liquidity was borrowed, updates along with initLiquidity
        uint256 lpTokens;
        /// @dev Reserve tokens held as collateral for the liquidity debt, indices match GammaPool's tokens[] array indices
        uint128[] tokensHeld; // array of 128 bit numbers

        /// @dev reference address of contract holding additional collateral for loan (e.g. CollateralManager)
        address refAddr;
        /// @dev reference fee of contract holding additional collateral for loan (e.g. CollateralManager)
        uint16 refFee;
        /// @dev reference type of contract holding additional collateral for loan (e.g. CollateralManager)
        uint8 refType;

        /// @dev price at which loan was opened
        uint256 px;
        /// @dev if true loan can be liquidated
        bool canLiquidate;

        /// @dev names of ERC20 tokens of CFMM
        uint256 accFeeIndex;
        /// @dev Percent accrual in CFMM invariant since last update
        uint256 lastCFMMFeeIndex;
        /// @dev names of ERC20 tokens of CFMM
        uint256 LAST_BLOCK_NUMBER;

        /// @dev ERC20 tokens of CFMM
        address[] tokens;
        /// @dev decimals of ERC20 tokens of CFMM
        uint8[] decimals;
        /// @dev symbols of ERC20 tokens of CFMM
        string[] symbols;
        /// @dev names of ERC20 tokens of CFMM
        string[] names;

        /// @dev interest rate model parameter store
        address paramsStore;
        /// @dev address of short strategy
        address shortStrategy;

        /// @dev borrowed liquidity invariant of the pool
        uint256 BORROWED_INVARIANT;
        /// @dev Quantity of CFMM's liquidity invariant held in GammaPool as LP tokens
        uint256 LP_INVARIANT;
        /// @dev balance of CFMM LP tokens in the pool
        uint256 LP_TOKEN_BALANCE;
        /// @dev last CFMM liquidity invariant
        uint256 lastCFMMInvariant;
        /// @dev last CFMM total supply of LP tokens
        uint256 lastCFMMTotalSupply;
        /// @dev LTV liquidation threshold
        uint256 ltvThreshold;
        /// @dev Liquidation fee
        uint256 liquidationFee;
    }

    /// @dev Struct returned in getLatestRates function. Contains all relevant global state variables
    struct RateData {
        /// @dev GammaPool's ever increasing interest rate index, tracks interest accrued through CFMM and liquidity loans, max 7.9% trillion
        uint256 accFeeIndex;
        /// @dev Percent accrual in CFMM invariant since last update
        uint256 lastCFMMFeeIndex;
        /// @dev Percent accrual in CFMM invariant and GammaPool interest since last update
        uint256 lastFeeIndex;
        /// @dev Borrow APR of LP tokens in GammaPool
        uint256 borrowRate;
        /// @dev Utilization rate of GammaPool
        uint256 utilizationRate;
        /// @dev last block an update to the GammaPool's global storage variables happened
        uint256 lastBlockNumber;
        /// @dev Current block number when requesting pool data
        uint256 currBlockNumber;
        /// @dev Last Price in CFMM
        uint256 lastPrice;
        /// @dev Supply APR of LP tokens in GammaPool
        uint256 supplyRate;
        /// @dev names of ERC20 tokens of CFMM
        uint256 BORROWED_INVARIANT;
        /// @dev Quantity of CFMM's liquidity invariant held in GammaPool as LP tokens
        uint256 LP_INVARIANT;
        /// @dev EMA of utilization Rate
        uint256 emaUtilRate;
        /// @dev Minimum Utilization Rate 1
        uint256 minUtilRate1;
        /// @dev Minimum Utilization Rate 2
        uint256 minUtilRate2;
        /// @dev Dynamic origination fee divisor
        uint256 feeDivisor;
        /// @dev Loan opening origination fee in basis points
        uint256 origFee; // 16 bits
        /// @dev LTV liquidation threshold
        uint256 ltvThreshold;
        /// @dev Liquidation fee
        uint256 liquidationFee;
        /// @dev Short Strategy implementation address
        address shortStrategy;
        /// @dev Interest Rate Parameters Store contract
        address paramsStore;
    }

    /// @dev Struct returned in getPoolData function. Contains all relevant global state variables
    struct PoolData {
        /// @dev GammaPool address
        address poolId;
        /// @dev Protocol id of the implementation contract for this GammaPool
        uint16 protocolId;
        /// @dev Borrow Strategy implementation contract for this GammaPool
        address borrowStrategy;
        /// @dev Repay Strategy implementation contract for this GammaPool
        address repayStrategy;
        /// @dev Rebalance Strategy implementation contract for this GammaPool
        address rebalanceStrategy;
        /// @dev Short Strategy implementation contract for this GammaPool
        address shortStrategy;
        /// @dev Single Liquidation Strategy implementation contract for this GammaPool
        address singleLiquidationStrategy;
        /// @dev Batch Liquidation Strategy implementation contract for this GammaPool
        address batchLiquidationStrategy;

        /// @dev factory - address of factory contract that instantiated this GammaPool
        address factory;
        /// @dev paramsStore - interest rate model parameters store contract
        address paramsStore;

        // LP Tokens
        /// @dev Quantity of CFMM's LP tokens deposited in GammaPool by liquidity providers
        uint256 LP_TOKEN_BALANCE;// LP Tokens in GS, LP_TOKEN_TOTAL = LP_TOKEN_BALANCE + LP_TOKEN_BORROWED_PLUS_INTEREST
        /// @dev Quantity of CFMM's LP tokens that have been borrowed by liquidity borrowers excluding accrued interest (principal)
        uint256 LP_TOKEN_BORROWED;//LP Tokens that have been borrowed (Principal)
        /// @dev Quantity of CFMM's LP tokens that have been borrowed by liquidity borrowers including accrued interest
        uint256 LP_TOKEN_BORROWED_PLUS_INTEREST;//LP Tokens that have been borrowed (principal) plus interest in LP Tokens

        // Invariants
        /// @dev Quantity of CFMM's liquidity invariant that has been borrowed including accrued interest, maps to LP_TOKEN_BORROWED_PLUS_INTEREST
        uint128 BORROWED_INVARIANT;
        /// @dev Quantity of CFMM's liquidity invariant held in GammaPool as LP tokens, maps to LP_TOKEN_BALANCE
        uint128 LP_INVARIANT;//Invariant from LP Tokens, TOTAL_INVARIANT = BORROWED_INVARIANT + LP_INVARIANT

        // Rates
        /// @dev cfmm - address of CFMM this GammaPool is for
        address cfmm;
        /// @dev GammaPool's ever increasing interest rate index, tracks interest accrued through CFMM and liquidity loans, max 30.9% billion
        uint80 accFeeIndex;
        /// @dev External swap fee in basis points, max 255 basis points = 2.55%
        uint8 extSwapFee; // 8 bits
        /// @dev Loan opening origination fee in basis points
        uint16 origFee; // 16 bits
        /// @dev LAST_BLOCK_NUMBER - last block an update to the GammaPool's global storage variables happened
        uint40 LAST_BLOCK_NUMBER;
        /// @dev Percent accrual in CFMM invariant since last update
        uint64 lastCFMMFeeIndex; // 64 bits
        /// @dev Total liquidity invariant amount in CFMM (from GammaPool and others), read in last update to GammaPool's storage variables
        uint128 lastCFMMInvariant;
        /// @dev Total LP token supply from CFMM (belonging to GammaPool and others), read in last update to GammaPool's storage variables
        uint256 lastCFMMTotalSupply;

        // ERC20 fields
        /// @dev Total supply of GammaPool's own ERC20 token representing the liquidity of depositors to the CFMM through the GammaPool
        uint256 totalSupply;

        // tokens and balances
        /// @dev ERC20 tokens of CFMM
        address[] tokens;
        /// @dev symbols of ERC20 tokens of CFMM
        string[] symbols;
        /// @dev names of ERC20 tokens of CFMM
        string[] names;
        /// @dev Decimals of CFMM tokens, indices match tokens[] array
        uint8[] decimals;
        /// @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
        uint128[] TOKEN_BALANCE;
        /// @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
        uint128[] CFMM_RESERVES; //keeps track of price of CFMM at time of update

        /// @dev Last Price in CFMM
        uint256 lastPrice;
        /// @dev Percent accrual in CFMM invariant and GammaPool interest since last update
        uint256 lastFeeIndex;
        /// @dev Borrow rate of LP tokens in GammaPool
        uint256 borrowRate;
        /// @dev Utilization rate of GammaPool
        uint256 utilizationRate;
        /// @dev Current block number when requesting pool data
        uint40 currBlockNumber;
        /// @dev LTV liquidation threshold
        uint8 ltvThreshold;
        /// @dev Liquidation fee
        uint8 liquidationFee;
        /// @dev Supply APR of LP tokens in GammaPool
        uint256 supplyRate;
        /// @dev EMA of utilization Rate
        uint40 emaUtilRate;
        /// @dev Multiplier of EMA Utilization Rate
        uint8 emaMultiplier;
        /// @dev Minimum Utilization Rate 1
        uint8 minUtilRate1;
        /// @dev Minimum Utilization Rate 2
        uint8 minUtilRate2;
        /// @dev Dynamic origination fee divisor
        uint16 feeDivisor;
        /// @dev Minimum liquidity amount that can be borrowed
        uint72 minBorrow;
    }

    /// @dev cfmm - address of CFMM this GammaPool is for
    function cfmm() external view returns(address);

    /// @dev ERC20 tokens of CFMM
    function tokens() external view returns(address[] memory);

    /// @dev address of factory contract that instantiated this GammaPool
    function factory() external view returns(address);

    /// @dev viewer contract to implement complex view functions for data in this GammaPool
    function viewer() external view returns(address);

    /// @dev Borrow Strategy implementation contract for this GammaPool
    function borrowStrategy() external view returns(address);

    /// @dev Repay Strategy implementation contract for this GammaPool
    function repayStrategy() external view returns(address);

    /// @dev Rebalance Strategy implementation contract for this GammaPool
    function rebalanceStrategy() external view returns(address);

    /// @dev Short Strategy implementation contract for this GammaPool
    function shortStrategy() external view returns(address);

    /// @dev Single Loan Liquidation Strategy implementation contract for this GammaPool
    function singleLiquidationStrategy() external view returns(address);

    /// @dev Batch Liquidations Strategy implementation contract for this GammaPool
    function batchLiquidationStrategy() external view returns(address);

    /// @dev Set parameters to calculate origination fee, liquidation fee, and ltv threshold
    /// @param origFee - loan opening origination fee in basis points
    /// @param extSwapFee - external swap fee in basis points, max 255 basis points = 2.55%
    /// @param emaMultiplier - multiplier used in EMA calculation of utilization rate
    /// @param minUtilRate1 - minimum utilization rate to calculate dynamic origination fee in exponential model
    /// @param minUtilRate2 - minimum utilization rate to calculate dynamic origination fee in linear model
    /// @param feeDivisor - fee divisor for calculating origination fee, based on 2^(maxUtilRate - minUtilRate1)
    /// @param liquidationFee - liquidation fee to charge during liquidations in basis points (1 - 255 => 0.01% to 2.55%)
    /// @param ltvThreshold - ltv threshold (1 - 255 => 0.1% to 25.5%)
    /// @param minBorrow - minimum liquidity amount that can be borrowed or left unpaid in a loan
    function setPoolParams(uint16 origFee, uint8 extSwapFee, uint8 emaMultiplier, uint8 minUtilRate1, uint8 minUtilRate2, uint16 feeDivisor, uint8 liquidationFee, uint8 ltvThreshold, uint72 minBorrow) external;

    /// @dev Balances in the GammaPool of collateral tokens, CFMM LP tokens, and invariant amounts at last update
    /// @return tokenBalances - balances of collateral tokens in GammaPool
    /// @return lpTokenBalance - CFMM LP token balance of GammaPool
    /// @return lpTokenBorrowed - CFMM LP token principal amounts borrowed from GammaPool
    /// @return lpTokenBorrowedPlusInterest - CFMM LP token amounts borrowed from GammaPool including accrued interest
    /// @return borrowedInvariant - invariant amount borrowed from GammaPool including accrued interest, maps to lpTokenBorrowedPlusInterest
    /// @return lpInvariant - invariant of CFMM LP tokens in GammaPool not borrowed, maps to lpTokenBalance
    function getPoolBalances() external view returns(uint128[] memory tokenBalances, uint256 lpTokenBalance, uint256 lpTokenBorrowed,
        uint256 lpTokenBorrowedPlusInterest, uint256 borrowedInvariant, uint256 lpInvariant);

    /// @dev Balances in CFMM at last update of GammaPool
    /// @return cfmmReserves - total reserve tokens in CFMM last time GammaPool was updated
    /// @return cfmmInvariant - total liquidity invariant of CFMM last time GammaPool was updated
    /// @return cfmmTotalSupply - total CFMM LP tokens in existence last time GammaPool was updated
    function getCFMMBalances() external view returns(uint128[] memory cfmmReserves, uint256 cfmmInvariant, uint256 cfmmTotalSupply);

    /// @dev Interest rate information in GammaPool at last update
    /// @return accFeeIndex - total accrued interest in GammaPool at last update
    /// @return lastCFMMFeeIndex - total accrued CFMM fee since last update
    /// @return lastBlockNumber - last block GammaPool was updated
    function getRates() external view returns(uint256 accFeeIndex, uint256 lastCFMMFeeIndex, uint256 lastBlockNumber);

    /// @return data - struct containing all relevant global state variables and descriptive information of GammaPool. Used to avoid making multiple calls
    function getPoolData() external view returns(PoolData memory data);

    // Short Gamma

    /// @dev Deposit CFMM LP token and get GS LP token, without doing a transferFrom transaction. Must have sent CFMM LP token first
    /// @param to - address of receiver of GS LP token
    /// @return shares - quantity of GS LP tokens received for CFMM LP tokens
    function depositNoPull(address to) external returns(uint256 shares);

    /// @dev Withdraw CFMM LP token, by burning GS LP token, without doing a transferFrom transaction. Must have sent GS LP token first
    /// @param to - address of receiver of CFMM LP tokens
    /// @return assets - quantity of CFMM LP tokens received for GS LP tokens
    function withdrawNoPull(address to) external returns(uint256 assets);

    /// @dev Withdraw reserve token quantities of CFMM (instead of CFMM LP tokens), by burning GS LP token
    /// @param to - address of receiver of reserve token quantities
    /// @return reserves - quantity of reserve tokens withdrawn from CFMM and sent to receiver
    /// @return assets - quantity of CFMM LP tokens representing reserve tokens withdrawn
    function withdrawReserves(address to) external returns (uint256[] memory reserves, uint256 assets);

    /// @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
    /// @param to - address of receiver of GS LP tokens
    /// @param amountsDesired - desired amounts of reserve tokens to deposit
    /// @param amountsMin - minimum amounts of reserve tokens to deposit
    /// @param data - information identifying request to deposit
    /// @return reserves - quantity of actual reserve tokens deposited in CFMM
    /// @return shares - quantity of GS LP tokens received for reserve tokens deposited
    function depositReserves(address to, uint256[] calldata amountsDesired, uint256[] calldata amountsMin, bytes calldata data) external returns(uint256[] memory reserves, uint256 shares);

    /// @return cfmmReserves - latest token reserves in the CFMM
    function getLatestCFMMReserves() external view returns(uint128[] memory cfmmReserves);

    /// @return cfmmReserves - latest token reserves in the CFMM
    /// @return cfmmInvariant - latest total invariant in the CFMM
    /// @return cfmmTotalSupply - latest total supply of LP tokens in CFMM
    function getLatestCFMMBalances() external view returns(uint128[] memory cfmmReserves, uint256 cfmmInvariant, uint256 cfmmTotalSupply);

    /// @return lastPrice - calculates and gets current price at CFMM
    function getLastCFMMPrice() external view returns(uint256);

    // Long Gamma

    /// @dev Create a new Loan struct
    /// @param refId - Reference id of post transaction activities attached to this loan
    /// @return tokenId - unique id of loan struct created
    function createLoan(uint16 refId) external returns(uint256 tokenId);

    /// @dev Get loan from storage and convert to LoanData struct
    /// @param _tokenId - tokenId of loan to convert
    /// @return _loanData - loan data struct (same as Loan + tokenId)
    function getLoanData(uint256 _tokenId) external view returns(LoanData memory _loanData);

    /// @dev Get loan with its most updated information
    /// @param _tokenId - unique id of loan, used to look up loan in GammaPool
    /// @return _loanData - loan data struct (same as Loan + tokenId)
    function loan(uint256 _tokenId) external view returns(LoanData memory _loanData);

    /// @dev Get list of loans and their corresponding tokenIds created in GammaPool. Capped at s.tokenIds.length.
    /// @param start - index from where to start getting tokenIds from array
    /// @param end - end index of array wishing to get tokenIds. If end > s.tokenIds.length, end is s.tokenIds.length
    /// @param active - if true, return loans that have an outstanding liquidity debt
    /// @return _loans - list of loans created in GammaPool
    function getLoans(uint256 start, uint256 end, bool active) external view returns(LoanData[] memory _loans);

    /// @dev calculate liquidity invariant from collateral tokens
    /// @param tokensHeld - loan's collateral tokens
    /// @return collateralInvariant - invariant calculated from loan's collateral tokens
    function calcInvariant(uint128[] memory tokensHeld) external view returns(uint256);

    /// @dev Get list of loans mapped to tokenIds in array `tokenIds`
    /// @param tokenIds - list of loan tokenIds
    /// @param active - if true, return loans that have an outstanding liquidity debt
    /// @return _loans - list of loans created in GammaPool
    function getLoansById(uint256[] calldata tokenIds, bool active) external view returns(LoanData[] memory _loans);

    /// @return loanCount - total number of loans opened
    function getLoanCount() external view returns(uint256);

    /// @dev Deposit more collateral in loan identified by tokenId
    /// @param tokenId - unique id identifying loan
    /// @param ratio - ratio to rebalance collateral after increasing collateral
    /// @return tokensHeld - updated collateral token amounts backing loan
    function increaseCollateral(uint256 tokenId, uint256[] calldata ratio) external returns(uint128[] memory tokensHeld);

    /// @dev Withdraw collateral from loan identified by tokenId
    /// @param tokenId - unique id identifying loan
    /// @param amounts - amounts of collateral tokens requested to withdraw
    /// @param to - destination address of receiver of collateral withdrawn
    /// @param ratio - ratio to rebalance collateral after withdrawing collateral
    /// @return tokensHeld - updated collateral token amounts backing loan
    function decreaseCollateral(uint256 tokenId, uint128[] memory amounts, address to, uint256[] calldata ratio) external returns(uint128[] memory tokensHeld);

    /// @dev Borrow liquidity from the CFMM and add it to the debt and collateral of loan identified by tokenId
    /// @param tokenId - unique id identifying loan
    /// @param lpTokens - quantity of CFMM LP tokens requested to short
    /// @param ratio - ratio to rebalance collateral after borrowing
    /// @return liquidityBorrowed - liquidity amount that has been borrowed
    /// @return amounts - reserves quantities withdrawn from CFMM that correspond to the LP tokens shorted, now used as collateral
    /// @return tokensHeld - updated collateral token amounts backing loan
    function borrowLiquidity(uint256 tokenId, uint256 lpTokens, uint256[] calldata ratio) external returns(uint256 liquidityBorrowed, uint256[] memory amounts, uint128[] memory tokensHeld);

    /// @dev Repay liquidity debt of loan identified by tokenId, debt is repaid using available collateral in loan
    /// @param tokenId - unique id identifying loan
    /// @param liquidity - liquidity debt being repaid, capped at actual liquidity owed. Can't repay more than you owe
    /// @param collateralId - index of collateral token + 1
    /// @param to - if repayment type requires withdrawal, the address that will receive the funds. Otherwise can be zero address
    /// @return liquidityPaid - liquidity amount that has been repaid
    /// @return amounts - collateral amounts consumed in repaying liquidity debt
    function repayLiquidity(uint256 tokenId, uint256 liquidity, uint256 collateralId, address to) external returns(uint256 liquidityPaid, uint256[] memory amounts);

    /// @dev Repay liquidity debt of loan identified by tokenId, debt is repaid using available collateral in loan
    /// @param tokenId - unique id identifying loan
    /// @param liquidity - liquidity debt being repaid, capped at actual liquidity owed. Can't repay more than you owe
    /// @param ratio - weights of collateral after repaying liquidity
    /// @return liquidityPaid - liquidity amount that has been repaid
    /// @return amounts - collateral amounts consumed in repaying liquidity debt
    function repayLiquiditySetRatio(uint256 tokenId, uint256 liquidity, uint256[] calldata ratio) external returns(uint256 liquidityPaid, uint256[] memory amounts);

    /// @dev Repay liquidity debt of loan identified by tokenId, using CFMM LP token
    /// @param tokenId - unique id identifying loan
    /// @param collateralId - index of collateral token to rebalance to + 1
    /// @param to - if repayment type requires withdrawal, the address that will receive the funds. Otherwise can be zero address
    /// @return liquidityPaid - liquidity amount that has been repaid
    /// @return tokensHeld - remaining token amounts collateralizing loan
    function repayLiquidityWithLP(uint256 tokenId, uint256 collateralId, address to) external returns(uint256 liquidityPaid, uint128[] memory tokensHeld);

    /// @dev Rebalance collateral amounts of loan identified by tokenId by purchasing or selling some of the collateral
    /// @param tokenId - unique id identifying loan
    /// @param deltas - collateral amounts being bought or sold (>0 buy, <0 sell), index matches tokensHeld[] index. Only n-1 tokens can be traded
    /// @param ratio - ratio to rebalance collateral
    /// @return tokensHeld - updated collateral token amounts backing loan
    function rebalanceCollateral(uint256 tokenId, int256[] memory deltas, uint256[] calldata ratio) external returns(uint128[] memory tokensHeld);

    /// @dev Update pool liquidity debt and optinally also loan liquidity debt
    /// @param tokenId - (optional) unique ids identifying loan, pass zero to ignore this parameter
    /// @return loanLiquidityDebt - updated liquidity debt amount of loan
    /// @return poolLiquidityDebt - updated liquidity debt amount of pool
    function updatePool(uint256 tokenId) external returns(uint256 loanLiquidityDebt, uint256 poolLiquidityDebt);

    /// @notice When calling this function and adding additional collateral it is assumed that you have sent the collateral first
    /// @dev Function to liquidate a loan using its own collateral or depositing additional tokens. Seeks full liquidation
    /// @param tokenId - tokenId of loan being liquidated
    /// @return loanLiquidity - loan liquidity liquidated (after write down)
    /// @return refund - amount of CFMM LP tokens being refunded to liquidator
    function liquidate(uint256 tokenId) external returns(uint256 loanLiquidity, uint256 refund);

    /// @dev Function to liquidate a loan using external LP tokens. Allows partial liquidation
    /// @param tokenId - tokenId of loan being liquidated
    /// @return loanLiquidity - loan liquidity liquidated (after write down)
    /// @return refund - amounts from collateral tokens being refunded to liquidator
    function liquidateWithLP(uint256 tokenId) external returns(uint256 loanLiquidity, uint256[] memory refund);

    /// @dev Function to liquidate multiple loans in batch.
    /// @param tokenIds - list of tokenIds of loans to liquidate
    /// @return totalLoanLiquidity - total loan liquidity liquidated (after write down)
    /// @return refund - amounts from collateral tokens being refunded to liquidator
    function batchLiquidations(uint256[] calldata tokenIds) external returns(uint256 totalLoanLiquidity, uint256[] memory refund);

    // Sync functions

    /// @dev Skim excess collateral tokens or CFMM LP tokens from GammaPool and send them to receiver (`to`) address
    /// @param to - address receiving excess tokens
    function skim(address to) external;

    /// @dev Synchronize LP_TOKEN_BALANCE with actual CFMM LP tokens deposited in GammaPool
    function sync() external;
}

File 3 of 20 : IGammaPoolEvents.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity >=0.8.0;

import "./strategies/events/ILiquidationStrategyEvents.sol";
import "./strategies/events/IShortStrategyEvents.sol";
import "./strategies/events/IExternalStrategyEvents.sol";

/// @title GammaPool Events Interface
/// @author Daniel D. Alcarraz (https://github.com/0xDanr)
/// @dev Events emitted by all GammaPool implementations (contains all strategy events)
interface IGammaPoolEvents is IShortStrategyEvents, ILiquidationStrategyEvents, IExternalStrategyEvents {
    /// @dev Event emitted when a Loan is created
    /// @param caller - address that created the loan
    /// @param tokenId - unique id that identifies the loan in question
    /// @param refId - Reference id of post transaction activities attached to this loan
    event LoanCreated(address indexed caller, uint256 tokenId, uint16 refId);
}

// SPDX-License-Identifier: BUSL-1.1
pragma solidity >=0.8.0;

/// @title Interface for factory contract to create more GammaPool contracts.
/// @author Daniel D. Alcarraz (https://github.com/0xDanr)
/// @dev All instantiated GammaPoolFactory contracts must implement this interface
interface IGammaPoolFactory {
    /// @dev Event emitted when a new GammaPool is instantiated
    /// @param pool - address of new pool that is created
    /// @param cfmm - address of CFMM the GammaPool is created for
    /// @param protocolId - id identifier of GammaPool protocol (can be thought of as version)
    /// @param implementation - implementation address of GammaPool proxy contract. Because all GammaPools are created as proxy contracts
    /// @param tokens - ERC20 tokens of CFMM
    /// @param count - number of GammaPools instantiated including this contract
    event PoolCreated(address indexed pool, address indexed cfmm, uint16 indexed protocolId, address implementation, address[] tokens, uint256 count);

    /// @dev Event emitted when a GammaPool fee is updated
    /// @param pool - address of new pool whose fee is updated (zero address is default params)
    /// @param to - receiving address of protocol fees
    /// @param protocolFee - protocol fee share charged from interest rate accruals
    /// @param origFeeShare - protocol fee share charged on origination fees
    /// @param isSet - bool flag, true use fee information, false use GammaSwap default fees
    event FeeUpdate(address indexed pool, address indexed to, uint16 protocolFee, uint16 origFeeShare, bool isSet);

    /// @dev Event emitted when a GammaPool parameters are updated
    /// @param pool - address of GammaPool whose origination fee parameters will be updated
    /// @param origFee - loan opening origination fee in basis points
    /// @param extSwapFee - external swap fee in basis points, max 255 basis points = 2.55%
    /// @param emaMultiplier - multiplier used in EMA calculation of utilization rate
    /// @param minUtilRate1 - minimum utilization rate to calculate dynamic origination fee using exponential model
    /// @param minUtilRate2 - minimum utilization rate to calculate dynamic origination fee using linear model
    /// @param feeDivisor - fee divisor for calculating origination fee, based on 2^(maxUtilRate - minUtilRate1)
    /// @param liquidationFee - liquidation fee to charge during liquidations in basis points (1 - 255 => 0.01% to 2.55%)
    /// @param ltvThreshold - ltv threshold (1 - 255 => 0.1% to 25.5%)
    /// @param minBorrow - minimum liquidity amount that can be borrowed or left unpaid in a loan
    event PoolParamsUpdate(address indexed pool, uint16 origFee, uint8 extSwapFee, uint8 emaMultiplier, uint8 minUtilRate1, uint8 minUtilRate2, uint16 feeDivisor, uint8 liquidationFee, uint8 ltvThreshold, uint72 minBorrow);

    /// @dev Check if protocol is restricted. Which means only owner of GammaPoolFactory is allowed to instantiate GammaPools using this protocol
    /// @param _protocolId - id identifier of GammaPool protocol (can be thought of as version) that is being checked
    /// @return _isRestricted - true if protocol is restricted, false otherwise
    function isProtocolRestricted(uint16 _protocolId) external view returns(bool);

    /// @dev Set a protocol to be restricted or unrestricted. That means only owner of GammaPoolFactory is allowed to instantiate GammaPools using this protocol
    /// @param _protocolId - id identifier of GammaPool protocol (can be thought of as version) that is being restricted
    /// @param _isRestricted - set to true for restricted, set to false for unrestricted
    function setIsProtocolRestricted(uint16 _protocolId, bool _isRestricted) external;

    /// @notice Only owner of GammaPoolFactory can call this function
    /// @dev Add a protocol implementation to GammaPoolFactory contract. Which means GammaPoolFactory can create GammaPools with this implementation (protocol)
    /// @param _implementation - implementation address of GammaPool proxy contract. Because all GammaPools are created as proxy contracts
    function addProtocol(address _implementation) external;

    /// @notice Only owner of GammaPoolFactory can call this function
    /// @dev Update protocol implementation for a protocol.
    /// @param _protocolId - id identifier of GammaPool implementation
    /// @param _newImplementation - implementation address of GammaPool proxy contract. Because all GammaPools are created as proxy contracts
    function updateProtocol(uint16 _protocolId, address _newImplementation) external;

    /// @notice Only owner of GammaPoolFactory can call this function
    /// @dev Locks protocol implementation for upgradable protocols (<10000) so GammaPoolFactory can no longer update the implementation contract for this upgradable protocol
    /// @param _protocolId - id identifier of GammaPool implementation
    function lockProtocol(uint16 _protocolId) external;

    /// @dev Get implementation address that maps to protocolId. This is the actual implementation code that a GammaPool implements for a protocolId
    /// @param _protocolId - id identifier of GammaPool implementation (can be thought of as version)
    /// @return _address - implementation address of GammaPool proxy contract. Because all GammaPools are created as proxy contracts
    function getProtocol(uint16 _protocolId) external view returns (address);

    /// @dev Get beacon address that maps to protocolId. This beacon contract contains the implementation address of the GammaPool proxy
    /// @param _protocolId - id identifier of GammaPool implementation (can be thought of as version)
    /// @return _address - address of beacon of GammaPool proxy contract. Because all GammaPools are created as proxy contracts if there is one
    function getProtocolBeacon(uint16 _protocolId) external view returns (address);

    /// @dev Instantiate a new GammaPool for a CFMM based on an existing implementation (protocolId)
    /// @param _protocolId - id identifier of GammaPool protocol (can be thought of as version)
    /// @param _cfmm - address of CFMM the GammaPool is created for
    /// @param _tokens - addresses of ERC20 tokens in CFMM, used for validation during runtime of function
    /// @param _data - custom struct containing additional information used to verify the `_cfmm`
    /// @return _address - address of new GammaPool proxy contract that was instantiated
    function createPool(uint16 _protocolId, address _cfmm, address[] calldata _tokens, bytes calldata _data) external returns(address);

    /// @dev Mapping of bytes32 salts (key) to GammaPool addresses. The salt is predetermined and used to instantiate a GammaPool with a unique address
    /// @param _salt - the bytes32 key that is unique to the GammaPool and therefore also used as a unique identifier of the GammaPool
    /// @return _address - address of GammaPool that maps to bytes32 salt (key)
    function getPool(bytes32 _salt) external view returns(address);

    /// @dev Mapping of bytes32 salts (key) to GammaPool addresses. The salt is predetermined and used to instantiate a GammaPool with a unique address
    /// @param _pool - address of GammaPool that maps to bytes32 salt (key)
    /// @return _salt - the bytes32 key that is unique to the GammaPool and therefore also used as a unique identifier of the GammaPool
    function getKey(address _pool) external view returns(bytes32);

    /// @return count - number of GammaPools that have been instantiated through this GammaPoolFactory contract
    function allPoolsLength() external view returns (uint256);

    /// @dev Get pool fee parameters used to calculate protocol fees
    /// @param _pool - pool address identifier
    /// @return _to - address receiving fee
    /// @return _protocolFee - protocol fee share charged from interest rate accruals
    /// @return _origFeeShare - protocol fee share charged on origination fees
    /// @return _isSet - bool flag, true use fee information, false use GammaSwap default fees
    function getPoolFee(address _pool) external view returns (address _to, uint256 _protocolFee, uint256 _origFeeShare, bool _isSet);

    /// @dev Set pool fee parameters used to calculate protocol fees
    /// @param _pool - id identifier of GammaPool protocol (can be thought of as version)
    /// @param _to - address receiving fee
    /// @param _protocolFee - protocol fee share charged from interest rate accruals
    /// @param _origFeeShare - protocol fee share charged on origination fees
    /// @param _isSet - bool flag, true use fee information, false use GammaSwap default fees
    function setPoolFee(address _pool, address _to, uint16 _protocolFee, uint16 _origFeeShare, bool _isSet) external;

    /// @dev Call admin function in GammaPool contract
    /// @param _pool - address of GammaPool whose admin function will be called
    /// @param _data - custom struct containing information to execute in pool contract
    function execute(address _pool, bytes calldata _data) external;

    /// @dev Pause a GammaPool's function identified by a `_functionId`
    /// @param _pool - address of GammaPool whose functions we will pause
    /// @param _functionId - id of function in GammaPool we want to pause
    /// @return _functionIds - uint256 number containing all turned on (paused) function ids
    function pausePoolFunction(address _pool, uint8 _functionId) external returns(uint256 _functionIds) ;

    /// @dev Unpause a GammaPool's function identified by a `_functionId`
    /// @param _pool - address of GammaPool whose functions we will unpause
    /// @param _functionId - id of function in GammaPool we want to unpause
    /// @return _functionIds - uint256 number containing all turned on (paused) function ids
    function unpausePoolFunction(address _pool, uint8 _functionId) external returns(uint256 _functionIds) ;

    /// @return fee - protocol fee charged by GammaPool to liquidity borrowers in terms of basis points
    function fee() external view returns(uint16);

    /// @return origFeeShare - protocol fee share charged on origination fees
    function origFeeShare() external view returns(uint16);

    /// @return feeTo - address that receives protocol fees
    function feeTo() external view returns(address);

    /// @return feeToSetter - address that has the power to set protocol fees
    function feeToSetter() external view returns(address);

    /// @return feeTo - address that receives protocol fees
    /// @return fee - protocol fee charged by GammaPool to liquidity borrowers in terms of basis points
    /// @return origFeeShare - protocol fee share charged on origination fees
    function feeInfo() external view returns(address,uint256,uint256);

    /// @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
    /// @param start - start index of pools to search
    /// @param end - end index of pools to search
    /// @return _pools - all pools requested
    function getPools(uint256 start, uint256 end) external view returns(address[] memory _pools);

    /// @dev See {IGammaPoolFactory-setFee}
    function setFee(uint16 _fee) external;

    /// @dev See {IGammaPoolFactory-setFeeTo}
    function setFeeTo(address _feeTo) external;

    /// @dev See {IGammaPoolFactory-setOrigFeeShare}
    function setOrigFeeShare(uint16 _origFeeShare) external;

    /// @dev See {IGammaPoolFactory-setFeeToSetter}
    function setFeeToSetter(address _feeToSetter) external;

}

// SPDX-License-Identifier: BUSL-1.1
pragma solidity >=0.8.0;

import "./IGammaPool.sol";

/// @title Interface for Viewer Contract for GammaPool
/// @author Daniel D. Alcarraz (https://github.com/0xDanr)
/// @dev Viewer makes complex view function calls from GammaPool's storage data (e.g. updated loan and pool debt)
interface IPoolViewer {

    /// @dev Check if can liquidate loan identified by `tokenId`
    /// @param pool - address of pool loans belong to
    /// @param tokenId - unique id of loan, used to look up loan in GammaPool
    /// @return canLiquidate - true if loan can be liquidated, false otherwise
    function canLiquidate(address pool, uint256 tokenId) external view returns(bool);

    /// @dev Get latest rate information from GammaPool
    /// @param pool - address of pool to request latest rates for
    /// @return data - RateData struct containing latest rate information
    function getLatestRates(address pool) external view returns(IGammaPool.RateData memory data);

    /// @dev Get list of loans and their corresponding tokenIds created in GammaPool. Capped at s.tokenIds.length.
    /// @param pool - address of pool loans belong to
    /// @param start - index from where to start getting tokenIds from array
    /// @param end - end index of array wishing to get tokenIds. If end > s.tokenIds.length, end is s.tokenIds.length
    /// @param active - if true, return loans that have an outstanding liquidity debt
    /// @return _loans - list of loans created in GammaPool
    function getLoans(address pool, uint256 start, uint256 end, bool active) external view returns(IGammaPool.LoanData[] memory _loans);

    /// @dev Get list of loans mapped to tokenIds in array `tokenIds`
    /// @param pool - address of pool loans belong to
    /// @param tokenIds - list of loan tokenIds
    /// @param active - if true, return loans that have an outstanding liquidity debt
    /// @return _loans - list of loans created in GammaPool
    function getLoansById(address pool, uint256[] calldata tokenIds, bool active) external view returns(IGammaPool.LoanData[] memory _loans);

    /// @dev Get loan with its most updated information
    /// @param pool - address of pool loan belongs to
    /// @param tokenId - unique id of loan, used to look up loan in GammaPool
    /// @return loanData - loan data struct (same as Loan + tokenId)
    function loan(address pool, uint256 tokenId) external view returns(IGammaPool.LoanData memory loanData);

    /// @dev Returns pool storage data updated to their latest values
    /// @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
    /// @param pool - address of pool to get pool data for
    /// @return data - struct containing all relevant global state variables and descriptive information of GammaPool. Used to avoid making multiple calls
    function getLatestPoolData(address pool) external view returns(IGammaPool.PoolData memory data);

    /// @dev Calculate origination fee that will be charged if borrowing liquidity amount
    /// @param pool - address of GammaPool to calculate origination fee for
    /// @param liquidity - liquidity to borrow
    /// @return origFee - calculated origination fee, without any discounts
    function calcDynamicOriginationFee(address pool, uint256 liquidity) external view returns(uint256 origFee);

    /// @dev Return pool storage data
    /// @param pool - address of pool to get pool data for
    /// @return data - struct containing all relevant global state variables and descriptive information of GammaPool. Used to avoid making multiple calls
    function getPoolData(address pool) external view returns(IGammaPool.PoolData memory data);

    /// @dev Get CFMM tokens meta data
    /// @param _tokens - array of token address of ERC20 tokens of CFMM
    /// @return _symbols - array of symbols of ERC20 tokens of CFMM
    /// @return _names - array of names of ERC20 tokens of CFMM
    /// @return _decimals - array of decimals of ERC20 tokens of CFMM
    function getTokensMetaData(address[] memory _tokens) external view returns(string[] memory _symbols, string[] memory _names, uint8[] memory _decimals);

}

// SPDX-License-Identifier: BUSL-1.1
pragma solidity >=0.8.0;

/// @title Interface for Protocol
/// @author Daniel D. Alcarraz (https://github.com/0xDanr)
/// @dev Interface used to add protocols and initialize them in GammaPoolFactory
interface IProtocol {
    /// @dev Protocol id of the implementation contract for this GammaPool
    function protocolId() external view returns(uint16);

    /// @dev Check GammaPool for CFMM and tokens can be created with this implementation
    /// @param _tokens - assumed tokens of CFMM, validate function should check CFMM is indeed for these tokens
    /// @param _cfmm - address of CFMM GammaPool will be for
    /// @param _data - custom struct containing additional information used to verify the `_cfmm`
    /// @return _tokensOrdered - tokens ordered to match the same order as in CFMM
    function validateCFMM(address[] calldata _tokens, address _cfmm, bytes calldata _data) external view returns(address[] memory _tokensOrdered);

    /// @dev Function to initialize state variables GammaPool, called usually from GammaPoolFactory contract right after GammaPool instantiation
    /// @param _cfmm - address of CFMM GammaPool is for
    /// @param _tokens - ERC20 tokens of CFMM
    /// @param _decimals - decimals of CFMM tokens, indices must match _tokens[] array
    /// @param _data - custom struct containing additional information used to verify the `_cfmm`
    /// @param _minBorrow - minimum amount of liquidity that can be borrowed or left unpaid in a loan
    function initialize(address _cfmm, address[] calldata _tokens, uint8[] calldata _decimals, uint72 _minBorrow, bytes calldata _data) external;
}

// SPDX-License-Identifier: BUSL-1.1
pragma solidity >=0.8.0;

/// @title Interface of Interest Rate Model Store
/// @author Daniel D. Alcarraz (https://github.com/0xDanr)
/// @notice Interface of contract that saves and retrieves interest rate model parameters
interface IRateModel {
    /// @dev Function to validate interest rate model parameters
    /// @param _data - bytes parameters containing interest rate model parameters
    /// @return validation - true if parameters passed validation
    function validateParameters(bytes calldata _data) external view returns(bool);

    /// @dev Gets address of contract containing parameters for interest rate model
    /// @return address - address of smart contract that stores interest rate parameters
    function rateParamsStore() external view returns(address);
}

File 8 of 20 : IExternalStrategyEvents.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity >=0.8.0;

import "./IStrategyEvents.sol";

/// @title External Strategy Events Interface
/// @author Daniel D. Alcarraz (https://github.com/0xDanr)
/// @dev Events emitted by external strategy (flash loans) implementations
interface IExternalStrategyEvents is IStrategyEvents {
    /// @dev Event emitted when a flash loan is made. Purpose of flash loan is for external swaps/rebalance of loan collateral
    /// @param tokenId - unique id that identifies the loan in question
    /// @param amounts - amounts of tokens held as collateral in pool that were swapped
    /// @param lpTokens - LP tokens swapped externally
    /// @param liquidity - total liquidity externally swapped in flash loan (amounts + lpTokens)
    /// @param txType - transaction type. Possible values come from enum TX_TYPE
    event ExternalSwap(uint256 indexed tokenId, uint128[] amounts, uint256 lpTokens, uint128 liquidity, TX_TYPE indexed txType);
}

File 9 of 20 : IGammaPoolERC20Events.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity >=0.8.0;

/// @title GammaPool ERC20 Events
/// @author Daniel D. Alcarraz (https://github.com/0xDanr)
/// @dev Events that should be emitted by all strategy implementations (root of all strategy events interfaces)
interface IGammaPoolERC20Events {
    /// @dev Emitted when `amount` GS LP tokens are moved from account `from` to account `to`.
    /// @param from - address sending GS LP tokens
    /// @param to - address receiving GS LP tokens
    /// @param amount - amount of GS LP tokens being sent
    event Transfer(address indexed from, address indexed to, uint256 amount);

    /// @dev Emitted when the allowance of a `spender` for an `owner` is set by a call to approve function. `amount` is the new allowance.
    /// @param owner - address which owns the GS LP tokens spender is being given permission to spend
    /// @param spender - address given permission to spend owner's GS LP tokens
    /// @param amount - amount of GS LP tokens spender is given permission to spend
    event Approval(address indexed owner, address indexed spender, uint256 amount);
}

File 10 of 20 : ILiquidationStrategyEvents.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity >=0.8.0;

import "./ILongStrategyEvents.sol";

/// @title Liquidation Strategy Events Interface
/// @author Daniel D. Alcarraz (https://github.com/0xDanr)
/// @dev Events emitted by all liquidation strategy implementations
interface ILiquidationStrategyEvents is ILongStrategyEvents {
    /// @dev Event emitted when liquidating through _liquidate or _liquidateWithLP functions
    /// @param tokenId - id identifier of loan being liquidated
    /// @param collateral - collateral of loan being liquidated
    /// @param liquidity - liquidity debt being repaid
    /// @param writeDownAmt - amount of liquidity invariant being written down
    /// @param fee - liquidation fee paid to liquidator in liquidity invariant units
    /// @param txType - type of liquidation. Possible values come from enum TX_TYPE
    event Liquidation(uint256 indexed tokenId, uint128 collateral, uint128 liquidity, uint128 writeDownAmt, uint128 fee, TX_TYPE txType);
}

File 11 of 20 : ILongStrategyEvents.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity >=0.8.0;

import "./IStrategyEvents.sol";

/// @title Long Strategy Events Interface
/// @author Daniel D. Alcarraz (https://github.com/0xDanr)
/// @dev Events emitted by all long strategy implementations
interface ILongStrategyEvents is IStrategyEvents {
    /// @dev Event emitted when a Loan is updated
    /// @param tokenId - unique id that identifies the loan in question
    /// @param tokensHeld - amounts of tokens held as collateral against the loan
    /// @param liquidity - liquidity invariant that was borrowed including accrued interest
    /// @param initLiquidity - initial liquidity borrowed excluding interest (principal)
    /// @param lpTokens - LP tokens borrowed excluding interest (principal)
    /// @param rateIndex - interest rate index of GammaPool at time loan is updated
    /// @param txType - transaction type. Possible values come from enum TX_TYPE
    event LoanUpdated(uint256 indexed tokenId, uint128[] tokensHeld, uint128 liquidity, uint128 initLiquidity, uint256 lpTokens, uint96 rateIndex, TX_TYPE indexed txType);
}

File 12 of 20 : IShortStrategyEvents.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity >=0.8.0;

import "./IStrategyEvents.sol";

/// @title Short Strategy Events Interface
/// @author Daniel D. Alcarraz (https://github.com/0xDanr)
/// @dev Events emitted by all short strategy implementations
interface IShortStrategyEvents is IStrategyEvents {
    /// @dev Event emitted when a deposit of CFMM LP tokens in exchange of GS LP tokens happens (e.g. _deposit, _mint, _depositReserves, _depositNoPull)
    /// @param caller - address calling the function to deposit CFMM LP tokens
    /// @param to - address receiving GS LP tokens
    /// @param assets - amount CFMM LP tokens deposited
    /// @param shares - amount GS LP tokens minted
    event Deposit(address indexed caller, address indexed to, uint256 assets, uint256 shares);

    /// @dev Event emitted when a withdrawal of CFMM LP tokens happens (e.g. _withdraw, _redeem, _withdrawReserves, _withdrawNoPull)
    /// @param caller - address calling the function to withdraw CFMM LP tokens
    /// @param to - address receiving CFMM LP tokens
    /// @param from - address redeeming/burning GS LP tokens
    /// @param assets - amount of CFMM LP tokens withdrawn
    /// @param shares - amount of GS LP tokens redeemed
    event Withdraw(address indexed caller, address indexed to, address indexed from, uint256 assets, uint256 shares);
}

File 13 of 20 : IStrategyEvents.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity >=0.8.0;

/// @title Strategy Events interface
/// @author Daniel D. Alcarraz (https://github.com/0xDanr)
/// @dev Events that should be emitted by all strategy implementations (root of all strategy events interfaces)
interface IStrategyEvents {
    enum TX_TYPE {
        DEPOSIT_LIQUIDITY,      // 0
        WITHDRAW_LIQUIDITY,     // 1
        DEPOSIT_RESERVES,       // 2
        WITHDRAW_RESERVES,      // 3
        INCREASE_COLLATERAL,    // 4
        DECREASE_COLLATERAL,    // 5
        REBALANCE_COLLATERAL,   // 6
        BORROW_LIQUIDITY,       // 7
        REPAY_LIQUIDITY,        // 8
        REPAY_LIQUIDITY_SET_RATIO,// 9
        REPAY_LIQUIDITY_WITH_LP,// 10
        LIQUIDATE,              // 11
        LIQUIDATE_WITH_LP,      // 12
        BATCH_LIQUIDATION,      // 13
        SYNC,                   // 14
        EXTERNAL_REBALANCE,     // 15
        EXTERNAL_LIQUIDATION,   // 16
        UPDATE_POOL }           // 17

    /// @dev Event emitted when the Pool's global state variables is updated
    /// @param lpTokenBalance - quantity of CFMM LP tokens deposited in the pool
    /// @param lpTokenBorrowed - quantity of CFMM LP tokens that have been borrowed from the pool (principal)
    /// @param lastBlockNumber - last block the Pool's where updated
    /// @param accFeeIndex - interest of total accrued interest in the GammaPool until current update
    /// @param lpTokenBorrowedPlusInterest - quantity of CFMM LP tokens that have been borrowed from the pool including interest
    /// @param lpInvariant - lpTokenBalance as invariant units
    /// @param borrowedInvariant - lpTokenBorrowedPlusInterest as invariant units
    /// @param cfmmReserves - reserves in CFMM. Used to track price
    /// @param txType - transaction type. Possible values come from enum TX_TYPE
    event PoolUpdated(uint256 lpTokenBalance, uint256 lpTokenBorrowed, uint40 lastBlockNumber, uint80 accFeeIndex,
        uint256 lpTokenBorrowedPlusInterest, uint128 lpInvariant, uint128 borrowedInvariant, uint128[] cfmmReserves, TX_TYPE indexed txType);
}

// SPDX-License-Identifier: BUSL-1.1
pragma solidity >=0.8.0;

/// @title Two Step Ownership Contract implementation
/// @author Daniel D. Alcarraz (https://github.com/0xDanr)
/// @dev Transfers ownership of contract to another address using a two step method
contract TwoStepOwnable {
    /// @dev Event emitted when ownership of GammaPoolFactory contract is transferred to a new address
    /// @param previousOwner - previous address that owned factory contract
    /// @param newOwner - new address that owns factory contract
    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /// @dev Event emitted when change of ownership of GammaPoolFactory contract is started
    /// @param currentOwner - current address that owns factory contract
    /// @param newOwner - new address that will own factory contract
    event OwnershipTransferStarted(address indexed currentOwner, address indexed newOwner);

    /// @dev Owner of contract
    address public owner;

    /// @dev Pending owner to implement transfer of ownership in two steps
    address public pendingOwner;

    /// @dev Initialize `owner` of smart contract
    constructor(address _owner) {
        owner = _owner;
    }

    /// @dev Throws if called by any account other than the owner.
    modifier onlyOwner() {
        _checkOwner();
        _;
    }

    /// @dev Throws if the sender is not the owner.
    function _checkOwner() internal view virtual {
        require(owner == msg.sender, "Forbidden");
    }

    /// @dev Starts ownership transfer to new account. Replaces the pending transfer if there is one. Can only be called by the current owner.
    /// @param newOwner - new address that will have the owner privileges over the factory contract
    function transferOwnership(address newOwner) external virtual onlyOwner {
        require(newOwner != address(0), "ZeroAddress");// not allow to transfer ownership to zero address (renounce ownership forever)
        pendingOwner = newOwner;
        emit OwnershipTransferStarted(owner, newOwner);
    }

    /// @notice The new owner accepts the ownership transfer.
    /// @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.
    function acceptOwnership() external virtual {
        address newOwner = msg.sender;
        require(pendingOwner == newOwner, "NotNewOwner");
        address oldOwner = owner;
        owner = newOwner;
        delete pendingOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }

}

// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.8.0;

import "@gammaswap/v1-core/contracts/interfaces/IGammaPool.sol";

/// @title Interface for IGammaPoolQueryableLoans
/// @author Daniel D. Alcarraz (https://github.com/0xDanr)
/// @dev Defines external functions used by PositionManager to query pools and loans
interface IGammaPoolQueryableLoans {
    /// @notice Loans are added to owner's loan array for a pool in the order they're created. Index = 0 is the first loan created
    /// @dev Get loans from specific GammaPool belonging to owner.
    /// @param owner - owner of loans to query loans for
    /// @param pool - GammaPool to look for loans belonging to owner
    /// @param start - start index of owner's loan array from `pool`
    /// @param end - end index of owner's loan array from `pool`
    /// @return _loans - loans belonging to user for specific gammaPool
    function getLoansByOwnerAndPool(address owner, address pool, uint256 start, uint256 end) external view returns(IGammaPool.LoanData[] memory _loans);

    /// @notice Loans are added to owner's loan array in the order they're created.
    /// @dev Get loans belonging to owner
    /// @param owner - owner of loans to query loans for
    /// @param start - start index of owner's loan array
    /// @param end - end index of owner's loan array
    /// @return _loans - loans belonging to user
    function getLoansByOwner(address owner, uint256 start, uint256 end) external view returns(IGammaPool.LoanData[] memory _loans);

}

// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.8.0;

/// @title Interface for Loan Store
/// @author Daniel D. Alcarraz (https://github.com/0xDanr)
/// @dev Interface to interact with contract that stores all loans on chain, if enabled in PositionManager
interface ILoanStore {

    /// @dev Struct to store identifiable information about loan to perform queries in PositionManager
    struct LoanInfo {
        /// @dev Address of pool loan belongs to
        address pool;
        /// @dev Add loan to mappings by user
        uint256 byOwnerAndPoolIdx;
        /// @dev Add loan to mappings by user
        uint256 byOwnerIdx;
    }

    /// @dev Add loan to mappings by user so that they can be queried
    /// @param pool - pool loan identified by `tokenId` belongs to
    /// @param tokenId - unique identifier of loan
    /// @param owner - owner of loan
    function addLoanToOwner(address pool, uint256 tokenId, address owner) external;

    /// @dev Transfer loan identified by `tokenId` from address `from` to another address `to`
    /// @param from - address transferring loan
    /// @param to - address receiving loan
    /// @param tokenId - unique identifier of loan
    function transferLoan(address from, address to, uint256 tokenId) external;

    /// @param _source - address supplying loan information
    function setSource(address _source) external;
}

// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.8.0;

import "@gammaswap/v1-core/contracts/interfaces/IGammaPool.sol";

/// @title Interface for IPositionManagerQueries
/// @author Daniel D. Alcarraz (https://github.com/0xDanr)
/// @dev Defines external functions used by PositionManager to query pools and loans
interface IPositionManagerQueries {
    /// @notice Loans exist in owner's loan array for a pool in the order they're created. Index = 0 is the first loan created
    /// @dev Get loans from specific GammaPool belonging to owner. If a loan is transferred to another address, that index in the array points to 0
    /// @param owner - owner of loans to query loans for
    /// @param pool - GammaPool to look for loans belonging to owner
    /// @param start - start index of owner's loan array from `pool`
    /// @param end - end index of owner's loan array from `pool`
    /// @return _loans - loans belonging to user for specific gammaPool
    function getLoansByOwnerAndPool(address owner, address pool, uint256 start, uint256 end) external view returns(IGammaPool.LoanData[] memory _loans);

    /// @notice Loans exist in owner's loan array in the order they're created.
    /// @dev Get loans belonging to owner. If a loan is transferred to another address, that index in the array points to 0
    /// @param owner - owner of loans to query loans for
    /// @param start - start index of owner's loan array
    /// @param end - end index of owner's loan array
    /// @return _loans - loans belonging to user
    function getLoansByOwner(address owner, uint256 start, uint256 end) external view returns(IGammaPool.LoanData[] memory _loans);

    /// @notice The order of the pools in the array is the order in which they were created. (e.g. index 0 is first pool created)
    /// @dev Get list of pools from start index to end index (inclusive)
    /// @param start - start index of owner's loan array
    /// @param end - end index of owner's loan array
    /// @return _pools - pools with current data
    function getPools(uint256 start, uint256 end) external view returns(IGammaPool.PoolData[] memory _pools);

    /// @dev Get pools by pool address
    /// @param poolAddresses - array of pool address to query
    /// @return _pools - pools with current data
    function getPoolsByAddresses(address[] calldata poolAddresses) external view returns(IGammaPool.PoolData[] memory _pools);

    /// @dev Get pools with LP balance from user listed in the poolAddresses array
    /// @param poolAddresses - array of pool address
    /// @param owner - user's address who owns the pool
    /// @return _pools - pools with current data
    /// @return _balances - balances with current data
    function getPoolsWithOwnerLPBalance(address[] calldata poolAddresses, address owner) external view returns(IGammaPool.PoolData[] memory _pools, uint256[] memory _balances);
}

// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.8.0;

/// @title Library used to help with PositionManager queries
/// @author Daniel D. Alcarraz (https://github.com/0xDanr)
/// @dev Library performs approvals, transfers and views ERC20 state fields
library QueryUtils {
    /// @notice Validate and get parameters to query loans or pools arrays. If query fails validation size is zero
    /// @dev Get search parameters to query array. If end > last index of array, cap it at array's last index
    /// @param start - start index of array
    /// @param end - end index array
    /// @param len - assumed length of array
    /// @return _start - start index of owner's loan array
    /// @return _end - end index of owner's loan array
    /// @return _size - expected number of results from query
    function getSearchParameters(uint256 start, uint256 end, uint256 len) internal pure returns(uint256 _start, uint256 _end, uint256 _size) {
        if(len != 0 && start <= end && start <= len - 1) {
            _start = start;
            unchecked {
                uint256 _lastIdx = len - 1;
                _end = _lastIdx < end ? _lastIdx : end;
                _size = _end - _start + 1;
            }
        }
    }
}

// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.8.4;

import "@gammaswap/v1-core/contracts/utils/TwoStepOwnable.sol";
import "../interfaces/ILoanStore.sol";

/// @title Implementation of ILoanStore interface
/// @author Daniel D. Alcarraz (https://github.com/0xDanr)
/// @notice It's meant to be inherited by other contracts to create queries
abstract contract LoanStore is ILoanStore, TwoStepOwnable {

    /// @dev Maps loan's tokenId to loanInfo for easier query
    mapping(uint256 => LoanInfo) internal loanToInfo;
    /// @dev Maps user address to array of loan tokenIds belonging to user for easier query
    mapping(address => uint256[]) internal loansByOwner;
    /// @dev Maps user address to map of GammaPool address to array of tokenIds belonging to user at specific GammaPool for easier query
    mapping(address => mapping(address => uint256[])) internal loansByOwnerAndPool;

    /// @dev Source address providing loan ownership information (executes addToLoanOwner and transferLoan)
    address public source;

    /// @dev Initializes the contract by setting `_owner`
    constructor(address _owner) TwoStepOwnable(_owner) {
    }

    /// @dev See {ILoanStore-setSource}.
    function setSource(address _source) external virtual override onlyOwner {
        source = _source;
    }

    /// @dev See {ILoanStore-addLoanToOwner}.
    function addLoanToOwner(address pool, uint256 tokenId, address user) public virtual override {
        require(msg.sender == source);
        uint256 byOwnerIdx = loansByOwner[user].length;
        uint256 byOwnerAndPoolIdx = loansByOwnerAndPool[user][pool].length;
        loanToInfo[tokenId] = LoanInfo({ pool: pool, byOwnerIdx: byOwnerIdx, byOwnerAndPoolIdx: byOwnerAndPoolIdx });
        loansByOwnerAndPool[user][pool].push(tokenId);
        loansByOwner[user].push(tokenId);
    }

    /// @dev See {ILoanStore-transferLoan}.
    function transferLoan(address from, address to, uint256 tokenId) public virtual override {
        require(msg.sender == source);
        LoanInfo memory _loanInfo = loanToInfo[tokenId];

        loansByOwnerAndPool[from][_loanInfo.pool][_loanInfo.byOwnerAndPoolIdx] = 0;
        loansByOwner[from][_loanInfo.byOwnerIdx] = 0;

        addLoanToOwner(_loanInfo.pool, tokenId, to);
    }

}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);

    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `from` to `to` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address from,
        address to,
        uint256 amount
    ) external returns (bool);
}

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": {}
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"address","name":"_factory","type":"address"},{"internalType":"address","name":"_owner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"currentOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"pool","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"user","type":"address"}],"name":"addLoanToOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"start","type":"uint256"},{"internalType":"uint256","name":"end","type":"uint256"}],"name":"getLoansByOwner","outputs":[{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"poolId","type":"address"},{"internalType":"uint96","name":"rateIndex","type":"uint96"},{"internalType":"uint128","name":"initLiquidity","type":"uint128"},{"internalType":"uint128","name":"lastLiquidity","type":"uint128"},{"internalType":"uint128","name":"liquidity","type":"uint128"},{"internalType":"uint256","name":"collateral","type":"uint256"},{"internalType":"uint256","name":"lpTokens","type":"uint256"},{"internalType":"uint128[]","name":"tokensHeld","type":"uint128[]"},{"internalType":"address","name":"refAddr","type":"address"},{"internalType":"uint16","name":"refFee","type":"uint16"},{"internalType":"uint8","name":"refType","type":"uint8"},{"internalType":"uint256","name":"px","type":"uint256"},{"internalType":"bool","name":"canLiquidate","type":"bool"},{"internalType":"uint256","name":"accFeeIndex","type":"uint256"},{"internalType":"uint256","name":"lastCFMMFeeIndex","type":"uint256"},{"internalType":"uint256","name":"LAST_BLOCK_NUMBER","type":"uint256"},{"internalType":"address[]","name":"tokens","type":"address[]"},{"internalType":"uint8[]","name":"decimals","type":"uint8[]"},{"internalType":"string[]","name":"symbols","type":"string[]"},{"internalType":"string[]","name":"names","type":"string[]"},{"internalType":"address","name":"paramsStore","type":"address"},{"internalType":"address","name":"shortStrategy","type":"address"},{"internalType":"uint256","name":"BORROWED_INVARIANT","type":"uint256"},{"internalType":"uint256","name":"LP_INVARIANT","type":"uint256"},{"internalType":"uint256","name":"LP_TOKEN_BALANCE","type":"uint256"},{"internalType":"uint256","name":"lastCFMMInvariant","type":"uint256"},{"internalType":"uint256","name":"lastCFMMTotalSupply","type":"uint256"},{"internalType":"uint256","name":"ltvThreshold","type":"uint256"},{"internalType":"uint256","name":"liquidationFee","type":"uint256"}],"internalType":"struct IGammaPool.LoanData[]","name":"_loans","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"gammaPool","type":"address"},{"internalType":"uint256","name":"start","type":"uint256"},{"internalType":"uint256","name":"end","type":"uint256"}],"name":"getLoansByOwnerAndPool","outputs":[{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"poolId","type":"address"},{"internalType":"uint96","name":"rateIndex","type":"uint96"},{"internalType":"uint128","name":"initLiquidity","type":"uint128"},{"internalType":"uint128","name":"lastLiquidity","type":"uint128"},{"internalType":"uint128","name":"liquidity","type":"uint128"},{"internalType":"uint256","name":"collateral","type":"uint256"},{"internalType":"uint256","name":"lpTokens","type":"uint256"},{"internalType":"uint128[]","name":"tokensHeld","type":"uint128[]"},{"internalType":"address","name":"refAddr","type":"address"},{"internalType":"uint16","name":"refFee","type":"uint16"},{"internalType":"uint8","name":"refType","type":"uint8"},{"internalType":"uint256","name":"px","type":"uint256"},{"internalType":"bool","name":"canLiquidate","type":"bool"},{"internalType":"uint256","name":"accFeeIndex","type":"uint256"},{"internalType":"uint256","name":"lastCFMMFeeIndex","type":"uint256"},{"internalType":"uint256","name":"LAST_BLOCK_NUMBER","type":"uint256"},{"internalType":"address[]","name":"tokens","type":"address[]"},{"internalType":"uint8[]","name":"decimals","type":"uint8[]"},{"internalType":"string[]","name":"symbols","type":"string[]"},{"internalType":"string[]","name":"names","type":"string[]"},{"internalType":"address","name":"paramsStore","type":"address"},{"internalType":"address","name":"shortStrategy","type":"address"},{"internalType":"uint256","name":"BORROWED_INVARIANT","type":"uint256"},{"internalType":"uint256","name":"LP_INVARIANT","type":"uint256"},{"internalType":"uint256","name":"LP_TOKEN_BALANCE","type":"uint256"},{"internalType":"uint256","name":"lastCFMMInvariant","type":"uint256"},{"internalType":"uint256","name":"lastCFMMTotalSupply","type":"uint256"},{"internalType":"uint256","name":"ltvThreshold","type":"uint256"},{"internalType":"uint256","name":"liquidationFee","type":"uint256"}],"internalType":"struct IGammaPool.LoanData[]","name":"_loans","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"start","type":"uint256"},{"internalType":"uint256","name":"end","type":"uint256"}],"name":"getPools","outputs":[{"components":[{"internalType":"address","name":"poolId","type":"address"},{"internalType":"uint16","name":"protocolId","type":"uint16"},{"internalType":"address","name":"borrowStrategy","type":"address"},{"internalType":"address","name":"repayStrategy","type":"address"},{"internalType":"address","name":"rebalanceStrategy","type":"address"},{"internalType":"address","name":"shortStrategy","type":"address"},{"internalType":"address","name":"singleLiquidationStrategy","type":"address"},{"internalType":"address","name":"batchLiquidationStrategy","type":"address"},{"internalType":"address","name":"factory","type":"address"},{"internalType":"address","name":"paramsStore","type":"address"},{"internalType":"uint256","name":"LP_TOKEN_BALANCE","type":"uint256"},{"internalType":"uint256","name":"LP_TOKEN_BORROWED","type":"uint256"},{"internalType":"uint256","name":"LP_TOKEN_BORROWED_PLUS_INTEREST","type":"uint256"},{"internalType":"uint128","name":"BORROWED_INVARIANT","type":"uint128"},{"internalType":"uint128","name":"LP_INVARIANT","type":"uint128"},{"internalType":"address","name":"cfmm","type":"address"},{"internalType":"uint80","name":"accFeeIndex","type":"uint80"},{"internalType":"uint8","name":"extSwapFee","type":"uint8"},{"internalType":"uint16","name":"origFee","type":"uint16"},{"internalType":"uint40","name":"LAST_BLOCK_NUMBER","type":"uint40"},{"internalType":"uint64","name":"lastCFMMFeeIndex","type":"uint64"},{"internalType":"uint128","name":"lastCFMMInvariant","type":"uint128"},{"internalType":"uint256","name":"lastCFMMTotalSupply","type":"uint256"},{"internalType":"uint256","name":"totalSupply","type":"uint256"},{"internalType":"address[]","name":"tokens","type":"address[]"},{"internalType":"string[]","name":"symbols","type":"string[]"},{"internalType":"string[]","name":"names","type":"string[]"},{"internalType":"uint8[]","name":"decimals","type":"uint8[]"},{"internalType":"uint128[]","name":"TOKEN_BALANCE","type":"uint128[]"},{"internalType":"uint128[]","name":"CFMM_RESERVES","type":"uint128[]"},{"internalType":"uint256","name":"lastPrice","type":"uint256"},{"internalType":"uint256","name":"lastFeeIndex","type":"uint256"},{"internalType":"uint256","name":"borrowRate","type":"uint256"},{"internalType":"uint256","name":"utilizationRate","type":"uint256"},{"internalType":"uint40","name":"currBlockNumber","type":"uint40"},{"internalType":"uint8","name":"ltvThreshold","type":"uint8"},{"internalType":"uint8","name":"liquidationFee","type":"uint8"},{"internalType":"uint256","name":"supplyRate","type":"uint256"},{"internalType":"uint40","name":"emaUtilRate","type":"uint40"},{"internalType":"uint8","name":"emaMultiplier","type":"uint8"},{"internalType":"uint8","name":"minUtilRate1","type":"uint8"},{"internalType":"uint8","name":"minUtilRate2","type":"uint8"},{"internalType":"uint16","name":"feeDivisor","type":"uint16"},{"internalType":"uint72","name":"minBorrow","type":"uint72"}],"internalType":"struct IGammaPool.PoolData[]","name":"_pools","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"poolAddresses","type":"address[]"}],"name":"getPoolsByAddresses","outputs":[{"components":[{"internalType":"address","name":"poolId","type":"address"},{"internalType":"uint16","name":"protocolId","type":"uint16"},{"internalType":"address","name":"borrowStrategy","type":"address"},{"internalType":"address","name":"repayStrategy","type":"address"},{"internalType":"address","name":"rebalanceStrategy","type":"address"},{"internalType":"address","name":"shortStrategy","type":"address"},{"internalType":"address","name":"singleLiquidationStrategy","type":"address"},{"internalType":"address","name":"batchLiquidationStrategy","type":"address"},{"internalType":"address","name":"factory","type":"address"},{"internalType":"address","name":"paramsStore","type":"address"},{"internalType":"uint256","name":"LP_TOKEN_BALANCE","type":"uint256"},{"internalType":"uint256","name":"LP_TOKEN_BORROWED","type":"uint256"},{"internalType":"uint256","name":"LP_TOKEN_BORROWED_PLUS_INTEREST","type":"uint256"},{"internalType":"uint128","name":"BORROWED_INVARIANT","type":"uint128"},{"internalType":"uint128","name":"LP_INVARIANT","type":"uint128"},{"internalType":"address","name":"cfmm","type":"address"},{"internalType":"uint80","name":"accFeeIndex","type":"uint80"},{"internalType":"uint8","name":"extSwapFee","type":"uint8"},{"internalType":"uint16","name":"origFee","type":"uint16"},{"internalType":"uint40","name":"LAST_BLOCK_NUMBER","type":"uint40"},{"internalType":"uint64","name":"lastCFMMFeeIndex","type":"uint64"},{"internalType":"uint128","name":"lastCFMMInvariant","type":"uint128"},{"internalType":"uint256","name":"lastCFMMTotalSupply","type":"uint256"},{"internalType":"uint256","name":"totalSupply","type":"uint256"},{"internalType":"address[]","name":"tokens","type":"address[]"},{"internalType":"string[]","name":"symbols","type":"string[]"},{"internalType":"string[]","name":"names","type":"string[]"},{"internalType":"uint8[]","name":"decimals","type":"uint8[]"},{"internalType":"uint128[]","name":"TOKEN_BALANCE","type":"uint128[]"},{"internalType":"uint128[]","name":"CFMM_RESERVES","type":"uint128[]"},{"internalType":"uint256","name":"lastPrice","type":"uint256"},{"internalType":"uint256","name":"lastFeeIndex","type":"uint256"},{"internalType":"uint256","name":"borrowRate","type":"uint256"},{"internalType":"uint256","name":"utilizationRate","type":"uint256"},{"internalType":"uint40","name":"currBlockNumber","type":"uint40"},{"internalType":"uint8","name":"ltvThreshold","type":"uint8"},{"internalType":"uint8","name":"liquidationFee","type":"uint8"},{"internalType":"uint256","name":"supplyRate","type":"uint256"},{"internalType":"uint40","name":"emaUtilRate","type":"uint40"},{"internalType":"uint8","name":"emaMultiplier","type":"uint8"},{"internalType":"uint8","name":"minUtilRate1","type":"uint8"},{"internalType":"uint8","name":"minUtilRate2","type":"uint8"},{"internalType":"uint16","name":"feeDivisor","type":"uint16"},{"internalType":"uint72","name":"minBorrow","type":"uint72"}],"internalType":"struct IGammaPool.PoolData[]","name":"_pools","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"poolAddresses","type":"address[]"},{"internalType":"address","name":"owner","type":"address"}],"name":"getPoolsWithOwnerLPBalance","outputs":[{"components":[{"internalType":"address","name":"poolId","type":"address"},{"internalType":"uint16","name":"protocolId","type":"uint16"},{"internalType":"address","name":"borrowStrategy","type":"address"},{"internalType":"address","name":"repayStrategy","type":"address"},{"internalType":"address","name":"rebalanceStrategy","type":"address"},{"internalType":"address","name":"shortStrategy","type":"address"},{"internalType":"address","name":"singleLiquidationStrategy","type":"address"},{"internalType":"address","name":"batchLiquidationStrategy","type":"address"},{"internalType":"address","name":"factory","type":"address"},{"internalType":"address","name":"paramsStore","type":"address"},{"internalType":"uint256","name":"LP_TOKEN_BALANCE","type":"uint256"},{"internalType":"uint256","name":"LP_TOKEN_BORROWED","type":"uint256"},{"internalType":"uint256","name":"LP_TOKEN_BORROWED_PLUS_INTEREST","type":"uint256"},{"internalType":"uint128","name":"BORROWED_INVARIANT","type":"uint128"},{"internalType":"uint128","name":"LP_INVARIANT","type":"uint128"},{"internalType":"address","name":"cfmm","type":"address"},{"internalType":"uint80","name":"accFeeIndex","type":"uint80"},{"internalType":"uint8","name":"extSwapFee","type":"uint8"},{"internalType":"uint16","name":"origFee","type":"uint16"},{"internalType":"uint40","name":"LAST_BLOCK_NUMBER","type":"uint40"},{"internalType":"uint64","name":"lastCFMMFeeIndex","type":"uint64"},{"internalType":"uint128","name":"lastCFMMInvariant","type":"uint128"},{"internalType":"uint256","name":"lastCFMMTotalSupply","type":"uint256"},{"internalType":"uint256","name":"totalSupply","type":"uint256"},{"internalType":"address[]","name":"tokens","type":"address[]"},{"internalType":"string[]","name":"symbols","type":"string[]"},{"internalType":"string[]","name":"names","type":"string[]"},{"internalType":"uint8[]","name":"decimals","type":"uint8[]"},{"internalType":"uint128[]","name":"TOKEN_BALANCE","type":"uint128[]"},{"internalType":"uint128[]","name":"CFMM_RESERVES","type":"uint128[]"},{"internalType":"uint256","name":"lastPrice","type":"uint256"},{"internalType":"uint256","name":"lastFeeIndex","type":"uint256"},{"internalType":"uint256","name":"borrowRate","type":"uint256"},{"internalType":"uint256","name":"utilizationRate","type":"uint256"},{"internalType":"uint40","name":"currBlockNumber","type":"uint40"},{"internalType":"uint8","name":"ltvThreshold","type":"uint8"},{"internalType":"uint8","name":"liquidationFee","type":"uint8"},{"internalType":"uint256","name":"supplyRate","type":"uint256"},{"internalType":"uint40","name":"emaUtilRate","type":"uint40"},{"internalType":"uint8","name":"emaMultiplier","type":"uint8"},{"internalType":"uint8","name":"minUtilRate1","type":"uint8"},{"internalType":"uint8","name":"minUtilRate2","type":"uint8"},{"internalType":"uint16","name":"feeDivisor","type":"uint16"},{"internalType":"uint72","name":"minBorrow","type":"uint72"}],"internalType":"struct IGammaPool.PoolData[]","name":"_pools","type":"tuple[]"},{"internalType":"uint256[]","name":"_balances","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_source","type":"address"}],"name":"setSource","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"source","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferLoan","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60a06040523480156200001157600080fd5b506040516200298038038062002980833981016040819052620000349162000077565b600080546001600160a01b0319166001600160a01b0392831617905516608052620000af565b80516001600160a01b03811681146200007257600080fd5b919050565b600080604083850312156200008b57600080fd5b62000096836200005a565b9150620000a6602084016200005a565b90509250929050565b6080516128b5620000cb6000396000610ab001526128b56000f3fe608060405234801561001057600080fd5b50600436106100cf5760003560e01c8063a80269121161008c578063c67e240311610066578063c67e2403146101bb578063c70bdbca146101ce578063e30c3978146101e1578063f2fde38b146101f457600080fd5b8063a802691214610174578063b46814e514610187578063bbe95837146101a857600080fd5b806302ca8acf146100d457806367e828bf146100e95780636af354941461011957806379ba5097146101395780638d1006e1146101415780638da5cb5b14610161575b600080fd5b6100e76100e23660046113de565b610207565b005b6005546100fc906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b61012c61012736600461141f565b6102e2565b6040516101109190611592565b6100e761054e565b61015461014f36600461182f565b6105f7565b6040516101109190611b8b565b6000546100fc906001600160a01b031681565b6100e7610182366004611ba5565b6107ad565b61019a610195366004611bc2565b6107d7565b604051610110929190611c48565b6101546101b6366004611c76565b610a85565b6100e76101c9366004611c98565b610cc2565b61012c6101dc366004611ccf565b610d83565b6001546100fc906001600160a01b031681565b6100e7610202366004611ba5565b610fed565b6005546001600160a01b0316331461021e57600080fd5b6000818152600260208181526040808420815160608101835281546001600160a01b03908116825260018301548286019081529290950154818401528885168652600484528286208151909516865293909252832090518154929392811061028857610288611d15565b60009182526020808320909101929092556001600160a01b03861681526003909152604080822090830151815481106102c3576102c3611d15565b60009182526020909120015580516102dc908385610cc2565b50505050565b6001600160a01b038316600090815260036020908152604080832080548251818502810185019093528083526060949383018282801561034157602002820191906000526020600020905b81548152602001906001019080831161032d575b5050505050905060008060006103598787865161108a565b91945092509050801561050e57806001600160401b0381111561037e5761037e611d2b565b6040519080825280602002602001820160405280156103b757816020015b6103a461112c565b81526020019060019003908161039c5790505b5094506000835b8381116105075760008682815181106103d9576103d9611d15565b6020026020010151905060008111156104fa5760008181526002602090815260409182902054825163f30878c160e01b815292516001600160a01b0390911692839263f30878c1926004808401938290030181865afa158015610440573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104649190611d51565b60405163185cc75160e01b81526001600160a01b03838116600483015260248201859052919091169063185cc75190604401600060405180830381865afa1580156104b3573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526104db91908101906122e7565b8985815181106104ed576104ed611d15565b6020026020010181905250505b50600191820191016103be565b5050610543565b604080516000808252602082019092529061053f565b61052c61112c565b8152602001906001900390816105245790505b5094505b505050509392505050565b60015433906001600160a01b0316811461059d5760405162461bcd60e51b815260206004820152600b60248201526a2737ba2732bba7bbb732b960a91b60448201526064015b60405180910390fd5b600080546001600160a01b038381166001600160a01b031980841682178555600180549091169055604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6060816001600160401b0381111561061157610611611d2b565b60405190808252806020026020018201604052801561064a57816020015b610637611263565b81526020019060019003908161062f5790505b50905060005b828110156107a65783838281811061066a5761066a611d15565b905060200201602081019061067f9190611ba5565b6001600160a01b031663f30878c16040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106e09190611d51565b6001600160a01b031663fc517b5885858481811061070057610700611d15565b90506020020160208101906107159190611ba5565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401600060405180830381865afa158015610759573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526107819190810190612382565b82828151811061079357610793611d15565b6020908102919091010152600101610650565b5092915050565b6107b56110e4565b600580546001600160a01b0319166001600160a01b0392909216919091179055565b606080836001600160401b038111156107f2576107f2611d2b565b60405190808252806020026020018201604052801561082b57816020015b610818611263565b8152602001906001900390816108105790505b509150836001600160401b0381111561084657610846611d2b565b60405190808252806020026020018201604052801561086f578160200160208202803683370190505b50905060005b84811015610a7c5785858281811061088f5761088f611d15565b90506020020160208101906108a49190611ba5565b6040516370a0823160e01b81526001600160a01b03868116600483015291909116906370a0823190602401602060405180830381865afa1580156108ec573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109109190612725565b82828151811061092257610922611d15565b60200260200101818152505085858281811061094057610940611d15565b90506020020160208101906109559190611ba5565b6001600160a01b031663f30878c16040518163ffffffff1660e01b8152600401602060405180830381865afa158015610992573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109b69190611d51565b6001600160a01b031663fc517b588787848181106109d6576109d6611d15565b90506020020160208101906109eb9190611ba5565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401600060405180830381865afa158015610a2f573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610a579190810190612382565b838281518110610a6957610a69611d15565b6020908102919091010152600101610875565b50935093915050565b60405163bbe9583760e01b815260048101839052602481018290526060906000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063bbe9583790604401600060405180830381865afa158015610af7573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610b1f919081019061273e565b905080516001600160401b03811115610b3a57610b3a611d2b565b604051908082528060200260200182016040528015610b7357816020015b610b60611263565b815260200190600190039081610b585790505b50915060005b8151811015610cba57818181518110610b9457610b94611d15565b60200260200101516001600160a01b031663f30878c16040518163ffffffff1660e01b8152600401602060405180830381865afa158015610bd9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bfd9190611d51565b6001600160a01b031663fc517b58838381518110610c1d57610c1d611d15565b60200260200101516040518263ffffffff1660e01b8152600401610c5091906001600160a01b0391909116815260200190565b600060405180830381865afa158015610c6d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610c959190810190612382565b838281518110610ca757610ca7611d15565b6020908102919091010152600101610b79565b505092915050565b6005546001600160a01b03163314610cd957600080fd5b6001600160a01b039081166000908152600360208181526040808420805460048452828620988716808752988452828620805484516060810186529a8b528a86019081528a850192835289885260028087529488209a518b546001600160a01b0319169916989098178a5596516001808b01919091559051989092019790975584548082018655948452818420909401859055908152845492830185559381529290922090910155565b6001600160a01b0380851660009081526004602090815260408083209387168352928152828220805484518184028101840190955280855260609492830182828015610dee57602002820191906000526020600020905b815481526020019060010190808311610dda575b505050505090506000806000610e068787865161108a565b919450925090508015610fac576000816001600160401b03811115610e2d57610e2d611d2b565b604051908082528060200260200182016040528015610e56578160200160208202803683370190505b5090506000845b848111610ecb576000878281518110610e7857610e78611d15565b60200260200101511115610ebf57868181518110610e9857610e98611d15565b6020026020010151838381518110610eb257610eb2611d15565b6020026020010181815250505b60019182019101610e5d565b50896001600160a01b031663f30878c16040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f0a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f2e9190611d51565b6001600160a01b0316637edd64b68b8460006040518463ffffffff1660e01b8152600401610f5e93929190612772565b600060405180830381865afa158015610f7b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610fa391908101906127a8565b96505050610fe1565b6040805160008082526020820190925290610fdd565b610fca61112c565b815260200190600190039081610fc25790505b5094505b50505050949350505050565b610ff56110e4565b6001600160a01b0381166110395760405162461bcd60e51b815260206004820152600b60248201526a5a65726f4164647265737360a81b6044820152606401610594565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e227009190a350565b60008080831580159061109d5750848611155b80156110b357506110af600185612858565b8611155b156110db5785925060001984018581106110cd57856110cf565b805b92508383036001019150505b93509350939050565b6000546001600160a01b0316331461112a5760405162461bcd60e51b81526020600482015260096024820152682337b93134b23232b760b91b6044820152606401610594565b565b604051806103e00160405280600081526020016000815260200160006001600160a01b0316815260200160006001600160601b0316815260200160006001600160801b0316815260200160006001600160801b0316815260200160006001600160801b0316815260200160008152602001600081526020016060815260200160006001600160a01b03168152602001600061ffff168152602001600060ff168152602001600081526020016000151581526020016000815260200160008152602001600081526020016060815260200160608152602001606081526020016060815260200160006001600160a01b0316815260200160006001600160a01b03168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b604080516105808101825260008082526020820181905291810182905260608082018390526080820183905260a0820183905260c0820183905260e08201839052610100820183905261012082018390526101408201839052610160820183905261018082018390526101a082018390526101c082018390526101e08201839052610200820183905261022082018390526102408201839052610260820183905261028082018390526102a082018390526102c082018390526102e08201839052610300820181905261032082018190526103408201819052610360820181905261038082018190526103a08201526103c081018290526103e08101829052610400810182905261042081018290526104408101829052610460810182905261048081018290526104a081018290526104c081018290526104e0810182905261050081018290526105208101829052610540810182905261056081019190915290565b6001600160a01b03811681146113db57600080fd5b50565b6000806000606084860312156113f357600080fd5b83356113fe816113c6565b9250602084013561140e816113c6565b929592945050506040919091013590565b60008060006060848603121561143457600080fd5b833561143f816113c6565b95602085013595506040909401359392505050565b600081518084526020808501945080840160005b8381101561148d5781516001600160801b031687529582019590820190600101611468565b509495945050505050565b600081518084526020808501945080840160005b8381101561148d5781516001600160a01b0316875295820195908201906001016114ac565b600081518084526020808501945080840160005b8381101561148d57815160ff16875295820195908201906001016114e5565b60005b8381101561151f578181015183820152602001611507565b50506000910152565b6000815180845260208085019450848260051b860182860160005b858110156115855783830389528151805180855261156681888701898501611504565b99860199601f01601f1916939093018501925090840190600101611543565b5090979650505050505050565b60006020808301818452808551808352604092508286019150828160051b87010184880160005b838110156117d657603f198984030185528151805184528781015188850152868101516001600160a01b0316878501526060808201516001600160601b0316908501526080808201516001600160801b039081169186019190915260a08083015182169086015260c0808301519091169085015260e080820151908501526101008082015190850152610120808201516103e0828701819052919061166083880182611454565b925050506101408083015161167f828801826001600160a01b03169052565b50506101608281015161ffff16908601526101808083015160ff16908601526101a080830151908601526101c0808301511515908601526101e080830151908601526102008083015190860152610220808301519086015261024080830151868303828801526116ef8382611498565b92505050610260808301518683038288015261170b83826114d1565b9250505061028080830151868303828801526117278382611528565b925050506102a080830151868303828801526117438382611528565b925050506102c080830151611762828801826001600160a01b03169052565b50506102e0828101516001600160a01b031690860152610300808301519086015261032080830151908601526103408083015190860152610360808301519086015261038080830151908601526103a080830151908601526103c091820151919094015293860193908601906001016115b9565b509098975050505050505050565b60008083601f8401126117f657600080fd5b5081356001600160401b0381111561180d57600080fd5b6020830191508360208260051b850101111561182857600080fd5b9250929050565b6000806020838503121561184257600080fd5b82356001600160401b0381111561185857600080fd5b611864858286016117e4565b90969095509350505050565b600081518084526020808501808196508360051b8101915082860160005b85811015611b7e578284038952815180516001600160a01b0390811686528682015161ffff9081168888015260408084015183169088015260608084015183169088015260808084015183169088015260a08084015183169088015260c08084015183169088015260e08084015183169088015261010080840151831690880152610120808401518316908801526101408084015190880152610160808401519088015261018080840151908801526101a0808401516001600160801b03908116918901919091526101c0808501518216908901526101e080850151909316928801929092526102008084015169ffffffffffffffffffff16908801526102208084015160ff169088015261024080840151909116908701526102608083015164ffffffffff1690870152610280808301516001600160401b0316908701526102a080830151909116908601526102c080820151908601526102e08082015190860152610300808201516105808288018190529190611a0f83890182611498565b925050506103208083015187830382890152611a2b8382611528565b925050506103408083015187830382890152611a478382611528565b925050506103608083015187830382890152611a6383826114d1565b925050506103808083015187830382890152611a7f8382611454565b925050506103a08083015187830382890152611a9b8382611454565b6103c085810151908a01526103e080860151908a015261040080860151908a015261042080860151908a01526104408086015164ffffffffff908116918b01919091526104608087015160ff908116918c0191909152610480808801518216908c01526104a080880151908c01526104c080880151909216918b01919091526104e0808701518216908b0152610500808701518216908b015261052080870151909116908a01526105408086015161ffff16908a01526105609485015168ffffffffffffffffff169490980193909352505050978401979084019060010161188e565b5091979650505050505050565b602081526000611b9e6020830184611870565b9392505050565b600060208284031215611bb757600080fd5b8135611b9e816113c6565b600080600060408486031215611bd757600080fd5b83356001600160401b03811115611bed57600080fd5b611bf9868287016117e4565b9094509250506020840135611c0d816113c6565b809150509250925092565b600081518084526020808501945080840160005b8381101561148d57815187529582019590820190600101611c2c565b604081526000611c5b6040830185611870565b8281036020840152611c6d8185611c18565b95945050505050565b60008060408385031215611c8957600080fd5b50508035926020909101359150565b600080600060608486031215611cad57600080fd5b8335611cb8816113c6565b9250602084013591506040840135611c0d816113c6565b60008060008060808587031215611ce557600080fd5b8435611cf0816113c6565b93506020850135611d00816113c6565b93969395505050506040820135916060013590565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b8051611d4c816113c6565b919050565b600060208284031215611d6357600080fd5b8151611b9e816113c6565b6040516103e081016001600160401b0381118282101715611d9157611d91611d2b565b60405290565b60405161058081016001600160401b0381118282101715611d9157611d91611d2b565b604051601f8201601f191681016001600160401b0381118282101715611de257611de2611d2b565b604052919050565b80516001600160601b0381168114611d4c57600080fd5b80516001600160801b0381168114611d4c57600080fd5b60006001600160401b03821115611e3157611e31611d2b565b5060051b60200190565b600082601f830112611e4c57600080fd5b81516020611e61611e5c83611e18565b611dba565b82815260059290921b84018101918181019086841115611e8057600080fd5b8286015b84811015611ea257611e9581611e01565b8352918301918301611e84565b509695505050505050565b805161ffff81168114611d4c57600080fd5b805160ff81168114611d4c57600080fd5b80518015158114611d4c57600080fd5b600082601f830112611ef157600080fd5b81516020611f01611e5c83611e18565b82815260059290921b84018101918181019086841115611f2057600080fd5b8286015b84811015611ea2578051611f37816113c6565b8352918301918301611f24565b600082601f830112611f5557600080fd5b81516020611f65611e5c83611e18565b82815260059290921b84018101918181019086841115611f8457600080fd5b8286015b84811015611ea257611f9981611ebf565b8352918301918301611f88565b6000601f8381840112611fb857600080fd5b82516020611fc8611e5c83611e18565b82815260059290921b85018101918181019087841115611fe757600080fd5b8287015b8481101561207d5780516001600160401b038082111561200b5760008081fd5b818a0191508a603f8301126120205760008081fd5b8582015160408282111561203657612036611d2b565b612047828b01601f19168901611dba565b92508183528c8183860101111561205e5760008081fd5b61206d82898501838701611504565b5050845250918301918301611feb565b50979650505050505050565b60006103e0828403121561209c57600080fd5b6120a4611d6e565b905081518152602082015160208201526120c060408301611d41565b60408201526120d160608301611dea565b60608201526120e260808301611e01565b60808201526120f360a08301611e01565b60a082015261210460c08301611e01565b60c082015260e082015160e0820152610100808301518183015250610120808301516001600160401b038082111561213b57600080fd5b61214786838701611e3b565b83850152610140925061215b838601611d41565b83850152610160925061216f838601611ead565b838501526101809250612183838601611ebf565b838501526101a0925082850151838501526101c092506121a4838601611ed0565b92840192909252506101e0838101519083015261020080840151908301526102208084015190830152610240808401519091808211156121e357600080fd5b6121ef86838701611ee0565b8385015261026092508285015191508082111561220b57600080fd5b61221786838701611f44565b8385015261028092508285015191508082111561223357600080fd5b61223f86838701611fa6565b838501526102a092508285015191508082111561225b57600080fd5b5061226885828601611fa6565b8284015250506102c061227c818401611d41565b908201526102e061228e838201611d41565b90820152610300828101519082015261032080830151908201526103408083015190820152610360808301519082015261038080830151908201526103a080830151908201526103c09182015191810191909152919050565b6000602082840312156122f957600080fd5b81516001600160401b0381111561230f57600080fd5b61231b84828501612089565b949350505050565b805169ffffffffffffffffffff81168114611d4c57600080fd5b805164ffffffffff81168114611d4c57600080fd5b80516001600160401b0381168114611d4c57600080fd5b805168ffffffffffffffffff81168114611d4c57600080fd5b60006020828403121561239457600080fd5b81516001600160401b03808211156123ab57600080fd5b9083019061058082860312156123c057600080fd5b6123c8611d97565b6123d183611d41565b81526123df60208401611ead565b60208201526123f060408401611d41565b604082015261240160608401611d41565b606082015261241260808401611d41565b608082015261242360a08401611d41565b60a082015261243460c08401611d41565b60c082015261244560e08401611d41565b60e0820152610100612458818501611d41565b9082015261012061246a848201611d41565b908201526101408381015190820152610160808401519082015261018080840151908201526101a061249d818501611e01565b908201526101c06124af848201611e01565b908201526101e06124c1848201611d41565b908201526102006124d3848201612323565b908201526102206124e5848201611ebf565b908201526102406124f7848201611ead565b9082015261026061250984820161233d565b9082015261028061251b848201612352565b908201526102a061252d848201611e01565b908201526102c083810151908201526102e08084015190820152610300808401518381111561255b57600080fd5b61256788828701611ee0565b828401525050610320808401518381111561258157600080fd5b61258d88828701611fa6565b82840152505061034080840151838111156125a757600080fd5b6125b388828701611fa6565b82840152505061036080840151838111156125cd57600080fd5b6125d988828701611f44565b82840152505061038080840151838111156125f357600080fd5b6125ff88828701611e3b565b8284015250506103a0808401518381111561261957600080fd5b61262588828701611e3b565b91830191909152506103c083810151908201526103e0808401519082015261040080840151908201526104208084015190820152610440915061266982840161233d565b82820152610460915061267d828401611ebf565b828201526104809150612691828401611ebf565b828201526104a0915081830151828201526104c091506126b282840161233d565b828201526104e091506126c6828401611ebf565b8282015261050091506126da828401611ebf565b8282015261052091506126ee828401611ebf565b828201526105409150612702828401611ead565b828201526105609150612716828401612369565b91810191909152949350505050565b60006020828403121561273757600080fd5b5051919050565b60006020828403121561275057600080fd5b81516001600160401b0381111561276657600080fd5b61231b84828501611ee0565b6001600160a01b038416815260606020820181905260009061279690830185611c18565b90508215156040830152949350505050565b600060208083850312156127bb57600080fd5b82516001600160401b03808211156127d257600080fd5b818501915085601f8301126127e657600080fd5b81516127f4611e5c82611e18565b81815260059190911b8301840190848101908883111561281357600080fd5b8585015b8381101561284b5780518581111561282f5760008081fd5b61283d8b89838a0101612089565b845250918601918601612817565b5098975050505050505050565b8181038181111561287957634e487b7160e01b600052601160045260246000fd5b9291505056fea2646970667358221220ee36b2a7e0e45179ad0a729fd5c7570d703a2408b61e0e8552c912d80a88a85e64736f6c63430008150033000000000000000000000000fd513630f697a9c1731f196185fb9eba6eaac20b000000000000000000000000937fd8cc7f7d2ef5b801e44c03218ade5648c3fb

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106100cf5760003560e01c8063a80269121161008c578063c67e240311610066578063c67e2403146101bb578063c70bdbca146101ce578063e30c3978146101e1578063f2fde38b146101f457600080fd5b8063a802691214610174578063b46814e514610187578063bbe95837146101a857600080fd5b806302ca8acf146100d457806367e828bf146100e95780636af354941461011957806379ba5097146101395780638d1006e1146101415780638da5cb5b14610161575b600080fd5b6100e76100e23660046113de565b610207565b005b6005546100fc906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b61012c61012736600461141f565b6102e2565b6040516101109190611592565b6100e761054e565b61015461014f36600461182f565b6105f7565b6040516101109190611b8b565b6000546100fc906001600160a01b031681565b6100e7610182366004611ba5565b6107ad565b61019a610195366004611bc2565b6107d7565b604051610110929190611c48565b6101546101b6366004611c76565b610a85565b6100e76101c9366004611c98565b610cc2565b61012c6101dc366004611ccf565b610d83565b6001546100fc906001600160a01b031681565b6100e7610202366004611ba5565b610fed565b6005546001600160a01b0316331461021e57600080fd5b6000818152600260208181526040808420815160608101835281546001600160a01b03908116825260018301548286019081529290950154818401528885168652600484528286208151909516865293909252832090518154929392811061028857610288611d15565b60009182526020808320909101929092556001600160a01b03861681526003909152604080822090830151815481106102c3576102c3611d15565b60009182526020909120015580516102dc908385610cc2565b50505050565b6001600160a01b038316600090815260036020908152604080832080548251818502810185019093528083526060949383018282801561034157602002820191906000526020600020905b81548152602001906001019080831161032d575b5050505050905060008060006103598787865161108a565b91945092509050801561050e57806001600160401b0381111561037e5761037e611d2b565b6040519080825280602002602001820160405280156103b757816020015b6103a461112c565b81526020019060019003908161039c5790505b5094506000835b8381116105075760008682815181106103d9576103d9611d15565b6020026020010151905060008111156104fa5760008181526002602090815260409182902054825163f30878c160e01b815292516001600160a01b0390911692839263f30878c1926004808401938290030181865afa158015610440573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104649190611d51565b60405163185cc75160e01b81526001600160a01b03838116600483015260248201859052919091169063185cc75190604401600060405180830381865afa1580156104b3573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526104db91908101906122e7565b8985815181106104ed576104ed611d15565b6020026020010181905250505b50600191820191016103be565b5050610543565b604080516000808252602082019092529061053f565b61052c61112c565b8152602001906001900390816105245790505b5094505b505050509392505050565b60015433906001600160a01b0316811461059d5760405162461bcd60e51b815260206004820152600b60248201526a2737ba2732bba7bbb732b960a91b60448201526064015b60405180910390fd5b600080546001600160a01b038381166001600160a01b031980841682178555600180549091169055604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6060816001600160401b0381111561061157610611611d2b565b60405190808252806020026020018201604052801561064a57816020015b610637611263565b81526020019060019003908161062f5790505b50905060005b828110156107a65783838281811061066a5761066a611d15565b905060200201602081019061067f9190611ba5565b6001600160a01b031663f30878c16040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106e09190611d51565b6001600160a01b031663fc517b5885858481811061070057610700611d15565b90506020020160208101906107159190611ba5565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401600060405180830381865afa158015610759573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526107819190810190612382565b82828151811061079357610793611d15565b6020908102919091010152600101610650565b5092915050565b6107b56110e4565b600580546001600160a01b0319166001600160a01b0392909216919091179055565b606080836001600160401b038111156107f2576107f2611d2b565b60405190808252806020026020018201604052801561082b57816020015b610818611263565b8152602001906001900390816108105790505b509150836001600160401b0381111561084657610846611d2b565b60405190808252806020026020018201604052801561086f578160200160208202803683370190505b50905060005b84811015610a7c5785858281811061088f5761088f611d15565b90506020020160208101906108a49190611ba5565b6040516370a0823160e01b81526001600160a01b03868116600483015291909116906370a0823190602401602060405180830381865afa1580156108ec573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109109190612725565b82828151811061092257610922611d15565b60200260200101818152505085858281811061094057610940611d15565b90506020020160208101906109559190611ba5565b6001600160a01b031663f30878c16040518163ffffffff1660e01b8152600401602060405180830381865afa158015610992573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109b69190611d51565b6001600160a01b031663fc517b588787848181106109d6576109d6611d15565b90506020020160208101906109eb9190611ba5565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401600060405180830381865afa158015610a2f573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610a579190810190612382565b838281518110610a6957610a69611d15565b6020908102919091010152600101610875565b50935093915050565b60405163bbe9583760e01b815260048101839052602481018290526060906000906001600160a01b037f000000000000000000000000fd513630f697a9c1731f196185fb9eba6eaac20b169063bbe9583790604401600060405180830381865afa158015610af7573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610b1f919081019061273e565b905080516001600160401b03811115610b3a57610b3a611d2b565b604051908082528060200260200182016040528015610b7357816020015b610b60611263565b815260200190600190039081610b585790505b50915060005b8151811015610cba57818181518110610b9457610b94611d15565b60200260200101516001600160a01b031663f30878c16040518163ffffffff1660e01b8152600401602060405180830381865afa158015610bd9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bfd9190611d51565b6001600160a01b031663fc517b58838381518110610c1d57610c1d611d15565b60200260200101516040518263ffffffff1660e01b8152600401610c5091906001600160a01b0391909116815260200190565b600060405180830381865afa158015610c6d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610c959190810190612382565b838281518110610ca757610ca7611d15565b6020908102919091010152600101610b79565b505092915050565b6005546001600160a01b03163314610cd957600080fd5b6001600160a01b039081166000908152600360208181526040808420805460048452828620988716808752988452828620805484516060810186529a8b528a86019081528a850192835289885260028087529488209a518b546001600160a01b0319169916989098178a5596516001808b01919091559051989092019790975584548082018655948452818420909401859055908152845492830185559381529290922090910155565b6001600160a01b0380851660009081526004602090815260408083209387168352928152828220805484518184028101840190955280855260609492830182828015610dee57602002820191906000526020600020905b815481526020019060010190808311610dda575b505050505090506000806000610e068787865161108a565b919450925090508015610fac576000816001600160401b03811115610e2d57610e2d611d2b565b604051908082528060200260200182016040528015610e56578160200160208202803683370190505b5090506000845b848111610ecb576000878281518110610e7857610e78611d15565b60200260200101511115610ebf57868181518110610e9857610e98611d15565b6020026020010151838381518110610eb257610eb2611d15565b6020026020010181815250505b60019182019101610e5d565b50896001600160a01b031663f30878c16040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f0a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f2e9190611d51565b6001600160a01b0316637edd64b68b8460006040518463ffffffff1660e01b8152600401610f5e93929190612772565b600060405180830381865afa158015610f7b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610fa391908101906127a8565b96505050610fe1565b6040805160008082526020820190925290610fdd565b610fca61112c565b815260200190600190039081610fc25790505b5094505b50505050949350505050565b610ff56110e4565b6001600160a01b0381166110395760405162461bcd60e51b815260206004820152600b60248201526a5a65726f4164647265737360a81b6044820152606401610594565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e227009190a350565b60008080831580159061109d5750848611155b80156110b357506110af600185612858565b8611155b156110db5785925060001984018581106110cd57856110cf565b805b92508383036001019150505b93509350939050565b6000546001600160a01b0316331461112a5760405162461bcd60e51b81526020600482015260096024820152682337b93134b23232b760b91b6044820152606401610594565b565b604051806103e00160405280600081526020016000815260200160006001600160a01b0316815260200160006001600160601b0316815260200160006001600160801b0316815260200160006001600160801b0316815260200160006001600160801b0316815260200160008152602001600081526020016060815260200160006001600160a01b03168152602001600061ffff168152602001600060ff168152602001600081526020016000151581526020016000815260200160008152602001600081526020016060815260200160608152602001606081526020016060815260200160006001600160a01b0316815260200160006001600160a01b03168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b604080516105808101825260008082526020820181905291810182905260608082018390526080820183905260a0820183905260c0820183905260e08201839052610100820183905261012082018390526101408201839052610160820183905261018082018390526101a082018390526101c082018390526101e08201839052610200820183905261022082018390526102408201839052610260820183905261028082018390526102a082018390526102c082018390526102e08201839052610300820181905261032082018190526103408201819052610360820181905261038082018190526103a08201526103c081018290526103e08101829052610400810182905261042081018290526104408101829052610460810182905261048081018290526104a081018290526104c081018290526104e0810182905261050081018290526105208101829052610540810182905261056081019190915290565b6001600160a01b03811681146113db57600080fd5b50565b6000806000606084860312156113f357600080fd5b83356113fe816113c6565b9250602084013561140e816113c6565b929592945050506040919091013590565b60008060006060848603121561143457600080fd5b833561143f816113c6565b95602085013595506040909401359392505050565b600081518084526020808501945080840160005b8381101561148d5781516001600160801b031687529582019590820190600101611468565b509495945050505050565b600081518084526020808501945080840160005b8381101561148d5781516001600160a01b0316875295820195908201906001016114ac565b600081518084526020808501945080840160005b8381101561148d57815160ff16875295820195908201906001016114e5565b60005b8381101561151f578181015183820152602001611507565b50506000910152565b6000815180845260208085019450848260051b860182860160005b858110156115855783830389528151805180855261156681888701898501611504565b99860199601f01601f1916939093018501925090840190600101611543565b5090979650505050505050565b60006020808301818452808551808352604092508286019150828160051b87010184880160005b838110156117d657603f198984030185528151805184528781015188850152868101516001600160a01b0316878501526060808201516001600160601b0316908501526080808201516001600160801b039081169186019190915260a08083015182169086015260c0808301519091169085015260e080820151908501526101008082015190850152610120808201516103e0828701819052919061166083880182611454565b925050506101408083015161167f828801826001600160a01b03169052565b50506101608281015161ffff16908601526101808083015160ff16908601526101a080830151908601526101c0808301511515908601526101e080830151908601526102008083015190860152610220808301519086015261024080830151868303828801526116ef8382611498565b92505050610260808301518683038288015261170b83826114d1565b9250505061028080830151868303828801526117278382611528565b925050506102a080830151868303828801526117438382611528565b925050506102c080830151611762828801826001600160a01b03169052565b50506102e0828101516001600160a01b031690860152610300808301519086015261032080830151908601526103408083015190860152610360808301519086015261038080830151908601526103a080830151908601526103c091820151919094015293860193908601906001016115b9565b509098975050505050505050565b60008083601f8401126117f657600080fd5b5081356001600160401b0381111561180d57600080fd5b6020830191508360208260051b850101111561182857600080fd5b9250929050565b6000806020838503121561184257600080fd5b82356001600160401b0381111561185857600080fd5b611864858286016117e4565b90969095509350505050565b600081518084526020808501808196508360051b8101915082860160005b85811015611b7e578284038952815180516001600160a01b0390811686528682015161ffff9081168888015260408084015183169088015260608084015183169088015260808084015183169088015260a08084015183169088015260c08084015183169088015260e08084015183169088015261010080840151831690880152610120808401518316908801526101408084015190880152610160808401519088015261018080840151908801526101a0808401516001600160801b03908116918901919091526101c0808501518216908901526101e080850151909316928801929092526102008084015169ffffffffffffffffffff16908801526102208084015160ff169088015261024080840151909116908701526102608083015164ffffffffff1690870152610280808301516001600160401b0316908701526102a080830151909116908601526102c080820151908601526102e08082015190860152610300808201516105808288018190529190611a0f83890182611498565b925050506103208083015187830382890152611a2b8382611528565b925050506103408083015187830382890152611a478382611528565b925050506103608083015187830382890152611a6383826114d1565b925050506103808083015187830382890152611a7f8382611454565b925050506103a08083015187830382890152611a9b8382611454565b6103c085810151908a01526103e080860151908a015261040080860151908a015261042080860151908a01526104408086015164ffffffffff908116918b01919091526104608087015160ff908116918c0191909152610480808801518216908c01526104a080880151908c01526104c080880151909216918b01919091526104e0808701518216908b0152610500808701518216908b015261052080870151909116908a01526105408086015161ffff16908a01526105609485015168ffffffffffffffffff169490980193909352505050978401979084019060010161188e565b5091979650505050505050565b602081526000611b9e6020830184611870565b9392505050565b600060208284031215611bb757600080fd5b8135611b9e816113c6565b600080600060408486031215611bd757600080fd5b83356001600160401b03811115611bed57600080fd5b611bf9868287016117e4565b9094509250506020840135611c0d816113c6565b809150509250925092565b600081518084526020808501945080840160005b8381101561148d57815187529582019590820190600101611c2c565b604081526000611c5b6040830185611870565b8281036020840152611c6d8185611c18565b95945050505050565b60008060408385031215611c8957600080fd5b50508035926020909101359150565b600080600060608486031215611cad57600080fd5b8335611cb8816113c6565b9250602084013591506040840135611c0d816113c6565b60008060008060808587031215611ce557600080fd5b8435611cf0816113c6565b93506020850135611d00816113c6565b93969395505050506040820135916060013590565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b8051611d4c816113c6565b919050565b600060208284031215611d6357600080fd5b8151611b9e816113c6565b6040516103e081016001600160401b0381118282101715611d9157611d91611d2b565b60405290565b60405161058081016001600160401b0381118282101715611d9157611d91611d2b565b604051601f8201601f191681016001600160401b0381118282101715611de257611de2611d2b565b604052919050565b80516001600160601b0381168114611d4c57600080fd5b80516001600160801b0381168114611d4c57600080fd5b60006001600160401b03821115611e3157611e31611d2b565b5060051b60200190565b600082601f830112611e4c57600080fd5b81516020611e61611e5c83611e18565b611dba565b82815260059290921b84018101918181019086841115611e8057600080fd5b8286015b84811015611ea257611e9581611e01565b8352918301918301611e84565b509695505050505050565b805161ffff81168114611d4c57600080fd5b805160ff81168114611d4c57600080fd5b80518015158114611d4c57600080fd5b600082601f830112611ef157600080fd5b81516020611f01611e5c83611e18565b82815260059290921b84018101918181019086841115611f2057600080fd5b8286015b84811015611ea2578051611f37816113c6565b8352918301918301611f24565b600082601f830112611f5557600080fd5b81516020611f65611e5c83611e18565b82815260059290921b84018101918181019086841115611f8457600080fd5b8286015b84811015611ea257611f9981611ebf565b8352918301918301611f88565b6000601f8381840112611fb857600080fd5b82516020611fc8611e5c83611e18565b82815260059290921b85018101918181019087841115611fe757600080fd5b8287015b8481101561207d5780516001600160401b038082111561200b5760008081fd5b818a0191508a603f8301126120205760008081fd5b8582015160408282111561203657612036611d2b565b612047828b01601f19168901611dba565b92508183528c8183860101111561205e5760008081fd5b61206d82898501838701611504565b5050845250918301918301611feb565b50979650505050505050565b60006103e0828403121561209c57600080fd5b6120a4611d6e565b905081518152602082015160208201526120c060408301611d41565b60408201526120d160608301611dea565b60608201526120e260808301611e01565b60808201526120f360a08301611e01565b60a082015261210460c08301611e01565b60c082015260e082015160e0820152610100808301518183015250610120808301516001600160401b038082111561213b57600080fd5b61214786838701611e3b565b83850152610140925061215b838601611d41565b83850152610160925061216f838601611ead565b838501526101809250612183838601611ebf565b838501526101a0925082850151838501526101c092506121a4838601611ed0565b92840192909252506101e0838101519083015261020080840151908301526102208084015190830152610240808401519091808211156121e357600080fd5b6121ef86838701611ee0565b8385015261026092508285015191508082111561220b57600080fd5b61221786838701611f44565b8385015261028092508285015191508082111561223357600080fd5b61223f86838701611fa6565b838501526102a092508285015191508082111561225b57600080fd5b5061226885828601611fa6565b8284015250506102c061227c818401611d41565b908201526102e061228e838201611d41565b90820152610300828101519082015261032080830151908201526103408083015190820152610360808301519082015261038080830151908201526103a080830151908201526103c09182015191810191909152919050565b6000602082840312156122f957600080fd5b81516001600160401b0381111561230f57600080fd5b61231b84828501612089565b949350505050565b805169ffffffffffffffffffff81168114611d4c57600080fd5b805164ffffffffff81168114611d4c57600080fd5b80516001600160401b0381168114611d4c57600080fd5b805168ffffffffffffffffff81168114611d4c57600080fd5b60006020828403121561239457600080fd5b81516001600160401b03808211156123ab57600080fd5b9083019061058082860312156123c057600080fd5b6123c8611d97565b6123d183611d41565b81526123df60208401611ead565b60208201526123f060408401611d41565b604082015261240160608401611d41565b606082015261241260808401611d41565b608082015261242360a08401611d41565b60a082015261243460c08401611d41565b60c082015261244560e08401611d41565b60e0820152610100612458818501611d41565b9082015261012061246a848201611d41565b908201526101408381015190820152610160808401519082015261018080840151908201526101a061249d818501611e01565b908201526101c06124af848201611e01565b908201526101e06124c1848201611d41565b908201526102006124d3848201612323565b908201526102206124e5848201611ebf565b908201526102406124f7848201611ead565b9082015261026061250984820161233d565b9082015261028061251b848201612352565b908201526102a061252d848201611e01565b908201526102c083810151908201526102e08084015190820152610300808401518381111561255b57600080fd5b61256788828701611ee0565b828401525050610320808401518381111561258157600080fd5b61258d88828701611fa6565b82840152505061034080840151838111156125a757600080fd5b6125b388828701611fa6565b82840152505061036080840151838111156125cd57600080fd5b6125d988828701611f44565b82840152505061038080840151838111156125f357600080fd5b6125ff88828701611e3b565b8284015250506103a0808401518381111561261957600080fd5b61262588828701611e3b565b91830191909152506103c083810151908201526103e0808401519082015261040080840151908201526104208084015190820152610440915061266982840161233d565b82820152610460915061267d828401611ebf565b828201526104809150612691828401611ebf565b828201526104a0915081830151828201526104c091506126b282840161233d565b828201526104e091506126c6828401611ebf565b8282015261050091506126da828401611ebf565b8282015261052091506126ee828401611ebf565b828201526105409150612702828401611ead565b828201526105609150612716828401612369565b91810191909152949350505050565b60006020828403121561273757600080fd5b5051919050565b60006020828403121561275057600080fd5b81516001600160401b0381111561276657600080fd5b61231b84828501611ee0565b6001600160a01b038416815260606020820181905260009061279690830185611c18565b90508215156040830152949350505050565b600060208083850312156127bb57600080fd5b82516001600160401b03808211156127d257600080fd5b818501915085601f8301126127e657600080fd5b81516127f4611e5c82611e18565b81815260059190911b8301840190848101908883111561281357600080fd5b8585015b8381101561284b5780518581111561282f5760008081fd5b61283d8b89838a0101612089565b845250918601918601612817565b5098975050505050505050565b8181038181111561287957634e487b7160e01b600052601160045260246000fd5b9291505056fea2646970667358221220ee36b2a7e0e45179ad0a729fd5c7570d703a2408b61e0e8552c912d80a88a85e64736f6c63430008150033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

000000000000000000000000fd513630f697a9c1731f196185fb9eba6eaac20b000000000000000000000000937fd8cc7f7d2ef5b801e44c03218ade5648c3fb

-----Decoded View---------------
Arg [0] : _factory (address): 0xFD513630F697A9C1731F196185fb9ebA6eAAc20B
Arg [1] : _owner (address): 0x937fd8CC7f7D2ef5B801E44c03218ade5648C3Fb

-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000fd513630f697a9c1731f196185fb9eba6eaac20b
Arg [1] : 000000000000000000000000937fd8cc7f7d2ef5b801e44c03218ade5648c3fb


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.