Source Code

;; title: sbtc-reputation-oracle
;; version:
;; summary:
;; description:
;; Music Royalty Distribution and Rights Management System
;; This contract manages the transparent distribution of music royalties among artists, 
;; producers, and rights holders with secure tracking of payments and earnings.

;; Error constants
(define-constant ERR-UNAUTHORIZED-ACCESS (err u100))
(define-constant ERR-INVALID-SHARE-VALUE (err u101))
(define-constant ERR-TRACK-ALREADY-EXISTS (err u102))
(define-constant ERR-TRACK-NOT-FOUND (err u103))
(define-constant ERR-PAYMENT-SHORTAGE (err u104))
(define-constant ERR-INVALID-STAKEHOLDER (err u105))
(define-constant ERR-DISBURSEMENT-FAILED (err u106))
(define-constant ERR-INVALID-STRING-SIZE (err u107))
(define-constant ERR-INVALID-TRACK-NAME (err u108))
(define-constant ERR-INVALID-MEMBER-TYPE (err u109))
(define-constant ERR-INVALID-PERFORMER (err u110))
(define-constant ERR-INVALID-MANAGER (err u111))

;; Data structures
(define-map track-catalog
    { track-id: uint }
    {
        track-name: (string-ascii 50),
        performer: principal,
        lifetime-revenue: uint,
        registration-date: uint,
        distribution-enabled: bool
    }
)

(define-map revenue-shares
    { track-id: uint, stakeholder: principal }
    {
        percentage-share: uint,
        member-type: (string-ascii 20),
        earned-to-date: uint
    }
)

;; State variables
(define-data-var catalog-size uint u0)
(define-data-var catalog-manager principal tx-sender)

;; Read-only functions - Data access
(define-read-only (get-track-info (track-id uint))
    (map-get? track-catalog { track-id: track-id })
)

(define-read-only (get-stakeholder-info (track-id uint) (stakeholder principal))
    (map-get? revenue-shares { track-id: track-id, stakeholder: stakeholder })
)

(define-read-only (get-catalog-size)
    (var-get catalog-size)
)

(define-read-only (get-track-stakeholders (track-id uint))
    (let (
        (track-info (get-track-info track-id))
        (main-performer (match track-info record (get performer record) tx-sender))
    )
    (let ((stakeholder-data (get-stakeholder-info track-id main-performer)))
        (match stakeholder-data share
            (list {
                stakeholder: main-performer,
                percentage-share: (get percentage-share share)
            })
            (list))))
)

;; Private validation functions
(define-private (is-valid-share-data (share {
    percentage-share: uint,
    member-type: (string-ascii 20),
    earned-to-date: uint
}))
    (> (get percentage-share share) u0)
)

(define-private (is-catalog-manager)
    (is-eq tx-sender (var-get catalog-manager))
)

(define-private (validate-percentage-range (percentage uint))
    (and (>= percentage u0) (<= percentage u100))
)

(define-private (validate-string-input (input (string-ascii 50)))
    (let ((string-length (len input)))
        (and (> string-length u0) (<= string-length u50))))

(define-private (validate-member-type (type-value (string-ascii 20)))
    (let ((type-length (len type-value)))
        (and (> type-length u0) (<= type-length u20))))

(define-private (validate-stakeholder-address (address principal))
    (and 
        (not (is-eq address tx-sender))
        (not (is-eq address (var-get catalog-manager)))
    ))

;; Private payment processing functions
(define-private (process-share-payment
    (allocation {stakeholder: principal, percentage-share: uint}) 
    (payout-amount uint))
    (let (
        (recipient-share (/ (* payout-amount (get percentage-share allocation)) u100))
    )
    (if (> recipient-share u0)
        (match (stx-transfer? recipient-share tx-sender (get stakeholder allocation))
            success payout-amount
            error u0)
        u0))
)

(define-private (execute-payments (track-id uint) (payout-amount uint))
    (let (
        (stakeholder-list (get-track-stakeholders track-id))
        (total-distributed (fold process-share-payment 
                          stakeholder-list 
                          payout-amount))
    )
    (begin
        (asserts! (> (len stakeholder-list) u0) ERR-TRACK-NOT-FOUND)
        (asserts! (> total-distributed u0) ERR-DISBURSEMENT-FAILED)
        (ok total-distributed)))
)

;; Public functions - Administrative
(define-public (register-track (track-name (string-ascii 50)) (performer principal))
    (let (
        (new-track-id (+ (var-get catalog-size) u1))
    )
    (begin
        (asserts! (is-catalog-manager) ERR-UNAUTHORIZED-ACCESS)
        (asserts! (validate-string-input track-name) ERR-INVALID-TRACK-NAME)
        (asserts! (validate-stakeholder-address performer) ERR-INVALID-PERFORMER)
        
        (map-set track-catalog
            { track-id: new-track-id }
            {
                track-name: track-name,
                performer: performer,
                lifetime-revenue: u0,
                registration-date: stacks-block-height,
                distribution-enabled: true
            }
        )
        (var-set catalog-size new-track-id)
        (ok new-track-id)))
)

(define-public (set-share-allocation 
    (track-id uint) 
    (stakeholder principal) 
    (percentage-share uint) 
    (member-type (string-ascii 20)))
    (let (
        (track-data (get-track-info track-id))
    )
    (begin
        (asserts! (is-some track-data) ERR-TRACK-NOT-FOUND)
        (asserts! (validate-percentage-range percentage-share) ERR-INVALID-SHARE-VALUE)
        (asserts! (validate-member-type member-type) ERR-INVALID-MEMBER-TYPE)
        (asserts! (validate-stakeholder-address stakeholder) ERR-INVALID-STAKEHOLDER)
        
        (map-set revenue-shares
            { track-id: track-id, stakeholder: stakeholder }
            {
                percentage-share: percentage-share,
                member-type: member-type,
                earned-to-date: u0
            }
        )
        (ok true)))
)

(define-public (set-track-status (track-id uint) (status-enabled bool))
    (let (
        (track-data (get-track-info track-id))
    )
    (begin
        (asserts! (is-catalog-manager) ERR-UNAUTHORIZED-ACCESS)
        (asserts! (is-some track-data) ERR-TRACK-NOT-FOUND)
        
        (map-set track-catalog
            { track-id: track-id }
            (merge (unwrap-panic track-data)
                { distribution-enabled: status-enabled }
            )
        )
        (ok true)))
)

(define-public (assign-manager (new-manager principal))
    (begin
        (asserts! (is-catalog-manager) ERR-UNAUTHORIZED-ACCESS)
        (asserts! (validate-stakeholder-address new-manager) ERR-INVALID-MANAGER)
        
        (var-set catalog-manager new-manager)
        (ok true))
)

;; Public functions - Payment processing
(define-public (distribute-royalties (track-id uint) (royalty-amount uint))
    (let (
        (track-data (get-track-info track-id))
    )
    (begin
        (asserts! (is-some track-data) ERR-TRACK-NOT-FOUND)
        (asserts! (>= (stx-get-balance tx-sender) royalty-amount) ERR-PAYMENT-SHORTAGE)
        
        (try! (execute-payments track-id royalty-amount))
        (map-set track-catalog
            { track-id: track-id }
            (merge (unwrap-panic track-data)
                { lifetime-revenue: (+ (get lifetime-revenue (unwrap-panic track-data)) royalty-amount) }
            )
        )
        (ok true)))
)

;; Contract initialization
(begin
    (var-set catalog-size u0))

Functions (16)

FunctionAccessArgs
get-track-inforead-onlytrack-id: uint
get-stakeholder-inforead-onlytrack-id: uint, stakeholder: principal
get-catalog-sizeread-only
get-track-stakeholdersread-onlytrack-id: uint
is-catalog-managerprivate
validate-percentage-rangeprivatepercentage: uint
validate-string-inputprivateinput: (string-ascii 50
validate-member-typeprivatetype-value: (string-ascii 20
validate-stakeholder-addressprivateaddress: principal
process-share-paymentprivateallocation: {stakeholder: principal, percentage-share: uint}, payout-amount: uint
execute-paymentsprivatetrack-id: uint, payout-amount: uint
register-trackpublictrack-name: (string-ascii 50
set-share-allocationpublictrack-id: uint, stakeholder: principal, percentage-share: uint, member-type: (string-ascii 20
set-track-statuspublictrack-id: uint, status-enabled: bool
assign-managerpublicnew-manager: principal
distribute-royaltiespublictrack-id: uint, royalty-amount: uint