Source Code

;; title: VaxiGuard
;; version:
;; summary:
;; description:

;; Vaccine Tracking Smart Contract
;; Contract Owner Management
(define-data-var vaccine-contract-owner principal tx-sender)

;; Error Codes
(define-constant ERROR-NOT-AUTHORIZED (err u100))
(define-constant ERROR-INVALID-BATCH (err u101))
(define-constant ERROR-BATCH-EXISTS (err u102))
(define-constant ERROR-BATCH-NOT-FOUND (err u103))
(define-constant ERROR-INSUFFICIENT-VACCINE-QUANTITY (err u104))
(define-constant ERROR-INVALID-PATIENT-ID (err u105))
(define-constant ERROR-PATIENT-ALREADY-VACCINATED (err u106))
(define-constant ERROR-TEMPERATURE-OUT-OF-RANGE (err u107))
(define-constant ERROR-VACCINE-BATCH-EXPIRED (err u108))
(define-constant ERROR-INVALID-VACCINATION-LOCATION (err u109))
(define-constant ERROR-MAXIMUM-DOSES-REACHED (err u110))
(define-constant ERROR-MINIMUM-DOSE-INTERVAL-NOT-MET (err u111))
(define-constant ERROR-CONTRACT-OWNER-ONLY (err u112))
(define-constant ERROR-INVALID-INPUT (err u113))
(define-constant ERROR-INVALID-EXPIRY-DATE (err u114))
(define-constant ERROR-INVALID-STORAGE-CAPACITY (err u115))

;; Constants
(define-constant MINIMUM-STORAGE-TEMPERATURE (- 70))
(define-constant MAXIMUM_STORAGE_TEMPERATURE 8)
(define-constant MINIMUM-DAYS-BETWEEN-DOSES u21) ;; 21 days minimum between doses
(define-constant MAXIMUM-DOSES-PER-PATIENT u4)
(define-constant MINIMUM_STRING_LENGTH u1)
(define-constant CURRENT_BLOCK stacks-block-time)

;; Data Maps
(define-map vaccine-batches
  { vaccine-batch-id: (string-ascii 32) }
  {
    vaccine-manufacturer: (string-ascii 50),
    vaccine-name: (string-ascii 50),
    manufacturing-date: uint,
    batch-expiry-date: uint,
    available-doses: uint,
    storage-temperature: int,
    batch-status: (string-ascii 20),
    temperature-breach-count: uint,
    storage-facility: (string-ascii 100),
    additional-batch-notes: (string-ascii 500),
  }
)

(define-map patient-vaccination-records
  { patient-identifier: (string-ascii 32) }
  {
    vaccination-history: (list
      10
      {
        vaccine-batch-id: (string-ascii 32),
        administration-date: uint,
        vaccine-type: (string-ascii 50),
        dose-sequence-number: uint,
        healthcare-provider: principal,
        vaccination-site: (string-ascii 100),
        next-vaccination-date: (optional uint),
      }
    ),
    completed-doses: uint,
    reported-side-effects: (list 5 (string-ascii 200)),
    vaccination-exemption-reason: (optional (string-ascii 200)),
  }
)

(define-map healthcare-providers
  principal
  {
    provider-role: (string-ascii 20),
    healthcare-facility: (string-ascii 100),
    credentials-expiry-date: uint,
  }
)

(define-map vaccine-storage-facilities
  (string-ascii 100)
  {
    facility-address: (string-ascii 200),
    maximum-storage-capacity: uint,
    current-inventory: uint,
    facility-temperature-history: (list 100 {
      reading-timestamp: uint,
      recorded-temperature: int,
    }),
  }
)

;; Private Functions
(define-private (is-vaccine-contract-owner)
  (is-eq tx-sender (var-get vaccine-contract-owner))
)

;; Updated validate-string functions for different string lengths
(define-private (validate-string-32 (input (string-ascii 32)))
  (> (len input) MINIMUM_STRING_LENGTH)
)

(define-private (validate-string-50 (input (string-ascii 50)))
  (> (len input) MINIMUM_STRING_LENGTH)
)

(define-private (validate-string-100 (input (string-ascii 100)))
  (> (len input) MINIMUM_STRING_LENGTH)
)

(define-private (validate-string-200 (input (string-ascii 200)))
  (> (len input) MINIMUM_STRING_LENGTH)
)

(define-private (validate-future-date (date uint))
  (> date CURRENT_BLOCK)
)

(define-private (validate-storage-capacity (capacity uint))
  (> capacity u0)
)

;; Read-only Functions
(define-read-only (get-vaccine-contract-owner)
  (ok (var-get vaccine-contract-owner))
)

(define-read-only (is-provider-authorized (provider-address principal))
  (match (map-get? healthcare-providers provider-address)
    provider-info (>= (get credentials-expiry-date provider-info) CURRENT_BLOCK)
    false
  )
)

;; Public Functions
(define-public (transfer-contract-ownership (new-contract-owner principal))
  (begin
    (asserts! (is-vaccine-contract-owner) ERROR-CONTRACT-OWNER-ONLY)
    (ok (var-set vaccine-contract-owner new-contract-owner))
  )
)

(define-public (register-storage-facility
    (facility-id (string-ascii 100))
    (facility-address (string-ascii 200))
    (maximum-storage-capacity uint)
  )
  (begin
    (asserts! (is-vaccine-contract-owner) ERROR-NOT-AUTHORIZED)
    (asserts! (validate-string-100 facility-id) ERROR-INVALID-INPUT)
    (asserts! (validate-string-200 facility-address) ERROR-INVALID-INPUT)
    (asserts! (validate-storage-capacity maximum-storage-capacity)
      ERROR-INVALID-STORAGE-CAPACITY
    )
    (ok (map-set vaccine-storage-facilities facility-id {
      facility-address: facility-address,
      maximum-storage-capacity: maximum-storage-capacity,
      current-inventory: u0,
      facility-temperature-history: (list),
    }))
  )
)

(define-public (register-vaccine-batch
    (vaccine-batch-id (string-ascii 32))
    (vaccine-manufacturer (string-ascii 50))
    (vaccine-name (string-ascii 50))
    (manufacturing-date uint)
    (batch-expiry-date uint)
    (initial-quantity uint)
    (storage-temperature int)
    (storage-facility (string-ascii 100))
  )
  (begin
    (asserts! (is-provider-authorized tx-sender) ERROR-NOT-AUTHORIZED)
    (asserts! (validate-string-32 vaccine-batch-id) ERROR-INVALID-INPUT)
    (asserts! (validate-string-50 vaccine-manufacturer) ERROR-INVALID-INPUT)
    (asserts! (validate-string-50 vaccine-name) ERROR-INVALID-INPUT)
    (asserts! (validate-string-100 storage-facility) ERROR-INVALID-INPUT)
    (asserts!
      (is-none (map-get? vaccine-batches { vaccine-batch-id: vaccine-batch-id }))
      ERROR-BATCH-EXISTS
    )
    (asserts! (validate-storage-capacity initial-quantity) ERROR-INVALID-BATCH)
    (asserts! (validate-future-date batch-expiry-date) ERROR-INVALID-EXPIRY-DATE)
    (asserts! (> batch-expiry-date manufacturing-date) ERROR-INVALID-BATCH)
    (asserts!
      (and
        (>= storage-temperature MINIMUM-STORAGE-TEMPERATURE)
        (<= storage-temperature MAXIMUM_STORAGE_TEMPERATURE)
      )
      ERROR-TEMPERATURE-OUT-OF-RANGE
    )

    (ok (map-set vaccine-batches { vaccine-batch-id: vaccine-batch-id } {
      vaccine-manufacturer: vaccine-manufacturer,
      vaccine-name: vaccine-name,
      manufacturing-date: manufacturing-date,
      batch-expiry-date: batch-expiry-date,
      available-doses: initial-quantity,
      storage-temperature: storage-temperature,
      batch-status: "active",
      temperature-breach-count: u0,
      storage-facility: storage-facility,
      additional-batch-notes: "",
    }))
  )
)

(define-public (record-temperature-breach
    (vaccine-batch-id (string-ascii 32))
    (breach-temperature int)
  )
  (begin
    (asserts! (is-provider-authorized tx-sender) ERROR-NOT-AUTHORIZED)
    (asserts! (validate-string-32 vaccine-batch-id) ERROR-INVALID-INPUT)
    (match (map-get? vaccine-batches { vaccine-batch-id: vaccine-batch-id })
      batch-info (ok (map-set vaccine-batches { vaccine-batch-id: vaccine-batch-id }
        (merge batch-info {
          temperature-breach-count: (+ (get temperature-breach-count batch-info) u1),
          batch-status: (if (> (get temperature-breach-count batch-info) u2)
            "compromised"
            (get batch-status batch-info)
          ),
        })
      ))
      ERROR-BATCH-NOT-FOUND
    )
  )
)

Functions (13)

FunctionAccessArgs
validate-string-32privateinput: (string-ascii 32
validate-string-50privateinput: (string-ascii 50
validate-string-100privateinput: (string-ascii 100
validate-string-200privateinput: (string-ascii 200
validate-future-dateprivatedate: uint
validate-storage-capacityprivatecapacity: uint
get-vaccine-contract-ownerread-only
is-provider-authorizedread-onlyprovider-address: principal
transfer-contract-ownershippublicnew-contract-owner: principal
register-storage-facilitypublicfacility-id: (string-ascii 100
register-vaccine-batchpublicvaccine-batch-id: (string-ascii 32
record-temperature-breachpublicvaccine-batch-id: (string-ascii 32
is-vaccine-contract-ownerprivate