Source Code

;; Test Token Contract
;; Implements SIP-010 fungible token standard for development and testing
;; Version: 1.0.0

(impl-trait .sip-010-trait.sip-010-trait)

;; Token Definition
(define-fungible-token test-token)

;; Constants
(define-constant CONTRACT_OWNER tx-sender)
(define-constant ERR_NOT_OWNER (err u7001))
(define-constant ERR_INSUFFICIENT_BALANCE (err u7002))
(define-constant ERR_NOT_AUTHORIZED (err u7003))
(define-constant ERR_INVALID_AMOUNT (err u7004))

;; Data Variables
(define-data-var token-name (string-ascii 32) "Test Token")
(define-data-var token-symbol (string-ascii 10) "TEST")
(define-data-var token-decimals uint u6)
(define-data-var token-uri (optional (string-utf8 256)) none)
(define-data-var contract-owner principal CONTRACT_OWNER)

;; Ownership Functions

(define-public (set-owner (new-owner principal))
  (begin
    (asserts! (is-eq tx-sender (var-get contract-owner)) ERR_NOT_OWNER)
    (var-set contract-owner new-owner)
    (ok true)))

(define-read-only (get-owner)
  (ok (var-get contract-owner)))

;; Mint Function - Owner Only (for testing)
(define-public (mint (amount uint) (recipient principal))
  (begin
    ;; Check caller is owner
    (asserts! (is-eq tx-sender (var-get contract-owner)) ERR_NOT_OWNER)
    ;; Check amount is valid
    (asserts! (> amount u0) ERR_INVALID_AMOUNT)
    ;; Mint tokens to recipient
    (ft-mint? test-token amount recipient)))

;; Burn Function - Any holder can burn their own tokens
(define-public (burn (amount uint))
  (begin
    ;; Check amount is valid
    (asserts! (> amount u0) ERR_INVALID_AMOUNT)
    ;; Check caller has sufficient balance
    (asserts! (>= (ft-get-balance test-token tx-sender) amount) ERR_INSUFFICIENT_BALANCE)
    ;; Burn tokens from caller
    (ft-burn? test-token amount tx-sender)))

;; SIP-010 Transfer Function
(define-public (transfer (amount uint) (sender principal) (recipient principal) (memo (optional (buff 34))))
  (begin
    ;; Check amount is valid
    (asserts! (> amount u0) ERR_INVALID_AMOUNT)
    ;; Sender must be tx-sender
    (asserts! (is-eq tx-sender sender) ERR_NOT_AUTHORIZED)
    ;; Check sender has sufficient balance
    (asserts! (>= (ft-get-balance test-token sender) amount) ERR_INSUFFICIENT_BALANCE)
    ;; Perform transfer
    (match (ft-transfer? test-token amount sender recipient)
      success (begin
        ;; Print transfer event
        (print {
          type: "sip010-transfer",
          sender: sender,
          recipient: recipient,
          amount: amount,
          memo: memo
        })
        (ok success))
      error (err error))))

;; SIP-010 Read-Only Functions

(define-read-only (get-name)
  (ok (var-get token-name)))

(define-read-only (get-symbol)
  (ok (var-get token-symbol)))

(define-read-only (get-decimals)
  (ok (var-get token-decimals)))

(define-read-only (get-balance (account principal))
  (ok (ft-get-balance test-token account)))

(define-read-only (get-total-supply)
  (ok (ft-get-supply test-token)))

(define-read-only (get-token-uri)
  (ok (var-get token-uri)))

;; Additional Helper Functions

(define-public (set-token-uri (uri (optional (string-utf8 256))))
  (begin
    (asserts! (is-eq tx-sender (var-get contract-owner)) ERR_NOT_OWNER)
    (var-set token-uri uri)
    (ok true)))

;; Batch Operations (useful for testing)

(define-public (mint-many (recipients (list 10 {to: principal, amount: uint})))
  (begin
    (asserts! (is-eq tx-sender (var-get contract-owner)) ERR_NOT_OWNER)
    (ok (map mint-many-iter recipients))))

(define-private (mint-many-iter (recipient {to: principal, amount: uint}))
  (ft-mint? test-token (get amount recipient) (get to recipient)))

;; Initial Supply Distribution (optional, called once)
(define-public (initialize-supply (initial-holders (list 5 {to: principal, amount: uint})))
  (begin
    (asserts! (is-eq tx-sender (var-get contract-owner)) ERR_NOT_OWNER)
    ;; Can only initialize once (when supply is 0)
    (asserts! (is-eq (ft-get-supply test-token) u0) ERR_NOT_AUTHORIZED)
    (ok (map mint-many-iter initial-holders))))

;; Get contract info
(define-read-only (get-contract-info)
  {
    name: (var-get token-name),
    symbol: (var-get token-symbol),
    decimals: (var-get token-decimals),
    total-supply: (ft-get-supply test-token),
    owner: (var-get contract-owner),
    uri: (var-get token-uri)
  })

Functions (16)

FunctionAccessArgs
set-ownerpublicnew-owner: principal
get-ownerread-only
mintpublicamount: uint, recipient: principal
burnpublicamount: uint
transferpublicamount: uint, sender: principal, recipient: principal, memo: (optional (buff 34
get-nameread-only
get-symbolread-only
get-decimalsread-only
get-balanceread-onlyaccount: principal
get-total-supplyread-only
get-token-uriread-only
set-token-uripublicuri: (optional (string-utf8 256
mint-manypublicrecipients: (list 10 {to: principal, amount: uint}
mint-many-iterprivaterecipient: {to: principal, amount: uint}
initialize-supplypublicinitial-holders: (list 5 {to: principal, amount: uint}
get-contract-inforead-only