Source Code

;; Dispute Resolution Contract
;; Decentralized arbitration system

(define-constant err-not-party (err u100))
(define-constant err-already-resolved (err u101))
(define-constant err-not-arbitrator (err u102))

(define-data-var dispute-nonce uint u0)
(define-data-var arbitration-fee uint u500000)

(define-map disputes
    uint
    {
        plaintiff: principal,
        defendant: principal,
        arbitrator: (optional principal),
        stake-amount: uint,
        description: (string-utf8 500),
        plaintiff-evidence: (optional (string-utf8 500)),
        defendant-evidence: (optional (string-utf8 500)),
        resolved: bool,
        winner: (optional principal),
        resolution-block: (optional uint)
    }
)

(define-map arbitrators principal bool)

(define-public (register-arbitrator)
    (begin
        (map-set arbitrators tx-sender true)
        (ok true)
    )
)

(define-public (create-dispute
    (defendant principal)
    (stake-amount uint)
    (description (string-utf8 500)))
    (let ((dispute-id (var-get dispute-nonce)))
        (try! (stx-transfer? stake-amount tx-sender (as-contract tx-sender)))

        (map-set disputes dispute-id {
            plaintiff: tx-sender,
            defendant: defendant,
            arbitrator: none,
            stake-amount: stake-amount,
            description: description,
            plaintiff-evidence: none,
            defendant-evidence: none,
            resolved: false,
            winner: none,
            resolution-block: none
        })

        (var-set dispute-nonce (+ dispute-id u1))
        (ok dispute-id)
    )
)

(define-public (join-dispute (dispute-id uint))
    (let ((dispute (unwrap! (map-get? disputes dispute-id) err-not-party)))
        (asserts! (is-eq tx-sender (get defendant dispute)) err-not-party)
        (asserts! (not (get resolved dispute)) err-already-resolved)
        (try! (stx-transfer? (get stake-amount dispute) tx-sender (as-contract tx-sender)))
        (ok true)
    )
)

(define-public (submit-evidence (dispute-id uint) (evidence (string-utf8 500)))
    (let ((dispute (unwrap! (map-get? disputes dispute-id) err-not-party)))
        (asserts! (not (get resolved dispute)) err-already-resolved)

        (asserts!
            (or
                (is-eq tx-sender (get plaintiff dispute))
                (is-eq tx-sender (get defendant dispute))
            )
            err-not-party
        )

        (if (is-eq tx-sender (get plaintiff dispute))
            (map-set disputes dispute-id (merge dispute {
                plaintiff-evidence: (some evidence)
            }))
            (map-set disputes dispute-id (merge dispute {
                defendant-evidence: (some evidence)
            }))
        )

        (ok true)
    )
)

(define-public (accept-arbitration (dispute-id uint))
    (let ((dispute (unwrap! (map-get? disputes dispute-id) err-not-party)))
        (asserts! (default-to false (map-get? arbitrators tx-sender)) err-not-arbitrator)
        (asserts! (is-none (get arbitrator dispute)) err-already-resolved)

        (map-set disputes dispute-id (merge dispute {
            arbitrator: (some tx-sender)
        }))

        (ok true)
    )
)

(define-public (resolve-dispute (dispute-id uint) (winner principal))
    (let (
        (dispute (unwrap! (map-get? disputes dispute-id) err-not-party))
        (total-stake (* (get stake-amount dispute) u2))
    )
        (asserts! (is-eq (some tx-sender) (get arbitrator dispute)) err-not-arbitrator)
        (asserts! (not (get resolved dispute)) err-already-resolved)

        (try! (as-contract (stx-transfer? total-stake tx-sender winner)))
        (try! (as-contract (stx-transfer? (var-get arbitration-fee) tx-sender tx-sender)))

        (map-set disputes dispute-id (merge dispute {
            resolved: true,
            winner: (some winner),
            resolution-block: (some block-height)
        }))

        (ok true)
    )
)

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

(define-read-only (is-arbitrator (user principal))
    (default-to false (map-get? arbitrators user))
)

Functions (8)

FunctionAccessArgs
register-arbitratorpublic
create-disputepublicdefendant: principal, stake-amount: uint, description: (string-utf8 500
join-disputepublicdispute-id: uint
submit-evidencepublicdispute-id: uint, evidence: (string-utf8 500
accept-arbitrationpublicdispute-id: uint
resolve-disputepublicdispute-id: uint, winner: principal
get-disputeread-onlydispute-id: uint
is-arbitratorread-onlyuser: principal