Source Code

;; 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))
)

Functions (23)

FunctionAccessArgs
is-contract-ownerprivate
is-minterprivateaccount: principal
is-blacklistedprivateaccount: principal
check-not-blacklistedprivatesender: principal, recipient: principal
transferpublicamount: uint, sender: principal, recipient: principal, memo: (optional (buff 34
mintpublicamount: uint, recipient: principal
burnpublicamount: uint, sender: principal
add-minterpublicaccount: principal
remove-minterpublicaccount: principal
add-to-blacklistpublicaccount: principal
remove-from-blacklistpublicaccount: principal
set-token-uripublicnew-uri: (optional (string-utf8 256
get-nameread-only
get-symbolread-only
get-decimalsread-only
get-balanceread-onlyaccount: principal
get-total-supplyread-only
get-token-uriread-only
get-max-supplyread-only
get-total-mintedread-only
get-remaining-supplyread-only
check-is-minterread-onlyaccount: principal
check-is-blacklistedread-onlyaccount: principal