Source Code

;; Halal Certifier Contract
;; Halal food/product certification system
;; Halal - ensuring product compliance
;; Clarity 4 compatible

(define-constant CONTRACT-OWNER tx-sender)
(define-constant ERR-NOT-AUTHORIZED (err u401))
(define-constant ERR-NOT-FOUND (err u404))
(define-constant ERR-NOT-INSPECTOR (err u405))
(define-constant ERR-ALREADY-CERTIFIED (err u406))

(define-data-var cert-count uint u0)
(define-data-var total-certified uint u0)

(define-map inspectors principal { name: (string-utf8 100), authority: (string-utf8 100), inspections: uint, active: bool })
(define-map certifications uint {
  product: (string-utf8 100), producer: principal, inspector: principal,
  category: (string-ascii 20), cert-hash: (buff 32),
  valid-until: uint, status: (string-ascii 20), issued: uint
})
(define-map producer-certs principal uint)

(define-public (register-inspector (name (string-utf8 100)) (authority (string-utf8 100)))
  (begin
    (asserts! (is-eq tx-sender CONTRACT-OWNER) ERR-NOT-AUTHORIZED)
    (map-set inspectors tx-sender { name: name, authority: authority, inspections: u0, active: true }) (ok true)))

(define-public (add-inspector (inspector principal) (name (string-utf8 100)) (authority (string-utf8 100)))
  (begin
    (asserts! (is-eq tx-sender CONTRACT-OWNER) ERR-NOT-AUTHORIZED)
    (map-set inspectors inspector { name: name, authority: authority, inspections: u0, active: true }) (ok true)))

(define-public (certify-product (product (string-utf8 100)) (producer principal) (category (string-ascii 20)) (cert-hash (buff 32)) (validity uint))
  (let (
    (insp (unwrap! (map-get? inspectors tx-sender) ERR-NOT-INSPECTOR))
    (id (+ (var-get cert-count) u1))
  )
    (asserts! (get active insp) ERR-NOT-INSPECTOR)
    (map-set certifications id { product: product, producer: producer, inspector: tx-sender, category: category, cert-hash: cert-hash, valid-until: (+ stacks-block-height validity), status: "active", issued: stacks-block-height })
    (map-set inspectors tx-sender (merge insp { inspections: (+ (get inspections insp) u1) }))
    (map-set producer-certs producer (+ (default-to u0 (map-get? producer-certs producer)) u1))
    (var-set cert-count id)
    (var-set total-certified (+ (var-get total-certified) u1))
    (ok id)))

(define-public (revoke-certification (cert-id uint))
  (let ((cert (unwrap! (map-get? certifications cert-id) ERR-NOT-FOUND)))
    (asserts! (or (is-eq tx-sender (get inspector cert)) (is-eq tx-sender CONTRACT-OWNER)) ERR-NOT-AUTHORIZED)
    (map-set certifications cert-id (merge cert { status: "revoked" })) (ok true)))

(define-public (renew-certification (cert-id uint) (validity uint))
  (let ((cert (unwrap! (map-get? certifications cert-id) ERR-NOT-FOUND)))
    (asserts! (is-eq tx-sender (get inspector cert)) ERR-NOT-AUTHORIZED)
    (map-set certifications cert-id (merge cert { valid-until: (+ stacks-block-height validity), status: "active" })) (ok true)))

(define-read-only (get-certification (id uint)) (map-get? certifications id))
(define-read-only (get-inspector (who principal)) (map-get? inspectors who))
(define-read-only (get-cert-count) (ok (var-get cert-count)))
(define-read-only (get-total-certified) (ok (var-get total-certified)))
(define-read-only (is-valid-cert (id uint))
  (match (map-get? certifications id) c (ok (and (is-eq (get status c) "active") (< stacks-block-height (get valid-until c)))) (ok false)))

Functions (10)

FunctionAccessArgs
register-inspectorpublicname: (string-utf8 100
add-inspectorpublicinspector: principal, name: (string-utf8 100
certify-productpublicproduct: (string-utf8 100
revoke-certificationpubliccert-id: uint
renew-certificationpubliccert-id: uint, validity: uint
get-certificationread-onlyid: uint
get-inspectorread-onlywho: principal
get-cert-countread-only
get-total-certifiedread-only
is-valid-certread-onlyid: uint