Source Code

(define-constant CONTRACT_OWNER tx-sender)

(define-constant ERR_NOT_AUTHORIZED (err u1001))
(define-constant ERR_FACET_NOT_FOUND (err u1002))
(define-constant ERR_SELECTOR_EXISTS (err u1003))
(define-constant ERR_SELECTOR_NOT_FOUND (err u1004))
(define-constant ERR_INVALID_ACTION (err u1005))
(define-constant ERR_IMMUTABLE_FUNCTION (err u1006))
(define-constant ERR_INVALID_FACET (err u1007))
(define-constant ERR_ASSET_RESTRICTED (err u1008))
(define-constant ERR_INVALID_SIGNATURE (err u1009))
(define-constant ERR_DIAMOND_FROZEN (err u1010))

(define-constant ACTION_ADD u0)
(define-constant ACTION_REPLACE u1)
(define-constant ACTION_REMOVE u2)

(define-data-var diamond-owner principal CONTRACT_OWNER)
(define-data-var is-frozen bool false)
(define-data-var assets-restricted bool false)
(define-data-var facet-count uint u0)
(define-data-var selector-count uint u0)
(define-data-var cut-nonce uint u0)

(define-map facets
  principal
  {
    selector-count: uint,
    is-active: bool,
    added-at: uint,
    code-hash: (response (buff 32) uint)
  }
)

(define-map selectors
  (buff 4)
  {
    facet: principal,
    is-immutable: bool,
    added-at: uint
  }
)

(define-map facet-selectors
  { facet: principal, index: uint }
  (buff 4)
)

(define-map immutable-selectors (buff 4) bool)

(define-map pending-cuts
  (buff 32)
  {
    proposer: principal,
    proposed-at: uint,
    executed: bool,
    action: uint,
    facet: principal
  }
)

(define-map authorized-signers principal bool)

(define-private (is-owner)
  (is-eq tx-sender (var-get diamond-owner))
)

(define-private (emit-diamond-cut (action uint) (facet principal) (sel (buff 4)))
  (print { 
    event: "DiamondCut", 
    action: action, 
    facet: facet, 
    selector: sel,
    timestamp: stacks-block-time 
  })
)

(define-read-only (get-facet (facet-addr principal))
  (map-get? facets facet-addr)
)

(define-read-only (get-selector-facet (sel (buff 4)))
  (match (map-get? selectors sel) data (some (get facet data)) none)
)

(define-read-only (facet-address (sel (buff 4)))
  (get-selector-facet sel)
)

(define-read-only (facet-addresses)
  (var-get facet-count)
)

(define-read-only (get-facet-selector (facet principal) (index uint))
  (map-get? facet-selectors { facet: facet, index: index })
)

(define-read-only (is-selector-immutable (sel (buff 4)))
  (default-to false (map-get? immutable-selectors sel))
)

(define-read-only (get-diamond-owner)
  (var-get diamond-owner)
)

(define-read-only (is-diamond-frozen)
  (var-get is-frozen)
)

(define-read-only (get-cut-nonce)
  (var-get cut-nonce)
)

(define-read-only (get-contract-hash)
  (contract-hash? tx-sender)
)

(define-read-only (get-current-time)
  stacks-block-time
)

(define-read-only (check-restrictions)
  (var-get assets-restricted)
)

(define-read-only (verify-cut-signature 
  (cut-hash (buff 32))
  (sig (buff 64))
  (pub-key (buff 33)))
  (secp256r1-verify cut-hash sig pub-key)
)

(define-public (add-facet 
  (facet-addr principal) 
  (sel (buff 4)) 
  (is-immutable bool))
  (begin
    (asserts! (is-owner) ERR_NOT_AUTHORIZED)
    (asserts! (not (var-get is-frozen)) ERR_DIAMOND_FROZEN)
    (asserts! (not (var-get assets-restricted)) ERR_ASSET_RESTRICTED)
    (asserts! (is-none (map-get? selectors sel)) ERR_SELECTOR_EXISTS)
    (match (map-get? facets facet-addr)
      existing
      (map-set facets facet-addr (merge existing { 
        selector-count: (+ (get selector-count existing) u1) 
      }))
      (begin
        (map-set facets facet-addr {
          selector-count: u1,
          is-active: true,
          added-at: stacks-block-time,
          code-hash: (contract-hash? facet-addr)
        })
        (var-set facet-count (+ (var-get facet-count) u1))
      )
    )
    (map-set selectors sel {
      facet: facet-addr,
      is-immutable: is-immutable,
      added-at: stacks-block-time
    })
    (if is-immutable
      (map-set immutable-selectors sel true)
      true
    )
    (var-set selector-count (+ (var-get selector-count) u1))
    (var-set cut-nonce (+ (var-get cut-nonce) u1))
    (emit-diamond-cut ACTION_ADD facet-addr sel)
    (ok true)
  )
)

(define-public (replace-facet 
  (sel (buff 4)) 
  (new-facet principal))
  (let ((selector-data (unwrap! (map-get? selectors sel) ERR_SELECTOR_NOT_FOUND)))
    (asserts! (is-owner) ERR_NOT_AUTHORIZED)
    (asserts! (not (var-get is-frozen)) ERR_DIAMOND_FROZEN)
    (asserts! (not (get is-immutable selector-data)) ERR_IMMUTABLE_FUNCTION)
    (asserts! (not (is-eq (get facet selector-data) new-facet)) ERR_INVALID_FACET)
    (match (map-get? facets new-facet)
      existing
      (map-set facets new-facet (merge existing { 
        selector-count: (+ (get selector-count existing) u1) 
      }))
      (begin
        (map-set facets new-facet {
          selector-count: u1,
          is-active: true,
          added-at: stacks-block-time,
          code-hash: (contract-hash? new-facet)
        })
        (var-set facet-count (+ (var-get facet-count) u1))
      )
    )
    (map-set selectors sel (merge selector-data { 
      facet: new-facet,
      added-at: stacks-block-time
    }))
    (var-set cut-nonce (+ (var-get cut-nonce) u1))
    (emit-diamond-cut ACTION_REPLACE new-facet sel)
    (ok true)
  )
)

(define-public (remove-facet (sel (buff 4)))
  (let ((selector-data (unwrap! (map-get? selectors sel) ERR_SELECTOR_NOT_FOUND)))
    (asserts! (is-owner) ERR_NOT_AUTHORIZED)
    (asserts! (not (var-get is-frozen)) ERR_DIAMOND_FROZEN)
    (asserts! (not (get is-immutable selector-data)) ERR_IMMUTABLE_FUNCTION)
    (map-delete selectors sel)
    (var-set selector-count (- (var-get selector-count) u1))
    (var-set cut-nonce (+ (var-get cut-nonce) u1))
    (emit-diamond-cut ACTION_REMOVE (get facet selector-data) sel)
    (ok true)
  )
)

(define-public (diamond-cut-with-sig
  (action uint)
  (facet-addr principal)
  (sel (buff 4))
  (sig (buff 64))
  (pub-key (buff 33)))
  (let (
    (nonce (var-get cut-nonce))
    (cut-hash (keccak256 (concat (concat sel (unwrap-panic (to-consensus-buff? facet-addr))) (unwrap-panic (to-consensus-buff? nonce)))))
  )
    (asserts! (default-to false (map-get? authorized-signers tx-sender)) ERR_NOT_AUTHORIZED)
    (asserts! (secp256r1-verify cut-hash sig pub-key) ERR_INVALID_SIGNATURE)
    (if (is-eq action ACTION_ADD)
      (add-facet facet-addr sel false)
      (if (is-eq action ACTION_REPLACE)
        (replace-facet sel facet-addr)
        (if (is-eq action ACTION_REMOVE)
          (remove-facet sel)
          ERR_INVALID_ACTION
        )
      )
    )
  )
)

(define-public (authorize-signer (signer principal))
  (begin
    (asserts! (is-owner) ERR_NOT_AUTHORIZED)
    (map-set authorized-signers signer true)
    (ok true)
  )
)

(define-public (revoke-signer (signer principal))
  (begin
    (asserts! (is-owner) ERR_NOT_AUTHORIZED)
    (map-delete authorized-signers signer)
    (ok true)
  )
)

(define-public (freeze-diamond)
  (begin
    (asserts! (is-owner) ERR_NOT_AUTHORIZED)
    (var-set is-frozen true)
    (print { event: "DiamondFrozen", timestamp: stacks-block-time })
    (ok true)
  )
)

(define-public (transfer-ownership (new-owner principal))
  (begin
    (asserts! (is-owner) ERR_NOT_AUTHORIZED)
    (var-set diamond-owner new-owner)
    (print { event: "OwnershipTransferred", new-owner: new-owner, timestamp: stacks-block-time })
    (ok true)
  )
)

(define-public (set-asset-restriction (restricted bool))
  (begin
    (asserts! (is-owner) ERR_NOT_AUTHORIZED)
    (var-set assets-restricted restricted)
    (ok true)
  )
)

(define-read-only (loupe-facets)
  (var-get facet-count)
)

(define-read-only (loupe-facet-function-selectors (facet-addr principal))
  (match (map-get? facets facet-addr) data (get selector-count data) u0)
)

(define-read-only (supports-interface (interface-id (buff 4)))
  (or 
    (is-eq interface-id 0x1f931c1c)
    (is-eq interface-id 0x48e2b093)
    (is-eq interface-id 0x01ffc9a7)
  )
)

(define-read-only (get-selector-info (sel (buff 4)))
  (map-get? selectors sel)
)

(define-read-only (selector-to-ascii (sel (buff 4)))
  (to-ascii? sel)
)

Functions (29)

FunctionAccessArgs
is-ownerprivate
emit-diamond-cutprivateaction: uint, facet: principal, sel: (buff 4
get-facetread-onlyfacet-addr: principal
get-selector-facetread-onlysel: (buff 4
facet-addressread-onlysel: (buff 4
facet-addressesread-only
get-facet-selectorread-onlyfacet: principal, index: uint
is-selector-immutableread-onlysel: (buff 4
get-diamond-ownerread-only
is-diamond-frozenread-only
get-cut-nonceread-only
get-contract-hashread-only
get-current-timeread-only
check-restrictionsread-only
verify-cut-signatureread-onlycut-hash: (buff 32
add-facetpublicfacet-addr: principal, sel: (buff 4
replace-facetpublicsel: (buff 4
remove-facetpublicsel: (buff 4
diamond-cut-with-sigpublicaction: uint, facet-addr: principal, sel: (buff 4
authorize-signerpublicsigner: principal
revoke-signerpublicsigner: principal
freeze-diamondpublic
transfer-ownershippublicnew-owner: principal
set-asset-restrictionpublicrestricted: bool
loupe-facetsread-only
loupe-facet-function-selectorsread-onlyfacet-addr: principal
supports-interfaceread-onlyinterface-id: (buff 4
get-selector-inforead-onlysel: (buff 4
selector-to-asciiread-onlysel: (buff 4