Maple
  • Welcome to Maple
  • Maple for Lenders
    • Introduction
    • Lending
    • Defaults and Impairments
    • Margin Calls and Liquidations
    • Risk
    • Withdrawal Process
  • syrupUSDC for Lenders
    • Powered by Maple
    • Lending in syrupUSDC and syrupUSDT
    • Commitments
    • Drips Rewards
    • Withdrawals
    • Monthly Updates
    • Pendle Integration
  • SyrupUSDC Rewards Prize Draw Program Summary
  • FAQ
  • Maple for Borrowers
    • Introduction
    • Loan Management
  • Maple for Token Holders
    • Introduction to SYRUP
      • MPL to SYRUP Conversion
      • FAQs
    • SYRUP Tokenomics
      • Staking
      • Staking Smart Contract Details
    • Governance and Voting
    • Drips Rewards
    • Research and Media
      • Podcasts
      • News Articles
      • TV Segments
      • Research Reports
      • Data Dashboards
    • Additional Resources
  • Technical Resources
    • Protocol Overview
      • Background
      • Protocol Actors
      • Smart Contract Architecture
      • Glossary
      • Smart Contract Addresses
      • Fees
      • Composability
      • Proxies and Upgradeability
    • Security
      • Security
      • List of Assumptions
      • External Entry Points
      • Emergency Protocol Pause
      • Protocol Invariants
      • Test Report
    • Loans
      • Loans
      • Fixed Term Loans
      • Open Term Loans
      • Refinancing
      • Impairments
      • Defaults
    • Pools
      • Pools
      • Pool Creation
      • PoolManager
      • PoolDelegateCover
      • Accounting
        • Pool Accounting
        • Pool Exchange Rates
    • Strategies
      • Fixed Term Loan Manager
        • Overview
        • Claims
        • Advance Payment Accounting
        • Accounting Examples
      • Open Term Loan Manager
      • DeFi Strategies
    • Withdrawal Managers
      • WithdrawalManager (Cyclical)
      • WithdrawalManager (Queue)
    • Singletons
      • Globals
      • MapleTreasury
      • Oracles
      • Pool Permission Manager
    • Admin Functions
      • Governor Admin Actions
        • Operational Admin Actions
      • Pool Delegate Admin Actions
      • Timelocks
    • Operations
      • Protocol Deployment
      • Open Term Loan Deployment
      • December 2023 Deployment & Upgrade Procedure
      • Strategies Release Deployment Procedure
    • Interfaces
      • FixedTermLoan
      • FixedTermLoanFactory
      • FixedTermLoanFeeManager
      • FixedTermLoanInitializer
      • FixedTermLoanManager
      • FixedTermLoanManagerFactory
      • FixedTermLoanManagerInitializer
      • FixedTermLoanRefinancer
      • Globals
      • Liquidator
      • LiquidatorFactory
      • LiquidatorInitializer
      • OpenTermLoan
      • OpenTermLoanFactory
      • OpenTermLoanInitializer
      • OpenTermLoanManager
      • OpenTermLoanManagerFactory
      • OpenTermLoanManagerInitializer
      • OpenTermLoanRefinancer
      • Pool
      • PoolDelegateCover
      • PoolDeployer
      • PoolManager
      • PoolManagerFactory
      • PoolManagerInitializer
      • PoolPermissionManager
      • WithdrawalManager (Cyclical)
      • WithdrawalManagerFactory (Cyclical)
      • WithdrawalManagerInitializer (Cyclical)
      • WithdrawalManager (Queue)
      • WithdrawalManagerFactory (Queue)
      • WithdrawalManagerInitializer (Queue)
    • SYRUP Token
      • Architectural Overview
      • Base ERC20 Structure
      • Upgradability
      • Modules
      • Time Locks
      • Recapitalization Module
      • Emergency Module
      • Deployment and Migration Procedure
    • GraphQL API
    • SDK
      • Introduction
      • Installation
      • Protocol Actors
      • Usage Guide
  • Troubleshooting & Support
    • Intercom
  • Maple 1.0
    • Access to deprecated Maple 1.0
  • Legal
    • Borrower MLA
    • KYC
    • Interface Terms of Use
    • Privacy Policy
    • syrupUSDC and syrupUSDT - Risks
    • syrupUSDC and syrupUSDT - Defaults and Impairments
    • syrupUSDC and syrupUSDT - Available Jurisdictions
    • Interface Terms of Use [syrupUSDC and syrupUSDT]
    • Interface Terms of Use [Syrup.fi/convert/ and Syrup.fi/stake/]
    • syrupUSDC and syrupUSDT- Privacy Policy
    • SyrupUSDC Rewards Prize Draw Terms & Conditions
Powered by GitBook
On this page
  1. Technical Resources
  2. Security

Protocol Invariants

* Fixed Term Loan
   * Invariant A: collateral balance >= collateral`
   * Invariant B: fundsAsset >= drawableFunds`
   * Invariant C: `collateral >= collateralRequired * (principal - drawableFunds) / principalRequested`

* Fixed Term Loan Manager (non-liquidating)
   * Invariant A: domainStart <= domainEnd
   * Invariant B: sortedPayments is always sorted
   * Invariant C: outstandingInterest = ∑outstandingInterest(loan) (theoretical)
   * Invariant D: totalPrincipal = ∑loan.principal()
   * Invariant E: issuanceRate = ∑issuanceRate(payment)
   * Invariant F: unrealizedLosses <= assetsUnderManagement()
   * Invariant G: unrealizedLosses == 0
   * Invariant H: assetsUnderManagement == ∑loan.principal() + ∑outstandingInterest(loan)
   * Invariant I: domainStart <= block.timestamp
   * Invariant J: if (loanManager.paymentWithEarliestDueDate != 0) then issuanceRate > 0
   * Invariant K: if (loanManager.paymentWithEarliestDueDate != 0) then domainEnd == paymentWithEarliestDueDate
   * Invariant L: refinanceInterest[payment] = loan.refinanceInterest()
   * Invariant M: paymentDueDate[payment] = loan.paymentDueDate()
   * Invariant N: startDate[payment] <= loan.paymentDueDate() - loan.paymentInterval()

* Open Term Loan
   * Invariant A: dateFunded <= datePaid, dateCalled, dateImpaired (if not zero)
   * Invariant B: datePaid <= dateImpaired (if not zero)
   * Invariant C: datePaid <= dateCalled (if not zero)
   * Invariant D: calledPrincipal <= principal
   * Invariant E: dateCalled != 0 -> calledPrincipal != 0
   * Invariant F: paymentDueDate() <= defaultDate()
   * Invariant G: getPaymentBreakdown == theoretical calculation

* Open Term Loan Manager
   * Invariant A: accountedInterest + accruedInterest() == ∑loan.getPaymentBreakdown(block.timestamp) (minus fees)
   * Invariant B: if no payments exist: accountedInterest == 0
   * Invariant C: principalOut = ∑loan.principal()
   * Invariant D: issuanceRate = ∑payment.issuanceRate
   * Invariant E: unrealizedLosses <= assetsUnderManagement()
   * Invariant F: if no impairments exist: unrealizedLosses == 0
   * Invariant G: block.timestamp >= domainStart
   * Invariant H: payment.startDate == loan.dateFunded() || loan.datePaid()
   * Invariant I: payment.issuanceRate == theoretical calculation (minus management fees)
   * Invariant J: payment.impairedDate >= payment.startDate
   * Invariant K: assetsUnderManagement - unrealizedLosses - ∑outstandingValue(loan) ~= 0

* Pool (non-liquidating)
   * Invariant A: totalAssets > fundsAsset balance of pool
   * Invariant B: ∑balanceOfAssets == totalAssets (with rounding)
   * Invariant C: totalAssets >= totalSupply (in non-liquidating scenario)
   * Invariant D: convertToAssets(totalSupply) == totalAssets (with rounding)
   * Invariant E: convertToShares(totalAssets) == totalSupply (with rounding)
   * Invariant F: balanceOfAssets[user] >= balanceOf[user]
   * Invariant G: ∑balanceOf[user] == totalSupply
   * Invariant H: convertToExitShares == convertToShares
   * Invariant I: totalAssets == poolManager.totalAssets()
   * Invariant J: unrealizedLosses == poolManager.unrealizedLosses()
   * Invariant K: convertToExitShares == poolManager.convertToExitShares()

* PoolManager (non-liquidating)
   * Invariant A: totalAssets == cash + ∑assetsUnderManagement[loanManager]
   * Invariant B: hasSufficientCover == fundsAsset balance of cover > globals.minCoverAmount

* Pool Permission Manager
   * Invariant A: pool.permissionLevel ∈ [0, 3]
   * Invariant B: pool.bitmap ∈ [0, MAX]
   * Invariant C: lender.bitmap ∈ [0, MAX]
   * Invariant D: pool.permissionLevel == public -> permanently public

* Withdrawal Manager (Cyclical)
   * Invariant A: WM LP balance == ∑lockedShares(user)
   * Invariant B: totalCycleShares == ∑lockedShares(user)[cycle] (for all cycles)
   * Invariant C: windowStart[currentCycle] <= block.timestamp
   * Invariant D: initialCycleTime[currentConfig] <= block.timestamp
   * Invariant E: initialCycleId[currentConfig] <= currentCycle
   * Invariant F: getRedeemableAmounts.shares[owner] <= WM LP balance
   * Invariant G: getRedeemableAmounts.shares[owner] <= lockedShares[user]
   * Invariant H: getRedeemableAmounts.shares[owner] <= totalCycleShares[exitCycleId[user]]
   * Invariant I: getRedeemableAmounts.assets[owner] <= fundsAsset balance of pool
   * Invariant J: getRedeemableAmounts.assets[owner] <= totalCycleShares[exitCycleId[user]] * exchangeRate
   * Invariant K: getRedeemableAmounts.assets[owner] <= lockedShares[user] * exchangeRate
   * Invariant L: getRedeemableAmounts.partialLiquidity == (lockedShares[user] * exchangeRate < fundsAsset balance of pool)
   * Invariant M: lockedLiquidity <= pool.totalAssets()
   * Invariant N: lockedLiquidity <= totalCycleShares[exitCycleId[user]] * exchangeRate

* Withdrawal Manager (Queue)
   * Invariant A: ∑request.shares + ∑owner.manualShares == totalShares
   * Invariant B: balanceOf(this) >= totalShares
   * Invariant C: ∀ requestId(owner) != 0 -> request.shares > 0 && request.owner == owner
   * Invariant D: nextRequestId <= lastRequestId + 1
   * Invariant E: nextRequestId != 0
   * Invariant F: requests(0) == (0, 0)
   * Invariant G: ∀ requestId[lender] ∈ [0, lastRequestId]
   * Invariant H: requestId is unique
   * Invariant I: lender is unique

* Strategy
   * Invariant A: assetsUnderManagement == currentTotalAssets - accruedFees
   * Invariant B: currentAccruedFees <= currentTotalAssets
   * Invariant C: strategyState == ACTIVE -> unrealizedLosses == 0
   * Invariant D: strategyState == IMPAIRED -> assetsUnderManagement == unrealizedLosses
   * Invariant E: strategyState == INACTIVE -> assetsUnderManagement == unrealizedLosses == 0
   * Invariant F: strategyState ∈ [0, 2]
   * Invariant G: strategyFeeRate <= 1e6
PreviousEmergency Protocol PauseNextTest Report

Last updated 2 months ago