creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "contracts/utils/SpigotLib.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0\n// Copyright: https://github.com/credit-cooperative/Line-Of-Credit/blob/master/COPYRIGHT.md\n\n pragma solidity ^0.8.16;\n\nimport {ReentrancyGuard} from \"openzeppelin/utils/ReentrancyGuard.sol\";\nimport {LineLib} from \"../utils/LineLib.sol\";\nimport {ISpigot} from \"../interfaces/ISpigot.sol\";\n\nstruct SpigotState {\n    /// @notice Economic owner of Spigot revenue streams\n    address owner;\n    /// @notice account in charge of running onchain ops of spigoted contracts on behalf of owner\n    address operator;\n    /// @notice Total amount of revenue tokens help by the Spigot and available to be claimed by owner\n    mapping(address => uint256) ownerTokens; // token -> claimable\n    /// @notice Total amount of revenue tokens help by the Spigot and available to be claimed by operator\n    mapping(address => uint256) operatorTokens; // token -> claimable\n    /// @notice Functions that the operator is allowed to run on all revenue contracts controlled by the Spigot\n    mapping(bytes4 => bool) whitelistedFunctions; // function -> allowed\n    /// @notice Configurations for revenue contracts related to the split of revenue, access control to claiming revenue tokens and transfer of Spigot ownership\n    mapping(address => ISpigot.Setting) settings; // revenue contract -> settings\n}\n\n/**\n * @notice - helper lib for Spigot\n * @dev see Spigot docs\n */\nlibrary SpigotLib {\n    // Maximum numerator for Setting.ownerSplit param to ensure that the Owner can't claim more than 100% of revenue\n    uint8 constant MAX_SPLIT = 100;\n    // cap revenue per claim to avoid overflows on multiplication when calculating percentages\n    uint256 constant MAX_REVENUE = type(uint256).max / MAX_SPLIT;\n\n    function _claimRevenue(\n        SpigotState storage self,\n        address revenueContract,\n        address token,\n        bytes calldata data\n    ) public returns (uint256 claimed) {\n        if (self.settings[revenueContract].transferOwnerFunction == bytes4(0)) {\n            revert InvalidRevenueContract();\n        }\n\n        uint256 existingBalance = LineLib.getBalance(token);\n\n        if (self.settings[revenueContract].claimFunction == bytes4(0)) {\n            // push payments\n\n            // claimed = total balance - already accounted for balance\n            claimed = existingBalance - self.ownerTokens[token] - self.operatorTokens[token];\n\n            // underflow revert ensures we have more tokens than we started with and actually claimed revenue\n        } else {\n            // pull payments\n            if (bytes4(data) != self.settings[revenueContract].claimFunction) {\n                revert BadFunction();\n            }\n            (bool claimSuccess, ) = revenueContract.call(data);\n            if (!claimSuccess) {\n                revert ClaimFailed();\n            }\n\n            // claimed = total balance - existing balance\n            claimed = LineLib.getBalance(token) - existingBalance;\n            // underflow revert ensures we have more tokens than we started with and actually claimed revenue\n        }\n\n        if (claimed == 0) {\n            revert NoRevenue();\n        }\n\n        // cap so uint doesnt overflow in split calculations.\n        // can sweep by \"attaching\" a push payment spigot with same token\n        if (claimed > MAX_REVENUE) claimed = MAX_REVENUE;\n\n        return claimed;\n    }\n\n    /** see Spigot.claimRevenue */\n    function claimRevenue(\n        SpigotState storage self,\n        address revenueContract,\n        address token,\n        bytes calldata data\n    ) external returns (uint256 claimed) {\n        claimed = _claimRevenue(self, revenueContract, token, data);\n\n        // splits revenue stream according to Spigot settings\n        uint256 ownerTokens = (claimed * self.settings[revenueContract].ownerSplit) / 100;\n        // update escrowed balance\n        self.ownerTokens[token] = self.ownerTokens[token] + ownerTokens;\n\n        // update operator amount\n        if (claimed > ownerTokens) {\n            self.operatorTokens[token] = self.operatorTokens[token] + (claimed - ownerTokens);\n        }\n\n        emit ClaimRevenue(token, claimed, ownerTokens, revenueContract);\n\n        return claimed;\n    }\n\n    /** see Spigot.operate */\n    function operate(SpigotState storage self, address revenueContract, bytes calldata data) external returns (bool) {\n        if (msg.sender != self.operator) {\n            revert CallerAccessDenied();\n        }\n\n        // extract function signature from tx data and check whitelist\n        bytes4 func = bytes4(data);\n\n        if (!self.whitelistedFunctions[func]) {\n            revert OperatorFnNotWhitelisted();\n        }\n\n        // cant claim revenue via operate() because that fucks up accounting logic. Owner shouldn't whitelist it anyway but just in case\n        // also can't transfer ownership so Owner retains control of revenue contract\n        if (\n            func == self.settings[revenueContract].claimFunction ||\n            func == self.settings[revenueContract].transferOwnerFunction\n        ) {\n            revert OperatorFnNotValid();\n        }\n\n        (bool success, ) = revenueContract.call(data);\n        if (!success) {\n            revert OperatorFnCallFailed();\n        }\n\n        return true;\n    }\n\n    /** see Spigot.claimOwnerTokens */\n    function claimOwnerTokens(SpigotState storage self, address token) external returns (uint256 claimed) {\n        if (msg.sender != self.owner) {\n            revert CallerAccessDenied();\n        }\n\n        claimed = self.ownerTokens[token];\n\n        if (claimed == 0) {\n            revert ClaimFailed();\n        }\n\n        self.ownerTokens[token] = 0; // reset before send to prevent reentrancy\n\n        LineLib.sendOutTokenOrETH(token, self.owner, claimed);\n\n        emit ClaimOwnerTokens(token, claimed, self.owner);\n\n        return claimed;\n    }\n\n    /** see Spigot.claimOperatorTokens */\n    function claimOperatorTokens(SpigotState storage self, address token) external returns (uint256 claimed) {\n        if (msg.sender != self.operator) {\n            revert CallerAccessDenied();\n        }\n\n        claimed = self.operatorTokens[token];\n\n        if (claimed == 0) {\n            revert ClaimFailed();\n        }\n\n        self.operatorTokens[token] = 0; // reset before send to prevent reentrancy\n\n        LineLib.sendOutTokenOrETH(token, self.operator, claimed);\n\n        emit ClaimOperatorTokens(token, claimed, self.operator);\n\n        return claimed;\n    }\n\n    /** see Spigot.addSpigot */\n    function addSpigot(\n        SpigotState storage self,\n        address revenueContract,\n        ISpigot.Setting memory setting\n    ) external returns (bool) {\n        if (msg.sender != self.owner) {\n            revert CallerAccessDenied();\n        }\n\n        if (revenueContract == address(this)) {\n            revert InvalidRevenueContract();\n        }\n\n        // spigot setting already exists\n        if (self.settings[revenueContract].transferOwnerFunction != bytes4(0)) {\n            revert SpigotSettingsExist();\n        }\n\n        // must set transfer func\n        if (setting.transferOwnerFunction == bytes4(0)) {\n            revert BadSetting();\n        }\n        if (setting.ownerSplit > MAX_SPLIT) {\n            revert BadSetting();\n        }\n\n        self.settings[revenueContract] = setting;\n        emit AddSpigot(revenueContract, setting.ownerSplit, setting.claimFunction, setting.transferOwnerFunction);\n\n        return true;\n    }\n\n    /** see Spigot.removeSpigot */\n    function removeSpigot(SpigotState storage self, address revenueContract) external returns (bool) {\n        if (msg.sender != self.owner) {\n            revert CallerAccessDenied();\n        }\n\n        (bool success, ) = revenueContract.call(\n            abi.encodeWithSelector(\n                self.settings[revenueContract].transferOwnerFunction,\n                self.operator // assume function only takes one param that is new owner address\n            )\n        );\n        require(success);\n\n        delete self.settings[revenueContract];\n        emit RemoveSpigot(revenueContract);\n\n        return true;\n    }\n\n    /** see Spigot.updateOwnerSplit */\n    function updateOwnerSplit(\n        SpigotState storage self,\n        address revenueContract,\n        uint8 ownerSplit\n    ) external returns (bool) {\n        if (msg.sender != self.owner) {\n            revert CallerAccessDenied();\n        }\n        if (ownerSplit > MAX_SPLIT) {\n            revert BadSetting();\n        }\n\n        self.settings[revenueContract].ownerSplit = ownerSplit;\n        emit UpdateOwnerSplit(revenueContract, ownerSplit);\n\n        return true;\n    }\n\n    /** see Spigot.updateOwner */\n    function updateOwner(SpigotState storage self, address newOwner) external returns (bool) {\n        if (msg.sender != self.owner) {\n            revert CallerAccessDenied();\n        }\n        require(newOwner != address(0));\n        self.owner = newOwner;\n        emit UpdateOwner(newOwner);\n        return true;\n    }\n\n    /** see Spigot.updateOperator */\n    function updateOperator(SpigotState storage self, address newOperator) external returns (bool) {\n        if (msg.sender != self.operator && msg.sender != self.owner) {\n            revert CallerAccessDenied();\n        }\n        require(newOperator != address(0));\n        self.operator = newOperator;\n        emit UpdateOperator(newOperator);\n        return true;\n    }\n\n    /** see Spigot.updateWhitelistedFunction*/\n    function updateWhitelistedFunction(SpigotState storage self, bytes4 func, bool allowed) external returns (bool) {\n        if (msg.sender != self.owner) {\n            revert CallerAccessDenied();\n        }\n        self.whitelistedFunctions[func] = allowed;\n        emit UpdateWhitelistFunction(func, allowed);\n        return true;\n    }\n\n    /** see Spigot.isWhitelisted*/\n    function isWhitelisted(SpigotState storage self, bytes4 func) external view returns (bool) {\n        return self.whitelistedFunctions[func];\n    }\n\n    /** see Spigot.getSetting*/\n    function getSetting(\n        SpigotState storage self,\n        address revenueContract\n    ) external view returns (uint8, bytes4, bytes4) {\n        return (\n            self.settings[revenueContract].ownerSplit,\n            self.settings[revenueContract].claimFunction,\n            self.settings[revenueContract].transferOwnerFunction\n        );\n    }\n\n    // Spigot Events\n    event AddSpigot(address indexed revenueContract, uint256 ownerSplit, bytes4 claimFnSig, bytes4 trsfrFnSig);\n\n    event RemoveSpigot(address indexed revenueContract);\n\n    event UpdateWhitelistFunction(bytes4 indexed func, bool indexed allowed);\n\n    event UpdateOwnerSplit(address indexed revenueContract, uint8 indexed split);\n\n    event ClaimRevenue(address indexed token, uint256 indexed amount, uint256 ownerTokens, address revenueContract);\n\n    event ClaimOwnerTokens(address indexed token, uint256 indexed amount, address owner);\n\n    event ClaimOperatorTokens(address indexed token, uint256 indexed amount, address ooperator);\n\n    // Stakeholder Events\n\n    event UpdateOwner(address indexed newOwner);\n\n    event UpdateOperator(address indexed newOperator);\n\n    event UpdateTreasury(address indexed newTreasury);\n\n    // Errors\n\n    error BadFunction();\n\n    error OperatorFnNotWhitelisted();\n\n    error OperatorFnNotValid();\n\n    error OperatorFnCallFailed();\n\n    error ClaimFailed();\n\n    error NoRevenue();\n\n    error UnclaimedRevenue();\n\n    error CallerAccessDenied();\n\n    error BadSetting();\n\n    error InvalidRevenueContract();\n\n    error SpigotSettingsExist();\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/utils/ReentrancyGuard.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/ReentrancyGuard.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuard {\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant NOT_ENTERED = 1;\n    uint256 private constant ENTERED = 2;\n\n    uint256 private _status;\n\n    /**\n     * @dev Unauthorized reentrant call.\n     */\n    error ReentrancyGuardReentrantCall();\n\n    constructor() {\n        _status = NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and making it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        _nonReentrantBefore();\n        _;\n        _nonReentrantAfter();\n    }\n\n    function _nonReentrantBefore() private {\n        // On the first call to nonReentrant, _status will be NOT_ENTERED\n        if (_status == ENTERED) {\n            revert ReentrancyGuardReentrantCall();\n        }\n\n        // Any calls to nonReentrant after this point will fail\n        _status = ENTERED;\n    }\n\n    function _nonReentrantAfter() private {\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        _status = NOT_ENTERED;\n    }\n\n    /**\n     * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n     * `nonReentrant` function in the call stack.\n     */\n    function _reentrancyGuardEntered() internal view returns (bool) {\n        return _status == ENTERED;\n    }\n}\n"
      },
      "contracts/utils/LineLib.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0\n// Copyright: https://github.com/credit-cooperative/Line-Of-Credit/blob/master/COPYRIGHT.md\n\n pragma solidity ^0.8.16;\nimport {IInterestRateCredit} from \"../interfaces/IInterestRateCredit.sol\";\nimport {ILineOfCredit} from \"../interfaces/ILineOfCredit.sol\";\nimport {IOracle} from \"../interfaces/IOracle.sol\";\nimport {IERC20} from \"openzeppelin/token/ERC20/IERC20.sol\";\nimport {SafeERC20} from \"openzeppelin/token/ERC20/utils/SafeERC20.sol\";\nimport {Denominations} from \"chainlink/Denominations.sol\";\n\n/**\n * @title Credit Cooperative Line of Credit Library\n * @notice Core logic and variables to be reused across all Credit Cooperative Marketplace Line of Credit contracts\n */\nlibrary LineLib {\n    using SafeERC20 for IERC20;\n\n    address constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; // mainnet WETH\n\n    error EthSentWithERC20();\n    error TransferFailed();\n    error SendingEthFailed();\n    error RefundEthFailed();\n\n    error BadToken();\n\n    event RefundIssued(address indexed recipient, uint256 value);\n\n    enum STATUS {\n        UNINITIALIZED,\n        ACTIVE,\n        LIQUIDATABLE,\n        REPAID,\n        INSOLVENT\n    }\n\n    /**\n     * @notice - Send ETH or ERC20 token from this contract to an external contract\n     * @param token - address of token to send out. Denominations.ETH for raw ETH\n     * @param receiver - address to send tokens to\n     * @param amount - amount of tokens to send\n     */\n    function sendOutTokenOrETH(address token, address receiver, uint256 amount) external returns (bool) {\n        if (token == address(0)) {\n            revert TransferFailed();\n        }\n\n        // both branches revert if call failed\n        if (token != Denominations.ETH) {\n            // ERC20\n            IERC20(token).safeTransfer(receiver, amount);\n        } else {\n            // ETH\n            bool success = _safeTransferFunds(receiver, amount);\n            if (!success) {\n                revert SendingEthFailed();\n            }\n        }\n        return true;\n    }\n\n    /**\n     * @notice - Receive ETH or ERC20 token at this contract from an external contract\n     * @dev    - If the sender overpays, the difference will be refunded to the sender\n     * @dev    - If the sender is unable to receive the refund, it will be diverted to the calling contract\n     * @param token - address of token to receive. Denominations.ETH for raw ETH\n     * @param sender - address that is sendingtokens/ETH\n     * @param amount - amount of tokens to send\n     */\n    function receiveTokenOrETH(address token, address sender, uint256 amount) external returns (bool) {\n        if (token == address(0)) {\n            revert TransferFailed();\n        }\n        if (token != Denominations.ETH) {\n            // ERC20\n            if (msg.value != 0) {\n                revert EthSentWithERC20();\n            }\n            IERC20(token).safeTransferFrom(sender, address(this), amount);\n        } else {\n            // ETH\n            if (msg.value < amount) {\n                revert TransferFailed();\n            }\n\n            if (msg.value > amount) {\n                uint256 refund = msg.value - amount;\n\n                if (_safeTransferFunds(msg.sender, refund)) {\n                    emit RefundIssued(msg.sender, refund);\n                }\n            }\n        }\n        return true;\n    }\n\n    /**\n     * @notice - Helper function to get current balance of this contract for ERC20 or ETH\n     * @param token - address of token to check. Denominations.ETH for raw ETH\n     */\n    function getBalance(address token) external view returns (uint256) {\n        if (token == address(0)) return 0;\n        return token != Denominations.ETH ? IERC20(token).balanceOf(address(this)) : address(this).balance;\n    }\n\n    /**\n     * @notice  - Helper function to safely transfer Eth using native call\n     * @dev     - Errors should be handled in the calling function\n     * @param recipient - address of the recipient\n     * @param value - value to be sent (in wei)\n     */\n    function _safeTransferFunds(address recipient, uint256 value) internal returns (bool success) {\n        (success, ) = payable(recipient).call{value: value}(\"\");\n    }\n}\n"
      },
      "contracts/interfaces/ISpigot.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0\n// Copyright: https://github.com/credit-cooperative/Line-Of-Credit/blob/master/COPYRIGHT.md\n\n pragma solidity ^0.8.16;\n\ninterface ISpigot {\n    struct Setting {\n        uint8 ownerSplit; // x/100 % to Owner, rest to Operator\n        bytes4 claimFunction; // function signature on contract to call and claim revenue\n        bytes4 transferOwnerFunction; // function signature on contract to call and transfer ownership\n    }\n\n    // Spigot Events\n    event AddSpigot(address indexed revenueContract, uint256 ownerSplit, bytes4 claimFnSig, bytes4 trsfrFnSig);\n\n    event RemoveSpigot(address indexed revenueContract, address token);\n\n    event UpdateWhitelistFunction(bytes4 indexed func, bool indexed allowed);\n\n    event UpdateOwnerSplit(address indexed revenueContract, uint8 indexed split);\n\n    event ClaimRevenue(address indexed token, uint256 indexed amount, uint256 escrowed, address revenueContract);\n\n    event ClaimOwnerTokens(address indexed token, uint256 indexed amount, address owner);\n\n    event ClaimOperatorTokens(address indexed token, uint256 indexed amount, address operator);\n\n    // Stakeholder Events\n\n    event UpdateOwner(address indexed newOwner);\n\n    event UpdateOperator(address indexed newOperator);\n\n    // Errors\n    error BadFunction();\n\n    error OperatorFnNotWhitelisted();\n\n    error OperatorFnNotValid();\n\n    error OperatorFnCallFailed();\n\n    error ClaimFailed();\n\n    error NoRevenue();\n\n    error UnclaimedRevenue();\n\n    error CallerAccessDenied();\n\n    error BadSetting();\n\n    error InvalidRevenueContract();\n\n    // ops funcs\n\n    function claimRevenue(\n        address revenueContract,\n        address token,\n        bytes calldata data\n    ) external returns (uint256 claimed);\n\n    function operate(address revenueContract, bytes calldata data) external returns (bool);\n\n    // owner funcs\n\n    function claimOwnerTokens(address token) external returns (uint256 claimed);\n\n    function claimOperatorTokens(address token) external returns (uint256 claimed);\n\n    function addSpigot(address revenueContract, Setting memory setting) external returns (bool);\n\n    function removeSpigot(address revenueContract) external returns (bool);\n\n    // stakeholder funcs\n\n    function updateOwnerSplit(address revenueContract, uint8 ownerSplit) external returns (bool);\n\n    function updateOwner(address newOwner) external returns (bool);\n\n    function updateOperator(address newOperator) external returns (bool);\n\n    function updateWhitelistedFunction(bytes4 func, bool allowed) external returns (bool);\n\n    // Getters\n    function owner() external view returns (address);\n\n    function operator() external view returns (address);\n\n    function isWhitelisted(bytes4 func) external view returns (bool);\n\n    function getOwnerTokens(address token) external view returns (uint256);\n\n    function getOperatorTokens(address token) external view returns (uint256);\n\n    function getSetting(\n        address revenueContract\n    ) external view returns (uint8 split, bytes4 claimFunc, bytes4 transferFunc);\n}\n"
      },
      "contracts/interfaces/IInterestRateCredit.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0\n// Copyright: https://github.com/credit-cooperative/Line-Of-Credit/blob/master/COPYRIGHT.md\n\n pragma solidity ^0.8.16;\n\ninterface IInterestRateCredit {\n    struct Rate {\n        // The interest rate charged to a Borrower on borrowed / drawn down funds\n        // in bps, 4 decimals\n        uint128 dRate;\n        // The interest rate charged to a Borrower on the remaining funds available, but not yet drawn down (rate charged on the available headroom)\n        // in bps, 4 decimals\n        uint128 fRate;\n        // The time stamp at which accrued interest was last calculated on an ID and then added to the overall interestAccrued (interest due but not yet repaid)\n        uint256 lastAccrued;\n    }\n\n    /**\n     * @notice - allows `lineContract to calculate how much interest is owed since it was last calculated charged at time `lastAccrued`\n     * @dev    - pure function that only calculates interest owed. Line is responsible for actually updating credit balances with returned value\n     * @dev    - callable by `lineContract`\n     * @param id - position id on Line to look up interest rates for\n     * @param drawnBalance the balance of funds that a Borrower has drawn down on the credit line\n     * @param facilityBalance the remaining balance of funds that a Borrower can still drawn down on a credit line (aka headroom)\n     *\n     * @return - the amount of interest to be repaid for this interest period\n     */\n\n    function accrueInterest(bytes32 id, uint256 drawnBalance, uint256 facilityBalance) external returns (uint256);\n\n    /**\n     * @notice - updates interest rates on a lender's position. Updates lastAccrued time to block.timestamp\n     * @dev    - MUST call accrueInterest() on Line before changing rates. If not, lender will not accrue interest over previous interest period.\n     * @dev    - callable by `line`\n     * @return - if call was successful or not\n     */\n    function setRate(bytes32 id, uint128 dRate, uint128 fRate) external returns (bool);\n\n    function getInterestAccrued(\n        bytes32 id,\n        uint256 drawnBalance,\n        uint256 facilityBalance\n    ) external view returns (uint256);\n\n    function getRates(bytes32 id) external view returns (uint128, uint128);\n}\n"
      },
      "contracts/interfaces/ILineOfCredit.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0\n// Copyright: https://github.com/credit-cooperative/Line-Of-Credit/blob/master/COPYRIGHT.md\n\n pragma solidity ^0.8.16;\n\nimport {LineLib} from \"../utils/LineLib.sol\";\nimport {IOracle} from \"../interfaces/IOracle.sol\";\n\ninterface ILineOfCredit {\n    // Lender data\n    struct Credit {\n        //  all denominated in token, not USD\n        uint256 deposit; // The total liquidity provided by a Lender in a given token on a Line of Credit\n        uint256 principal; // The amount of a Lender's Deposit on a Line of Credit that has actually been drawn down by the Borrower (in Tokens)\n        uint256 interestAccrued; // Interest due by a Borrower but not yet repaid to the Line of Credit contract\n        uint256 interestRepaid; // Interest repaid by a Borrower to the Line of Credit contract but not yet withdrawn by a Lender\n        uint8 decimals; // Decimals of Credit Token for calcs\n        address token; // The token being lent out (Credit Token)\n        address lender; // The person to repay\n        bool isOpen; // Status of position\n    }\n\n    // General Events\n    event UpdateStatus(uint256 indexed status); // store as normal uint so it can be indexed in subgraph\n\n    event DeployLine(address indexed oracle, address indexed arbiter, address indexed borrower);\n\n    event SortedIntoQ(bytes32 indexed id, uint256 indexed newIdx, uint256 indexed oldIdx, bytes32 oldId);\n\n    // MutualConsent borrower/lender events\n\n    event AddCredit(address indexed lender, address indexed token, uint256 indexed deposit, bytes32 id);\n    // can only reference id once AddCredit is emitted because it will be indexed offchain\n\n    event SetRates(bytes32 indexed id, uint128 indexed dRate, uint128 indexed fRate);\n\n    event IncreaseCredit(bytes32 indexed id, uint256 indexed deposit);\n\n    // Lender Events\n\n    // Emits data re Lender removes funds (principal) - there is no corresponding function, just withdraw()\n    event WithdrawDeposit(bytes32 indexed id, uint256 indexed amount);\n\n    // Emits data re Lender withdraws interest - there is no corresponding function, just withdraw()\n    event WithdrawProfit(bytes32 indexed id, uint256 indexed amount);\n\n    // Emitted when any credit line is closed by the line's borrower or the position's lender\n    event CloseCreditPosition(bytes32 indexed id);\n\n    // After accrueInterest runs, emits the amount of interest added to a Borrower's outstanding balance of interest due\n    // but not yet repaid to the Line of Credit contract\n    event InterestAccrued(bytes32 indexed id, uint256 indexed amount);\n\n    // Borrower Events\n\n    // receive full line or drawdown on credit\n    event Borrow(bytes32 indexed id, uint256 indexed amount);\n\n    // Emits that a Borrower has repaid an amount of interest Results in an increase in interestRepaid, i.e. interest not yet withdrawn by a Lender). There is no corresponding function\n    event RepayInterest(bytes32 indexed id, uint256 indexed amount);\n\n    // Emits that a Borrower has repaid an amount of principal - there is no corresponding function\n    event RepayPrincipal(bytes32 indexed id, uint256 indexed amount);\n\n    event Default(bytes32 indexed id);\n\n    // Access Errors\n    error NotActive();\n    error NotBorrowing();\n    error CallerAccessDenied();\n\n    // Tokens\n    error TokenTransferFailed();\n    error NoTokenPrice();\n\n    // Line\n    error BadModule(address module);\n    error NoLiquidity();\n    error PositionExists();\n    error CloseFailedWithPrincipal();\n    error NotInsolvent(address module);\n    error NotLiquidatable();\n    error AlreadyInitialized();\n    error PositionIsClosed();\n    error RepayAmountExceedsDebt(uint256 totalAvailable);\n    error CantStepQ();\n    error EthSupportDisabled();\n    error BorrowFailed();\n\n    // Fully public functions\n\n    /**\n     * @notice - Runs logic to ensure Line owns all modules are configured properly - collateral, interest rates, arbiter, etc.\n     *          - Changes `status` from UNINITIALIZED to ACTIVE\n     * @dev     - Reverts on failure to update status\n     */\n    function init() external;\n\n    // MutualConsent functions\n\n    /**\n    * @notice        - On first call, creates proposed terms and emits MutualConsentRegistsered event. No position is created.\n                      - On second call, creates position and stores in Line contract, sets interest rates, and starts accruing facility rate fees.\n    * @dev           - Requires mutualConsent participants send EXACT same params when calling addCredit\n    * @dev           - Fully executes function after a Borrower and a Lender have agreed terms, both Lender and borrower have agreed through mutualConsent\n    * @dev           - callable by `lender` and `borrower`\n    * @param drate   - The interest rate charged to a Borrower on borrowed / drawn down funds. In bps, 4 decimals.\n    * @param frate   - The interest rate charged to a Borrower on the remaining funds available, but not yet drawn down\n                        (rate charged on the available headroom). In bps, 4 decimals.\n    * @param amount  - The amount of Credit Token to initially deposit by the Lender\n    * @param token   - The Credit Token, i.e. the token to be lent out\n    * @param lender  - The address that will manage credit line\n    * @return id     - Lender's position id to look up in `credits`\n  */\n    function addCredit(\n        uint128 drate,\n        uint128 frate,\n        uint256 amount,\n        address token,\n        address lender\n    ) external payable returns (bytes32);\n\n    /**\n     * @notice           - lets Lender and Borrower update rates on the lender's position\n     *                   - accrues interest before updating terms, per InterestRate docs\n     *                   - can do so even when LIQUIDATABLE for the purpose of refinancing and/or renego\n     * @dev              - callable by Borrower or Lender\n     * @param id         - position id that we are updating\n     * @param drate      - new drawn rate. In bps, 4 decimals\n     * @param frate      - new facility rate. In bps, 4 decimals\n     */\n    function setRates(bytes32 id, uint128 drate, uint128 frate) external;\n\n    /**\n     * @notice           - Lets a Lender and a Borrower increase the credit limit on a position\n     * @dev              - line status must be ACTIVE\n     * @dev              - callable by borrower\n     * @dev              - The function retains the `payable` designation, despite not accepting Eth via mutualConsent modifier, as a gas-optimization\n     * @param id         - position id that we are updating\n     * @param amount     - amount to deposit by the Lender\n     */\n    function increaseCredit(bytes32 id, uint256 amount) external payable;\n\n    // Borrower functions\n\n    /**\n     * @notice       - Borrower chooses which lender position draw down on and transfers tokens from Line contract to Borrower\n     * @dev          - callable by borrower\n     * @param id     - the position to draw down on\n     * @param amount - amount of tokens the borrower wants to withdraw\n     */\n    function borrow(bytes32 id, uint256 amount) external;\n\n    /**\n     * @notice       - Transfers token used in position id from msg.sender to Line contract.\n     * @dev          - Available for anyone to deposit Credit Tokens to be available to be withdrawn by Lenders\n     * @dev          - The function retains the `payable` designation, despite reverting with a non-zero msg.value, as a gas-optimization\n     * @notice       - see LineOfCredit._repay() for more details\n     * @param amount - amount of `token` in `id` to pay back\n     */\n    function depositAndRepay(uint256 amount) external payable;\n\n    /**\n     * @notice       - A Borrower deposits enough tokens to repay and close a credit line.\n     * @dev          - callable by borrower\n     * @dev          - The function retains the `payable` designation, despite reverting with a non-zero msg.value, as a gas-optimization\n     */\n    function depositAndClose() external payable;\n\n    /**\n     * @notice - Removes and deletes a position, preventing any more borrowing or interest.\n     *         - Requires that the position principal has already been repais in full\n     * @dev      - MUST repay accrued interest from facility fee during call\n     * @dev - callable by `borrower` or Lender\n     * @dev          - The function retains the `payable` designation, despite reverting with a non-zero msg.value, as a gas-optimization\n     * @param id -the position id to be closed\n     */\n    function close(bytes32 id) external payable;\n\n    // Lender functions\n\n    /**\n     * @notice - Withdraws liquidity from a Lender's position available to the Borrower.\n     *         - Lender is only allowed to withdraw tokens not already lent out\n     *         - Withdraws from repaid interest (profit) first and then deposit is reduced\n     * @dev - can only withdraw tokens from their own position. If multiple lenders lend DAI, the lender1 can't withdraw using lender2's tokens\n     * @dev - callable by Lender on `id`\n     * @param id - the position id that Lender is withdrawing from\n     * @param amount - amount of tokens the Lender would like to withdraw (withdrawn amount may be lower)\n     */\n    function withdraw(bytes32 id, uint256 amount) external;\n\n    // Arbiter functions\n    /**\n     * @notice - Allow the Arbiter to signify that the Borrower is incapable of repaying debt permanently.\n     *         - Recoverable funds for Lender after declaring insolvency = deposit + interestRepaid - principal\n     * @dev    - Needed for onchain impairment accounting e.g. updating ERC4626 share price\n     *         - MUST NOT have collateral left for call to succeed. Any collateral must already have been liquidated.\n     * @dev    - Callable only by Arbiter.\n     */\n    function declareInsolvent() external;\n\n    /**\n     *\n     * @notice - Updates accrued interest for the whole Line of Credit facility (i.e. for all credit lines)\n     * @dev    - Loops over all position ids and calls related internal functions during which InterestRateCredit.sol\n     *           is called with the id data and then 'interestAccrued' is updated.\n     * @dev    - The related internal function _accrue() is called by other functions any time the balance on an individual\n     *           credit line changes or if the interest rates of a credit line are changed by mutual consent\n     *           between a Borrower and a Lender.\n     */\n    function accrueInterest() external;\n\n    function healthcheck() external returns (LineLib.STATUS);\n\n    /**\n     * @notice - Cycles through position ids andselects first position with non-null principal to the zero index\n     * @dev - Only works if the first element in the queue is null\n     */\n    function stepQ() external;\n\n    /**\n     * @notice - Returns the total debt of a Borrower across all positions for all Lenders.\n     * @dev    - Denominated in USD, 8 decimals.\n     * @dev    - callable by anyone\n     * @return totalPrincipal - total amount of principal, in USD, owed across all positions\n     * @return totalInterest - total amount of interest, in USD,  owed across all positions\n     */\n    function updateOutstandingDebt() external returns (uint256, uint256);\n\n    // State getters\n\n    function status() external returns (LineLib.STATUS);\n\n    function borrower() external returns (address);\n\n    function arbiter() external returns (address);\n\n    function oracle() external returns (IOracle);\n\n    /**\n     * @notice - getter for amount of active ids + total ids in list\n     * @return - (uint256, uint256) - active credit lines, total length\n     */\n    function counts() external view returns (uint256, uint256);\n\n    /**\n     * @notice - getter for amount of active ids + total ids in list\n     * @return - (uint256, uint256) - active credit lines, total length\n     */\n\n    function interestAccrued(bytes32 id) external returns (uint256);\n\n    /**\n     * @notice - info on the next lender position that must be repaid\n     * @return - (bytes32, address, address, uint, uint) - id, lender, token, principal, interestAccrued\n     */\n    function nextInQ() external view returns (bytes32, address, address, uint256, uint256, uint256, uint128, uint128);\n\n    /**\n     * @notice - how many tokens can be withdrawn from positions by borrower or lender\n     * @return - (uint256, uint256) - remaining deposit, claimable interest\n     */\n    function available(bytes32 id) external returns (uint256, uint256);\n}\n"
      },
      "contracts/interfaces/IOracle.sol": {
        "content": " pragma solidity ^0.8.16;\n\ninterface IOracle {\n    /** current price for token asset. denominated in USD */\n    function getLatestAnswer(address token) external returns (int256);\n\n    /** Readonly function providing the current price for token asset. denominated in USD */\n    function _getLatestAnswer(address token) external view returns (int256);\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n    /**\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\n     * another (`to`).\n     *\n     * Note that `value` may be zero.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 value);\n\n    /**\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n     * a call to {approve}. `value` is the new allowance.\n     */\n    event Approval(address indexed owner, address indexed spender, uint256 value);\n\n    /**\n     * @dev Returns the value of tokens in existence.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns the value of tokens owned by `account`.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /**\n     * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transfer(address to, uint256 value) external returns (bool);\n\n    /**\n     * @dev Returns the remaining number of tokens that `spender` will be\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\n     * zero by default.\n     *\n     * This value changes when {approve} or {transferFrom} are called.\n     */\n    function allowance(address owner, address spender) external view returns (uint256);\n\n    /**\n     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n     * caller's tokens.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\n     * that someone may use both the old and the new allowance by unfortunate\n     * transaction ordering. One possible solution to mitigate this race\n     * condition is to first reduce the spender's allowance to 0 and set the\n     * desired value afterwards:\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address spender, uint256 value) external returns (bool);\n\n    /**\n     * @dev Moves a `value` amount of tokens from `from` to `to` using the\n     * allowance mechanism. `value` is then deducted from the caller's\n     * allowance.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC20} from \"../IERC20.sol\";\nimport {IERC20Permit} from \"../extensions/IERC20Permit.sol\";\nimport {Address} from \"../../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n    using Address for address;\n\n    /**\n     * @dev An operation with an ERC20 token failed.\n     */\n    error SafeERC20FailedOperation(address token);\n\n    /**\n     * @dev Indicates a failed `decreaseAllowance` request.\n     */\n    error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n    /**\n     * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful.\n     */\n    function safeTransfer(IERC20 token, address to, uint256 value) internal {\n        _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n    }\n\n    /**\n     * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n     * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n     */\n    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n        _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n    }\n\n    /**\n     * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful.\n     */\n    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n        uint256 oldAllowance = token.allowance(address(this), spender);\n        forceApprove(token, spender, oldAllowance + value);\n    }\n\n    /**\n     * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n     * value, non-reverting calls are assumed to be successful.\n     */\n    function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n        unchecked {\n            uint256 currentAllowance = token.allowance(address(this), spender);\n            if (currentAllowance < requestedDecrease) {\n                revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n            }\n            forceApprove(token, spender, currentAllowance - requestedDecrease);\n        }\n    }\n\n    /**\n     * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n     * to be set to zero before setting it to a non-zero value, such as USDT.\n     */\n    function forceApprove(IERC20 token, address spender, uint256 value) internal {\n        bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n        if (!_callOptionalReturnBool(token, approvalCall)) {\n            _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n            _callOptionalReturn(token, approvalCall);\n        }\n    }\n\n    /**\n     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n     * on the return value: the return value is optional (but if data is returned, it must not be false).\n     * @param token The token targeted by the call.\n     * @param data The call data (encoded using abi.encode or one of its variants).\n     */\n    function _callOptionalReturn(IERC20 token, bytes memory data) private {\n        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n        // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n        // the target address contains contract code and also asserts for success in the low-level call.\n\n        bytes memory returndata = address(token).functionCall(data);\n        if (returndata.length != 0 && !abi.decode(returndata, (bool))) {\n            revert SafeERC20FailedOperation(address(token));\n        }\n    }\n\n    /**\n     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n     * on the return value: the return value is optional (but if data is returned, it must not be false).\n     * @param token The token targeted by the call.\n     * @param data The call data (encoded using abi.encode or one of its variants).\n     *\n     * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n     */\n    function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n        // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n        // and not revert is the subcall reverts.\n\n        (bool success, bytes memory returndata) = address(token).call(data);\n        return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && address(token).code.length > 0;\n    }\n}\n"
      },
      "lib/chainlink/contracts/src/v0.8/Denominations.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nlibrary Denominations {\n  address public constant ETH = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n  address public constant BTC = 0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB;\n\n  // Fiat currencies follow https://en.wikipedia.org/wiki/ISO_4217\n  address public constant USD = address(840);\n  address public constant GBP = address(826);\n  address public constant EUR = address(978);\n  address public constant JPY = address(392);\n  address public constant KRW = address(410);\n  address public constant CNY = address(156);\n  address public constant AUD = address(36);\n  address public constant CAD = address(124);\n  address public constant CHF = address(756);\n  address public constant ARS = address(32);\n  address public constant PHP = address(608);\n  address public constant NZD = address(554);\n  address public constant SGD = address(702);\n  address public constant NGN = address(566);\n  address public constant ZAR = address(710);\n  address public constant RUB = address(643);\n  address public constant INR = address(356);\n  address public constant BRL = address(986);\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n *     try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n *     doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n *     token.safeTransferFrom(msg.sender, address(this), value);\n *     ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20Permit {\n    /**\n     * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n     * given ``owner``'s signed approval.\n     *\n     * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n     * ordering also apply here.\n     *\n     * Emits an {Approval} event.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     * - `deadline` must be a timestamp in the future.\n     * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n     * over the EIP712-formatted function arguments.\n     * - the signature must use ``owner``'s current nonce (see {nonces}).\n     *\n     * For more information on the signature format, see the\n     * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n     * section].\n     *\n     * CAUTION: See Security Considerations above.\n     */\n    function permit(\n        address owner,\n        address spender,\n        uint256 value,\n        uint256 deadline,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) external;\n\n    /**\n     * @dev Returns the current nonce for `owner`. This value must be\n     * included whenever a signature is generated for {permit}.\n     *\n     * Every successful call to {permit} increases ``owner``'s nonce by one. This\n     * prevents a signature from being used multiple times.\n     */\n    function nonces(address owner) external view returns (uint256);\n\n    /**\n     * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n     */\n    // solhint-disable-next-line func-name-mixedcase\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/utils/Address.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n    /**\n     * @dev The ETH balance of the account is not enough to perform the operation.\n     */\n    error AddressInsufficientBalance(address account);\n\n    /**\n     * @dev There's no code at `target` (it is not a contract).\n     */\n    error AddressEmptyCode(address target);\n\n    /**\n     * @dev A call to an address target failed. The target may have reverted.\n     */\n    error FailedInnerCall();\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        if (address(this).balance < amount) {\n            revert AddressInsufficientBalance(address(this));\n        }\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        if (!success) {\n            revert FailedInnerCall();\n        }\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason or custom error, it is bubbled\n     * up by this function (like regular Solidity function calls). However, if\n     * the call reverted with no returned reason, this function reverts with a\n     * {FailedInnerCall} error.\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     */\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n        if (address(this).balance < value) {\n            revert AddressInsufficientBalance(address(this));\n        }\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, success, returndata);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, success, returndata);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResultFromTarget(target, success, returndata);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n     * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\n     * unsuccessful call.\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata\n    ) internal view returns (bytes memory) {\n        if (!success) {\n            _revert(returndata);\n        } else {\n            // only check if target is a contract if the call was successful and the return data is empty\n            // otherwise we already know that it was a contract\n            if (returndata.length == 0 && target.code.length == 0) {\n                revert AddressEmptyCode(target);\n            }\n            return returndata;\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n     * revert reason or with a default {FailedInnerCall} error.\n     */\n    function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n        if (!success) {\n            _revert(returndata);\n        } else {\n            return returndata;\n        }\n    }\n\n    /**\n     * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\n     */\n    function _revert(bytes memory returndata) private pure {\n        // Look for revert reason and bubble it up if present\n        if (returndata.length > 0) {\n            // The easiest way to bubble the revert reason is using memory via assembly\n            /// @solidity memory-safe-assembly\n            assembly {\n                let returndata_size := mload(returndata)\n                revert(add(32, returndata), returndata_size)\n            }\n        } else {\n            revert FailedInnerCall();\n        }\n    }\n}\n"
      }
    },
    "settings": {
      "remappings": [
        "chainlink/=lib/chainlink/contracts/src/v0.8/",
        "ds-test/=lib/forge-std/lib/ds-test/src/",
        "forge-std/=lib/forge-std/src/",
        "openzeppelin/=lib/openzeppelin-contracts/contracts/",
        "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
        "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
        "openzeppelin-contracts/=lib/openzeppelin-contracts/"
      ],
      "optimizer": {
        "enabled": true,
        "runs": 200
      },
      "metadata": {
        "useLiteralContent": false,
        "bytecodeHash": "ipfs",
        "appendCBOR": true
      },
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "evmVersion": "london",
      "libraries": {
        "contracts/utils/CreditLib.sol": {
          "CreditLib": "0x4dca189d7fb51d9cc375e4d697e5800c5d21ff87"
        },
        "contracts/utils/CreditListLib.sol": {
          "CreditListLib": "0x9cbe9741b3503a790e69e1587b5d51c0056154dc"
        },
        "contracts/utils/EscrowLib.sol": {
          "EscrowLib": "0x9ae9c76276e503105f20c8b452ccd0c4ee3b2df2"
        },
        "contracts/utils/LineFactoryLib.sol": {
          "LineFactoryLib": "0x2b721a999b83cbcc1DBD697A27199d5b4Be70102"
        },
        "contracts/utils/LineLib.sol": {
          "LineLib": "0x73cb72a7efaddd99cdd2d110e2f4b8b65bf3b812"
        },
        "contracts/utils/SpigotLib.sol": {
          "SpigotLib": "0x05b4180e2ee77a04f3f0dc833e36b7d9f1141e02"
        },
        "contracts/utils/SpigotedLineLib.sol": {
          "SpigotedLineLib": "0x274946031D204567281F7616718b4aBB940Ef784"
        }
      }
    }
  }}