Source Code

;; Price Oracle Contract
;; On-chain price feed with multiple reporters
;; Halal - transparent pricing
;; Clarity 4 compatible

(define-constant CONTRACT-OWNER tx-sender)
(define-constant ERR-NOT-AUTHORIZED (err u401))
(define-constant ERR-NOT-REPORTER (err u402))
(define-constant ERR-NOT-FOUND (err u404))

(define-data-var feed-count uint u0)

(define-map reporters principal bool)
(define-map price-feeds (string-ascii 20) { price: uint, last-updated: uint, reporter: principal, decimals: uint })
(define-map price-history { pair: (string-ascii 20), index: uint } { price: uint, block: uint, reporter: principal })
(define-map history-count (string-ascii 20) uint)

(map-set reporters CONTRACT-OWNER true)

(define-public (add-reporter (r principal))
  (begin (asserts! (is-eq tx-sender CONTRACT-OWNER) ERR-NOT-AUTHORIZED) (map-set reporters r true) (ok true)))

(define-public (remove-reporter (r principal))
  (begin (asserts! (is-eq tx-sender CONTRACT-OWNER) ERR-NOT-AUTHORIZED) (map-set reporters r false) (ok true)))

(define-public (submit-price (pair (string-ascii 20)) (price uint) (decimals uint))
  (let ((idx (default-to u0 (map-get? history-count pair))))
    (asserts! (default-to false (map-get? reporters tx-sender)) ERR-NOT-REPORTER)
    (map-set price-feeds pair { price: price, last-updated: stacks-block-height, reporter: tx-sender, decimals: decimals })
    (map-set price-history { pair: pair, index: idx } { price: price, block: stacks-block-height, reporter: tx-sender })
    (map-set history-count pair (+ idx u1))
    (if (is-none (map-get? price-feeds pair)) (var-set feed-count (+ (var-get feed-count) u1)) true)
    (ok price)))

(define-read-only (get-price (pair (string-ascii 20))) (map-get? price-feeds pair))
(define-read-only (get-price-at (pair (string-ascii 20)) (index uint)) (map-get? price-history { pair: pair, index: index }))
(define-read-only (get-history-length (pair (string-ascii 20))) (ok (default-to u0 (map-get? history-count pair))))
(define-read-only (get-feed-count) (ok (var-get feed-count)))
(define-read-only (is-reporter (who principal)) (ok (default-to false (map-get? reporters who))))

Functions (8)

FunctionAccessArgs
add-reporterpublicr: principal
remove-reporterpublicr: principal
submit-pricepublicpair: (string-ascii 20
get-priceread-onlypair: (string-ascii 20
get-price-atread-onlypair: (string-ascii 20
get-history-lengthread-onlypair: (string-ascii 20
get-feed-countread-only
is-reporterread-onlywho: principal