;; sip010-token-v1.clar
;; SIP-010 Compliant Fungible Token
;; Implements the full SIP-010 trait with minter role management,
;; max supply cap, and compliance blacklist.
;; ============================================================
;; TRAIT IMPLEMENTATION
;; ============================================================
;; SIP-010 trait defined inline for standalone deployment
(define-trait sip-010-ft-trait
((transfer (uint principal principal (optional (buff 34))) (response bool uint))
(get-name () (response (string-ascii 32) uint))
(get-symbol () (response (string-ascii 10) uint))
(get-decimals () (response uint uint))
(get-balance (principal) (response uint uint))
(get-total-supply () (response uint uint))
(get-token-uri () (response (optional (string-utf8 256)) uint))))
;; ============================================================
;; ERROR CONSTANTS
;; ============================================================
(define-constant ERR-NOT-AUTHORIZED (err u1000))
(define-constant ERR-INSUFFICIENT-BALANCE (err u1001))
(define-constant ERR-INVALID-AMOUNT (err u1002))
(define-constant ERR-MAX-SUPPLY-REACHED (err u1003))
(define-constant ERR-BLACKLISTED (err u1004))
(define-constant ERR-ALREADY-MINTER (err u1005))
(define-constant ERR-NOT-MINTER (err u1006))
(define-constant ERR-SELF-TRANSFER (err u1007))
;; ============================================================
;; TOKEN DEFINITION & CONSTANTS
;; ============================================================
(define-fungible-token stacks-defi-token u1000000000000000) ;; 1 billion with 6 decimals
(define-constant CONTRACT-OWNER tx-sender)
(define-constant TOKEN-NAME "Stacks DeFi Token")
(define-constant TOKEN-SYMBOL "SDT")
(define-constant TOKEN-DECIMALS u6)
(define-constant MAX-SUPPLY u1000000000000000) ;; 1B * 10^6
;; ============================================================
;; DATA VARIABLES
;; ============================================================
(define-data-var token-uri (optional (string-utf8 256)) (some u"https://stacks-defi-suite.io/metadata/sdt.json"))
(define-data-var total-minted uint u0)
;; ============================================================
;; DATA MAPS
;; ============================================================
(define-map minters principal bool)
(define-map blacklist principal bool)
;; ============================================================
;; AUTHORIZATION HELPERS
;; ============================================================
(define-private (is-contract-owner)
(is-eq tx-sender CONTRACT-OWNER)
)
(define-private (is-minter (account principal))
(default-to false (map-get? minters account))
)
(define-private (is-blacklisted (account principal))
(default-to false (map-get? blacklist account))
)
(define-private (check-not-blacklisted (sender principal) (recipient principal))
(if (or (is-blacklisted sender) (is-blacklisted recipient))
ERR-BLACKLISTED
(ok true)
)
)
;; ============================================================
;; SIP-010 PUBLIC FUNCTIONS
;; ============================================================
(define-public (transfer (amount uint) (sender principal) (recipient principal) (memo (optional (buff 34))))
(begin
(asserts! (is-eq tx-sender sender) ERR-NOT-AUTHORIZED)
(asserts! (> amount u0) ERR-INVALID-AMOUNT)
(asserts! (not (is-eq sender recipient)) ERR-SELF-TRANSFER)
(try! (check-not-blacklisted sender recipient))
(match memo
m (print m)
0x
)
(ft-transfer? stacks-defi-token amount sender recipient)
)
)
;; ============================================================
;; MINT & BURN FUNCTIONS
;; ============================================================
(define-public (mint (amount uint) (recipient principal))
(begin
(asserts! (or (is-contract-owner) (is-minter tx-sender)) ERR-NOT-AUTHORIZED)
(asserts! (> amount u0) ERR-INVALID-AMOUNT)
(asserts! (not (is-blacklisted recipient)) ERR-BLACKLISTED)
(asserts! (<= (+ (var-get total-minted) amount) MAX-SUPPLY) ERR-MAX-SUPPLY-REACHED)
(var-set total-minted (+ (var-get total-minted) amount))
(ft-mint? stacks-defi-token amount recipient)
)
)
(define-public (burn (amount uint) (sender principal))
(begin
(asserts! (is-eq tx-sender sender) ERR-NOT-AUTHORIZED)
(asserts! (> amount u0) ERR-INVALID-AMOUNT)
(ft-burn? stacks-defi-token amount sender)
)
)
;; ============================================================
;; MINTER MANAGEMENT
;; ============================================================
(define-public (add-minter (account principal))
(begin
(asserts! (is-contract-owner) ERR-NOT-AUTHORIZED)
(asserts! (not (is-minter account)) ERR-ALREADY-MINTER)
(ok (map-set minters account true))
)
)
(define-public (remove-minter (account principal))
(begin
(asserts! (is-contract-owner) ERR-NOT-AUTHORIZED)
(asserts! (is-minter account) ERR-NOT-MINTER)
(ok (map-delete minters account))
)
)
;; ============================================================
;; BLACKLIST MANAGEMENT
;; ============================================================
(define-public (add-to-blacklist (account principal))
(begin
(asserts! (is-contract-owner) ERR-NOT-AUTHORIZED)
(ok (map-set blacklist account true))
)
)
(define-public (remove-from-blacklist (account principal))
(begin
(asserts! (is-contract-owner) ERR-NOT-AUTHORIZED)
(ok (map-delete blacklist account))
)
)
;; ============================================================
;; TOKEN URI MANAGEMENT
;; ============================================================
(define-public (set-token-uri (new-uri (optional (string-utf8 256))))
(begin
(asserts! (is-contract-owner) ERR-NOT-AUTHORIZED)
(ok (var-set token-uri new-uri))
)
)
;; ============================================================
;; SIP-010 READ-ONLY FUNCTIONS
;; ============================================================
(define-read-only (get-name)
(ok TOKEN-NAME)
)
(define-read-only (get-symbol)
(ok TOKEN-SYMBOL)
)
(define-read-only (get-decimals)
(ok TOKEN-DECIMALS)
)
(define-read-only (get-balance (account principal))
(ok (ft-get-balance stacks-defi-token account))
)
(define-read-only (get-total-supply)
(ok (ft-get-supply stacks-defi-token))
)
(define-read-only (get-token-uri)
(ok (var-get token-uri))
)
;; ============================================================
;; ADDITIONAL READ-ONLY FUNCTIONS
;; ============================================================
(define-read-only (get-max-supply)
(ok MAX-SUPPLY)
)
(define-read-only (get-total-minted)
(ok (var-get total-minted))
)
(define-read-only (get-remaining-supply)
(ok (- MAX-SUPPLY (var-get total-minted)))
)
(define-read-only (check-is-minter (account principal))
(ok (is-minter account))
)
(define-read-only (check-is-blacklisted (account principal))
(ok (is-blacklisted account))
)