{"file_path":"contracts/LoanManager.sol","creation_status":"success","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.7;\n\nimport { ERC20Helper }           from \"../modules/erc20-helper/src/ERC20Helper.sol\";\nimport { IMapleProxyFactory }    from \"../modules/maple-proxy-factory/contracts/interfaces/IMapleProxyFactory.sol\";\nimport { MapleProxiedInternals } from \"../modules/maple-proxy-factory/contracts/MapleProxiedInternals.sol\";\n\nimport { ILoanManager }                                                from \"./interfaces/ILoanManager.sol\";\nimport { IGlobalsLike, ILoanFactoryLike, ILoanLike, IPoolManagerLike } from \"./interfaces/Interfaces.sol\";\n\nimport { LoanManagerStorage } from \"./LoanManagerStorage.sol\";\n\n/*\n\n    ██╗      ██████╗  █████╗ ███╗   ██╗    ███╗   ███╗ █████╗ ███╗   ██╗ █████╗  ██████╗ ███████╗██████╗\n    ██║     ██╔═══██╗██╔══██╗████╗  ██║    ████╗ ████║██╔══██╗████╗  ██║██╔══██╗██╔════╝ ██╔════╝██╔══██╗\n    ██║     ██║   ██║███████║██╔██╗ ██║    ██╔████╔██║███████║██╔██╗ ██║███████║██║  ███╗█████╗  ██████╔╝\n    ██║     ██║   ██║██╔══██║██║╚██╗██║    ██║╚██╔╝██║██╔══██║██║╚██╗██║██╔══██║██║   ██║██╔══╝  ██╔══██╗\n    ███████╗╚██████╔╝██║  ██║██║ ╚████║    ██║ ╚═╝ ██║██║  ██║██║ ╚████║██║  ██║╚██████╔╝███████╗██║  ██║\n    ╚══════╝ ╚═════╝ ╚═╝  ╚═╝╚═╝  ╚═══╝    ╚═╝     ╚═╝╚═╝  ╚═╝╚═╝  ╚═══╝╚═╝  ╚═╝ ╚═════╝ ╚══════╝╚═╝  ╚═╝\n\n*/\n\ncontract LoanManager is ILoanManager, MapleProxiedInternals, LoanManagerStorage {\n\n    uint256 public override constant HUNDRED_PERCENT = 1e6;   // 100.0000%\n    uint256 public override constant PRECISION       = 1e27;\n\n    /**************************************************************************************************************************************/\n    /*** Modifiers                                                                                                                      ***/\n    /**************************************************************************************************************************************/\n\n    modifier isLoan(address loan_) {\n        _revertIfNotLoan(loan_);\n        _;\n    }\n\n    modifier nonReentrant() {\n        require(_locked == 1, \"LM:LOCKED\");\n\n        _locked = 2;\n\n        _;\n\n        _locked = 1;\n    }\n\n    modifier onlyPoolDelegate() {\n        _revertIfNotPoolDelegate();\n        _;\n    }\n\n    modifier whenNotPaused() {\n        _revertIfPaused();\n        _;\n    }\n\n    /**************************************************************************************************************************************/\n    /*** Upgradeability Functions                                                                                                       ***/\n    /**************************************************************************************************************************************/\n\n    function migrate(address migrator_, bytes calldata arguments_) external override whenNotPaused {\n        require(msg.sender == _factory(),        \"LM:M:NOT_FACTORY\");\n        require(_migrate(migrator_, arguments_), \"LM:M:FAILED\");\n    }\n\n    function setImplementation(address implementation_) external override whenNotPaused {\n        require(msg.sender == _factory(), \"LM:SI:NOT_FACTORY\");\n\n        _setImplementation(implementation_);\n    }\n\n    function upgrade(uint256 version_, bytes calldata arguments_) external override whenNotPaused {\n        IGlobalsLike globals_ = IGlobalsLike(_globals());\n\n        if (msg.sender == _poolDelegate()) {\n            require(globals_.isValidScheduledCall(msg.sender, address(this), \"LM:UPGRADE\", msg.data), \"LM:U:INVALID_SCHED_CALL\");\n\n            globals_.unscheduleCall(msg.sender, \"LM:UPGRADE\", msg.data);\n        } else {\n            require(msg.sender == globals_.securityAdmin(), \"LM:U:NO_AUTH\");\n        }\n\n        emit Upgraded(version_, arguments_);\n\n        IMapleProxyFactory(_factory()).upgradeInstance(version_, arguments_);\n    }\n\n    /**************************************************************************************************************************************/\n    /*** Loan Funding and Refinancing Functions                                                                                         ***/\n    /**************************************************************************************************************************************/\n\n    function fund(address loan_) external override whenNotPaused nonReentrant onlyPoolDelegate {\n        address      factory_ = ILoanLike(loan_).factory();\n        IGlobalsLike globals_ = IGlobalsLike(_globals());\n\n        require(globals_.isInstanceOf(\"OT_LOAN_FACTORY\", factory_),    \"LM:F:INVALID_LOAN_FACTORY\");\n        require(ILoanFactoryLike(factory_).isLoan(loan_),              \"LM:F:INVALID_LOAN_INSTANCE\");\n        require(globals_.isBorrower(ILoanLike(loan_).borrower()), \"LM:F:INVALID_BORROWER\");\n\n        uint256 principal_ = ILoanLike(loan_).principal();\n\n        require(principal_ != 0, \"LM:F:LOAN_NOT_ACTIVE\");\n\n        _prepareFundsForLoan(loan_, principal_);\n\n        ( uint256 fundsLent_, , ) = ILoanLike(loan_).fund();\n\n        require(fundsLent_ == principal_, \"LM:F:FUNDING_MISMATCH\");\n\n        _updatePrincipalOut(_int256(fundsLent_));\n\n        Payment memory payment_ = _addPayment(loan_);\n\n        _updateInterestAccounting(0, _int256(payment_.issuanceRate));\n    }\n\n    function proposeNewTerms(address loan_, address refinancer_, uint256 deadline_, bytes[] calldata calls_)\n        external override whenNotPaused onlyPoolDelegate isLoan(loan_)\n    {\n        ILoanLike(loan_).proposeNewTerms(refinancer_, deadline_, calls_);\n    }\n\n    function rejectNewTerms(address loan_, address refinancer_, uint256 deadline_, bytes[] calldata calls_)\n        external override whenNotPaused onlyPoolDelegate isLoan(loan_)\n    {\n        ILoanLike(loan_).rejectNewTerms(refinancer_, deadline_, calls_);\n    }\n\n    /**************************************************************************************************************************************/\n    /*** Loan Payment Claim Function                                                                                                    ***/\n    /**************************************************************************************************************************************/\n\n    function claim(\n        int256  principal_,\n        uint256 interest_,\n        uint256 delegateServiceFee_,\n        uint256 platformServiceFee_,\n        uint40  nextPaymentDueDate_\n    )\n        external override whenNotPaused isLoan(msg.sender) nonReentrant\n    {\n        uint256 principalRemaining_ = ILoanLike(msg.sender).principal();\n\n        // Either a next payment and remaining principal exists, or neither exist and principal is returned.\n        require(\n            (nextPaymentDueDate_ > 0 && principalRemaining_ > 0) ||                          // First given it's most likely.\n            ((nextPaymentDueDate_ == 0) && (principalRemaining_ == 0) && (principal_ > 0)),\n            \"LM:C:INVALID\"\n        );\n\n        // Calculate the original principal to correctly account for removing `unrealizedLosses` when removing the impairment.\n        uint256 originalPrincipal_ = uint256(_int256(principalRemaining_) + principal_);\n\n        _accountForLoanImpairmentRemoval(msg.sender, originalPrincipal_);\n\n        // Transfer the funds from the loan to the `pool`, `poolDelegate`, and `mapleTreasury`.\n        _distributeClaimedFunds(msg.sender, principal_, interest_, delegateServiceFee_, platformServiceFee_);\n\n        // If principal is changing, update `principalOut`.\n        // If principal is positive, it is being repaid, so `principalOut` is decremented.\n        // If principal is negative, it is being taken from the Pool, so `principalOut` is incremented.\n        if (principal_ != 0) {\n            _updatePrincipalOut(-principal_);\n        }\n\n        // Remove the payment and cache the struct.\n        Payment memory claimedPayment_ = _removePayment(msg.sender);\n\n        int256 accountedInterestAdjustment_\n            = -_int256(_getIssuance(claimedPayment_.issuanceRate, block.timestamp - claimedPayment_.startDate));\n\n        // If no new payment to track, update accounting and account for discrepancies in paid interest vs accrued interest since the\n        // payment's start date, and exit.\n        if (nextPaymentDueDate_ == 0) {\n            return _updateInterestAccounting(accountedInterestAdjustment_, -_int256(claimedPayment_.issuanceRate));\n        }\n\n        if (principal_ < 0) {\n            address borrower_ = ILoanLike(msg.sender).borrower();\n\n            require(IGlobalsLike(_globals()).isBorrower(borrower_), \"LM:C:INVALID_BORROWER\");\n\n            _prepareFundsForLoan(msg.sender, _uint256(-principal_));\n        }\n\n        // Track the new payment.\n        Payment memory nextPayment_ = _addPayment(msg.sender);\n\n        // Update accounting and account for discrepancies in paid interest vs accrued interest since the payment's start date, and exit.\n        _updateInterestAccounting(accountedInterestAdjustment_, _int256(nextPayment_.issuanceRate) - _int256(claimedPayment_.issuanceRate));\n    }\n\n    /**************************************************************************************************************************************/\n    /*** Loan Call Functions                                                                                                            ***/\n    /**************************************************************************************************************************************/\n\n    function callPrincipal(address loan_, uint256 principal_) external override whenNotPaused onlyPoolDelegate isLoan(loan_) {\n        ILoanLike(loan_).callPrincipal(principal_);\n    }\n\n    function removeCall(address loan_) external override whenNotPaused onlyPoolDelegate isLoan(loan_) {\n        ILoanLike(loan_).removeCall();\n    }\n\n    /**************************************************************************************************************************************/\n    /*** Loan Impairment Functions                                                                                                      ***/\n    /**************************************************************************************************************************************/\n\n    function impairLoan(address loan_) external override whenNotPaused isLoan(loan_) {\n        bool isGovernor_ = msg.sender == _governor();\n\n        require(isGovernor_ || msg.sender == _poolDelegate(), \"LM:IL:NO_AUTH\");\n\n        ILoanLike(loan_).impair();\n\n        if (isGovernor_) {\n            _accountForLoanImpairmentAsGovernor(loan_);\n        } else {\n            _accountForLoanImpairment(loan_);\n        }\n    }\n\n    function removeLoanImpairment(address loan_) external override whenNotPaused isLoan(loan_) {\n        ( , bool impairedByGovernor_ ) = _accountForLoanImpairmentRemoval(loan_, ILoanLike(loan_).principal());\n\n        require(msg.sender == _governor() || (!impairedByGovernor_ && msg.sender == _poolDelegate()), \"LM:RLI:NO_AUTH\");\n\n        ILoanLike(loan_).removeImpairment();\n    }\n\n    /**************************************************************************************************************************************/\n    /*** Loan Default Functions                                                                                                         ***/\n    /**************************************************************************************************************************************/\n\n    function triggerDefault(address loan_, address liquidatorFactory_)\n        external override returns (bool liquidationComplete_, uint256 remainingLosses_, uint256 unrecoveredPlatformFees_)\n    {\n        liquidatorFactory_;  // Silence compiler warning.\n\n        ( remainingLosses_, unrecoveredPlatformFees_ ) = triggerDefault(loan_);\n\n        liquidationComplete_ = true;\n    }\n\n    function triggerDefault(address loan_)\n        public override whenNotPaused isLoan(loan_) returns (uint256 remainingLosses_, uint256 unrecoveredPlatformFees_)\n    {\n        require(msg.sender == poolManager, \"LM:TD:NOT_PM\");\n\n        // Note: Always impair before proceeding, this ensures a consistent approach to reduce the `accountedInterest` for the Loan.\n        //       If the Loan is already impaired, this will be a no-op and just return the `impairedDate`.\n        //       If the Loan is not impaired, the accountedInterest will be updated to block.timestamp,\n        //       which will include the total interest due for the Loan.\n        uint40 impairedDate_ = _accountForLoanImpairment(loan_);\n\n        ( , uint256 interest_, uint256 lateInterest_, , uint256 platformServiceFee_ ) = ILoanLike(loan_).getPaymentBreakdown(impairedDate_);\n\n        uint256 principal_ = ILoanLike(loan_).principal();\n\n        interest_ += lateInterest_;\n\n        // Pull any `fundsAsset` in loan into LM.\n        uint256 recoveredFunds_ = ILoanLike(loan_).repossess(address(this));\n\n        // Distribute the recovered funds (to treasury, pool, and borrower) and determine the losses, if any, that must still be realized.\n        (\n            remainingLosses_,\n            unrecoveredPlatformFees_\n        ) = _distributeLiquidationFunds(loan_, principal_, interest_, platformServiceFee_, recoveredFunds_);\n\n        // Remove the payment and cache the struct.\n        Payment memory payment_ = _removePayment(loan_);\n\n        // NOTE: This is the amount of interest accounted for, before the loan's impairment,\n        //       that is still in the aggregate `accountedInterest` and offset in `unrealizedLosses`\n        //       The original `impairedDate` is always used over the current `impairedDate` on the Loan,\n        //       this ensures the interest calculated for `unrealizedLosses` matches the original impairment calculation.\n        uint256 accountedImpairedInterest_ = _getIssuance(payment_.issuanceRate, impairedDate_ - payment_.startDate);\n\n        // The payment's interest until the `impairedDate` must be deducted from `accountedInterest`, thus realizing the interest loss.\n        // The unrealized losses incurred due to the impairment must be deducted from the global `unrealizedLosses`.\n        // The loan's principal must be deducted from `principalOut`, thus realizing the principal loss.\n        _updateInterestAccounting(-_int256(accountedImpairedInterest_), 0);\n        _updateUnrealizedLosses(-_int256(principal_ + accountedImpairedInterest_));\n        _updatePrincipalOut(-_int256(principal_));\n\n        delete impairmentFor[loan_];\n    }\n\n    /**************************************************************************************************************************************/\n    /*** Internal Functions                                                                                                             ***/\n    /**************************************************************************************************************************************/\n\n    function _addPayment(address loan_) internal returns (Payment memory payment_) {\n        uint256 platformManagementFeeRate_ = IGlobalsLike(_globals()).platformManagementFeeRate(poolManager);\n        uint256 delegateManagementFeeRate_ = IPoolManagerLike(poolManager).delegateManagementFeeRate();\n        uint256 managementFeeRate_         = platformManagementFeeRate_ + delegateManagementFeeRate_;\n\n        // NOTE: If combined fee is greater than 100%, then cap delegate fee and clamp management fee.\n        if (managementFeeRate_ > HUNDRED_PERCENT) {\n            delegateManagementFeeRate_ = HUNDRED_PERCENT - platformManagementFeeRate_;\n            managementFeeRate_         = HUNDRED_PERCENT;\n        }\n\n        uint256 paymentDueDate_ = ILoanLike(loan_).paymentDueDate();\n        uint256 dueInterest_    = _getNetInterest(loan_, paymentDueDate_, managementFeeRate_);\n\n        // NOTE: Can assume `paymentDueDate_ > block.timestamp` and interest at `block.timestamp` is 0 because payments are only added when\n        //         - loans are funded, or\n        //         - payments are claimed, resulting in a new payment.\n        uint256 paymentIssuanceRate_ = (dueInterest_ * PRECISION) / (paymentDueDate_ - block.timestamp);\n\n        paymentFor[loan_] = payment_ = Payment({\n            platformManagementFeeRate: _uint24(platformManagementFeeRate_),\n            delegateManagementFeeRate: _uint24(delegateManagementFeeRate_),\n            startDate:                 _uint40(block.timestamp),\n            issuanceRate:              _uint168(paymentIssuanceRate_)\n        });\n\n        emit PaymentAdded(\n            loan_,\n            platformManagementFeeRate_,\n            delegateManagementFeeRate_,\n            paymentDueDate_,\n            paymentIssuanceRate_\n        );\n    }\n\n    function _accountForLoanImpairment(address loan_, bool isGovernor_) internal returns (uint40 impairedDate_) {\n        impairedDate_ = impairmentFor[loan_].impairedDate;\n\n        // NOTE: Impairing an already-impaired loan simply updates the `dateImpaired` of the loan, which can push the due date further,\n        //       however, the `impairedDate` in the struct should not be updated since it defines the moment when accounting for the loan's\n        //       payment was paused, and is needed to restore accounting for the eventual removal of the impairment, or the default.\n        if (impairedDate_ != 0) return impairedDate_;\n\n        Payment memory payment_ = paymentFor[loan_];\n\n        impairmentFor[loan_] = Impairment(impairedDate_ = _uint40(block.timestamp), isGovernor_);\n\n        // Account for all interest until now (including this payment's), then remove payment's `issuanceRate` from global `issuanceRate`.\n        _updateInterestAccounting(0, -_int256(payment_.issuanceRate));\n\n        uint256 principal_ = ILoanLike(loan_).principal();\n\n        // Add the payment's entire interest until now (negating above), and the loan's principal, to unrealized losses.\n        _updateUnrealizedLosses(_int256(principal_ + _getIssuance(payment_.issuanceRate, block.timestamp - payment_.startDate)));\n    }\n\n    function _accountForLoanImpairment(address loan_) internal returns (uint40 impairedDate_) {\n        impairedDate_ = _accountForLoanImpairment(loan_, false);\n    }\n\n    function _accountForLoanImpairmentAsGovernor(address loan_) internal returns (uint40 impairedDate_) {\n        impairedDate_ = _accountForLoanImpairment(loan_, true);\n    }\n\n    function _accountForLoanImpairmentRemoval(address loan_, uint256 originalPrincipal_) internal returns (uint40 impairedDate_, bool impairedByGovernor_) {\n        Impairment memory impairment_ = impairmentFor[loan_];\n\n        impairedDate_       = impairment_.impairedDate;\n        impairedByGovernor_ = impairment_.impairedByGovernor;\n\n        if (impairedDate_ == 0) return ( impairedDate_, impairedByGovernor_ );\n\n        delete impairmentFor[loan_];\n\n        Payment memory payment_ = paymentFor[loan_];\n\n        // Subtract the payment's entire interest until it's impairment date, and the loan's principal, from unrealized losses.\n        _updateUnrealizedLosses(-_int256(originalPrincipal_ + _getIssuance(payment_.issuanceRate, impairedDate_ - payment_.startDate)));\n\n        // Account for all interest until now, adjusting for payment's interest between its impairment date and now,\n        // then add payment's `issuanceRate` to the global `issuanceRate`.\n        // NOTE: Upon impairment, for payment's interest between its start date and its impairment date were accounted for.\n        _updateInterestAccounting(\n            _int256(_getIssuance(payment_.issuanceRate, block.timestamp - impairedDate_)),\n            _int256(payment_.issuanceRate)\n        );\n    }\n\n    function _removePayment(address loan_) internal returns (Payment memory payment_) {\n        payment_ = paymentFor[loan_];\n\n        delete paymentFor[loan_];\n\n        emit PaymentRemoved(loan_);\n    }\n\n    function _updateInterestAccounting(int256 accountedInterestAdjustment_, int256 issuanceRateAdjustment_) internal {\n        // NOTE: Order of operations is important as `accruedInterest()` depends on the pre-adjusted `issuanceRate` and `domainStart`.\n        accountedInterest = _uint112(_max(_int256(accountedInterest + accruedInterest()) + accountedInterestAdjustment_, 0));\n        domainStart       = _uint40(block.timestamp);\n        issuanceRate      = _uint256(_max(_int256(issuanceRate) + issuanceRateAdjustment_, 0));\n\n        emit AccountingStateUpdated(issuanceRate, accountedInterest);\n    }\n\n    function _updatePrincipalOut(int256 principalOutAdjustment_) internal {\n        emit PrincipalOutUpdated(principalOut = _uint128(_max(_int256(principalOut) + principalOutAdjustment_, 0)));\n    }\n\n    function _updateUnrealizedLosses(int256 lossesAdjustment_) internal {\n        emit UnrealizedLossesUpdated(unrealizedLosses = _uint128(_max(_int256(unrealizedLosses) + lossesAdjustment_, 0)));\n    }\n\n    /**************************************************************************************************************************************/\n    /*** Funds Distribution Functions                                                                                                   ***/\n    /**************************************************************************************************************************************/\n\n    function _distributeClaimedFunds(\n        address loan_,\n        int256  principal_,\n        uint256 interest_,\n        uint256 delegateServiceFee_,\n        uint256 platformServiceFee_\n    )\n        internal\n    {\n        Payment memory payment_ = paymentFor[loan_];\n\n        uint256 delegateManagementFee_ = _getRatedAmount(interest_, payment_.delegateManagementFeeRate);\n        uint256 platformManagementFee_ = _getRatedAmount(interest_, payment_.platformManagementFeeRate);\n\n        // If the coverage is not sufficient move the delegate service fee to the platform and remove the delegate management fee.\n        if (!IPoolManagerLike(poolManager).hasSufficientCover()) {\n            platformServiceFee_ += delegateServiceFee_;\n\n            delegateServiceFee_    = 0;\n            delegateManagementFee_ = 0;\n        }\n\n        uint256 netInterest_ = interest_ - (platformManagementFee_ + delegateManagementFee_);\n\n        principal_ = principal_ > int256(0) ? principal_ : int256(0);\n\n        emit ClaimedFundsDistributed(\n            loan_,\n            uint256(principal_),\n            interest_,\n            delegateManagementFee_,\n            delegateServiceFee_,\n            platformManagementFee_,\n            platformServiceFee_\n        );\n\n        address fundsAsset_ = fundsAsset;\n\n        require(_transfer(fundsAsset_, _pool(),         uint256(principal_) + netInterest_),           \"LM:DCF:TRANSFER_P\");\n        require(_transfer(fundsAsset_, _poolDelegate(), delegateServiceFee_ + delegateManagementFee_), \"LM:DCF:TRANSFER_PD\");\n        require(_transfer(fundsAsset_, _treasury(),     platformServiceFee_ + platformManagementFee_), \"LM:DCF:TRANSFER_MT\");\n    }\n\n    function _distributeLiquidationFunds(\n        address loan_,\n        uint256 principal_,\n        uint256 interest_,\n        uint256 platformServiceFee_,\n        uint256 recoveredFunds_\n    )\n        internal returns (uint256 remainingLosses_, uint256 unrecoveredPlatformFees_)\n    {\n        Payment memory payment_ = paymentFor[loan_];\n\n        uint256 platformManagementFee_ = _getRatedAmount(interest_, payment_.platformManagementFeeRate);\n        uint256 delegateManagementFee_ = _getRatedAmount(interest_, payment_.delegateManagementFeeRate);\n\n        uint256 netInterest_ = interest_ - (platformManagementFee_ + delegateManagementFee_);\n        uint256 platformFee_ = platformServiceFee_ + platformManagementFee_;\n\n        uint256 toTreasury_ = _min(recoveredFunds_, platformFee_);\n\n        unrecoveredPlatformFees_ = platformFee_ - toTreasury_;\n\n        recoveredFunds_ -= toTreasury_;\n\n        uint256 toPool_ = _min(recoveredFunds_, principal_ + netInterest_);\n\n        remainingLosses_ = principal_ + netInterest_ - toPool_;\n\n        recoveredFunds_ -= toPool_;\n\n        emit ExpectedClaim(loan_, principal_, netInterest_, platformManagementFee_, platformServiceFee_);\n\n        emit LiquidatedFundsDistributed(loan_, recoveredFunds_, toPool_, toTreasury_);\n\n        // NOTE: Cannot cache `fundsAsset` due to \"Stack too deep\" issue.\n        require(_transfer(fundsAsset, ILoanLike(loan_).borrower(), recoveredFunds_), \"LM:DLF:TRANSFER_B\");\n        require(_transfer(fundsAsset, _pool(),                     toPool_),         \"LM:DLF:TRANSFER_P\");\n        require(_transfer(fundsAsset, _treasury(),                 toTreasury_),     \"LM:DLF:TRANSFER_MT\");\n    }\n\n    function _prepareFundsForLoan(address loan_, uint256 amount_) internal {\n        // Request funds from pool manager.\n        IPoolManagerLike(poolManager).requestFunds(address(this), amount_);\n\n        // Approve the loan to use these funds.\n        require(ERC20Helper.approve(fundsAsset, loan_, amount_), \"LM:PFFL:APPROVE_FAILED\");\n    }\n\n    function _transfer(address asset_, address to_, uint256 amount_) internal returns (bool success_) {\n        success_ = (to_ != address(0)) && ((amount_ == 0) || ERC20Helper.transfer(asset_, to_, amount_));\n    }\n\n    /**************************************************************************************************************************************/\n    /*** Internal Loan Accounting Helper Functions                                                                                      ***/\n    /**************************************************************************************************************************************/\n\n    function _getIssuance(uint256 issuanceRate_, uint256 interval_) internal pure returns (uint256 issuance_) {\n        issuance_ = (issuanceRate_ * interval_) / PRECISION;\n    }\n\n    function _getNetInterest(address loan_, uint256 timestamp_, uint256 managementFeeRate_) internal view returns (uint256 netInterest_) {\n        ( , uint256 interest_, , , ) = ILoanLike(loan_).getPaymentBreakdown(timestamp_);\n\n        netInterest_ = _getNetInterest(interest_, managementFeeRate_);\n    }\n\n    function _getNetInterest(uint256 interest_, uint256 feeRate_) internal pure returns (uint256 netInterest_) {\n        // NOTE: This ensures that `netInterest_ == interest_ - fee_`, since absolutes are subtracted, not rates.\n        netInterest_ = interest_ - _getRatedAmount(interest_, feeRate_);\n    }\n\n    function _getRatedAmount(uint256 amount_, uint256 rate_) internal pure returns (uint256 ratedAmount_) {\n        ratedAmount_ = (amount_ * rate_) / HUNDRED_PERCENT;\n    }\n\n    /**************************************************************************************************************************************/\n    /*** Loan Manager View Functions                                                                                                    ***/\n    /**************************************************************************************************************************************/\n\n    function accruedInterest() public view override returns (uint256 accruedInterest_) {\n        uint256 issuanceRate_ = issuanceRate;\n\n        accruedInterest_ = issuanceRate_ == 0 ? 0 : _getIssuance(issuanceRate_, block.timestamp - domainStart);\n    }\n\n    function assetsUnderManagement() public view virtual override returns (uint256 assetsUnderManagement_) {\n        assetsUnderManagement_ = principalOut + accountedInterest + accruedInterest();\n    }\n\n    /**************************************************************************************************************************************/\n    /*** Protocol Address View Functions                                                                                                ***/\n    /**************************************************************************************************************************************/\n\n    function factory() external view override returns (address factory_) {\n        factory_ = _factory();\n    }\n\n    function implementation() external view override returns (address implementation_) {\n        implementation_ = _implementation();\n    }\n\n    /**************************************************************************************************************************************/\n    /*** Internal View Functions                                                                                                        ***/\n    /**************************************************************************************************************************************/\n\n    function _globals() internal view returns (address globals_) {\n        globals_ = IMapleProxyFactory(_factory()).mapleGlobals();\n    }\n\n    function _governor() internal view returns (address governor_) {\n        governor_ = IGlobalsLike(_globals()).governor();\n    }\n\n    function _pool() internal view returns (address pool_) {\n        pool_ = IPoolManagerLike(poolManager).pool();\n    }\n\n    function _poolDelegate() internal view returns (address poolDelegate_) {\n        poolDelegate_ = IPoolManagerLike(poolManager).poolDelegate();\n    }\n\n    function _revertIfNotLoan(address loan_) internal view {\n        require(paymentFor[loan_].startDate != 0, \"LM:NOT_LOAN\");\n    }\n\n    function _revertIfNotPoolDelegate() internal view {\n        require(msg.sender == _poolDelegate(), \"LM:NOT_PD\");\n    }\n\n    function _revertIfPaused() internal view {\n        require(!IGlobalsLike(_globals()).isFunctionPaused(msg.sig), \"LM:PAUSED\");\n    }\n\n    function _treasury() internal view returns (address treasury_) {\n        treasury_ = IGlobalsLike(_globals()).mapleTreasury();\n    }\n\n    /**************************************************************************************************************************************/\n    /*** Internal Pure Utility Functions                                                                                                ***/\n    /**************************************************************************************************************************************/\n\n    function _int256(uint256 input_) internal pure returns (int256 output_) {\n        require(input_ <= uint256(type(int256).max), \"LM:UINT256_OOB_FOR_INT256\");\n        output_ = int256(input_);\n    }\n\n    function _max(int256 a_, int256 b_) internal pure returns (int256 maximum_) {\n        maximum_ = a_ > b_ ? a_ : b_;\n    }\n\n    function _min(uint256 a_, uint256 b_) internal pure returns (uint256 minimum_) {\n        minimum_ = a_ < b_ ? a_ : b_;\n    }\n\n    function _uint24(uint256 input_) internal pure returns (uint24 output_) {\n        require(input_ <= type(uint24).max, \"LM:UINT256_OOB_FOR_UINT24\");\n        output_ = uint24(input_);\n    }\n\n    function _uint40(uint256 input_) internal pure returns (uint40 output_) {\n        require(input_ <= type(uint40).max, \"LM:UINT256_OOB_FOR_UINT40\");\n        output_ = uint40(input_);\n    }\n\n    function _uint112(int256 input_) internal pure returns (uint112 output_) {\n        require(input_ <= int256(uint256(type(uint112).max)) && input_ >= 0, \"LM:INT256_OOB_FOR_UINT112\");\n        output_ = uint112(uint256(input_));\n    }\n\n    function _uint128(int256 input_) internal pure returns (uint128 output_) {\n        require(input_ <= int256(uint256(type(uint128).max)) && input_ >= 0, \"LM:INT256_OOB_FOR_UINT128\");\n        output_ = uint128(uint256(input_));\n    }\n\n    function _uint168(uint256 input_) internal pure returns (uint168 output_) {\n        require(input_ <= type(uint168).max, \"LM:UINT256_OOB_FOR_UINT168\");\n        output_ = uint168(input_);\n    }\n\n    function _uint168(int256 input_) internal pure returns (uint168 output_) {\n        require(input_ <= int256(uint256(type(uint168).max)) && input_ >= 0, \"LM:INT256_OOB_FOR_UINT168\");\n        output_ = uint168(uint256(input_));\n    }\n\n    function _uint256(int256 input_) internal pure returns (uint256 output_) {\n        require(input_ >= 0, \"LM:INT256_OOB_FOR_UINT256\");\n        output_ = uint256(input_);\n    }\n\n}\n","deployed_bytecode":"0x608060405234801561001057600080fd5b50600436106101c45760003560e01c80635c60da1b116100f9578063c45a015511610097578063dac83f8d11610071578063dac83f8d146104b1578063dc4c90d3146104c4578063f6de0bd2146104d7578063ffb43a5f146104df57600080fd5b8063c45a015514610483578063d784d4261461048b578063d97aea121461049e57600080fd5b80639e5d9942116100d35780639e5d994214610437578063aaf5eb681461044a578063ac6416551461045d578063c3fbb6fd1461047057600080fd5b80635c60da1b146103f357806367e2ba23146103fb5780636ed93dd01461042d57600080fd5b806339ba9f861161016657806340504ba01161014057806340504ba0146103395780634189182e1461036957806345fe329f146103b9578063546ef145146103c157600080fd5b806339ba9f86146102e45780633b99bcee1461030f5780633c9ae2ba1461032257600080fd5b80631cd8d07b116101a25780631cd8d07b1461029857806320d61476146102ab57806323024408146102be57806337fdb36f146102d157600080fd5b80630827b071146101c957806309be15e0146101de578063165b0a9c14610271575b600080fd5b6101dc6101d73660046135bf565b610507565b005b6102306101ec3660046133ee565b60076020526000908152604090205462ffffff808216916301000000810490911690600160301b810464ffffffffff1690600160581b90046001600160a81b031684565b6040805162ffffff958616815294909316602085015264ffffffffff909116918301919091526001600160a81b031660608201526080015b60405180910390f35b6001546102829064ffffffffff1681565b60405164ffffffffff9091168152602001610268565b6101dc6102a63660046133ee565b6108df565b6101dc6102b93660046133ee565b610a6e565b6101dc6102cc3660046133ee565b610b97565b6101dc6102df366004613461565b611101565b6004546102f7906001600160a01b031681565b6040516001600160a01b039091168152602001610268565b6101dc61031d36600461360c565b6111a8565b61032b60035481565b604051908152602001610268565b61034c610347366004613428565b61147e565b604080519315158452602084019290925290820152606001610268565b61039c6103773660046133ee565b60066020526000908152604090205464ffffffffff811690600160281b900460ff1682565b6040805164ffffffffff9093168352901515602083015201610268565b61032b61149a565b6001546103db90600160281b90046001600160701b031681565b6040516001600160701b039091168152602001610268565b6102f76114ce565b60025461041590600160801b90046001600160801b031681565b6040516001600160801b039091168152602001610268565b61032b620f424081565b6101dc6104453660046133ee565b6114dd565b61032b6b033b2e3c9fd0803ce800000081565b600254610415906001600160801b031681565b6101dc61047e366004613503565b611569565b6102f7611611565b6101dc6104993660046133ee565b61161b565b6101dc6104ac366004613558565b6116b0565b6101dc6104bf366004613461565b61170b565b6005546102f7906001600160a01b031681565b61032b611757565b6104f26104ed3660046133ee565b61179d565b60408051928352602083019190915201610268565b61050f611a6c565b3361051981611b34565b60005460011461055c5760405162461bcd60e51b815260206004820152600960248201526813134e9313d0d2d15160ba1b60448201526064015b60405180910390fd5b60026000819055506000336001600160a01b031663ba5d30786040518163ffffffff1660e01b815260040160206040518083038186803b15801561059f57600080fd5b505afa1580156105b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105d791906135a6565b905060008364ffffffffff161180156105f05750600081115b80610615575064ffffffffff8316158015610609575080155b80156106155750600087135b6106505760405162461bcd60e51b815260206004820152600c60248201526b13134e90ce9253959053125160a21b6044820152606401610553565b60008761065c83611b98565b61066691906138d3565b90506106723382611bf5565b50506106813389898989611d2f565b87156106985761069861069389613a14565b612009565b60006106a33361209d565b905060006106dc6106d783606001516001600160a81b0316846040015164ffffffffff16426106d291906139d7565b61215a565b611b98565b6106e590613a14565b905064ffffffffff86166107245761071b8161070d84606001516001600160a81b0316611b98565b61071690613a14565b612184565b505050506108d2565b60008a1215610885576000336001600160a01b0316637df1f1b96040518163ffffffff1660e01b815260040160206040518083038186803b15801561076857600080fd5b505afa15801561077c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107a0919061340b565b90506107aa61226f565b60405163eaf6e48360e01b81526001600160a01b038381166004830152919091169063eaf6e4839060240160206040518083038186803b1580156107ed57600080fd5b505afa158015610801573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108259190613584565b6108695760405162461bcd60e51b815260206004820152601560248201527426269d219d24a72b20a624a22fa127a92927aba2a960591b6044820152606401610553565b6108833361087e6108798e613a14565b6122e9565b61233b565b505b6000610890336123fc565b90506108cc826108ac85606001516001600160a81b0316611b98565b6108c284606001516001600160a81b0316611b98565b6107169190613998565b50505050505b5050600160005550505050565b6108e7611a6c565b806108f181611b34565b600061096d83846001600160a01b031663ba5d30786040518163ffffffff1660e01b815260040160206040518083038186803b15801561093057600080fd5b505afa158015610944573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061096891906135a6565b611bf5565b915050610978612753565b6001600160a01b0316336001600160a01b031614806109b85750801580156109b857506109a3612795565b6001600160a01b0316336001600160a01b0316145b6109f55760405162461bcd60e51b815260206004820152600e60248201526d0989a74a49892749c9ebe82aaa8960931b6044820152606401610553565b826001600160a01b03166365cd0a4c6040518163ffffffff1660e01b81526004016040805180830381600087803b158015610a2f57600080fd5b505af1158015610a43573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a6791906136df565b5050505050565b610a76611a6c565b80610a8081611b34565b6000610a8a612753565b6001600160a01b0316336001600160a01b03161490508080610ac45750610aaf612795565b6001600160a01b0316336001600160a01b0316145b610b005760405162461bcd60e51b815260206004820152600d60248201526c0989a749298749c9ebe82aaa89609b1b6044820152606401610553565b826001600160a01b0316630548d2676040518163ffffffff1660e01b81526004016040805180830381600087803b158015610b3a57600080fd5b505af1158015610b4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b7291906136df565b50508015610b8957610b83836127da565b50505050565b610b83836127ed565b505050565b610b9f611a6c565b600054600114610bdd5760405162461bcd60e51b815260206004820152600960248201526813134e9313d0d2d15160ba1b6044820152606401610553565b6002600055610bea6127fa565b6000816001600160a01b031663c45a01556040518163ffffffff1660e01b815260040160206040518083038186803b158015610c2557600080fd5b505afa158015610c39573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c5d919061340b565b90506000610c6961226f565b60405163305c9e0560e01b81526e4f545f4c4f414e5f464143544f525960881b60048201526001600160a01b0384811660248301529192509082169063305c9e059060440160206040518083038186803b158015610cc657600080fd5b505afa158015610cda573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cfe9190613584565b610d4a5760405162461bcd60e51b815260206004820152601960248201527f4c4d3a463a494e56414c49445f4c4f414e5f464143544f5259000000000000006044820152606401610553565b60405163140ce5e160e11b81526001600160a01b038481166004830152831690632819cbc29060240160206040518083038186803b158015610d8b57600080fd5b505afa158015610d9f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dc39190613584565b610e0f5760405162461bcd60e51b815260206004820152601a60248201527f4c4d3a463a494e56414c49445f4c4f414e5f494e5354414e43450000000000006044820152606401610553565b806001600160a01b031663eaf6e483846001600160a01b0316637df1f1b96040518163ffffffff1660e01b815260040160206040518083038186803b158015610e5757600080fd5b505afa158015610e6b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e8f919061340b565b6040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260240160206040518083038186803b158015610ece57600080fd5b505afa158015610ee2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f069190613584565b610f4a5760405162461bcd60e51b815260206004820152601560248201527426269d231d24a72b20a624a22fa127a92927aba2a960591b6044820152606401610553565b6000836001600160a01b031663ba5d30786040518163ffffffff1660e01b815260040160206040518083038186803b158015610f8557600080fd5b505afa158015610f99573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fbd91906135a6565b9050806110035760405162461bcd60e51b81526020600482015260146024820152734c4d3a463a4c4f414e5f4e4f545f41435449564560601b6044820152606401610553565b61100d848261233b565b6000846001600160a01b031663b60d42886040518163ffffffff1660e01b8152600401606060405180830381600087803b15801561104a57600080fd5b505af115801561105e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611082919061367f565b505090508181146110cd5760405162461bcd60e51b81526020600482015260156024820152740989a748c748caa9c88929c8ebe9a92a69a82a8869605b1b6044820152606401610553565b6110d961069382611b98565b60006110e4866123fc565b90506108d2600061071683606001516001600160a81b0316611b98565b611109611a6c565b6111116127fa565b8461111b81611b34565b604051632b2d48ad60e21b81526001600160a01b0387169063acb522b49061114d908890889088908890600401613804565b602060405180830381600087803b15801561116757600080fd5b505af115801561117b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061119f91906135a6565b50505050505050565b6111b0611a6c565b60006111ba61226f565b90506111c4612795565b6001600160a01b0316336001600160a01b031614156113145760405163fd4c5b3760e01b81526001600160a01b0382169063fd4c5b379061121090339030906000903690600401613782565b60206040518083038186803b15801561122857600080fd5b505afa15801561123c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112609190613584565b6112ac5760405162461bcd60e51b815260206004820152601760248201527f4c4d3a553a494e56414c49445f53434845445f43414c4c0000000000000000006044820152606401610553565b604051635ad5b6f760e11b81526001600160a01b0382169063b5ab6dee906112dd90339060009036906004016137cc565b600060405180830381600087803b1580156112f757600080fd5b505af115801561130b573d6000803e3d6000fd5b505050506113d4565b806001600160a01b031663be7c13f76040518163ffffffff1660e01b815260040160206040518083038186803b15801561134d57600080fd5b505afa158015611361573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611385919061340b565b6001600160a01b0316336001600160a01b0316146113d45760405162461bcd60e51b815260206004820152600c60248201526b0989a74aa749c9ebe82aaa8960a31b6044820152606401610553565b7faaaa7ee6b0c2f4ee1fa7312c7d5b3623a434da5a1a9ce3cb6e629caa23454ab6848484604051611407939291906138b9565b60405180910390a161141761284e565b6001600160a01b031663fe69f7088585856040518463ffffffff1660e01b8152600401611446939291906138b9565b600060405180830381600087803b15801561146057600080fd5b505af1158015611474573d6000803e3d6000fd5b5050505050505050565b600080600061148c8561179d565b600197919650945092505050565b60035460009080156114c5576001546114c09082906106d29064ffffffffff16426139d7565b6114c8565b60005b91505090565b60006114d861287d565b905090565b6114e5611a6c565b6114ed6127fa565b806114f781611b34565b816001600160a01b031663200e53456040518163ffffffff1660e01b81526004016040805180830381600087803b15801561153157600080fd5b505af1158015611545573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b8391906136df565b611571611a6c565b61157961284e565b6001600160a01b0316336001600160a01b0316146115cc5760405162461bcd60e51b815260206004820152601060248201526f4c4d3a4d3a4e4f545f464143544f525960801b6044820152606401610553565b6115d78383836128a7565b610b925760405162461bcd60e51b815260206004820152600b60248201526a13134e934e91905253115160aa1b6044820152606401610553565b60006114d861284e565b611623611a6c565b61162b61284e565b6001600160a01b0316336001600160a01b03161461167f5760405162461bcd60e51b81526020600482015260116024820152704c4d3a53493a4e4f545f464143544f525960781b6044820152606401610553565b6001600160a01b03167f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc55565b5050565b6116b8611a6c565b6116c06127fa565b816116ca81611b34565b604051630c7341dd60e31b8152600481018390526001600160a01b0384169063639a0ee8906024016040805180830381600087803b158015610a2f57600080fd5b611713611a6c565b61171b6127fa565b8461172581611b34565b6040516387accaf160e01b81526001600160a01b038716906387accaf19061114d908890889088908890600401613804565b600061176161149a565b60015460025461178a91600160281b90046001600160701b0316906001600160801b0316613914565b6001600160801b03166114d8919061393f565b6000806117a8611a6c565b826117b281611b34565b6005546001600160a01b031633146117fb5760405162461bcd60e51b815260206004820152600c60248201526b4c4d3a54443a4e4f545f504d60a01b6044820152606401610553565b6000611806856127ed565b604051630938afdd60e41b815264ffffffffff82166004820152909150600090819081906001600160a01b0389169063938afdd09060240160a06040518083038186803b15801561185657600080fd5b505afa15801561186a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061188e919061363f565b94505093509350506000886001600160a01b031663ba5d30786040518163ffffffff1660e01b815260040160206040518083038186803b1580156118d157600080fd5b505afa1580156118e5573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061190991906135a6565b9050611915838561393f565b6040516347350e9f60e01b81523060048201529094506000906001600160a01b038b16906347350e9f90602401602060405180830381600087803b15801561195c57600080fd5b505af1158015611970573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061199491906135a6565b90506119a38a83878685612920565b909950975060006119b38b61209d565b905060006119e482606001516001600160a81b031683604001518a6119d891906139ee565b64ffffffffff1661215a565b9050611a026119f282611b98565b6119fb90613a14565b6000612184565b611a20611a126106d7838761393f565b611a1b90613a14565b612c79565b611a35611a2c85611b98565b61069390613a14565b5050506001600160a01b039098166000908152600660205260409020805465ffffffffffff19169055509496939550929350505050565b611a7461226f565b604051634c532de160e01b81526001600160e01b03196000351660048201526001600160a01b039190911690634c532de19060240160206040518083038186803b158015611ac157600080fd5b505afa158015611ad5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611af99190613584565b15611b325760405162461bcd60e51b815260206004820152600960248201526813134e94105554d15160ba1b6044820152606401610553565b565b6001600160a01b038116600090815260076020526040902054600160301b900464ffffffffff16611b955760405162461bcd60e51b815260206004820152600b60248201526a26269d2727aa2fa627a0a760a91b6044820152606401610553565b50565b60006001600160ff1b03821115611bf15760405162461bcd60e51b815260206004820152601960248201527f4c4d3a55494e543235365f4f4f425f464f525f494e54323536000000000000006044820152606401610553565b5090565b6001600160a01b03821660009081526006602090815260409182902082518084019093525464ffffffffff8116808452600160281b90910460ff1615159183018290529182611c445750611d28565b6001600160a01b0385166000908152600660209081526040808320805465ffffffffffff1916905560078252918290208251608081018452905462ffffff808216835263010000008204169282019290925264ffffffffff600160301b830416928101839052600160581b9091046001600160a81b0316606082018190529091611ce591611a1291611cdb91906119d890896139ee565b6106d7908861393f565b611d25611d0f6106d783606001516001600160a81b03168764ffffffffff16426106d291906139d7565b61071683606001516001600160a81b0316611b98565b50505b9250929050565b6001600160a01b03851660009081526007602090815260408083208151608081018352905462ffffff80821683526301000000820416938201849052600160301b810464ffffffffff1692820192909252600160581b9091046001600160a81b031660608201529190611da3908690612cf4565b90506000611dba86846000015162ffffff16612cf4565b9050600560009054906101000a90046001600160a01b03166001600160a01b031663caf901dd6040518163ffffffff1660e01b815260040160206040518083038186803b158015611e0a57600080fd5b505afa158015611e1e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e429190613584565b611e5b57611e50858561393f565b935060009450600091505b6000611e67838361393f565b611e7190886139d7565b905060008813611e82576000611e84565b875b60408051828152602081018a9052908101859052606081018890526080810184905260a081018790529098506001600160a01b038a16907f5a3aaae9941b918d74569012f48c308c4044705e7ece73e7834f0f7ffd938b859060c00160405180910390a26004546001600160a01b0316611f0f81611f00612d04565b611f0a858d61393f565b612d49565b611f4f5760405162461bcd60e51b815260206004820152601160248201527004c4d3a4443463a5452414e534645525f5607c1b6044820152606401610553565b611f6581611f5b612795565b611f0a878b61393f565b611fa65760405162461bcd60e51b815260206004820152601260248201527113134e9110d18e9514905394d1915497d41160721b6044820152606401610553565b611fbc81611fb2612d79565b611f0a868a61393f565b611ffd5760405162461bcd60e51b815260206004820152601260248201527113134e9110d18e9514905394d1915497d35560721b6044820152606401610553565b50505050505050505050565b6002547f8e82b75967acb8b37df8c3edc1ef9712a6c32f8a42dbbd441f49be7cab41aee2906120609061205b90849061204a906001600160801b0316611b98565b61205491906138d3565b6000612dbb565b612dd1565b600280546fffffffffffffffffffffffffffffffff19166001600160801b039290921691821790556040519081526020015b60405180910390a150565b604080516080810182526000808252602082018190529181018290526060810191909152506001600160a01b03811660008181526007602081815260408084208151608081018352815462ffffff8082168352630100000082041682860152600160301b810464ffffffffff1682850152600160581b90046001600160a81b031660608201528686529390925290839055519092917f98e0ae8c0ac21cdd4b0a6a2c72737be54e995c54f6ef61b3cd19ec71ed22533b91a2919050565b60006b033b2e3c9fd0803ce80000006121738385613979565b61217d9190613957565b9392505050565b6121b86121b38361204a61219661149a565b6001546106d79190600160281b90046001600160701b031661393f565b612e37565b600160056101000a8154816001600160701b0302191690836001600160701b031602179055506121e742612e9d565b600160006101000a81548164ffffffffff021916908364ffffffffff16021790555061221b6108798261204a600354611b98565b600381905560015460408051928352600160281b9091046001600160701b031660208301527f1e2d80f327730eb6faf6e0ed856016385059a20185b280cb5293a05883ee6f81910160405180910390a15050565b600061227961284e565b6001600160a01b0316633a60339a6040518163ffffffff1660e01b815260040160206040518083038186803b1580156122b157600080fd5b505afa1580156122c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114d8919061340b565b600080821215611bf15760405162461bcd60e51b815260206004820152601960248201527f4c4d3a494e543235365f4f4f425f464f525f55494e54323536000000000000006044820152606401610553565b6005546040516324a3335b60e11b8152306004820152602481018390526001600160a01b039091169063494666b690604401600060405180830381600087803b15801561238757600080fd5b505af115801561239b573d6000803e3d6000fd5b50506004546123b792506001600160a01b031690508383612ef4565b6116ac5760405162461bcd60e51b815260206004820152601660248201527513134e941191930e9054141493d59157d1905253115160521b6044820152606401610553565b60408051608081018252600080825260208201819052918101829052606081018290529061242861226f565b600554604051631b14131d60e11b81526001600160a01b039182166004820152911690633628263a9060240160206040518083038186803b15801561246c57600080fd5b505afa158015612480573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124a491906135a6565b90506000600560009054906101000a90046001600160a01b03166001600160a01b0316635dd284496040518163ffffffff1660e01b815260040160206040518083038186803b1580156124f657600080fd5b505afa15801561250a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061252e91906135a6565b9050600061253c828461393f565b9050620f424081111561255f5761255683620f42406139d7565b9150620f424090505b6000856001600160a01b031663d9ef04596040518163ffffffff1660e01b815260040160206040518083038186803b15801561259a57600080fd5b505afa1580156125ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125d291906136c2565b64ffffffffff16905060006125e8878385612fa3565b905060006125f642846139d7565b61260c6b033b2e3c9fd0803ce800000084613979565b6126169190613957565b9050604051806080016040528061262c88613039565b62ffffff16815260200161263f87613039565b62ffffff16815260200161265242612e9d565b64ffffffffff1681526020016126678361308e565b6001600160a81b039081169091526001600160a01b038a166000818152600760209081526040918290208551815487840151888601516060808b0151909916600160581b026affffffffffffffffffffff64ffffffffff909216600160301b029190911665ffffffffffff62ffffff93841663010000000265ffffffffffff19909516939095169290921792909217929092169190911717905581518b81529081018a90529081018790529182018490529198507f948106bee3c901826daa4428037840a48300999c9a8911510b1beb56f2dc02769060800160405180910390a2505050505050919050565b600061275d61226f565b6001600160a01b0316630c340a246040518163ffffffff1660e01b815260040160206040518083038186803b1580156122b157600080fd5b60055460408051634046af2b60e01b815290516000926001600160a01b031691634046af2b916004808301926020929190829003018186803b1580156122b157600080fd5b60006127e78260016130e7565b92915050565b60006127e78260006130e7565b612802612795565b6001600160a01b0316336001600160a01b031614611b325760405162461bcd60e51b815260206004820152600960248201526813134e9393d517d41160ba1b6044820152606401610553565b60006128787f7a45a402e4cb6e08ebc196f20f66d5d30e67285a2a8aa80503fa409e727a4af15490565b919050565b60006128787f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6000833b806128ba57600091505061217d565b846001600160a01b031684846040516128d4929190613737565b600060405180830381855af49150503d806000811461290f576040519150601f19603f3d011682016040523d82523d6000602084013e612914565b606091505b50909695505050505050565b6001600160a01b03851660009081526007602090815260408083208151608081018352905462ffffff8082168084526301000000830490911694830194909452600160301b810464ffffffffff1692820192909252600160581b9091046001600160a81b031660608201528291829061299a908890612cf4565b905060006129b188846020015162ffffff16612cf4565b905060006129bf828461393f565b6129c9908a6139d7565b905060006129d7848a61393f565b905060006129e589836132b4565b90506129f181836139d7565b96506129fd818a6139d7565b98506000612a168a858f612a11919061393f565b6132b4565b905080612a23858f61393f565b612a2d91906139d7565b9850612a39818b6139d7565b604080518f815260208101879052908101889052606081018d9052909a506001600160a01b038f16907fd6c35cb94fcd8788f1d1e61f1f635e83b26421b57c5db5bb71b275e41588be249060800160405180910390a2604080518b8152602081018390529081018390526001600160a01b038f16907f6fe470ca125c8e736c97af4412c288b2a0417f3f146625f3ff2280449b1e7a8b9060600160405180910390a2612b6b600460009054906101000a90046001600160a01b03168f6001600160a01b0316637df1f1b96040518163ffffffff1660e01b815260040160206040518083038186803b158015612b2d57600080fd5b505afa158015612b41573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b65919061340b565b8c612d49565b612bab5760405162461bcd60e51b815260206004820152601160248201527026269d2226231d2a2920a729a322a92fa160791b6044820152606401610553565b600454612bc9906001600160a01b0316612bc3612d04565b83612d49565b612c095760405162461bcd60e51b815260206004820152601160248201527004c4d3a444c463a5452414e534645525f5607c1b6044820152606401610553565b600454612c27906001600160a01b0316612c21612d79565b84612d49565b612c685760405162461bcd60e51b815260206004820152601260248201527113134e9113118e9514905394d1915497d35560721b6044820152606401610553565b505050505050509550959350505050565b7fa6fdea32383e711b89178e80732f32dd09a53fe2cfc2f613a7e5035de5e0bef6612cc861205b8361204a600260109054906101000a90046001600160801b03166001600160801b0316611b98565b600280546001600160801b03908116600160801b93909116928302179055604051908152602001612092565b6000620f42406121738385613979565b600554604080516316f0115b60e01b815290516000926001600160a01b0316916316f0115b916004808301926020929190829003018186803b1580156122b157600080fd5b60006001600160a01b03831615801590612d715750811580612d715750612d718484846132c3565b949350505050565b6000612d8361226f565b6001600160a01b031663a5a276056040518163ffffffff1660e01b815260040160206040518083038186803b1580156122b157600080fd5b6000818313612dca578161217d565b5090919050565b60006001600160801b038213801590612deb575060008212155b611bf15760405162461bcd60e51b815260206004820152601960248201527f4c4d3a494e543235365f4f4f425f464f525f55494e54313238000000000000006044820152606401610553565b60006001600160701b038213801590612e51575060008212155b611bf15760405162461bcd60e51b815260206004820152601960248201527f4c4d3a494e543235365f4f4f425f464f525f55494e54313132000000000000006044820152606401610553565b600064ffffffffff821115611bf15760405162461bcd60e51b815260206004820152601960248201527f4c4d3a55494e543235365f4f4f425f464f525f55494e543430000000000000006044820152606401610553565b6040516001600160a01b038316602482015260006044820181905290612f5a90859063095ea7b360e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526132f6565b612f665750600061217d565b81612f735750600161217d565b6040516001600160a01b038416602482015260448101839052612d7190859063095ea7b360e01b90606401612f23565b604051630938afdd60e41b81526004810183905260009081906001600160a01b0386169063938afdd09060240160a06040518083038186803b158015612fe857600080fd5b505afa158015612ffc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613020919061363f565b5050509150506130308184613396565b95945050505050565b600062ffffff821115611bf15760405162461bcd60e51b815260206004820152601960248201527f4c4d3a55494e543235365f4f4f425f464f525f55494e543234000000000000006044820152606401610553565b60006001600160a81b03821115611bf15760405162461bcd60e51b815260206004820152601a60248201527f4c4d3a55494e543235365f4f4f425f464f525f55494e543136380000000000006044820152606401610553565b6001600160a01b03821660009081526006602052604090205464ffffffffff168015613112576127e7565b6001600160a01b0383166000908152600760209081526040918290208251608081018452905462ffffff8082168352630100000082041692820192909252600160301b820464ffffffffff1681840152600160581b9091046001600160a81b031660608201528151808301909252908061318b42612e9d565b64ffffffffff80821683528615156020938401526001600160a01b038816600090815260068452604081208551815496909501511515600160281b0265ffffffffffff1990961694909216939093179390931790925560608301519193506131ff9161070d906001600160a81b0316611b98565b6000846001600160a01b031663ba5d30786040518163ffffffff1660e01b815260040160206040518083038186803b15801561323a57600080fd5b505afa15801561324e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061327291906135a6565b90506132ac611a1b6132a284606001516001600160a81b0316856040015164ffffffffff16426106d291906139d7565b6106d7908461393f565b505092915050565b6000818310612dca578161217d565b6040516001600160a01b038316602482015260448101829052600090612d7190859063a9059cbb60e01b90606401612f23565b60006001600160a01b0383163b61330f575060006127e7565b6060836001600160a01b0316836040516133299190613747565b6000604051808303816000865af19150503d8060008114613366576040519150601f19603f3d011682016040523d82523d6000602084013e61336b565b606091505b509092509050818015612d71575080511580612d71575080806020019051810190612d719190613584565b60006133a28383612cf4565b61217d90846139d7565b60008083601f8401126133be57600080fd5b50813567ffffffffffffffff8111156133d657600080fd5b602083019150836020828501011115611d2857600080fd5b60006020828403121561340057600080fd5b813561217d81613a47565b60006020828403121561341d57600080fd5b815161217d81613a47565b6000806040838503121561343b57600080fd5b823561344681613a47565b9150602083013561345681613a47565b809150509250929050565b60008060008060006080868803121561347957600080fd5b853561348481613a47565b9450602086013561349481613a47565b935060408601359250606086013567ffffffffffffffff808211156134b857600080fd5b818801915088601f8301126134cc57600080fd5b8135818111156134db57600080fd5b8960208260051b85010111156134f057600080fd5b9699959850939650602001949392505050565b60008060006040848603121561351857600080fd5b833561352381613a47565b9250602084013567ffffffffffffffff81111561353f57600080fd5b61354b868287016133ac565b9497909650939450505050565b6000806040838503121561356b57600080fd5b823561357681613a47565b946020939093013593505050565b60006020828403121561359657600080fd5b8151801515811461217d57600080fd5b6000602082840312156135b857600080fd5b5051919050565b600080600080600060a086880312156135d757600080fd5b8535945060208601359350604086013592506060860135915060808601356135fe81613a5c565b809150509295509295909350565b60008060006040848603121561362157600080fd5b83359250602084013567ffffffffffffffff81111561353f57600080fd5b600080600080600060a0868803121561365757600080fd5b5050835160208501516040860151606087015160809097015192989197509594509092509050565b60008060006060848603121561369457600080fd5b8351925060208401516136a681613a5c565b60408501519092506136b781613a5c565b809150509250925092565b6000602082840312156136d457600080fd5b815161217d81613a5c565b600080604083850312156136f257600080fd5b82516136fd81613a5c565b602084015190925061345681613a5c565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b8183823760009101908152919050565b6000825160005b81811015613768576020818601810151858301520161374e565b81811115613777576000828501525b509190910192915050565b6001600160a01b03858116825284166020820152694c4d3a5550475241444560b01b60408201526080606082018190526000906137c2908301848661370e565b9695505050505050565b6001600160a01b0384168152694c4d3a5550475241444560b01b6020820152606060408201819052600090613030908301848661370e565b6001600160a01b0385168152602080820185905260606040830181905282018390526000906080600585901b840181019190840186845b878110156138aa57868503607f190183528135368a9003601e1901811261386157600080fd5b8901803567ffffffffffffffff81111561387a57600080fd5b8036038b131561388957600080fd5b613896878288850161370e565b96505050918301919083019060010161383b565b50929998505050505050505050565b83815260406020820152600061303060408301848661370e565b600080821280156001600160ff1b03849003851316156138f5576138f5613a31565b600160ff1b839003841281161561390e5761390e613a31565b50500190565b60006001600160801b0380831681851680830382111561393657613936613a31565b01949350505050565b6000821982111561395257613952613a31565b500190565b60008261397457634e487b7160e01b600052601260045260246000fd5b500490565b600081600019048311821515161561399357613993613a31565b500290565b60008083128015600160ff1b8501841216156139b6576139b6613a31565b6001600160ff1b03840183138116156139d1576139d1613a31565b50500390565b6000828210156139e9576139e9613a31565b500390565b600064ffffffffff83811690831681811015613a0c57613a0c613a31565b039392505050565b6000600160ff1b821415613a2a57613a2a613a31565b5060000390565b634e487b7160e01b600052601160045260246000fd5b6001600160a01b0381168114611b9557600080fd5b64ffffffffff81168114611b9557600080fdfea2646970667358221220688db322fbb27c42a3319d07e951e68b121e403abc92ae93a9d52b35b023332964736f6c63430008070033","optimization_enabled":true,"verified_twin_address_hash":null,"is_verified":true,"compiler_settings":{"evmVersion":"london","libraries":{},"metadata":{"bytecodeHash":"ipfs"},"optimizer":{"enabled":true,"runs":200},"remappings":[":contract-test-utils/=modules/erc20/modules/contract-test-utils/contracts/",":ds-test/=modules/forge-std/lib/ds-test/src/",":erc20-helper/=modules/erc20-helper/src/",":erc20/=modules/erc20/",":forge-std/=modules/forge-std/src/",":maple-proxy-factory/=modules/maple-proxy-factory/",":proxy-factory/=modules/maple-proxy-factory/modules/proxy-factory/"]},"optimization_runs":200,"sourcify_repo_url":"https://repo.sourcify.dev/contracts/partial_match/1/0xbAD003DA1e107f537Ae2f687f5FE7a7aFFe9B241/","decoded_constructor_args":null,"compiler_version":"0.8.7+commit.e28d00a7","is_verified_via_verifier_alliance":null,"verified_at":"2024-02-10T02:51:34.302425Z","implementations":[],"proxy_type":null,"external_libraries":[],"creation_bytecode":"0x608060405234801561001057600080fd5b50613aa5806100206000396000f3fe608060405234801561001057600080fd5b50600436106101c45760003560e01c80635c60da1b116100f9578063c45a015511610097578063dac83f8d11610071578063dac83f8d146104b1578063dc4c90d3146104c4578063f6de0bd2146104d7578063ffb43a5f146104df57600080fd5b8063c45a015514610483578063d784d4261461048b578063d97aea121461049e57600080fd5b80639e5d9942116100d35780639e5d994214610437578063aaf5eb681461044a578063ac6416551461045d578063c3fbb6fd1461047057600080fd5b80635c60da1b146103f357806367e2ba23146103fb5780636ed93dd01461042d57600080fd5b806339ba9f861161016657806340504ba01161014057806340504ba0146103395780634189182e1461036957806345fe329f146103b9578063546ef145146103c157600080fd5b806339ba9f86146102e45780633b99bcee1461030f5780633c9ae2ba1461032257600080fd5b80631cd8d07b116101a25780631cd8d07b1461029857806320d61476146102ab57806323024408146102be57806337fdb36f146102d157600080fd5b80630827b071146101c957806309be15e0146101de578063165b0a9c14610271575b600080fd5b6101dc6101d73660046135bf565b610507565b005b6102306101ec3660046133ee565b60076020526000908152604090205462ffffff808216916301000000810490911690600160301b810464ffffffffff1690600160581b90046001600160a81b031684565b6040805162ffffff958616815294909316602085015264ffffffffff909116918301919091526001600160a81b031660608201526080015b60405180910390f35b6001546102829064ffffffffff1681565b60405164ffffffffff9091168152602001610268565b6101dc6102a63660046133ee565b6108df565b6101dc6102b93660046133ee565b610a6e565b6101dc6102cc3660046133ee565b610b97565b6101dc6102df366004613461565b611101565b6004546102f7906001600160a01b031681565b6040516001600160a01b039091168152602001610268565b6101dc61031d36600461360c565b6111a8565b61032b60035481565b604051908152602001610268565b61034c610347366004613428565b61147e565b604080519315158452602084019290925290820152606001610268565b61039c6103773660046133ee565b60066020526000908152604090205464ffffffffff811690600160281b900460ff1682565b6040805164ffffffffff9093168352901515602083015201610268565b61032b61149a565b6001546103db90600160281b90046001600160701b031681565b6040516001600160701b039091168152602001610268565b6102f76114ce565b60025461041590600160801b90046001600160801b031681565b6040516001600160801b039091168152602001610268565b61032b620f424081565b6101dc6104453660046133ee565b6114dd565b61032b6b033b2e3c9fd0803ce800000081565b600254610415906001600160801b031681565b6101dc61047e366004613503565b611569565b6102f7611611565b6101dc6104993660046133ee565b61161b565b6101dc6104ac366004613558565b6116b0565b6101dc6104bf366004613461565b61170b565b6005546102f7906001600160a01b031681565b61032b611757565b6104f26104ed3660046133ee565b61179d565b60408051928352602083019190915201610268565b61050f611a6c565b3361051981611b34565b60005460011461055c5760405162461bcd60e51b815260206004820152600960248201526813134e9313d0d2d15160ba1b60448201526064015b60405180910390fd5b60026000819055506000336001600160a01b031663ba5d30786040518163ffffffff1660e01b815260040160206040518083038186803b15801561059f57600080fd5b505afa1580156105b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105d791906135a6565b905060008364ffffffffff161180156105f05750600081115b80610615575064ffffffffff8316158015610609575080155b80156106155750600087135b6106505760405162461bcd60e51b815260206004820152600c60248201526b13134e90ce9253959053125160a21b6044820152606401610553565b60008761065c83611b98565b61066691906138d3565b90506106723382611bf5565b50506106813389898989611d2f565b87156106985761069861069389613a14565b612009565b60006106a33361209d565b905060006106dc6106d783606001516001600160a81b0316846040015164ffffffffff16426106d291906139d7565b61215a565b611b98565b6106e590613a14565b905064ffffffffff86166107245761071b8161070d84606001516001600160a81b0316611b98565b61071690613a14565b612184565b505050506108d2565b60008a1215610885576000336001600160a01b0316637df1f1b96040518163ffffffff1660e01b815260040160206040518083038186803b15801561076857600080fd5b505afa15801561077c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107a0919061340b565b90506107aa61226f565b60405163eaf6e48360e01b81526001600160a01b038381166004830152919091169063eaf6e4839060240160206040518083038186803b1580156107ed57600080fd5b505afa158015610801573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108259190613584565b6108695760405162461bcd60e51b815260206004820152601560248201527426269d219d24a72b20a624a22fa127a92927aba2a960591b6044820152606401610553565b6108833361087e6108798e613a14565b6122e9565b61233b565b505b6000610890336123fc565b90506108cc826108ac85606001516001600160a81b0316611b98565b6108c284606001516001600160a81b0316611b98565b6107169190613998565b50505050505b5050600160005550505050565b6108e7611a6c565b806108f181611b34565b600061096d83846001600160a01b031663ba5d30786040518163ffffffff1660e01b815260040160206040518083038186803b15801561093057600080fd5b505afa158015610944573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061096891906135a6565b611bf5565b915050610978612753565b6001600160a01b0316336001600160a01b031614806109b85750801580156109b857506109a3612795565b6001600160a01b0316336001600160a01b0316145b6109f55760405162461bcd60e51b815260206004820152600e60248201526d0989a74a49892749c9ebe82aaa8960931b6044820152606401610553565b826001600160a01b03166365cd0a4c6040518163ffffffff1660e01b81526004016040805180830381600087803b158015610a2f57600080fd5b505af1158015610a43573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a6791906136df565b5050505050565b610a76611a6c565b80610a8081611b34565b6000610a8a612753565b6001600160a01b0316336001600160a01b03161490508080610ac45750610aaf612795565b6001600160a01b0316336001600160a01b0316145b610b005760405162461bcd60e51b815260206004820152600d60248201526c0989a749298749c9ebe82aaa89609b1b6044820152606401610553565b826001600160a01b0316630548d2676040518163ffffffff1660e01b81526004016040805180830381600087803b158015610b3a57600080fd5b505af1158015610b4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b7291906136df565b50508015610b8957610b83836127da565b50505050565b610b83836127ed565b505050565b610b9f611a6c565b600054600114610bdd5760405162461bcd60e51b815260206004820152600960248201526813134e9313d0d2d15160ba1b6044820152606401610553565b6002600055610bea6127fa565b6000816001600160a01b031663c45a01556040518163ffffffff1660e01b815260040160206040518083038186803b158015610c2557600080fd5b505afa158015610c39573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c5d919061340b565b90506000610c6961226f565b60405163305c9e0560e01b81526e4f545f4c4f414e5f464143544f525960881b60048201526001600160a01b0384811660248301529192509082169063305c9e059060440160206040518083038186803b158015610cc657600080fd5b505afa158015610cda573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cfe9190613584565b610d4a5760405162461bcd60e51b815260206004820152601960248201527f4c4d3a463a494e56414c49445f4c4f414e5f464143544f5259000000000000006044820152606401610553565b60405163140ce5e160e11b81526001600160a01b038481166004830152831690632819cbc29060240160206040518083038186803b158015610d8b57600080fd5b505afa158015610d9f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dc39190613584565b610e0f5760405162461bcd60e51b815260206004820152601a60248201527f4c4d3a463a494e56414c49445f4c4f414e5f494e5354414e43450000000000006044820152606401610553565b806001600160a01b031663eaf6e483846001600160a01b0316637df1f1b96040518163ffffffff1660e01b815260040160206040518083038186803b158015610e5757600080fd5b505afa158015610e6b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e8f919061340b565b6040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260240160206040518083038186803b158015610ece57600080fd5b505afa158015610ee2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f069190613584565b610f4a5760405162461bcd60e51b815260206004820152601560248201527426269d231d24a72b20a624a22fa127a92927aba2a960591b6044820152606401610553565b6000836001600160a01b031663ba5d30786040518163ffffffff1660e01b815260040160206040518083038186803b158015610f8557600080fd5b505afa158015610f99573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fbd91906135a6565b9050806110035760405162461bcd60e51b81526020600482015260146024820152734c4d3a463a4c4f414e5f4e4f545f41435449564560601b6044820152606401610553565b61100d848261233b565b6000846001600160a01b031663b60d42886040518163ffffffff1660e01b8152600401606060405180830381600087803b15801561104a57600080fd5b505af115801561105e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611082919061367f565b505090508181146110cd5760405162461bcd60e51b81526020600482015260156024820152740989a748c748caa9c88929c8ebe9a92a69a82a8869605b1b6044820152606401610553565b6110d961069382611b98565b60006110e4866123fc565b90506108d2600061071683606001516001600160a81b0316611b98565b611109611a6c565b6111116127fa565b8461111b81611b34565b604051632b2d48ad60e21b81526001600160a01b0387169063acb522b49061114d908890889088908890600401613804565b602060405180830381600087803b15801561116757600080fd5b505af115801561117b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061119f91906135a6565b50505050505050565b6111b0611a6c565b60006111ba61226f565b90506111c4612795565b6001600160a01b0316336001600160a01b031614156113145760405163fd4c5b3760e01b81526001600160a01b0382169063fd4c5b379061121090339030906000903690600401613782565b60206040518083038186803b15801561122857600080fd5b505afa15801561123c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112609190613584565b6112ac5760405162461bcd60e51b815260206004820152601760248201527f4c4d3a553a494e56414c49445f53434845445f43414c4c0000000000000000006044820152606401610553565b604051635ad5b6f760e11b81526001600160a01b0382169063b5ab6dee906112dd90339060009036906004016137cc565b600060405180830381600087803b1580156112f757600080fd5b505af115801561130b573d6000803e3d6000fd5b505050506113d4565b806001600160a01b031663be7c13f76040518163ffffffff1660e01b815260040160206040518083038186803b15801561134d57600080fd5b505afa158015611361573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611385919061340b565b6001600160a01b0316336001600160a01b0316146113d45760405162461bcd60e51b815260206004820152600c60248201526b0989a74aa749c9ebe82aaa8960a31b6044820152606401610553565b7faaaa7ee6b0c2f4ee1fa7312c7d5b3623a434da5a1a9ce3cb6e629caa23454ab6848484604051611407939291906138b9565b60405180910390a161141761284e565b6001600160a01b031663fe69f7088585856040518463ffffffff1660e01b8152600401611446939291906138b9565b600060405180830381600087803b15801561146057600080fd5b505af1158015611474573d6000803e3d6000fd5b5050505050505050565b600080600061148c8561179d565b600197919650945092505050565b60035460009080156114c5576001546114c09082906106d29064ffffffffff16426139d7565b6114c8565b60005b91505090565b60006114d861287d565b905090565b6114e5611a6c565b6114ed6127fa565b806114f781611b34565b816001600160a01b031663200e53456040518163ffffffff1660e01b81526004016040805180830381600087803b15801561153157600080fd5b505af1158015611545573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b8391906136df565b611571611a6c565b61157961284e565b6001600160a01b0316336001600160a01b0316146115cc5760405162461bcd60e51b815260206004820152601060248201526f4c4d3a4d3a4e4f545f464143544f525960801b6044820152606401610553565b6115d78383836128a7565b610b925760405162461bcd60e51b815260206004820152600b60248201526a13134e934e91905253115160aa1b6044820152606401610553565b60006114d861284e565b611623611a6c565b61162b61284e565b6001600160a01b0316336001600160a01b03161461167f5760405162461bcd60e51b81526020600482015260116024820152704c4d3a53493a4e4f545f464143544f525960781b6044820152606401610553565b6001600160a01b03167f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc55565b5050565b6116b8611a6c565b6116c06127fa565b816116ca81611b34565b604051630c7341dd60e31b8152600481018390526001600160a01b0384169063639a0ee8906024016040805180830381600087803b158015610a2f57600080fd5b611713611a6c565b61171b6127fa565b8461172581611b34565b6040516387accaf160e01b81526001600160a01b038716906387accaf19061114d908890889088908890600401613804565b600061176161149a565b60015460025461178a91600160281b90046001600160701b0316906001600160801b0316613914565b6001600160801b03166114d8919061393f565b6000806117a8611a6c565b826117b281611b34565b6005546001600160a01b031633146117fb5760405162461bcd60e51b815260206004820152600c60248201526b4c4d3a54443a4e4f545f504d60a01b6044820152606401610553565b6000611806856127ed565b604051630938afdd60e41b815264ffffffffff82166004820152909150600090819081906001600160a01b0389169063938afdd09060240160a06040518083038186803b15801561185657600080fd5b505afa15801561186a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061188e919061363f565b94505093509350506000886001600160a01b031663ba5d30786040518163ffffffff1660e01b815260040160206040518083038186803b1580156118d157600080fd5b505afa1580156118e5573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061190991906135a6565b9050611915838561393f565b6040516347350e9f60e01b81523060048201529094506000906001600160a01b038b16906347350e9f90602401602060405180830381600087803b15801561195c57600080fd5b505af1158015611970573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061199491906135a6565b90506119a38a83878685612920565b909950975060006119b38b61209d565b905060006119e482606001516001600160a81b031683604001518a6119d891906139ee565b64ffffffffff1661215a565b9050611a026119f282611b98565b6119fb90613a14565b6000612184565b611a20611a126106d7838761393f565b611a1b90613a14565b612c79565b611a35611a2c85611b98565b61069390613a14565b5050506001600160a01b039098166000908152600660205260409020805465ffffffffffff19169055509496939550929350505050565b611a7461226f565b604051634c532de160e01b81526001600160e01b03196000351660048201526001600160a01b039190911690634c532de19060240160206040518083038186803b158015611ac157600080fd5b505afa158015611ad5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611af99190613584565b15611b325760405162461bcd60e51b815260206004820152600960248201526813134e94105554d15160ba1b6044820152606401610553565b565b6001600160a01b038116600090815260076020526040902054600160301b900464ffffffffff16611b955760405162461bcd60e51b815260206004820152600b60248201526a26269d2727aa2fa627a0a760a91b6044820152606401610553565b50565b60006001600160ff1b03821115611bf15760405162461bcd60e51b815260206004820152601960248201527f4c4d3a55494e543235365f4f4f425f464f525f494e54323536000000000000006044820152606401610553565b5090565b6001600160a01b03821660009081526006602090815260409182902082518084019093525464ffffffffff8116808452600160281b90910460ff1615159183018290529182611c445750611d28565b6001600160a01b0385166000908152600660209081526040808320805465ffffffffffff1916905560078252918290208251608081018452905462ffffff808216835263010000008204169282019290925264ffffffffff600160301b830416928101839052600160581b9091046001600160a81b0316606082018190529091611ce591611a1291611cdb91906119d890896139ee565b6106d7908861393f565b611d25611d0f6106d783606001516001600160a81b03168764ffffffffff16426106d291906139d7565b61071683606001516001600160a81b0316611b98565b50505b9250929050565b6001600160a01b03851660009081526007602090815260408083208151608081018352905462ffffff80821683526301000000820416938201849052600160301b810464ffffffffff1692820192909252600160581b9091046001600160a81b031660608201529190611da3908690612cf4565b90506000611dba86846000015162ffffff16612cf4565b9050600560009054906101000a90046001600160a01b03166001600160a01b031663caf901dd6040518163ffffffff1660e01b815260040160206040518083038186803b158015611e0a57600080fd5b505afa158015611e1e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e429190613584565b611e5b57611e50858561393f565b935060009450600091505b6000611e67838361393f565b611e7190886139d7565b905060008813611e82576000611e84565b875b60408051828152602081018a9052908101859052606081018890526080810184905260a081018790529098506001600160a01b038a16907f5a3aaae9941b918d74569012f48c308c4044705e7ece73e7834f0f7ffd938b859060c00160405180910390a26004546001600160a01b0316611f0f81611f00612d04565b611f0a858d61393f565b612d49565b611f4f5760405162461bcd60e51b815260206004820152601160248201527004c4d3a4443463a5452414e534645525f5607c1b6044820152606401610553565b611f6581611f5b612795565b611f0a878b61393f565b611fa65760405162461bcd60e51b815260206004820152601260248201527113134e9110d18e9514905394d1915497d41160721b6044820152606401610553565b611fbc81611fb2612d79565b611f0a868a61393f565b611ffd5760405162461bcd60e51b815260206004820152601260248201527113134e9110d18e9514905394d1915497d35560721b6044820152606401610553565b50505050505050505050565b6002547f8e82b75967acb8b37df8c3edc1ef9712a6c32f8a42dbbd441f49be7cab41aee2906120609061205b90849061204a906001600160801b0316611b98565b61205491906138d3565b6000612dbb565b612dd1565b600280546fffffffffffffffffffffffffffffffff19166001600160801b039290921691821790556040519081526020015b60405180910390a150565b604080516080810182526000808252602082018190529181018290526060810191909152506001600160a01b03811660008181526007602081815260408084208151608081018352815462ffffff8082168352630100000082041682860152600160301b810464ffffffffff1682850152600160581b90046001600160a81b031660608201528686529390925290839055519092917f98e0ae8c0ac21cdd4b0a6a2c72737be54e995c54f6ef61b3cd19ec71ed22533b91a2919050565b60006b033b2e3c9fd0803ce80000006121738385613979565b61217d9190613957565b9392505050565b6121b86121b38361204a61219661149a565b6001546106d79190600160281b90046001600160701b031661393f565b612e37565b600160056101000a8154816001600160701b0302191690836001600160701b031602179055506121e742612e9d565b600160006101000a81548164ffffffffff021916908364ffffffffff16021790555061221b6108798261204a600354611b98565b600381905560015460408051928352600160281b9091046001600160701b031660208301527f1e2d80f327730eb6faf6e0ed856016385059a20185b280cb5293a05883ee6f81910160405180910390a15050565b600061227961284e565b6001600160a01b0316633a60339a6040518163ffffffff1660e01b815260040160206040518083038186803b1580156122b157600080fd5b505afa1580156122c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114d8919061340b565b600080821215611bf15760405162461bcd60e51b815260206004820152601960248201527f4c4d3a494e543235365f4f4f425f464f525f55494e54323536000000000000006044820152606401610553565b6005546040516324a3335b60e11b8152306004820152602481018390526001600160a01b039091169063494666b690604401600060405180830381600087803b15801561238757600080fd5b505af115801561239b573d6000803e3d6000fd5b50506004546123b792506001600160a01b031690508383612ef4565b6116ac5760405162461bcd60e51b815260206004820152601660248201527513134e941191930e9054141493d59157d1905253115160521b6044820152606401610553565b60408051608081018252600080825260208201819052918101829052606081018290529061242861226f565b600554604051631b14131d60e11b81526001600160a01b039182166004820152911690633628263a9060240160206040518083038186803b15801561246c57600080fd5b505afa158015612480573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124a491906135a6565b90506000600560009054906101000a90046001600160a01b03166001600160a01b0316635dd284496040518163ffffffff1660e01b815260040160206040518083038186803b1580156124f657600080fd5b505afa15801561250a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061252e91906135a6565b9050600061253c828461393f565b9050620f424081111561255f5761255683620f42406139d7565b9150620f424090505b6000856001600160a01b031663d9ef04596040518163ffffffff1660e01b815260040160206040518083038186803b15801561259a57600080fd5b505afa1580156125ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125d291906136c2565b64ffffffffff16905060006125e8878385612fa3565b905060006125f642846139d7565b61260c6b033b2e3c9fd0803ce800000084613979565b6126169190613957565b9050604051806080016040528061262c88613039565b62ffffff16815260200161263f87613039565b62ffffff16815260200161265242612e9d565b64ffffffffff1681526020016126678361308e565b6001600160a81b039081169091526001600160a01b038a166000818152600760209081526040918290208551815487840151888601516060808b0151909916600160581b026affffffffffffffffffffff64ffffffffff909216600160301b029190911665ffffffffffff62ffffff93841663010000000265ffffffffffff19909516939095169290921792909217929092169190911717905581518b81529081018a90529081018790529182018490529198507f948106bee3c901826daa4428037840a48300999c9a8911510b1beb56f2dc02769060800160405180910390a2505050505050919050565b600061275d61226f565b6001600160a01b0316630c340a246040518163ffffffff1660e01b815260040160206040518083038186803b1580156122b157600080fd5b60055460408051634046af2b60e01b815290516000926001600160a01b031691634046af2b916004808301926020929190829003018186803b1580156122b157600080fd5b60006127e78260016130e7565b92915050565b60006127e78260006130e7565b612802612795565b6001600160a01b0316336001600160a01b031614611b325760405162461bcd60e51b815260206004820152600960248201526813134e9393d517d41160ba1b6044820152606401610553565b60006128787f7a45a402e4cb6e08ebc196f20f66d5d30e67285a2a8aa80503fa409e727a4af15490565b919050565b60006128787f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6000833b806128ba57600091505061217d565b846001600160a01b031684846040516128d4929190613737565b600060405180830381855af49150503d806000811461290f576040519150601f19603f3d011682016040523d82523d6000602084013e612914565b606091505b50909695505050505050565b6001600160a01b03851660009081526007602090815260408083208151608081018352905462ffffff8082168084526301000000830490911694830194909452600160301b810464ffffffffff1692820192909252600160581b9091046001600160a81b031660608201528291829061299a908890612cf4565b905060006129b188846020015162ffffff16612cf4565b905060006129bf828461393f565b6129c9908a6139d7565b905060006129d7848a61393f565b905060006129e589836132b4565b90506129f181836139d7565b96506129fd818a6139d7565b98506000612a168a858f612a11919061393f565b6132b4565b905080612a23858f61393f565b612a2d91906139d7565b9850612a39818b6139d7565b604080518f815260208101879052908101889052606081018d9052909a506001600160a01b038f16907fd6c35cb94fcd8788f1d1e61f1f635e83b26421b57c5db5bb71b275e41588be249060800160405180910390a2604080518b8152602081018390529081018390526001600160a01b038f16907f6fe470ca125c8e736c97af4412c288b2a0417f3f146625f3ff2280449b1e7a8b9060600160405180910390a2612b6b600460009054906101000a90046001600160a01b03168f6001600160a01b0316637df1f1b96040518163ffffffff1660e01b815260040160206040518083038186803b158015612b2d57600080fd5b505afa158015612b41573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b65919061340b565b8c612d49565b612bab5760405162461bcd60e51b815260206004820152601160248201527026269d2226231d2a2920a729a322a92fa160791b6044820152606401610553565b600454612bc9906001600160a01b0316612bc3612d04565b83612d49565b612c095760405162461bcd60e51b815260206004820152601160248201527004c4d3a444c463a5452414e534645525f5607c1b6044820152606401610553565b600454612c27906001600160a01b0316612c21612d79565b84612d49565b612c685760405162461bcd60e51b815260206004820152601260248201527113134e9113118e9514905394d1915497d35560721b6044820152606401610553565b505050505050509550959350505050565b7fa6fdea32383e711b89178e80732f32dd09a53fe2cfc2f613a7e5035de5e0bef6612cc861205b8361204a600260109054906101000a90046001600160801b03166001600160801b0316611b98565b600280546001600160801b03908116600160801b93909116928302179055604051908152602001612092565b6000620f42406121738385613979565b600554604080516316f0115b60e01b815290516000926001600160a01b0316916316f0115b916004808301926020929190829003018186803b1580156122b157600080fd5b60006001600160a01b03831615801590612d715750811580612d715750612d718484846132c3565b949350505050565b6000612d8361226f565b6001600160a01b031663a5a276056040518163ffffffff1660e01b815260040160206040518083038186803b1580156122b157600080fd5b6000818313612dca578161217d565b5090919050565b60006001600160801b038213801590612deb575060008212155b611bf15760405162461bcd60e51b815260206004820152601960248201527f4c4d3a494e543235365f4f4f425f464f525f55494e54313238000000000000006044820152606401610553565b60006001600160701b038213801590612e51575060008212155b611bf15760405162461bcd60e51b815260206004820152601960248201527f4c4d3a494e543235365f4f4f425f464f525f55494e54313132000000000000006044820152606401610553565b600064ffffffffff821115611bf15760405162461bcd60e51b815260206004820152601960248201527f4c4d3a55494e543235365f4f4f425f464f525f55494e543430000000000000006044820152606401610553565b6040516001600160a01b038316602482015260006044820181905290612f5a90859063095ea7b360e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526132f6565b612f665750600061217d565b81612f735750600161217d565b6040516001600160a01b038416602482015260448101839052612d7190859063095ea7b360e01b90606401612f23565b604051630938afdd60e41b81526004810183905260009081906001600160a01b0386169063938afdd09060240160a06040518083038186803b158015612fe857600080fd5b505afa158015612ffc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613020919061363f565b5050509150506130308184613396565b95945050505050565b600062ffffff821115611bf15760405162461bcd60e51b815260206004820152601960248201527f4c4d3a55494e543235365f4f4f425f464f525f55494e543234000000000000006044820152606401610553565b60006001600160a81b03821115611bf15760405162461bcd60e51b815260206004820152601a60248201527f4c4d3a55494e543235365f4f4f425f464f525f55494e543136380000000000006044820152606401610553565b6001600160a01b03821660009081526006602052604090205464ffffffffff168015613112576127e7565b6001600160a01b0383166000908152600760209081526040918290208251608081018452905462ffffff8082168352630100000082041692820192909252600160301b820464ffffffffff1681840152600160581b9091046001600160a81b031660608201528151808301909252908061318b42612e9d565b64ffffffffff80821683528615156020938401526001600160a01b038816600090815260068452604081208551815496909501511515600160281b0265ffffffffffff1990961694909216939093179390931790925560608301519193506131ff9161070d906001600160a81b0316611b98565b6000846001600160a01b031663ba5d30786040518163ffffffff1660e01b815260040160206040518083038186803b15801561323a57600080fd5b505afa15801561324e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061327291906135a6565b90506132ac611a1b6132a284606001516001600160a81b0316856040015164ffffffffff16426106d291906139d7565b6106d7908461393f565b505092915050565b6000818310612dca578161217d565b6040516001600160a01b038316602482015260448101829052600090612d7190859063a9059cbb60e01b90606401612f23565b60006001600160a01b0383163b61330f575060006127e7565b6060836001600160a01b0316836040516133299190613747565b6000604051808303816000865af19150503d8060008114613366576040519150601f19603f3d011682016040523d82523d6000602084013e61336b565b606091505b509092509050818015612d71575080511580612d71575080806020019051810190612d719190613584565b60006133a28383612cf4565b61217d90846139d7565b60008083601f8401126133be57600080fd5b50813567ffffffffffffffff8111156133d657600080fd5b602083019150836020828501011115611d2857600080fd5b60006020828403121561340057600080fd5b813561217d81613a47565b60006020828403121561341d57600080fd5b815161217d81613a47565b6000806040838503121561343b57600080fd5b823561344681613a47565b9150602083013561345681613a47565b809150509250929050565b60008060008060006080868803121561347957600080fd5b853561348481613a47565b9450602086013561349481613a47565b935060408601359250606086013567ffffffffffffffff808211156134b857600080fd5b818801915088601f8301126134cc57600080fd5b8135818111156134db57600080fd5b8960208260051b85010111156134f057600080fd5b9699959850939650602001949392505050565b60008060006040848603121561351857600080fd5b833561352381613a47565b9250602084013567ffffffffffffffff81111561353f57600080fd5b61354b868287016133ac565b9497909650939450505050565b6000806040838503121561356b57600080fd5b823561357681613a47565b946020939093013593505050565b60006020828403121561359657600080fd5b8151801515811461217d57600080fd5b6000602082840312156135b857600080fd5b5051919050565b600080600080600060a086880312156135d757600080fd5b8535945060208601359350604086013592506060860135915060808601356135fe81613a5c565b809150509295509295909350565b60008060006040848603121561362157600080fd5b83359250602084013567ffffffffffffffff81111561353f57600080fd5b600080600080600060a0868803121561365757600080fd5b5050835160208501516040860151606087015160809097015192989197509594509092509050565b60008060006060848603121561369457600080fd5b8351925060208401516136a681613a5c565b60408501519092506136b781613a5c565b809150509250925092565b6000602082840312156136d457600080fd5b815161217d81613a5c565b600080604083850312156136f257600080fd5b82516136fd81613a5c565b602084015190925061345681613a5c565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b8183823760009101908152919050565b6000825160005b81811015613768576020818601810151858301520161374e565b81811115613777576000828501525b509190910192915050565b6001600160a01b03858116825284166020820152694c4d3a5550475241444560b01b60408201526080606082018190526000906137c2908301848661370e565b9695505050505050565b6001600160a01b0384168152694c4d3a5550475241444560b01b6020820152606060408201819052600090613030908301848661370e565b6001600160a01b0385168152602080820185905260606040830181905282018390526000906080600585901b840181019190840186845b878110156138aa57868503607f190183528135368a9003601e1901811261386157600080fd5b8901803567ffffffffffffffff81111561387a57600080fd5b8036038b131561388957600080fd5b613896878288850161370e565b96505050918301919083019060010161383b565b50929998505050505050505050565b83815260406020820152600061303060408301848661370e565b600080821280156001600160ff1b03849003851316156138f5576138f5613a31565b600160ff1b839003841281161561390e5761390e613a31565b50500190565b60006001600160801b0380831681851680830382111561393657613936613a31565b01949350505050565b6000821982111561395257613952613a31565b500190565b60008261397457634e487b7160e01b600052601260045260246000fd5b500490565b600081600019048311821515161561399357613993613a31565b500290565b60008083128015600160ff1b8501841216156139b6576139b6613a31565b6001600160ff1b03840183138116156139d1576139d1613a31565b50500390565b6000828210156139e9576139e9613a31565b500390565b600064ffffffffff83811690831681811015613a0c57613a0c613a31565b039392505050565b6000600160ff1b821415613a2a57613a2a613a31565b5060000390565b634e487b7160e01b600052601160045260246000fd5b6001600160a01b0381168114611b9557600080fd5b64ffffffffff81168114611b9557600080fdfea2646970667358221220688db322fbb27c42a3319d07e951e68b121e403abc92ae93a9d52b35b023332964736f6c63430008070033","name":"LoanManager","is_blueprint":false,"license_type":"none","is_fully_verified":false,"is_verified_via_eth_bytecode_db":true,"language":"solidity","evm_version":"london","can_be_visualized_via_sol2uml":true,"is_verified_via_sourcify":true,"additional_sources":[{"file_path":"modules/erc20-helper/src/ERC20Helper.sol","source_code":"// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity ^0.8.7;\n\nimport { IERC20Like } from \"./interfaces/IERC20Like.sol\";\n\n/**\n * @title Small Library to standardize erc20 token interactions.\n */\nlibrary ERC20Helper {\n\n    /**************************************************************************************************************************************/\n    /*** Internal Functions                                                                                                             ***/\n    /**************************************************************************************************************************************/\n\n    function transfer(address token_, address to_, uint256 amount_) internal returns (bool success_) {\n        return _call(token_, abi.encodeWithSelector(IERC20Like.transfer.selector, to_, amount_));\n    }\n\n    function transferFrom(address token_, address from_, address to_, uint256 amount_) internal returns (bool success_) {\n        return _call(token_, abi.encodeWithSelector(IERC20Like.transferFrom.selector, from_, to_, amount_));\n    }\n\n    function approve(address token_, address spender_, uint256 amount_) internal returns (bool success_) {\n        // If setting approval to zero fails, return false.\n        if (!_call(token_, abi.encodeWithSelector(IERC20Like.approve.selector, spender_, uint256(0)))) return false;\n\n        // If `amount_` is zero, return true as the previous step already did this.\n        if (amount_ == uint256(0)) return true;\n\n        // Return the result of setting the approval to `amount_`.\n        return _call(token_, abi.encodeWithSelector(IERC20Like.approve.selector, spender_, amount_));\n    }\n\n    function _call(address token_, bytes memory data_) private returns (bool success_) {\n        if (token_.code.length == uint256(0)) return false;\n\n        bytes memory returnData;\n        ( success_, returnData ) = token_.call(data_);\n\n        return success_ && (returnData.length == uint256(0) || abi.decode(returnData, (bool)));\n    }\n\n}\n"},{"file_path":"modules/erc20-helper/src/interfaces/IERC20Like.sol","source_code":"// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity ^0.8.7;\n\n/// @title Interface of the ERC20 standard as needed by ERC20Helper.\ninterface IERC20Like {\n\n    function approve(address spender_, uint256 amount_) external returns (bool success_);\n\n    function transfer(address recipient_, uint256 amount_) external returns (bool success_);\n\n    function transferFrom(address owner_, address recipient_, uint256 amount_) external returns (bool success_);\n\n}\n"},{"file_path":"modules/maple-proxy-factory/contracts/MapleProxiedInternals.sol","source_code":"// SPDX-License-Identifier: AGPL-3.0-or-later\npragma solidity 0.8.7;\n\nimport { ProxiedInternals } from \"../modules/proxy-factory/contracts/ProxiedInternals.sol\";\n\n/// @title A Maple implementation that is to be proxied, will need MapleProxiedInternals.\nabstract contract MapleProxiedInternals is ProxiedInternals { }\n"},{"file_path":"contracts/interfaces/Interfaces.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.7;\n\ninterface IGlobalsLike {\n\n    function canDeploy(address caller_) external view returns (bool canDeploy_);\n\n    function governor() external view returns (address governor_);\n\n    function isBorrower(address borrower_) external view returns (bool isBorrower_);\n\n    function isFunctionPaused(bytes4 sig_) external view returns (bool isFunctionPaused_);\n\n    function isInstanceOf(bytes32 instanceId, address instance_) external view returns (bool isInstance_);\n\n    function isValidScheduledCall(address caller_, address contract_, bytes32 functionId_, bytes calldata callData_)\n        external view returns (bool isValid_);\n\n    function mapleTreasury() external view returns (address mapleTreasury_);\n\n    function platformManagementFeeRate(address poolManager_) external view returns (uint256 platformManagementFeeRate_);\n\n    function securityAdmin() external view returns (address securityAdmin_);\n\n    function unscheduleCall(address caller_, bytes32 functionId_, bytes calldata callData_) external;\n\n}\n\ninterface IMapleProxyFactoryLike {\n\n    function isInstance(address instance_) external returns (bool isInstance_);\n\n    function mapleGlobals() external returns (address globals_);\n\n}\n\ninterface ILoanFactoryLike {\n\n    function isLoan(address loan_) external view returns (bool isLoan_);\n\n}\n\ninterface ILoanLike {\n\n    function borrower() external view returns (address borrower_);\n\n    function callPrincipal(uint256 principalToReturn_) external returns (uint40 paymentDueDate_, uint40 defaultDate_);\n\n    function factory() external view returns (address factory_);\n\n    function fund() external returns (uint256 fundsLent_, uint40 paymentDueDate_, uint40 defaultDate_);\n\n    function impair() external returns (uint40 paymentDueDate_, uint40 defaultDate_);\n\n    function paymentDueDate() external view returns (uint40 paymentDueDate_);\n\n    function getPaymentBreakdown(uint256 paymentTimestamp_)\n        external view\n        returns (\n            uint256 principal_,\n            uint256 interest_,\n            uint256 lateInterest_,\n            uint256 delegateServiceFee_,\n            uint256 platformServiceFee_\n        );\n\n    function principal() external view returns (uint256 principal_);\n\n    function proposeNewTerms(\n        address refinancer_,\n        uint256 deadline_,\n        bytes[] calldata calls_\n    ) external returns (bytes32 refinanceCommitment_);\n\n    function rejectNewTerms(\n        address refinancer_,\n        uint256 deadline_,\n        bytes[] calldata calls_\n    ) external returns (bytes32 refinanceCommitment_);\n\n    function removeCall() external returns (uint40 paymentDueDate_, uint40 defaultDate_);\n\n    function removeImpairment() external returns (uint40 paymentDueDate_, uint40 defaultDate_);\n\n    function repossess(address destination_) external returns (uint256 fundsRepossessed_);\n\n}\n\ninterface IPoolManagerLike {\n\n    function asset() external view returns (address asset_);\n\n    function delegateManagementFeeRate() external view returns (uint256 delegateManagementFeeRate_);\n\n    function factory() external view returns (address factory_);\n\n    function hasSufficientCover() external view returns (bool hasSufficientCover_);\n\n    function pool() external view returns (address pool_);\n\n    function poolDelegate() external view returns (address poolDelegate_);\n\n    function requestFunds(address destination_, uint256 principal_) external;\n\n}\n"},{"file_path":"contracts/LoanManagerStorage.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.7;\n\nimport { ILoanManagerStorage } from \"./interfaces/ILoanManagerStorage.sol\";\n\nabstract contract LoanManagerStorage is ILoanManagerStorage {\n\n    struct Impairment {\n        uint40 impairedDate;        // Slot 1: uint40 - Until year 36,812.\n        bool   impairedByGovernor;  //         bool\n    }\n\n    struct Payment {\n        uint24  platformManagementFeeRate;  // Slot 1: uint24  - max = 1.6e7 (1600%)\n        uint24  delegateManagementFeeRate;  //         uint24  - max = 1.6e7 (1600%)\n        uint40  startDate;                  //         uint40  - Until year 36,812.\n        uint168 issuanceRate;               //         uint168 - max = 3.7e50 (3.2e10 * 1e18 / day)\n    }\n\n    uint256 internal _locked;  // Used when checking for reentrancy.\n\n    uint40  public override domainStart;        // Slot 1: uint40  - Until year 36,812.\n    uint112 public override accountedInterest;  //         uint112 - max = 5.1e33\n    uint128 public override principalOut;       // Slot 2: uint128 - max = 3.4e38\n    uint128 public override unrealizedLosses;   //         uint128 - max = 3.4e38\n    uint256 public override issuanceRate;       // Slot 3: uint256 - max = 1.1e77\n\n    // NOTE: Addresses below uints to preserve full storage slots\n    address public override fundsAsset;\n    address public override poolManager;\n\n    mapping(address => Impairment) public override impairmentFor;\n\n    mapping(address => Payment) public override paymentFor;\n\n}\n"},{"file_path":"contracts/interfaces/ILoanManager.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.7;\n\nimport { IMapleProxied } from \"../../modules/maple-proxy-factory/contracts/interfaces/IMapleProxied.sol\";\n\nimport { ILoanManagerStorage } from \"./ILoanManagerStorage.sol\";\n\ninterface ILoanManager is IMapleProxied, ILoanManagerStorage {\n\n    /**************************************************************************************************************************************/\n    /*** Events                                                                                                                         ***/\n    /**************************************************************************************************************************************/\n\n    /**\n     *  @dev   Emitted when the accounting state of the loan manager is updated.\n     *  @param issuanceRate_      New value for the issuance rate.\n     *  @param accountedInterest_ The amount of accounted interest.\n     */\n    event AccountingStateUpdated(uint256 issuanceRate_, uint112 accountedInterest_);\n\n    /**\n     *  @dev   Funds have been claimed and distributed to the Pool, Pool Delegate, and Maple Treasury.\n     *  @param loan_                  The address of the loan contract.\n     *  @param principal_             The amount of principal paid.\n     *  @param netInterest_           The amount of net interest paid.\n     *  @param delegateManagementFee_ The amount of delegate management fees paid.\n     *  @param delegateServiceFee_    The amount of delegate service fees paid.\n     *  @param platformManagementFee_ The amount of platform management fees paid.\n     *  @param platformServiceFee_    The amount of platform service fees paid.\n     */\n    event ClaimedFundsDistributed(\n        address indexed loan_,\n        uint256 principal_,\n        uint256 netInterest_,\n        uint256 delegateManagementFee_,\n        uint256 delegateServiceFee_,\n        uint256 platformManagementFee_,\n        uint256 platformServiceFee_\n    );\n\n    /**\n     *  @dev   Funds that were expected to be claimed and distributed to the Pool and Maple Treasury.\n     *  @param loan_                  The address of the loan contract.\n     *  @param principal_             The amount of principal that was expected to be paid.\n     *  @param netInterest_           The amount of net interest that was expected to be paid.\n     *  @param platformManagementFee_ The amount of platform management fees that were expected to be paid.\n     *  @param platformServiceFee_    The amount of platform service fees that were expected to paid.\n     */\n    event ExpectedClaim(\n        address indexed loan_,\n        uint256 principal_,\n        uint256 netInterest_,\n        uint256 platformManagementFee_,\n        uint256 platformServiceFee_\n    );\n\n    /**\n     *  @dev   Funds that were liquidated and distributed to the Pool, Maple Treasury, and Borrower.\n     *  @param loan_       The address of the loan contract that defaulted and was liquidated.\n     *  @param toBorrower_ The amount of recovered funds transferred to the Borrower.\n     *  @param toPool_     The amount of recovered funds transferred to the Pool.\n     *  @param toTreasury_ The amount of recovered funds transferred to the Treasury.\n     */\n    event LiquidatedFundsDistributed(address indexed loan_, uint256 toBorrower_, uint256 toPool_, uint256 toTreasury_);\n\n    /**\n     *  @dev   Emitted when a payment is added to the LoanManager payments mapping.\n     *  @param loan_                      The address of the loan.\n     *  @param platformManagementFeeRate_ The amount of platform management rate that will be used for the payment distribution.\n     *  @param delegateManagementFeeRate_ The amount of delegate management rate that will be used for the payment distribution.\n     *  @param paymentDueDate_            The due date of the payment.\n     *  @param issuanceRate_              The issuance of the payment, 1e27 precision.\n     */\n    event PaymentAdded(\n        address indexed loan_,\n        uint256 platformManagementFeeRate_,\n        uint256 delegateManagementFeeRate_,\n        uint256 paymentDueDate_,\n        uint256 issuanceRate_\n    );\n\n    /**\n     *  @dev   Emitted when a payment is removed from the LoanManager payments mapping.\n     *  @param loan_ The address of the loan.\n     */\n    event PaymentRemoved(address indexed loan_);\n\n    /**\n     *  @dev   Emitted when principal out is updated\n     *  @param principalOut_ The new value for principal out.\n     */\n    event PrincipalOutUpdated(uint128 principalOut_);\n\n    /**\n     *  @dev   Emitted when unrealized losses is updated.\n     *  @param unrealizedLosses_ The new value for unrealized losses.\n     */\n    event UnrealizedLossesUpdated(uint128 unrealizedLosses_);\n\n    /**************************************************************************************************************************************/\n    /*** External Functions                                                                                                             ***/\n    /**************************************************************************************************************************************/\n\n    // NOTE: setPendingLender and acceptPendingLender were not implemented in the LoanManager even though they exist on the Loan\n    //       contract. This is because the Loan will support this functionality always, but it was not deemed necessary for the\n    //       LoanManager to support this functionality.\n\n    /**\n     *  @dev   Calls a loan.\n     *  @param loan_      Loan to be called.\n     *  @param principal_ Amount of principal to call the Loan with.\n     */\n    function callPrincipal(address loan_, uint256 principal_) external;\n\n    /**\n     *  @dev   Called by loans when payments are made, updating the accounting.\n     *  @param principal_          The difference in principal. Positive if net principal change moves funds into pool, negative if it moves\n     *                             funds out of pool.\n     *  @param interest_           The amount of interest paid.\n     *  @param platformServiceFee_ The amount of platform service fee paid.\n     *  @param delegateServiceFee_ The amount of delegate service fee paid.\n     *  @param paymentDueDate_     The new payment due date.\n     */\n    function claim(\n        int256  principal_,\n        uint256 interest_,\n        uint256 delegateServiceFee_,\n        uint256 platformServiceFee_,\n        uint40  paymentDueDate_\n    ) external;\n\n    /**\n     *  @dev   Funds a new loan.\n     *  @param loan_ Loan to be funded.\n     */\n    function fund(address loan_) external;\n\n    /**\n     *  @dev   Triggers the impairment of a loan.\n     *  @param loan_ Loan to trigger the loan impairment.\n     */\n    function impairLoan(address loan_) external;\n\n    /**\n     *  @dev   Proposes new terms for a loan.\n     *  @param loan_       The loan to propose new changes to.\n     *  @param refinancer_ The refinancer to use in the refinance.\n     *  @param deadline_   The deadline by which the borrower must accept the new terms.\n     *  @param calls_      The array of calls to be made to the refinancer.\n     */\n    function proposeNewTerms(address loan_, address refinancer_, uint256 deadline_, bytes[] calldata calls_) external;\n\n    /**\n     *  @dev   Reject/cancel proposed new terms for a loan.\n     *  @param loan_       The loan with the proposed new changes.\n     *  @param refinancer_ The refinancer to use in the refinance.\n     *  @param deadline_   The deadline by which the borrower must accept the new terms.\n     *  @param calls_      The array of calls to be made to the refinancer.\n     */\n    function rejectNewTerms(address loan_, address refinancer_, uint256 deadline_, bytes[] calldata calls_) external;\n\n    /**\n     *  @dev   Removes a loan call.\n     *  @param loan_ Loan to remove call for.\n     */\n    function removeCall(address loan_) external;\n\n    /**\n     *  @dev   Removes the loan impairment for a loan.\n     *  @param loan_ Loan to remove the loan impairment.\n     */\n    function removeLoanImpairment(address loan_) external;\n\n    /**\n     *  @dev    Triggers the default of a loan. Different interface for PM to accommodate vs FT-LM.\n     *  @param  loan_                    Loan to trigger the default.\n     *  @param  liquidatorFactory_       Address of the liquidator factory (ignored for open-term loans).\n     *  @return liquidationComplete_     If the liquidation is complete (always true for open-term loans)\n     *  @return remainingLosses_         The amount of un-recovered principal and interest (net of management fees).\n     *  @return unrecoveredPlatformFees_ The amount of un-recovered platform fees.\n     */\n    function triggerDefault(\n        address loan_,\n        address liquidatorFactory_\n    ) external returns (bool liquidationComplete_, uint256 remainingLosses_, uint256 unrecoveredPlatformFees_);\n\n    /**\n     *  @dev    Triggers the default of a loan.\n     *  @param  loan_                    Loan to trigger the default.\n     *  @return remainingLosses_         The amount of un-recovered principal and interest (net of management fees).\n     *  @return unrecoveredPlatformFees_ The amount of un-recovered platform fees.\n     */\n    function triggerDefault(address loan_) external returns (uint256 remainingLosses_, uint256 unrecoveredPlatformFees_);\n\n    /**************************************************************************************************************************************/\n    /*** View Functions                                                                                                                 ***/\n    /**************************************************************************************************************************************/\n\n    /**\n     *  @dev    Returns the value considered as the hundred percent.\n     *  @return hundredPercent_ The value considered as the hundred percent.\n     */\n    function HUNDRED_PERCENT() external returns (uint256 hundredPercent_);\n\n    /**\n     *  @dev    Returns the precision used for the contract.\n     *  @return precision_ The precision used for the contract.\n     */\n    function PRECISION() external returns (uint256 precision_);\n\n    /**\n     *  @dev    Gets the amount of accrued interest up until this point in time.\n     *  @return accruedInterest_ The amount of accrued interest up until this point in time.\n     */\n    function accruedInterest() external view returns (uint256 accruedInterest_);\n\n    /**\n     *  @dev    Gets the amount of assets under the management of the contract.\n     *  @return assetsUnderManagement_ The amount of assets under the management of the contract.\n     */\n    function assetsUnderManagement() external view returns (uint256 assetsUnderManagement_);\n\n}\n"},{"file_path":"contracts/interfaces/ILoanManagerStorage.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.7;\n\ninterface ILoanManagerStorage {\n\n    /**\n     *  @dev    Gets the amount of accounted interest.\n     *  @return accountedInterest_ The amount of accounted interest.\n     */\n    function accountedInterest() external view returns (uint112 accountedInterest_);\n\n    /**\n     *  @dev    Gets the timestamp of the domain start.\n     *  @return domainStart_ The timestamp of the domain start.\n     */\n    function domainStart() external view returns (uint40 domainStart_);\n\n    /**\n     *  @dev    Gets the address of the funds asset.\n     *  @return fundsAsset_ The address of the funds asset.\n     */\n    function fundsAsset() external view returns (address fundsAsset_);\n\n    /**\n     *  @dev    Gets the information for an impairment.\n     *  @param  loan_              The address of the loan.\n     *  @return impairedDate       The date the impairment was triggered.\n     *  @return impairedByGovernor True if the impairment was triggered by the governor.\n     */\n    function impairmentFor(address loan_) external view returns (uint40 impairedDate, bool impairedByGovernor);\n\n    /**\n     *  @dev    Gets the current issuance rate.\n     *  @return issuanceRate_ The value for the issuance rate.\n     */\n    function issuanceRate() external view returns (uint256 issuanceRate_);\n\n    /**\n     *  @dev    Gets the information for a payment.\n     *  @param  loan_                     The address of the loan.\n     *  @return platformManagementFeeRate The value for the platform management fee rate.\n     *  @return delegateManagementFeeRate The value for the delegate management fee rate.\n     *  @return startDate                 The start date of the payment.\n     *  @return issuanceRate              The issuance rate for the loan.\n     */\n    function paymentFor(address loan_) external view returns (\n        uint24  platformManagementFeeRate,\n        uint24  delegateManagementFeeRate,\n        uint40  startDate,\n        uint168 issuanceRate\n    );\n\n    /**\n     *  @dev    Gets the address of the pool manager.\n     *  @return poolManager_ The address of the pool manager.\n     */\n    function poolManager() external view returns (address poolManager_);\n\n    /**\n     *  @dev    Gets the amount of principal out.\n     *  @return principalOut_ The amount of principal out.\n     */\n    function principalOut() external view returns (uint128 principalOut_);\n\n    /**\n     *  @dev    Returns the amount unrealized losses.\n     *  @return unrealizedLosses_ Amount of unrealized losses.\n     */\n    function unrealizedLosses() external view returns (uint128 unrealizedLosses_);\n\n}\n"},{"file_path":"modules/maple-proxy-factory/contracts/interfaces/IMapleProxied.sol","source_code":"// SPDX-License-Identifier: AGPL-3.0-or-later\npragma solidity 0.8.7;\n\nimport { IProxied } from \"../../modules/proxy-factory/contracts/interfaces/IProxied.sol\";\n\n/// @title A Maple implementation that is to be proxied, must implement IMapleProxied.\ninterface IMapleProxied is IProxied {\n\n    /**\n     *  @dev   The instance was upgraded.\n     *  @param toVersion_ The new version of the loan.\n     *  @param arguments_ The upgrade arguments, if any.\n     */\n    event Upgraded(uint256 toVersion_, bytes arguments_);\n\n    /**\n     *  @dev   Upgrades a contract implementation to a specific version.\n     *         Access control logic critical since caller can force a selfdestruct via a malicious `migrator_` which is delegatecalled.\n     *  @param toVersion_ The version to upgrade to.\n     *  @param arguments_ Some encoded arguments to use for the upgrade.\n     */\n    function upgrade(uint256 toVersion_, bytes calldata arguments_) external;\n\n}\n"},{"file_path":"modules/maple-proxy-factory/contracts/interfaces/IMapleProxyFactory.sol","source_code":"// SPDX-License-Identifier: AGPL-3.0-or-later\npragma solidity 0.8.7;\n\nimport { IDefaultImplementationBeacon } from \"../../modules/proxy-factory/contracts/interfaces/IDefaultImplementationBeacon.sol\";\n\n/// @title A Maple factory for Proxy contracts that proxy MapleProxied implementations.\ninterface IMapleProxyFactory is IDefaultImplementationBeacon {\n\n    /**************************************************************************************************************************************/\n    /*** Events                                                                                                                         ***/\n    /**************************************************************************************************************************************/\n\n    /**\n     *  @dev   A default version was set.\n     *  @param version_ The default version.\n     */\n    event DefaultVersionSet(uint256 indexed version_);\n\n    /**\n     *  @dev   A version of an implementation, at some address, was registered, with an optional initializer.\n     *  @param version_               The version registered.\n     *  @param implementationAddress_ The address of the implementation.\n     *  @param initializer_           The address of the initializer, if any.\n     */\n    event ImplementationRegistered(uint256 indexed version_, address indexed implementationAddress_, address indexed initializer_);\n\n    /**\n     *  @dev   A proxy contract was deployed with some initialization arguments.\n     *  @param version_                 The version of the implementation being proxied by the deployed proxy contract.\n     *  @param instance_                The address of the proxy contract deployed.\n     *  @param initializationArguments_ The arguments used to initialize the proxy contract, if any.\n     */\n    event InstanceDeployed(uint256 indexed version_, address indexed instance_, bytes initializationArguments_);\n\n    /**\n     *  @dev   A instance has upgraded by proxying to a new implementation, with some migration arguments.\n     *  @param instance_           The address of the proxy contract.\n     *  @param fromVersion_        The initial implementation version being proxied.\n     *  @param toVersion_          The new implementation version being proxied.\n     *  @param migrationArguments_ The arguments used to migrate, if any.\n     */\n    event InstanceUpgraded(address indexed instance_, uint256 indexed fromVersion_, uint256 indexed toVersion_, bytes migrationArguments_);\n\n    /**\n     *  @dev   The MapleGlobals was set.\n     *  @param mapleGlobals_ The address of a Maple Globals contract.\n     */\n    event MapleGlobalsSet(address indexed mapleGlobals_);\n\n    /**\n     *  @dev   An upgrade path was disabled, with an optional migrator contract.\n     *  @param fromVersion_ The starting version of the upgrade path.\n     *  @param toVersion_   The destination version of the upgrade path.\n     */\n    event UpgradePathDisabled(uint256 indexed fromVersion_, uint256 indexed toVersion_);\n\n    /**\n     *  @dev   An upgrade path was enabled, with an optional migrator contract.\n     *  @param fromVersion_ The starting version of the upgrade path.\n     *  @param toVersion_   The destination version of the upgrade path.\n     *  @param migrator_    The address of the migrator, if any.\n     */\n    event UpgradePathEnabled(uint256 indexed fromVersion_, uint256 indexed toVersion_, address indexed migrator_);\n\n    /**************************************************************************************************************************************/\n    /*** State Variables                                                                                                                ***/\n    /**************************************************************************************************************************************/\n\n    /**\n     *  @dev The default version.\n     */\n    function defaultVersion() external view returns (uint256 defaultVersion_);\n\n    /**\n     *  @dev The address of the MapleGlobals contract.\n     */\n    function mapleGlobals() external view returns (address mapleGlobals_);\n\n    /**\n     *  @dev    Whether the upgrade is enabled for a path from a version to another version.\n     *  @param  toVersion_   The initial version.\n     *  @param  fromVersion_ The destination version.\n     *  @return allowed_     Whether the upgrade is enabled.\n     */\n    function upgradeEnabledForPath(uint256 toVersion_, uint256 fromVersion_) external view returns (bool allowed_);\n\n    /**************************************************************************************************************************************/\n    /*** State Changing Functions                                                                                                       ***/\n    /**************************************************************************************************************************************/\n\n    /**\n     *  @dev    Deploys a new instance proxying the default implementation version, with some initialization arguments.\n     *          Uses a nonce and `msg.sender` as a salt for the CREATE2 opcode during instantiation to produce deterministic addresses.\n     *  @param  arguments_ The initialization arguments to use for the instance deployment, if any.\n     *  @param  salt_      The salt to use in the contract creation process.\n     *  @return instance_  The address of the deployed proxy contract.\n     */\n    function createInstance(bytes calldata arguments_, bytes32 salt_) external returns (address instance_);\n\n    /**\n     *  @dev   Enables upgrading from a version to a version of an implementation, with an optional migrator.\n     *         Only the Governor can call this function.\n     *  @param fromVersion_ The starting version of the upgrade path.\n     *  @param toVersion_   The destination version of the upgrade path.\n     *  @param migrator_    The address of the migrator, if any.\n     */\n    function enableUpgradePath(uint256 fromVersion_, uint256 toVersion_, address migrator_) external;\n\n    /**\n     *  @dev   Disables upgrading from a version to a version of a implementation.\n     *         Only the Governor can call this function.\n     *  @param fromVersion_ The starting version of the upgrade path.\n     *  @param toVersion_   The destination version of the upgrade path.\n     */\n    function disableUpgradePath(uint256 fromVersion_, uint256 toVersion_) external;\n\n    /**\n     *  @dev   Registers the address of an implementation contract as a version, with an optional initializer.\n     *         Only the Governor can call this function.\n     *  @param version_               The version to register.\n     *  @param implementationAddress_ The address of the implementation.\n     *  @param initializer_           The address of the initializer, if any.\n     */\n    function registerImplementation(uint256 version_, address implementationAddress_, address initializer_) external;\n\n    /**\n     *  @dev   Sets the default version.\n     *         Only the Governor can call this function.\n     *  @param version_ The implementation version to set as the default.\n     */\n    function setDefaultVersion(uint256 version_) external;\n\n    /**\n     *  @dev   Sets the Maple Globals contract.\n     *         Only the Governor can call this function.\n     *  @param mapleGlobals_ The address of a Maple Globals contract.\n     */\n    function setGlobals(address mapleGlobals_) external;\n\n    /**\n     *  @dev   Upgrades the calling proxy contract's implementation, with some migration arguments.\n     *  @param toVersion_ The implementation version to upgrade the proxy contract to.\n     *  @param arguments_ The migration arguments, if any.\n     */\n    function upgradeInstance(uint256 toVersion_, bytes calldata arguments_) external;\n\n    /**************************************************************************************************************************************/\n    /*** View Functions                                                                                                                 ***/\n    /**************************************************************************************************************************************/\n\n    /**\n     *  @dev    Returns the deterministic address of a potential proxy, given some arguments and salt.\n     *  @param  arguments_       The initialization arguments to be used when deploying the proxy.\n     *  @param  salt_            The salt to be used when deploying the proxy.\n     *  @return instanceAddress_ The deterministic address of a potential proxy.\n     */\n    function getInstanceAddress(bytes calldata arguments_, bytes32 salt_) external view returns (address instanceAddress_);\n\n    /**\n     *  @dev    Returns the address of an implementation version.\n     *  @param  version_        The implementation version.\n     *  @return implementation_ The address of the implementation.\n     */\n    function implementationOf(uint256 version_) external view returns (address implementation_);\n\n    /**\n     *  @dev    Returns if a given address has been deployed by this factory/\n     *  @param  instance_   The address to check.\n     *  @return isInstance_ A boolean indication if the address has been deployed by this factory.\n     */\n    function isInstance(address instance_) external view returns (bool isInstance_);\n\n    /**\n     *  @dev    Returns the address of a migrator contract for a migration path (from version, to version).\n     *          If oldVersion_ == newVersion_, the migrator is an initializer.\n     *  @param  oldVersion_ The old version.\n     *  @param  newVersion_ The new version.\n     *  @return migrator_   The address of a migrator contract.\n     */\n    function migratorForPath(uint256 oldVersion_, uint256 newVersion_) external view returns (address migrator_);\n\n    /**\n     *  @dev    Returns the version of an implementation contract.\n     *  @param  implementation_ The address of an implementation contract.\n     *  @return version_        The version of the implementation contract.\n     */\n    function versionOf(address implementation_) external view returns (uint256 version_);\n\n}\n"},{"file_path":"modules/maple-proxy-factory/modules/proxy-factory/contracts/ProxiedInternals.sol","source_code":"// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity ^0.8.7;\n\nimport { SlotManipulatable } from \"./SlotManipulatable.sol\";\n\n/// @title An implementation that is to be proxied, will need ProxiedInternals.\nabstract contract ProxiedInternals is SlotManipulatable {\n\n    /// @dev Storage slot with the address of the current factory. `keccak256('eip1967.proxy.factory') - 1`.\n    bytes32 private constant FACTORY_SLOT = bytes32(0x7a45a402e4cb6e08ebc196f20f66d5d30e67285a2a8aa80503fa409e727a4af1);\n\n    /// @dev Storage slot with the address of the current factory. `keccak256('eip1967.proxy.implementation') - 1`.\n    bytes32 private constant IMPLEMENTATION_SLOT = bytes32(0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc);\n\n    /// @dev Delegatecalls to a migrator contract to manipulate storage during an initialization or migration.\n    function _migrate(address migrator_, bytes calldata arguments_) internal virtual returns (bool success_) {\n        uint256 size;\n\n        assembly {\n            size := extcodesize(migrator_)\n        }\n\n        if (size == uint256(0)) return false;\n\n        ( success_, ) = migrator_.delegatecall(arguments_);\n    }\n\n    /// @dev Sets the factory address in storage.\n    function _setFactory(address factory_) internal virtual returns (bool success_) {\n        _setSlotValue(FACTORY_SLOT, bytes32(uint256(uint160(factory_))));\n        return true;\n    }\n\n    /// @dev Sets the implementation address in storage.\n    function _setImplementation(address implementation_) internal virtual returns (bool success_) {\n        _setSlotValue(IMPLEMENTATION_SLOT, bytes32(uint256(uint160(implementation_))));\n        return true;\n    }\n\n    /// @dev Returns the factory address.\n    function _factory() internal view virtual returns (address factory_) {\n        return address(uint160(uint256(_getSlotValue(FACTORY_SLOT))));\n    }\n\n    /// @dev Returns the implementation address.\n    function _implementation() internal view virtual returns (address implementation_) {\n        return address(uint160(uint256(_getSlotValue(IMPLEMENTATION_SLOT))));\n    }\n\n}\n"},{"file_path":"modules/maple-proxy-factory/modules/proxy-factory/contracts/SlotManipulatable.sol","source_code":"// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity ^0.8.7;\n\nabstract contract SlotManipulatable {\n\n    function _getReferenceTypeSlot(bytes32 slot_, bytes32 key_) internal pure returns (bytes32 value_) {\n        return keccak256(abi.encodePacked(key_, slot_));\n    }\n\n    function _getSlotValue(bytes32 slot_) internal view returns (bytes32 value_) {\n        assembly {\n            value_ := sload(slot_)\n        }\n    }\n\n    function _setSlotValue(bytes32 slot_, bytes32 value_) internal {\n        assembly {\n            sstore(slot_, value_)\n        }\n    }\n\n}\n"},{"file_path":"modules/maple-proxy-factory/modules/proxy-factory/contracts/interfaces/IDefaultImplementationBeacon.sol","source_code":"// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity ^0.8.7;\n\n/// @title An beacon that provides a default implementation for proxies, must implement IDefaultImplementationBeacon.\ninterface IDefaultImplementationBeacon {\n\n    /// @dev The address of an implementation for proxies.\n    function defaultImplementation() external view returns (address defaultImplementation_);\n\n}\n"},{"file_path":"modules/maple-proxy-factory/modules/proxy-factory/contracts/interfaces/IProxied.sol","source_code":"// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity ^0.8.7;\n\n/// @title An implementation that is to be proxied, must implement IProxied.\ninterface IProxied {\n\n    /**\n     *  @dev The address of the proxy factory.\n     */\n    function factory() external view returns (address factory_);\n\n    /**\n     *  @dev The address of the implementation contract being proxied.\n     */\n    function implementation() external view returns (address implementation_);\n\n    /**\n     *  @dev   Modifies the proxy's implementation address.\n     *  @param newImplementation_ The address of an implementation contract.\n     */\n    function setImplementation(address newImplementation_) external;\n\n    /**\n     *  @dev   Modifies the proxy's storage by delegate-calling a migrator contract with some arguments.\n     *         Access control logic critical since caller can force a selfdestruct via a malicious `migrator_` which is delegatecalled.\n     *  @param migrator_  The address of a migrator contract.\n     *  @param arguments_ Some encoded arguments to use for the migration.\n     */\n    function migrate(address migrator_, bytes calldata arguments_) external;\n\n}\n"}],"certified":false,"conflicting_implementations":null,"abi":[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"issuanceRate_","type":"uint256"},{"indexed":false,"internalType":"uint112","name":"accountedInterest_","type":"uint112"}],"name":"AccountingStateUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"loan_","type":"address"},{"indexed":false,"internalType":"uint256","name":"principal_","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"netInterest_","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"delegateManagementFee_","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"delegateServiceFee_","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"platformManagementFee_","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"platformServiceFee_","type":"uint256"}],"name":"ClaimedFundsDistributed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"loan_","type":"address"},{"indexed":false,"internalType":"uint256","name":"principal_","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"netInterest_","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"platformManagementFee_","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"platformServiceFee_","type":"uint256"}],"name":"ExpectedClaim","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"loan_","type":"address"},{"indexed":false,"internalType":"uint256","name":"toBorrower_","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"toPool_","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"toTreasury_","type":"uint256"}],"name":"LiquidatedFundsDistributed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"loan_","type":"address"},{"indexed":false,"internalType":"uint256","name":"platformManagementFeeRate_","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"delegateManagementFeeRate_","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"paymentDueDate_","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"issuanceRate_","type":"uint256"}],"name":"PaymentAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"loan_","type":"address"}],"name":"PaymentRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint128","name":"principalOut_","type":"uint128"}],"name":"PrincipalOutUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint128","name":"unrealizedLosses_","type":"uint128"}],"name":"UnrealizedLossesUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"toVersion_","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"arguments_","type":"bytes"}],"name":"Upgraded","type":"event"},{"inputs":[],"name":"HUNDRED_PERCENT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PRECISION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"accountedInterest","outputs":[{"internalType":"uint112","name":"","type":"uint112"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"accruedInterest","outputs":[{"internalType":"uint256","name":"accruedInterest_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"assetsUnderManagement","outputs":[{"internalType":"uint256","name":"assetsUnderManagement_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"loan_","type":"address"},{"internalType":"uint256","name":"principal_","type":"uint256"}],"name":"callPrincipal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"int256","name":"principal_","type":"int256"},{"internalType":"uint256","name":"interest_","type":"uint256"},{"internalType":"uint256","name":"delegateServiceFee_","type":"uint256"},{"internalType":"uint256","name":"platformServiceFee_","type":"uint256"},{"internalType":"uint40","name":"nextPaymentDueDate_","type":"uint40"}],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"domainStart","outputs":[{"internalType":"uint40","name":"","type":"uint40"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"factory","outputs":[{"internalType":"address","name":"factory_","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"loan_","type":"address"}],"name":"fund","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"fundsAsset","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"loan_","type":"address"}],"name":"impairLoan","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"impairmentFor","outputs":[{"internalType":"uint40","name":"impairedDate","type":"uint40"},{"internalType":"bool","name":"impairedByGovernor","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"implementation","outputs":[{"internalType":"address","name":"implementation_","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"issuanceRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"migrator_","type":"address"},{"internalType":"bytes","name":"arguments_","type":"bytes"}],"name":"migrate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"paymentFor","outputs":[{"internalType":"uint24","name":"platformManagementFeeRate","type":"uint24"},{"internalType":"uint24","name":"delegateManagementFeeRate","type":"uint24"},{"internalType":"uint40","name":"startDate","type":"uint40"},{"internalType":"uint168","name":"issuanceRate","type":"uint168"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"poolManager","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"principalOut","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"loan_","type":"address"},{"internalType":"address","name":"refinancer_","type":"address"},{"internalType":"uint256","name":"deadline_","type":"uint256"},{"internalType":"bytes[]","name":"calls_","type":"bytes[]"}],"name":"proposeNewTerms","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"loan_","type":"address"},{"internalType":"address","name":"refinancer_","type":"address"},{"internalType":"uint256","name":"deadline_","type":"uint256"},{"internalType":"bytes[]","name":"calls_","type":"bytes[]"}],"name":"rejectNewTerms","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"loan_","type":"address"}],"name":"removeCall","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"loan_","type":"address"}],"name":"removeLoanImpairment","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"implementation_","type":"address"}],"name":"setImplementation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"loan_","type":"address"},{"internalType":"address","name":"liquidatorFactory_","type":"address"}],"name":"triggerDefault","outputs":[{"internalType":"bool","name":"liquidationComplete_","type":"bool"},{"internalType":"uint256","name":"remainingLosses_","type":"uint256"},{"internalType":"uint256","name":"unrecoveredPlatformFees_","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"loan_","type":"address"}],"name":"triggerDefault","outputs":[{"internalType":"uint256","name":"remainingLosses_","type":"uint256"},{"internalType":"uint256","name":"unrecoveredPlatformFees_","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unrealizedLosses","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"version_","type":"uint256"},{"internalType":"bytes","name":"arguments_","type":"bytes"}],"name":"upgrade","outputs":[],"stateMutability":"nonpayable","type":"function"}],"is_changed_bytecode":false,"is_partially_verified":true,"constructor_args":null}