;; =====================================================================
;; SIP-010 Fungible Token 0.1% Transfer Tax & Auto-Burn
;; =====================================================================
;; TESTNET version uses ST prefix trait address
;; =====================================================================
(impl-trait 'SP3FBR2AGK5H9QBDH3EEN6DF8EK8JY7RX8QJ5SVTE.sip-010-trait-ft-standard.sip-010-trait)
;; --------------------------------------------------
;; Error Constants
;; --------------------------------------------------
(define-constant ERR-NOT-AUTHORIZED (err u1000))
(define-constant ERR-NOT-ADMIN (err u1001))
(define-constant ERR-INSUFFICIENT-BALANCE (err u1))
(define-constant ERR-SENDER-EQUALS-RECIPIENT (err u2))
(define-constant ERR-AMOUNT-ZERO (err u3))
(define-constant ERR-SENDER-NOT-TX-SENDER (err u4))
(define-constant ERR-MINT-FAILED (err u1002))
(define-constant ERR-BURN-FAILED (err u1003))
(define-constant ERR-TRANSFER-FAILED (err u1004))
(define-constant ERR-ADMIN-ALREADY-SET (err u1005))
(define-constant ERR-INVALID-PRINCIPAL (err u1006))
(define-constant ERR-AMOUNT-BELOW-MINIMUM (err u1007))
;; --------------------------------------------------
;; Token Definition
;; --------------------------------------------------
(define-fungible-token PAULO u1000000000000000)
;; --------------------------------------------------
;; Constants
;; --------------------------------------------------
(define-constant CONTRACT-DEPLOYER tx-sender)
(define-constant TOKEN-NAME "PAULO")
(define-constant TOKEN-SYMBOL "PAULO")
(define-constant TOKEN-DECIMALS u6)
(define-constant TOKEN-TOTAL-SUPPLY u1000000000000000)
(define-constant TAX-NUMERATOR u1)
(define-constant TAX-DENOMINATOR u1000)
(define-constant TOKEN-URI u"https://amethyst-voluntary-rat-144.mypinata.cloud/ipfs/bafkreifcxnom27jrgmjsdx2qtuphfnqynbju262m6vus56svu7talosp5q")
(define-constant MIN-TRANSFER-NON-EXEMPT u1000)
(define-constant BURN-ADDRESS 'SP000000000000000000002Q6VF78)
;; --------------------------------------------------
;; Data Variables
;; --------------------------------------------------
(define-data-var contract-owner principal CONTRACT-DEPLOYER)
(define-data-var admin principal CONTRACT-DEPLOYER)
(define-data-var total-burned uint u0)
;; --------------------------------------------------
;; Data Maps
;; --------------------------------------------------
(define-map tax-exempt-list principal bool)
;; --------------------------------------------------
;; Private Functions
;; --------------------------------------------------
(define-private (check-is-owner)
(is-eq tx-sender (var-get contract-owner))
)
(define-private (check-is-admin)
(is-eq tx-sender (var-get admin))
)
(define-private (check-tax-exempt (account principal))
(default-to false (map-get? tax-exempt-list account))
)
(define-private (calculate-tax (amount uint))
(/ (* amount TAX-NUMERATOR) TAX-DENOMINATOR)
)
(define-private (transfer-with-tax
(amount uint)
(sender principal)
(recipient principal)
(memo (optional (buff 34)))
)
(let
(
(sender-exempt (check-tax-exempt sender))
(recipient-exempt (check-tax-exempt recipient))
(any-exempt (or sender-exempt recipient-exempt))
(tax-amount (if any-exempt u0 (calculate-tax amount)))
(transfer-amount (- amount tax-amount))
)
(asserts! (> amount u0) ERR-AMOUNT-ZERO)
(asserts! (is-eq sender tx-sender) ERR-SENDER-NOT-TX-SENDER)
(asserts! (not (is-eq sender recipient)) ERR-SENDER-EQUALS-RECIPIENT)
(asserts! (or any-exempt (>= amount MIN-TRANSFER-NON-EXEMPT))
ERR-AMOUNT-BELOW-MINIMUM
)
(if (> tax-amount u0)
(begin
(try! (ft-burn? PAULO tax-amount sender))
(var-set total-burned (+ (var-get total-burned) tax-amount))
)
true
)
(try! (ft-transfer? PAULO transfer-amount sender recipient))
(match memo to-print (print to-print) 0x)
(ok true)
)
)
(define-private (set-exempt-iter (account principal) (prev-result (response bool uint)))
(match prev-result
success
(begin
(map-set tax-exempt-list account success)
(ok success)
)
err-val (err err-val)
)
)
;; --------------------------------------------------
;; SIP-010 Interface
;; --------------------------------------------------
(define-public (transfer
(amount uint)
(sender principal)
(recipient principal)
(memo (optional (buff 34)))
)
(transfer-with-tax amount sender recipient memo)
)
(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 PAULO account))
)
(define-read-only (get-total-supply)
(ok (ft-get-supply PAULO))
)
(define-read-only (get-token-uri)
(ok (some TOKEN-URI))
)
;; --------------------------------------------------
;; Admin & Governance
;; --------------------------------------------------
(define-public (set-admin (new-admin principal))
(begin
(asserts! (check-is-admin) ERR-NOT-ADMIN)
(asserts! (not (is-eq new-admin BURN-ADDRESS)) ERR-INVALID-PRINCIPAL)
(var-set admin new-admin)
(ok true)
)
)
(define-public (set-tax-exempt (account principal) (exempt bool))
(begin
(asserts! (check-is-admin) ERR-NOT-ADMIN)
(map-set tax-exempt-list account exempt)
(ok true)
)
)
(define-public (set-tax-exempt-many (accounts (list 200 principal)) (exempt bool))
(begin
(asserts! (check-is-admin) ERR-NOT-ADMIN)
(fold set-exempt-iter accounts (ok exempt))
)
)
(define-public (renounce-ownership)
(begin
(asserts! (check-is-owner) ERR-NOT-AUTHORIZED)
(var-set contract-owner BURN-ADDRESS)
(ok true)
)
)
(define-public (transfer-ownership (new-owner principal))
(begin
(asserts! (check-is-owner) ERR-NOT-AUTHORIZED)
(asserts! (not (is-eq new-owner BURN-ADDRESS)) ERR-INVALID-PRINCIPAL)
(var-set contract-owner new-owner)
(ok true)
)
)
;; --------------------------------------------------
;; Read-Only Utility
;; --------------------------------------------------
(define-read-only (get-contract-owner)
(ok (var-get contract-owner))
)
(define-read-only (get-admin)
(ok (var-get admin))
)
(define-read-only (get-is-tax-exempt (account principal))
(ok (check-tax-exempt account))
)
(define-read-only (get-total-burned)
(ok (var-get total-burned))
)
(define-read-only (get-tax-rate)
(ok {numerator: TAX-NUMERATOR, denominator: TAX-DENOMINATOR})
)
(define-read-only (get-min-transfer)
(ok MIN-TRANSFER-NON-EXEMPT)
)
(define-read-only (get-initial-total-supply)
(ok TOKEN-TOTAL-SUPPLY)
)
;; --------------------------------------------------
;; Initialization
;; --------------------------------------------------
(begin
(try! (ft-mint? PAULO TOKEN-TOTAL-SUPPLY CONTRACT-DEPLOYER))
(map-set tax-exempt-list CONTRACT-DEPLOYER true)
(map-set tax-exempt-list (as-contract tx-sender) true)
(map-set tax-exempt-list BURN-ADDRESS true)
)