Source Code

;; BNS Zonefile Management Contract

;; Error constants
(define-constant ERR-NOT-AUTHORIZED (err u100))
(define-constant ERR-NO-ZONEFILE-FOUND (err u101))
(define-constant ERR-NO-NAME (err u102))
(define-constant ERR-NO-NAMESPACE (err u103))
(define-constant ERR-NAME-REVOKED (err u104))
(define-constant ERR-MIGRATION-IN-PROGRESS (err u105))
(define-constant ERR-INVALID-PERIOD (err u106))

;; Data Maps

;; zonefile map: Stores zonefile information for each name in a namespace
;; Key: {name: (buff 48), namespace: (buff 20)}
;; Value: {owner: principal, zonefile: (optional (buff 8192)), revoked: bool}
(define-map zonefile {name: (buff 48), namespace: (buff 20)} 
    {
        owner: principal,
        zonefile: (optional (buff 8192)),
        revoked: bool
    }
)

;; Read-only Functions

;; Resolve a name to its zonefile
;; This function checks ownership and validity before returning the zonefile
(define-read-only (resolve-name (name (buff 48)) (namespace (buff 20))) 
    (let 
        (
            (name-resolve (unwrap! (contract-call? 'SP2QEZ06AGJ3RKJPBV14SY1V5BBFNAW33D96YPGZF.BNS-V2 can-resolve-name namespace name) ERR-NO-NAME))
            (current-zonefile (unwrap! (map-get? zonefile {name: name, namespace: namespace}) ERR-NO-ZONEFILE-FOUND))
        ) 
        ;; Check if the name is in a valid grace period
        (asserts! 
            (if (is-eq u0 (get renewal name-resolve))
                ;; If true it means that the name is in a managed namespace or the namespace does not require renewals
                true
                ;; If false then calculate valid period
                (<= burn-block-height (get renewal name-resolve))
            )
            ERR-INVALID-PERIOD
        )
        ;; Check that the name is not revoked
        (asserts! (not (get revoked current-zonefile)) ERR-NAME-REVOKED)
        (ok 
            (if (is-eq (get owner name-resolve) (get owner current-zonefile)) 
                ;; If the name owner matches the zonefile owner, return the zonefile
                (get zonefile current-zonefile)
                ;; If owners don't match, return none
                none
            )
        )
    )
)

;; Public Functions

;; Update the zonefile for a name
;; This function allows authorized users to update the zonefile of a name
(define-public (update-zonefile (name (buff 48)) (namespace (buff 20)) (new-zonefile (optional (buff 8192))))
    (let 
        (
            ;; Retrieve namespace and name properties
            (namespace-properties (try! (contract-call? 'SP2QEZ06AGJ3RKJPBV14SY1V5BBFNAW33D96YPGZF.BNS-V2 get-namespace-properties namespace)))
            (namespace-props (get properties namespace-properties))
            ;; Retrieve name properties from BNS-V2 contract
            (name-properties (unwrap! (contract-call? 'SP2QEZ06AGJ3RKJPBV14SY1V5BBFNAW33D96YPGZF.BNS-V2 get-bns-info name namespace) ERR-NO-NAME))
            (name-owner (get owner name-properties))
            (renewal (get renewal-height name-properties))
            (current-zonefile (map-get? zonefile {name: name, namespace: namespace}))
            (zonefile-owner (get owner current-zonefile))
        ) 
        ;; Check if the name is in a valid grace period
        (asserts! 
            (if (is-eq (get lifetime namespace-props) u0)
                ;; It's always in a valid period 
                true
                ;; Check if it's within the grace period
                (<= burn-block-height (+ renewal u5000))
            )
            ERR-INVALID-PERIOD
        )
        ;; Check if the zonefile exists
        (match current-zonefile 
            c-zonefile 
            ;; If it does check that the name is not revoked
            (asserts! (not (get revoked c-zonefile)) ERR-NAME-REVOKED)
            ;; If it doesn't then continue
            true
        )
        
        ;; Check authorization based on namespace manager
        (match (get namespace-manager namespace-props)
            manager 
            ;; If managed, check if contract-caller is the manager
            (asserts! (is-eq contract-caller manager) ERR-NOT-AUTHORIZED)
            ;; If not managed, check if contract-caller is the owner
            (asserts! (is-eq contract-caller name-owner) ERR-NOT-AUTHORIZED)
        )
        ;; Update the zonefile map
        (map-set zonefile {name: name, namespace: namespace} 
            {
                ;; Update owner to the current owner
                owner: name-owner,
                ;; Set new zonefile or CID
                zonefile: new-zonefile,
                ;; Set revoked to false since it's being updated
                revoked: false
            }
        )
        (print 
            {
                topic: "update-zonefile", 
                name: name,
                namespace: namespace,
                new-zonefile: new-zonefile
            }
        )
        (ok true)
    )
)

;; Revoke a name
;; This function allows authorized users to revoke a name
(define-public (revoke-name (name (buff 48)) (namespace (buff 20)))
    (let
        (
            ;; Retrieve namespace and name properties
            (namespace-properties (try! (contract-call? 'SP2QEZ06AGJ3RKJPBV14SY1V5BBFNAW33D96YPGZF.BNS-V2 get-namespace-properties namespace)))
            (namespace-props (get properties namespace-properties))
            (name-properties (unwrap! (contract-call? 'SP2QEZ06AGJ3RKJPBV14SY1V5BBFNAW33D96YPGZF.BNS-V2 get-bns-info name namespace) ERR-NO-NAME))
            (name-owner (get owner name-properties))
        )
        ;; Check authorization based on namespace manager
        (match (get namespace-manager namespace-props)
            manager 
            ;; If managed, check if contract-caller is the manager
            (asserts! (is-eq contract-caller manager) ERR-NOT-AUTHORIZED)
            ;; If not managed, check if contract-caller is the owner or namespace import principal
            (asserts! (or (is-eq contract-caller name-owner) (is-eq contract-caller (get namespace-import namespace-props))) ERR-NOT-AUTHORIZED)
        )
        ;; Update the zonefile information to revoke the name
        (map-set zonefile {name: name, namespace: namespace} 
            {
                ;; Update owner to the current owner
                owner: name-owner,
                ;; Clear the zonefile
                zonefile: none,
                ;; Set revoked to true
                revoked: true
            }
        )
        (print 
            {
                topic: "revoke-name", 
                name: name,
                namespace: namespace,
                zonefile: 0x
            }
        )
        (ok true)
    )
)

Functions (3)

FunctionAccessArgs
resolve-nameread-onlyname: (buff 48
update-zonefilepublicname: (buff 48
revoke-namepublicname: (buff 48