StacksMint — Token Factory & Registry

StacksMint/StacksMintContract · 2 contracts · ~300 lines · February 21, 2026

Overview

StacksMint is a two-contract token launchpad for the Stacks blockchain. The token-template.clar is a SIP-010 fungible token that creators fork and deploy. The stacksmint.clar registry is a shared on-chain directory where deployed tokens are listed with metadata (name, symbol, supply, URI).

The core issue: the registry is a trust-me directory with no on-chain verification. Anyone can register any contract principal with arbitrary metadata, enabling impersonation and front-running attacks. The token template itself is a competent SIP-010 implementation with a few design concerns.

SeverityCount
CRITICAL1
HIGH2
MEDIUM3
LOW / INFO4

Critical Findings

C-1 Registry Has No Ownership Verification — Full Impersonation Possible

Contract: stacksmint.clar · register-token

The register-token function accepts any token-contract principal and arbitrary metadata with zero on-chain verification:

(define-public (register-token
    (token-contract principal)
    (name (string-ascii 32))
    (symbol (string-ascii 10))
    (decimals uint)
    (total-supply uint)
    (token-uri (optional (string-utf8 256))))
  (let ((caller tx-sender) ...)
    ;; No verification that caller deployed token-contract
    ;; No contract-call? to verify metadata matches
    ;; owner is set to tx-sender, not the contract's deployer
    (map-set token-registry token-contract
      { ... owner: caller ... })))

Attack vectors:

The registry cannot call (contract-call? token-contract get-name) to verify because the token principal is a runtime parameter, not a known contract. This is a fundamental design limitation — the registry architecture cannot provide trustworthy data.

High Findings

H-1 Registration Fee Is Zero Despite Anti-Spam Claims

Contract: stacksmint.clar

The README advertises "STX registration fee (anti-spam)" as a feature. The code says otherwise:

;; Registration is free -- no STX fee required
(define-constant REGISTRATION-FEE u0)

With zero cost and no verification, an attacker can flood the registry with thousands of fake entries in a single block. The total-fees-collected data var increments by zero — pure dead code. The registry becomes trivially unusable as a discovery tool.

H-2 Front-Running Token Registration — Permanent Griefing

Contract: stacksmint.clar

Since register-token sets the owner field to tx-sender (not the token contract's actual deployer), and registration is free, a front-running attack is trivial:

  1. Attacker monitors mempool for deploy-contract transactions
  2. Attacker submits register-token with the victim's contract principal
  3. Victim's later register-token call fails with ERR-ALREADY-REGISTERED (u200)
  4. Only the attacker (fake owner) can call update-token-uri

There is no admin override, no dispute mechanism, and no deregistration function. The legitimate creator is permanently locked out of their registry entry.

Medium Findings

M-1 tx-sender Auth Limits Composability

Contract: token-template.clar · transfer

(asserts! (is-eq tx-sender sender) ERR-NOT-TOKEN-OWNER)

Using tx-sender instead of contract-caller means no smart contract can transfer tokens on behalf of a user. DEXes, vaults, and any intermediary contract calling transfer will fail. This is SIP-010 compliant but breaks DeFi composability. The standard allows either approach — this is the safer but more restrictive choice.

M-2 Unguarded Burn — Any Holder Can Deflate Supply

Contract: token-template.clar · burn

(define-public (burn (amount uint) (sender principal))
  (begin
    (asserts! (is-eq tx-sender sender) ERR-NOT-TOKEN-OWNER)
    (asserts! (> amount u0) ERR-INVALID-AMOUNT)
    (ft-burn? stacksmint-token amount sender)))

Any holder can burn their own tokens at will. Unlike minting (which has a mintable flag), there is no burnable control. For tokens where supply determines governance weight or economic value, unchecked burning by individual holders can skew distribution. Template users may not realize this is enabled by default.

M-3 Globally Writable Counter Utility — No Access Control

Contract: token-template.clar · increment / decrement

(define-public (increment)
  (begin
    (var-set utility-counter (+ (var-get utility-counter) u1))
    (ok (var-get utility-counter))))

The counter is a public function with no access control, sharing a single utility-counter across all callers. Anyone can increment/decrement it at any time. If any frontend or integration relies on this value, it's trivially manipulable. This pollutes the contract's ABI with a function that has no practical production use.

Low / Informational Findings

L-1 Registry Owner Cannot Be Transferred

(define-constant registry-owner tx-sender) — immutable. No ownership transfer function exists. Currently the owner has no admin functions, but if fee collection or entry management is added later, the owner is permanently fixed to the deploy-time principal.

L-2 Token Owner Cannot Be Transferred

Same issue in token-template.clar: (define-constant contract-owner tx-sender). If the deployer's key is lost, mint control is permanently inaccessible.

L-3 No Token Deregistration or Metadata Correction

Registry entries are permanent. update-token-uri exists, but name, symbol, decimals, and total-supply are immutable after registration. Typos, malicious registrations, and stale data have no correction path.

I-1 Unlimited Minting When Enabled

When the mintable flag is set to true, the owner can mint unlimited tokens with no maximum supply cap. This is a known trust assumption but should be prominently documented for token holders evaluating the contract.

Positive Observations

Architecture Assessment

The two-contract architecture (template + registry) is a reasonable approach given Clarity's lack of dynamic contract deployment. However, the registry has a fundamental problem: it cannot verify anything about the contracts it lists. Since the token principal is a runtime parameter, the registry can't call trait functions on it to verify metadata or ownership.

This means the registry is only as trustworthy as its participants — which, on a permissionless blockchain with zero registration cost, means it's not trustworthy at all. A frontend built on this registry would need its own off-chain verification layer, at which point the on-chain registry adds little value.

Verdict: The token template is a solid SIP-010 base suitable for simple tokens. The registry, however, is architecturally unable to fulfill its stated purpose as a trusted token directory.