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 (11)

FunctionAccessArgs
get-track-inforead-onlytrack-id: uint
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
register-trackpublictrack-name: (string-ascii 50
set-share-allocationpublictrack-id: uint, stakeholder: principal, percentage-share: uint, member-type: (string-ascii 20
assign-managerpublicnew-manager: principal