Source Code

;; clarity-version: 2
(define-constant contract-owner tx-sender)
(define-constant err-unauthorized (err u300))
(define-constant err-dispute-not-found (err u301))
(define-constant err-already-voted (err u302))
(define-constant err-not-arbiter (err u303))

(define-data-var dispute-nonce uint u0)
(define-data-var arbiter-count uint u0)

(define-map disputes
    { dispute-id: uint }
    {
        submission-id: uint,
        initiator: principal,
        reason: (string-utf8 100),
        created-at: uint,
        votes-for: uint,
        votes-against: uint,
        status: (string-ascii 8),
        resolved-at: (optional uint)
    }
)

(define-map arbiters
    { arbiter: principal }
    { 
        is-active: bool,
        total-votes: uint,
        correct-votes: uint
    }
)

(define-map arbiter-votes
    { dispute-id: uint, arbiter: principal }
    { vote: bool, voted-at: uint }
)

(define-public (register-arbiter)
    (begin
        (map-set arbiters
            { arbiter: tx-sender }
            {
                is-active: true,
                total-votes: u0,
                correct-votes: u0
            }
        )
        (var-set arbiter-count (+ (var-get arbiter-count) u1))
        (ok true)
    )
)

(define-public (create-dispute 
    (submission-id uint)
    (reason (string-utf8 100))
)
    (let
        (
            (dispute-id (+ (var-get dispute-nonce) u1))
        )
        (map-set disputes
            { dispute-id: dispute-id }
            {
                submission-id: submission-id,
                initiator: tx-sender,
                reason: reason,
                created-at: block-height,
                votes-for: u0,
                votes-against: u0,
                status: "open",
                resolved-at: none
            }
        )
        (var-set dispute-nonce dispute-id)
        (ok dispute-id)
    )
)

(define-public (vote-on-dispute (dispute-id uint) (vote-for bool))
    (let
        (
            (dispute (unwrap! (map-get? disputes { dispute-id: dispute-id }) err-dispute-not-found))
            (arbiter (unwrap! (map-get? arbiters { arbiter: tx-sender }) err-not-arbiter))
            (existing-vote (map-get? arbiter-votes { dispute-id: dispute-id, arbiter: tx-sender }))
        )
        (asserts! (is-none existing-vote) err-already-voted)
        (asserts! (get is-active arbiter) err-unauthorized)
        (map-set arbiter-votes
            { dispute-id: dispute-id, arbiter: tx-sender }
            { vote: vote-for, voted-at: block-height }
        )
        (map-set disputes
            { dispute-id: dispute-id }
            (merge dispute {
                votes-for: (if vote-for (+ (get votes-for dispute) u1) (get votes-for dispute)),
                votes-against: (if vote-for (get votes-against dispute) (+ (get votes-against dispute) u1))
            })
        )
        (ok true)
    )
)

(define-read-only (get-dispute (dispute-id uint))
    (map-get? disputes { dispute-id: dispute-id })
)

Functions (4)

FunctionAccessArgs
register-arbiterpublic
create-disputepublicsubmission-id: uint, reason: (string-utf8 100
vote-on-disputepublicdispute-id: uint, vote-for: bool
get-disputeread-onlydispute-id: uint