Source Code

;; Sukuk Bond Contract (Islamic Bond)
;; Asset-backed investment certificates
;; Halal - sukuk (not interest-based bonds)
;; Clarity 4 compatible

(define-fungible-token sukuk-cert)

(define-constant CONTRACT-OWNER tx-sender)
(define-constant ERR-NOT-AUTHORIZED (err u401))
(define-constant ERR-NOT-FOUND (err u404))
(define-constant ERR-INSUFFICIENT (err u405))
(define-constant ERR-MATURED (err u406))

(define-data-var issuance-count uint u0)
(define-data-var total-issued uint u0)
(define-data-var total-profit-paid uint u0)

(define-map sukuk-issuances uint {
  name: (string-utf8 100), underlying-asset: (string-utf8 100),
  face-value: uint, total-certificates: uint, sold: uint,
  profit-rate: uint, maturity-block: uint, status: (string-ascii 20)
})
(define-map holders principal { certificates: uint, invested: uint, profit-claimed: uint })

(define-public (issue-sukuk (name (string-utf8 100)) (asset (string-utf8 100)) (face-value uint) (total uint) (profit-rate uint) (maturity-blocks uint))
  (let ((id (+ (var-get issuance-count) u1)))
    (asserts! (is-eq tx-sender CONTRACT-OWNER) ERR-NOT-AUTHORIZED)
    (map-set sukuk-issuances id {
      name: name, underlying-asset: asset, face-value: face-value,
      total-certificates: total, sold: u0,
      profit-rate: profit-rate, maturity-block: (+ stacks-block-height maturity-blocks), status: "open"
    })
    (var-set issuance-count id) (ok id)))

(define-public (buy-sukuk (issuance-id uint) (quantity uint))
  (let (
    (sukuk (unwrap! (map-get? sukuk-issuances issuance-id) ERR-NOT-FOUND))
    (cost (* quantity (get face-value sukuk)))
    (prev (default-to { certificates: u0, invested: u0, profit-claimed: u0 } (map-get? holders tx-sender)))
  )
    (asserts! (is-eq (get status sukuk) "open") ERR-MATURED)
    (asserts! (<= (+ (get sold sukuk) quantity) (get total-certificates sukuk)) ERR-INSUFFICIENT)
    (try! (stx-transfer? cost tx-sender CONTRACT-OWNER))
    (try! (ft-mint? sukuk-cert quantity tx-sender))
    (map-set holders tx-sender { certificates: (+ (get certificates prev) quantity), invested: (+ (get invested prev) cost), profit-claimed: (get profit-claimed prev) })
    (map-set sukuk-issuances issuance-id (merge sukuk { sold: (+ (get sold sukuk) quantity) }))
    (var-set total-issued (+ (var-get total-issued) cost))
    (ok cost)))

(define-public (distribute-profit (holder principal) (amount uint))
  (let ((h (unwrap! (map-get? holders holder) ERR-NOT-FOUND)))
    (asserts! (is-eq tx-sender CONTRACT-OWNER) ERR-NOT-AUTHORIZED)
    (try! (stx-transfer? amount tx-sender holder))
    (map-set holders holder (merge h { profit-claimed: (+ (get profit-claimed h) amount) }))
    (var-set total-profit-paid (+ (var-get total-profit-paid) amount))
    (ok amount)))

(define-public (redeem-sukuk (quantity uint))
  (let ((h (unwrap! (map-get? holders tx-sender) ERR-NOT-FOUND)))
    (asserts! (>= (get certificates h) quantity) ERR-INSUFFICIENT)
    (try! (ft-burn? sukuk-cert quantity tx-sender))
    (map-set holders tx-sender (merge h { certificates: (- (get certificates h) quantity) }))
    (ok quantity)))

(define-read-only (get-issuance (id uint)) (map-get? sukuk-issuances id))
(define-read-only (get-holder (who principal)) (map-get? holders who))
(define-read-only (get-issuance-count) (ok (var-get issuance-count)))
(define-read-only (get-total-issued) (ok (var-get total-issued)))
(define-read-only (get-sukuk-balance (who principal)) (ok (ft-get-balance sukuk-cert who)))

Functions (9)

FunctionAccessArgs
issue-sukukpublicname: (string-utf8 100
buy-sukukpublicissuance-id: uint, quantity: uint
distribute-profitpublicholder: principal, amount: uint
redeem-sukukpublicquantity: uint
get-issuanceread-onlyid: uint
get-holderread-onlywho: principal
get-issuance-countread-only
get-total-issuedread-only
get-sukuk-balanceread-onlywho: principal