Source Code

;; SPDX-License-Identifier: BUSL-1.1

;; TRAITS
(use-trait callback-trait .trait-flash-loan-v1.flash-loan)

;; CONSTANTS
(define-constant SUCCESS (ok true))
;; Maximum fee percentage
(define-constant max-fee u100000000)


;; Errors
(define-constant ERR_CONTRACT_NOT_ALLOWED (err u110000))
(define-constant ERR-NOT-AUTHORIZED (err u110001))
(define-constant ERR-INVALID-FEE (err u110002))


;; Data vars
;; List of allowed contracts that are called back during the flash loan
(define-map allowed-contracts principal bool)
;; Flag to allow any contract to use flash loan
(define-data-var allow-any bool false)
;; Fee of 0.01% for processing flash loan scaled to 10^8
(define-data-var fee uint u10000)

;; Read only functions

(define-read-only (get-fee) (var-get fee))

(define-read-only (is-contract-allowed (contract principal))
  (if (var-get allow-any) true (default-to false (map-get? allowed-contracts contract)))
)

;; Public functions

(define-public (set-allowed-contract (contract principal))
  (begin
    (asserts! (is-governance) ERR-NOT-AUTHORIZED)
    (map-set allowed-contracts contract true)
    (print {
      action: "set-allowed-contract",
      contract: contract
    })
    SUCCESS
))

(define-public (remove-allowed-contract (contract principal))
  (begin
    (asserts! (is-governance) ERR-NOT-AUTHORIZED)
    (map-delete allowed-contracts contract)
    (print {
      action: "remove-allowed-contract",
      contract: contract
    })
    SUCCESS
))

(define-public (update-fee (new-fee uint))
  (begin
    (asserts! (is-governance) ERR-NOT-AUTHORIZED)
    (asserts! (<= new-fee max-fee) ERR-INVALID-FEE)
    (print {
      action: "update-fee",
      old-value: (var-get fee),
      new-value: new-fee,
    })
    (var-set fee new-fee)
    SUCCESS
))

(define-public (update-allow-any-contract (value bool))
  (begin
    (asserts! (is-governance) ERR-NOT-AUTHORIZED)
    (print {
      action: "update-allow-any-contract",
      old-value: (var-get allow-any),
      new-value: value,
    })
    (var-set allow-any value)
    SUCCESS
))

(define-public (flash-loan (amount uint) (callback <callback-trait>) (data (optional (buff 20480))))
  (let (
      (flash-loan-fee (contract-call? .math-v1 divide-round-up (* amount (var-get fee)) max-fee))
      (caller contract-caller)
      (callback-contract (contract-of callback))
    )
    (asserts! (is-contract-allowed callback-contract) ERR_CONTRACT_NOT_ALLOWED)
    ;; transfer funds to user
    (try! (contract-call? .state-v1 transfer-to 'SP120SBRBQJ00MCWS7TM5R8WJNTTKD5K0HFRC2CNE.usdcx caller amount))
    (try! (contract-call? callback on-granite-flash-loan amount flash-loan-fee data))
    (try! (contract-call? .state-v1 transfer-from 'SP120SBRBQJ00MCWS7TM5R8WJNTTKD5K0HFRC2CNE.usdcx caller amount))
    (try! (if (> flash-loan-fee u0)
      (contract-call? 'SP120SBRBQJ00MCWS7TM5R8WJNTTKD5K0HFRC2CNE.usdcx transfer flash-loan-fee caller (contract-call? .state-v1 get-governance) none)
      SUCCESS
    ))
    
    (print {
      action: "flash-loan",
      amount: amount,
      fee: flash-loan-fee,
      caller: caller,
      contract: callback-contract
    })
    SUCCESS
  )
)

;; private functions


(define-private (is-governance)
  (is-eq (contract-call? .state-v1 get-governance) contract-caller)
)

Functions (8)

FunctionAccessArgs
get-feeread-only
is-contract-allowedread-onlycontract: principal
set-allowed-contractpubliccontract: principal
remove-allowed-contractpubliccontract: principal
update-feepublicnew-fee: uint
update-allow-any-contractpublicvalue: bool
flash-loanpublicamount: uint, callback: <callback-trait>, data: (optional (buff 20480
is-governanceprivate