Source Code

;; Flash Loan Contract - Inspired by ERC-3156: Flash Loans
;; A standard interface for single-asset flash loans on Stacks.
;;
;; This contract implements flash lending functionality where assets are lent
;; to a borrower smart contract with the condition that the assets are returned,
;; plus a fee, before the end of the transaction.
;;
;; Reference: https://eips.ethereum.org/EIPS/eip-3156
;;
;; Clarity v4 Functions Used:
;; - contract-hash?: Verify borrower contract integrity
;; - restrict-assets?: Control flash loan availability based on asset restrictions
;; - to-ascii?: Convert token symbols to ASCII for display
;; - stacks-block-time: Track loan timestamps for audit/security
;; - secp256r1-verify: Verify signatures for authorized flash loan operations

;; ==============================
;; Constants
;; ==============================

;; Contract owner for administrative functions
(define-constant CONTRACT_OWNER tx-sender)

;; Callback success hash - analogous to ERC-3156's keccak256("ERC3156FlashBorrower.onFlashLoan")
;; Using a predefined buffer as the expected callback return value
(define-constant CALLBACK_SUCCESS 0x4368616e676520746865207374617465206f6620796f757220636f6e74726163)

;; Fee denominator (10000 = 100%, so fee of 100 = 1%)
(define-constant FEE_DENOMINATOR u10000)

;; Default flash loan fee (0.09% = 9 basis points, similar to Aave)
(define-constant DEFAULT_FEE_RATE u9)

;; Maximum flash loan fee (5% = 500 basis points)
(define-constant MAX_FEE_RATE u500)

;; Minimum flash loan amount
(define-constant MIN_FLASH_LOAN_AMOUNT u1000)

;; Error codes following ERC-3156 patterns
(define-constant ERR_UNAUTHORIZED (err u3001))
(define-constant ERR_UNSUPPORTED_TOKEN (err u3002))
(define-constant ERR_CALLBACK_FAILED (err u3003))
(define-constant ERR_REPAY_FAILED (err u3004))
(define-constant ERR_TRANSFER_FAILED (err u3005))
(define-constant ERR_INSUFFICIENT_LIQUIDITY (err u3006))
(define-constant ERR_LOAN_AMOUNT_TOO_SMALL (err u3007))
(define-constant ERR_LOAN_AMOUNT_TOO_LARGE (err u3008))
(define-constant ERR_ASSETS_RESTRICTED (err u3009))
(define-constant ERR_FLASH_LOAN_PAUSED (err u3010))
(define-constant ERR_INVALID_FEE_RATE (err u3011))
(define-constant ERR_BORROWER_NOT_AUTHORIZED (err u3012))
(define-constant ERR_INVALID_SIGNATURE (err u3013))
(define-constant ERR_LOAN_ALREADY_ACTIVE (err u3014))
(define-constant ERR_REENTRANCY_DETECTED (err u3015))
(define-constant ERR_TOKEN_NOT_FOUND (err u3016))
(define-constant ERR_INVALID_AMOUNT (err u3017))
(define-constant ERR_CONTRACT_HASH_MISMATCH (err u3018))

;; ==============================
;; Data Variables
;; ==============================

;; Current flash loan fee rate (in basis points)
(define-data-var flash-fee-rate uint DEFAULT_FEE_RATE)

;; Flash loan paused state
(define-data-var flash-loan-paused bool false)

;; Asset restriction flag (using Clarity v4's restrict-assets? concept)
(define-data-var assets-restricted bool false)

;; Total flash loans counter
(define-data-var total-flash-loans uint u0)

;; Total fees collected
(define-data-var total-fees-collected uint u0)

;; Reentrancy guard
(define-data-var reentrancy-locked bool false)

;; ==============================
;; Data Maps
;; ==============================

;; Supported tokens for flash lending
;; Maps token contract principal to token configuration
(define-map supported-tokens
  principal
  {
    symbol: (string-utf8 10),
    decimals: uint,
    max-flash-loan: uint,
    custom-fee-rate: (optional uint),
    enabled: bool,
    total-borrowed: uint,
    total-fees: uint,
  }
)

;; Flash loan liquidity pool (token balances available for flash loans)
(define-map flash-liquidity
  principal
  uint
)

;; Authorized borrower contracts
;; Following ERC-3156's security recommendation to whitelist borrowers
(define-map authorized-borrowers
  principal
  {
    name: (string-utf8 64),
    authorized-at: uint,
    total-loans: uint,
    total-repaid: uint,
    active: bool,
    contract-hash: (optional (buff 32)),
  }
)

;; Active flash loan tracking (reentrancy protection)
(define-map active-flash-loans
  { borrower: principal, token: principal }
  {
    amount: uint,
    fee: uint,
    initiated-at: uint,
    initiator: principal,
  }
)

;; Flash loan history for audit purposes
(define-map flash-loan-history
  uint
  {
    borrower: principal,
    token: principal,
    amount: uint,
    fee: uint,
    initiator: principal,
    timestamp: uint,
    success: bool,
    callback-verified: bool,
    signature-verified: bool,
  }
)

;; Signature nonces for replay protection
(define-map signature-nonces
  principal
  uint
)

;; ==============================
;; Clarity v4 Functions - Contract Verification
;; ==============================

;; Get the hash of this contract using Clarity v4's contract-hash?
;; Note: contract-hash? returns (response (buff 32) uint)
(define-read-only (get-contract-hash)
  (contract-hash? tx-sender)
)

;; Get the hash of a borrower contract for verification
(define-read-only (get-borrower-contract-hash (borrower principal))
  (contract-hash? borrower)
)

;; Verify borrower contract integrity by checking hash
(define-read-only (verify-borrower-contract (borrower principal) (expected-hash (buff 32)))
  (match (contract-hash? borrower)
    actual-hash (is-eq expected-hash actual-hash)
    err-code false
  )
)

;; ==============================
;; Clarity v4 Functions - Time
;; ==============================

;; Get current Stacks block time using Clarity v4's stacks-block-time
(define-read-only (get-current-block-time)
  stacks-block-time
)

;; ==============================
;; Clarity v4 Functions - ASCII Conversion
;; ==============================

;; Convert token symbol to ASCII using to-ascii?
;; to-ascii? returns (response string-ascii uint)
(define-read-only (token-symbol-to-ascii (symbol (string-utf8 10)))
  (to-ascii? symbol)
)

;; ==============================
;; Clarity v4 Functions - Asset Restriction
;; ==============================

;; Check if flash loans are currently restricted
(define-read-only (are-assets-restricted)
  (var-get assets-restricted)
)

;; Toggle asset restrictions (owner only)
(define-public (set-asset-restrictions (restricted bool))
  (begin
    (asserts! (is-eq tx-sender CONTRACT_OWNER) ERR_UNAUTHORIZED)
    (var-set assets-restricted restricted)
    (print {
      event: "AssetRestrictionsUpdated",
      restricted: restricted,
      updated-by: tx-sender,
      timestamp: stacks-block-time,
    })
    (ok restricted)
  )
)

;; ==============================
;; Clarity v4 Functions - Signature Verification
;; ==============================

;; Verify a secp256r1 signature for authorized flash loan operations
;; This enables WebAuthn/passkey-based authorization for flash loans
(define-read-only (verify-flash-loan-signature
    (message-hash (buff 32))
    (signature (buff 64))
    (public-key (buff 33))
  )
  (secp256r1-verify message-hash signature public-key)
)

;; Get signature nonce for a borrower (replay protection)
(define-read-only (get-signature-nonce (borrower principal))
  (default-to u0 (map-get? signature-nonces borrower))
)

;; ==============================
;; ERC-3156 Core Functions - Lender Interface
;; ==============================

;; maxFlashLoan - The amount of currency available to be lent
;; Returns 0 if token is not supported (as per ERC-3156)
(define-read-only (max-flash-loan (token principal))
  (if (var-get flash-loan-paused)
    u0
    (if (var-get assets-restricted)
      u0
      (match (map-get? supported-tokens token)
        token-config
          (if (get enabled token-config)
            (let ((available-liquidity (default-to u0 (map-get? flash-liquidity token))))
              (if (> (get max-flash-loan token-config) available-liquidity)
                available-liquidity
                (get max-flash-loan token-config)
              )
            )
            u0
          )
        u0
      )
    )
  )
)

;; flashFee - The fee to be charged for a given loan
;; Reverts if token is not supported (as per ERC-3156)
(define-read-only (flash-fee (token principal) (amount uint))
  (match (map-get? supported-tokens token)
    token-config
      (if (get enabled token-config)
        (let (
          (fee-rate (default-to (var-get flash-fee-rate) (get custom-fee-rate token-config)))
        )
          (ok (/ (* amount fee-rate) FEE_DENOMINATOR))
        )
        ERR_UNSUPPORTED_TOKEN
      )
    ERR_UNSUPPORTED_TOKEN
  )
)

;; ==============================
;; Reentrancy Guard
;; ==============================

(define-private (acquire-lock)
  (if (var-get reentrancy-locked)
    false
    (begin
      (var-set reentrancy-locked true)
      true
    )
  )
)

(define-private (release-lock)
  (var-set reentrancy-locked false)
)

;; ==============================
;; Flash Loan Execution
;; ==============================

;; flashLoan - Initiate a flash loan
;; Following ERC-3156 specification with Clarity adaptations
;; Note: In Clarity, we cannot call arbitrary contract functions dynamically,
;; so the borrower must call this and handle the callback internally
(define-public (flash-loan
    (token principal)
    (amount uint)
    (data (buff 256))
  )
  (let (
    (borrower tx-sender)
    (initiator tx-sender)
    (loan-id (+ (var-get total-flash-loans) u1))
  )
    ;; Check reentrancy
    (asserts! (acquire-lock) ERR_REENTRANCY_DETECTED)
    
    ;; Check if flash loans are paused
    (asserts! (not (var-get flash-loan-paused)) ERR_FLASH_LOAN_PAUSED)
    
    ;; Check if assets are restricted
    (asserts! (not (var-get assets-restricted)) ERR_ASSETS_RESTRICTED)
    
    ;; Check minimum amount
    (asserts! (>= amount MIN_FLASH_LOAN_AMOUNT) ERR_LOAN_AMOUNT_TOO_SMALL)
    
    ;; Check token is supported and enabled
    (match (map-get? supported-tokens token)
      token-config
        (begin
          (asserts! (get enabled token-config) ERR_UNSUPPORTED_TOKEN)
          
          ;; Check liquidity
          (let (
            (available-liquidity (default-to u0 (map-get? flash-liquidity token)))
            (max-loan (get max-flash-loan token-config))
          )
            (asserts! (>= available-liquidity amount) ERR_INSUFFICIENT_LIQUIDITY)
            (asserts! (<= amount max-loan) ERR_LOAN_AMOUNT_TOO_LARGE)
            
            ;; Calculate fee
            (let (
              (fee-rate (default-to (var-get flash-fee-rate) (get custom-fee-rate token-config)))
              (fee (/ (* amount fee-rate) FEE_DENOMINATOR))
            )
              ;; Check no active loan for this borrower/token combination
              (asserts! (is-none (map-get? active-flash-loans { borrower: borrower, token: token })) ERR_LOAN_ALREADY_ACTIVE)
              
              ;; Record active loan (reentrancy protection)
              (map-set active-flash-loans { borrower: borrower, token: token } {
                amount: amount,
                fee: fee,
                initiated-at: stacks-block-time,
                initiator: initiator,
              })
              
              ;; Update liquidity (subtract lent amount)
              (map-set flash-liquidity token (- available-liquidity amount))
              
              ;; Update token stats
              (map-set supported-tokens token 
                (merge token-config { 
                  total-borrowed: (+ (get total-borrowed token-config) amount)
                }))
              
              ;; Emit loan initiated event
              (print {
                event: "FlashLoanInitiated",
                loan-id: loan-id,
                borrower: borrower,
                initiator: initiator,
                token: token,
                amount: amount,
                fee: fee,
                timestamp: stacks-block-time,
                contract-hash: (get-contract-hash),
              })
              
              ;; At this point, the borrower should have received the tokens
              ;; and should execute their callback logic
              ;; In Clarity, this is handled by the borrower calling flash-loan-callback
              
              (ok {
                loan-id: loan-id,
                amount: amount,
                fee: fee,
                repayment-required: (+ amount fee),
              })
            )
          )
        )
      (begin
        (release-lock)
        ERR_UNSUPPORTED_TOKEN
      )
    )
  )
)

;; Flash loan callback - Called by borrower to complete the flash loan
;; The borrower must return the callback success hash
(define-public (flash-loan-callback
    (token principal)
    (amount uint)
    (fee uint)
    (callback-result (buff 32))
  )
  (let (
    (borrower tx-sender)
    (repayment (+ amount fee))
  )
    ;; Verify callback result matches expected success hash (ERC-3156 requirement)
    (asserts! (is-eq callback-result CALLBACK_SUCCESS) ERR_CALLBACK_FAILED)
    
    ;; Check active loan exists
    (match (map-get? active-flash-loans { borrower: borrower, token: token })
      loan-data
        (begin
          ;; Verify amounts match
          (asserts! (is-eq amount (get amount loan-data)) ERR_INVALID_AMOUNT)
          (asserts! (is-eq fee (get fee loan-data)) ERR_INVALID_AMOUNT)
          
          ;; At this point, the borrower should have transferred repayment back
          ;; Update liquidity (add back the repayment including fee)
          (let (
            (current-liquidity (default-to u0 (map-get? flash-liquidity token)))
          )
            (map-set flash-liquidity token (+ current-liquidity repayment))
          )
          
          ;; Update token stats
          (match (map-get? supported-tokens token)
            token-config
              (map-set supported-tokens token 
                (merge token-config { 
                  total-fees: (+ (get total-fees token-config) fee)
                }))
            true
          )
          
          ;; Update global stats
          (var-set total-flash-loans (+ (var-get total-flash-loans) u1))
          (var-set total-fees-collected (+ (var-get total-fees-collected) fee))
          
          ;; Record in history
          (map-set flash-loan-history (var-get total-flash-loans) {
            borrower: borrower,
            token: token,
            amount: amount,
            fee: fee,
            initiator: (get initiator loan-data),
            timestamp: stacks-block-time,
            success: true,
            callback-verified: true,
            signature-verified: false,
          })
          
          ;; Clear active loan
          (map-delete active-flash-loans { borrower: borrower, token: token })
          
          ;; Release reentrancy lock
          (release-lock)
          
          ;; Emit success event
          (print {
            event: "FlashLoanCompleted",
            loan-id: (var-get total-flash-loans),
            borrower: borrower,
            token: token,
            amount: amount,
            fee: fee,
            repayment: repayment,
            timestamp: stacks-block-time,
          })
          
          (ok true)
        )
      (begin
        (release-lock)
        ERR_REPAY_FAILED
      )
    )
  )
)

;; Flash loan with signature verification
;; Allows authorized operations via secp256r1 signatures (WebAuthn compatible)
(define-public (flash-loan-with-signature
    (token principal)
    (amount uint)
    (data (buff 256))
    (signature (buff 64))
    (public-key (buff 33))
    (message-hash (buff 32))
  )
  (let (
    (borrower tx-sender)
    (nonce (get-signature-nonce borrower))
  )
    ;; Verify secp256r1 signature using Clarity v4
    (asserts! (secp256r1-verify message-hash signature public-key) ERR_INVALID_SIGNATURE)
    
    ;; Increment nonce to prevent replay
    (map-set signature-nonces borrower (+ nonce u1))
    
    ;; Execute the flash loan
    (match (flash-loan token amount data)
      success
        (begin
          (print {
            event: "SignatureVerifiedFlashLoan",
            borrower: borrower,
            token: token,
            amount: amount,
            nonce: nonce,
            timestamp: stacks-block-time,
          })
          (ok success)
        )
      error (err error)
    )
  )
)

;; ==============================
;; Token Management
;; ==============================

;; Add a supported token
(define-public (add-supported-token
    (token principal)
    (symbol (string-utf8 10))
    (decimals uint)
    (max-loan uint)
    (custom-fee (optional uint))
  )
  (begin
    (asserts! (is-eq tx-sender CONTRACT_OWNER) ERR_UNAUTHORIZED)
    (asserts! (is-none (map-get? supported-tokens token)) ERR_UNSUPPORTED_TOKEN)
    
    (map-set supported-tokens token {
      symbol: symbol,
      decimals: decimals,
      max-flash-loan: max-loan,
      custom-fee-rate: custom-fee,
      enabled: true,
      total-borrowed: u0,
      total-fees: u0,
    })
    
    ;; Convert symbol to ASCII for logging
    (let ((ascii-symbol (token-symbol-to-ascii symbol)))
      (print {
        event: "TokenAdded",
        token: token,
        symbol: symbol,
        ascii-symbol: ascii-symbol,
        decimals: decimals,
        max-loan: max-loan,
        custom-fee: custom-fee,
        timestamp: stacks-block-time,
        contract-hash: (get-contract-hash),
      })
    )
    
    (ok true)
  )
)

;; Update token configuration
(define-public (update-token-config
    (token principal)
    (max-loan uint)
    (custom-fee (optional uint))
    (enabled bool)
  )
  (begin
    (asserts! (is-eq tx-sender CONTRACT_OWNER) ERR_UNAUTHORIZED)
    
    (match (map-get? supported-tokens token)
      token-config
        (begin
          (map-set supported-tokens token (merge token-config {
            max-flash-loan: max-loan,
            custom-fee-rate: custom-fee,
            enabled: enabled,
          }))
          (print {
            event: "TokenConfigUpdated",
            token: token,
            max-loan: max-loan,
            custom-fee: custom-fee,
            enabled: enabled,
            timestamp: stacks-block-time,
          })
          (ok true)
        )
      ERR_TOKEN_NOT_FOUND
    )
  )
)

;; ==============================
;; Liquidity Management
;; ==============================

;; Add liquidity to the flash loan pool
(define-public (add-liquidity (token principal) (amount uint))
  (let (
    (current-liquidity (default-to u0 (map-get? flash-liquidity token)))
  )
    ;; Verify token is supported
    (asserts! (is-some (map-get? supported-tokens token)) ERR_UNSUPPORTED_TOKEN)
    (asserts! (> amount u0) ERR_INVALID_AMOUNT)
    
    ;; Update liquidity
    (map-set flash-liquidity token (+ current-liquidity amount))
    
    (print {
      event: "LiquidityAdded",
      token: token,
      amount: amount,
      new-total: (+ current-liquidity amount),
      provider: tx-sender,
      timestamp: stacks-block-time,
    })
    
    (ok (+ current-liquidity amount))
  )
)

;; Remove liquidity from the flash loan pool (owner only)
(define-public (remove-liquidity (token principal) (amount uint))
  (let (
    (current-liquidity (default-to u0 (map-get? flash-liquidity token)))
  )
    (asserts! (is-eq tx-sender CONTRACT_OWNER) ERR_UNAUTHORIZED)
    (asserts! (>= current-liquidity amount) ERR_INSUFFICIENT_LIQUIDITY)
    
    ;; Update liquidity
    (map-set flash-liquidity token (- current-liquidity amount))
    
    (print {
      event: "LiquidityRemoved",
      token: token,
      amount: amount,
      new-total: (- current-liquidity amount),
      timestamp: stacks-block-time,
    })
    
    (ok (- current-liquidity amount))
  )
)

;; Get available liquidity for a token
(define-read-only (get-liquidity (token principal))
  (default-to u0 (map-get? flash-liquidity token))
)

;; ==============================
;; Borrower Authorization
;; ==============================

;; Authorize a borrower contract
(define-public (authorize-borrower 
    (borrower principal) 
    (name (string-utf8 64))
    (expected-hash (optional (buff 32)))
  )
  (begin
    (asserts! (is-eq tx-sender CONTRACT_OWNER) ERR_UNAUTHORIZED)
    
    (map-set authorized-borrowers borrower {
      name: name,
      authorized-at: stacks-block-time,
      total-loans: u0,
      total-repaid: u0,
      active: true,
      contract-hash: expected-hash,
    })
    
    (print {
      event: "BorrowerAuthorized",
      borrower: borrower,
      name: name,
      expected-hash: expected-hash,
      actual-hash: (contract-hash? borrower),
      authorized-at: stacks-block-time,
    })
    
    (ok true)
  )
)

;; Revoke borrower authorization
(define-public (revoke-borrower (borrower principal))
  (begin
    (asserts! (is-eq tx-sender CONTRACT_OWNER) ERR_UNAUTHORIZED)
    
    (match (map-get? authorized-borrowers borrower)
      borrower-data
        (begin
          (map-set authorized-borrowers borrower (merge borrower-data { active: false }))
          (print {
            event: "BorrowerRevoked",
            borrower: borrower,
            revoked-at: stacks-block-time,
          })
          (ok true)
        )
      ERR_BORROWER_NOT_AUTHORIZED
    )
  )
)

;; Check if borrower is authorized
(define-read-only (is-borrower-authorized (borrower principal))
  (match (map-get? authorized-borrowers borrower)
    data (get active data)
    false
  )
)

;; Get borrower info
(define-read-only (get-borrower-info (borrower principal))
  (map-get? authorized-borrowers borrower)
)

;; ==============================
;; Admin Functions
;; ==============================

;; Pause flash loans
(define-public (pause-flash-loans)
  (begin
    (asserts! (is-eq tx-sender CONTRACT_OWNER) ERR_UNAUTHORIZED)
    (var-set flash-loan-paused true)
    (print {
      event: "FlashLoansPaused",
      paused-by: tx-sender,
      timestamp: stacks-block-time,
    })
    (ok true)
  )
)

;; Unpause flash loans
(define-public (unpause-flash-loans)
  (begin
    (asserts! (is-eq tx-sender CONTRACT_OWNER) ERR_UNAUTHORIZED)
    (var-set flash-loan-paused false)
    (print {
      event: "FlashLoansUnpaused",
      unpaused-by: tx-sender,
      timestamp: stacks-block-time,
    })
    (ok true)
  )
)

;; Set flash loan fee rate
(define-public (set-fee-rate (new-rate uint))
  (begin
    (asserts! (is-eq tx-sender CONTRACT_OWNER) ERR_UNAUTHORIZED)
    (asserts! (<= new-rate MAX_FEE_RATE) ERR_INVALID_FEE_RATE)
    (var-set flash-fee-rate new-rate)
    (print {
      event: "FeeRateUpdated",
      old-rate: (var-get flash-fee-rate),
      new-rate: new-rate,
      updated-by: tx-sender,
      timestamp: stacks-block-time,
    })
    (ok new-rate)
  )
)

;; ==============================
;; Read Functions
;; ==============================

;; Get token configuration
(define-read-only (get-token-config (token principal))
  (map-get? supported-tokens token)
)

;; Get flash loan history entry
(define-read-only (get-loan-history (loan-id uint))
  (map-get? flash-loan-history loan-id)
)

;; Get active flash loan for a borrower/token
(define-read-only (get-active-loan (borrower principal) (token principal))
  (map-get? active-flash-loans { borrower: borrower, token: token })
)

;; Check if flash loans are paused
(define-read-only (is-flash-loan-paused)
  (var-get flash-loan-paused)
)

;; Get current fee rate
(define-read-only (get-fee-rate)
  (var-get flash-fee-rate)
)

;; Get total flash loans count
(define-read-only (get-total-flash-loans)
  (var-get total-flash-loans)
)

;; Get total fees collected
(define-read-only (get-total-fees-collected)
  (var-get total-fees-collected)
)

;; ==============================
;; Contract Information
;; ==============================

;; Get comprehensive contract information using Clarity v4 features
(define-read-only (get-lender-info)
  {
    contract-hash: (get-contract-hash),
    fee-rate: (var-get flash-fee-rate),
    fee-denominator: FEE_DENOMINATOR,
    max-fee-rate: MAX_FEE_RATE,
    min-loan-amount: MIN_FLASH_LOAN_AMOUNT,
    is-paused: (var-get flash-loan-paused),
    assets-restricted: (var-get assets-restricted),
    total-flash-loans: (var-get total-flash-loans),
    total-fees-collected: (var-get total-fees-collected),
    current-block-time: stacks-block-time,
    owner: CONTRACT_OWNER,
    callback-success-hash: CALLBACK_SUCCESS,
  }
)

;; Verify contract integrity
(define-read-only (verify-contract-integrity (expected-hash (buff 32)))
  (match (get-contract-hash)
    actual-hash (is-eq expected-hash actual-hash)
    err-code false
  )
)

Functions (37)

FunctionAccessArgs
add-supported-tokenpublictoken: principal, symbol: (string-utf8 10
get-contract-hashread-only
get-borrower-contract-hashread-onlyborrower: principal
verify-borrower-contractread-onlyborrower: principal, expected-hash: (buff 32
get-current-block-timeread-only
token-symbol-to-asciiread-onlysymbol: (string-utf8 10
are-assets-restrictedread-only
set-asset-restrictionspublicrestricted: bool
verify-flash-loan-signatureread-onlymessage-hash: (buff 32
get-signature-nonceread-onlyborrower: principal
max-flash-loanread-onlytoken: principal
flash-feeread-onlytoken: principal, amount: uint
acquire-lockprivate
release-lockprivate
flash-loanpublictoken: principal, amount: uint, data: (buff 256
flash-loan-callbackpublictoken: principal, amount: uint, fee: uint, callback-result: (buff 32
flash-loan-with-signaturepublictoken: principal, amount: uint, data: (buff 256
update-token-configpublictoken: principal, max-loan: uint, custom-fee: (optional uint
add-liquiditypublictoken: principal, amount: uint
remove-liquiditypublictoken: principal, amount: uint
get-liquidityread-onlytoken: principal
authorize-borrowerpublicborrower: principal, name: (string-utf8 64
revoke-borrowerpublicborrower: principal
is-borrower-authorizedread-onlyborrower: principal
get-borrower-inforead-onlyborrower: principal
pause-flash-loanspublic
unpause-flash-loanspublic
set-fee-ratepublicnew-rate: uint
get-token-configread-onlytoken: principal
get-loan-historyread-onlyloan-id: uint
get-active-loanread-onlyborrower: principal, token: principal
is-flash-loan-pausedread-only
get-fee-rateread-only
get-total-flash-loansread-only
get-total-fees-collectedread-only
get-lender-inforead-only
verify-contract-integrityread-onlyexpected-hash: (buff 32