SP2CXN6W7WDEHVWDC07BPP1RPY2Z07BR7Z689WAX3.trust-score-v1 ยท Reputation ยท February 24, 2026
A minimal on-chain reputation/trust scoring contract deployed on Stacks mainnet. The contract allows reading, increasing, and decreasing reputation scores for any principal, plus a self-reported action tracker.
Source: Fetched on-chain via Hiro API (immutable, canonical).
Clarity version: Not specified (pre-Clarity 4). -0.5 penalty applied.
Audit confidence: ๐ข HIGH โ contract is trivially small and all findings verified directly against source.
| Metric | Score | Weight | Weighted |
|---|---|---|---|
| Financial risk | 0 (no tokens/STX) | 3 | 0 |
| Deployment likelihood | 3 (deployed mainnet) | 2 | 6 |
| Code complexity | 0 (<50 lines) | 2 | 0 |
| User exposure | 0 (unknown) | 1.5 | 0 |
| Novelty | 1 (similar to CurateChain) | 1.5 | 1.5 |
| Total | 0.75 (below 1.8 threshold) | ||
Note: This contract scores below the normal audit threshold (0.75 < 1.8). Audited by explicit request. No financial risk but critical design flaws make the reputation system meaningless.
;; Reputation system contract
(define-map reputation principal uint)
(define-map user-history {user: principal, action: (string-ascii 32)} uint)
(define-read-only (get-reputation (user principal))
(default-to u0 (map-get? reputation user))
)
(define-public (increase-reputation (user principal) (amount uint))
(let ((current (get-reputation user)))
(begin
(asserts! (> amount u0) (err u1))
(ok (map-set reputation user (+ current amount)))
)
)
)
(define-public (decrease-reputation (user principal) (amount uint))
(let ((current (get-reputation user)))
(begin
(asserts! (>= current amount) (err u2))
(ok (map-set reputation user (- current amount)))
)
)
)
(define-public (track-action (action (string-ascii 32)))
(let ((count (default-to u0 (map-get? user-history {user: tx-sender, action: action}))))
(ok (map-set user-history {user: tx-sender, action: action} (+ count u1)))
)
)
| ID | Severity | Title |
|---|---|---|
| C-01 | CRITICAL | No access control โ anyone can set any user's reputation |
| H-01 | HIGH | Reputation overflow can brick a user's score |
| M-01 | MEDIUM | track-action disconnected from reputation โ no on-chain integration |
| L-01 | LOW | No event emission for reputation changes |
| I-01 | INFO | Pre-Clarity 4 โ no clarity_version specified |
Location: increase-reputation, decrease-reputation
Description: Both increase-reputation and decrease-reputation are fully permissionless. Any caller can arbitrarily inflate or zero out any user's reputation score. There is no owner check, no role-based access, no oracle requirement โ nothing prevents a random wallet from calling (increase-reputation 'SPVICTIM u999999999) or (decrease-reputation 'SPVICTIM (get-reputation 'SPVICTIM)).
;; Anyone can call this with any principal and any amount
(define-public (increase-reputation (user principal) (amount uint))
(let ((current (get-reputation user)))
(begin
(asserts! (> amount u0) (err u1))
(ok (map-set reputation user (+ current amount))) ;; no access control
)
)
)
Impact: The reputation system is completely meaningless. Any user can give themselves max reputation or destroy anyone else's score. If any system relies on these scores for trust decisions, it can be trivially gamed.
Recommendation: Add access control. Options:
(define-constant admin tx-sender) at deploy time + (asserts! (is-eq tx-sender admin) (err u403));; Exploit test for C-01: Anyone can manipulate any reputation
(define-public (test-exploit-c01-reputation-manipulation)
(begin
;; Attacker inflates own reputation
(try! (increase-reputation tx-sender u999999999))
;; Attacker zeros out victim
(let ((victim-rep (get-reputation 'SP000000000000000000002Q6VF78)))
(if (> victim-rep u0)
(try! (decrease-reputation 'SP000000000000000000002Q6VF78 victim-rep))
true
)
)
(asserts! (>= (get-reputation tx-sender) u999999999) (err u100))
(ok true)
)
)
Location: increase-reputation
Description: The addition (+ current amount) has no upper bound check. While Clarity's uint arithmetic will abort on overflow (exceeding u340282366920938463463374607431768211455), an attacker could repeatedly call increase-reputation to push a user's score so high that any further increase reverts. More practically, since there's no access control (C-01), an attacker can set any value they want โ but if C-01 is fixed with rate-limited peer attestation, the lack of bounds becomes relevant.
Impact: Griefing vector โ inflate a victim's score to near-max so legitimate updates revert on overflow.
Recommendation: Add a maximum reputation cap: (asserts! (<= (+ current amount) MAX-REPUTATION) (err u3))
Location: track-action
Description: The track-action function records self-reported action counts per user but has no connection to the reputation system. Actions don't affect reputation, and reputation doesn't depend on actions. The two systems are completely independent, making the action tracker dead weight in a "trust score" contract.
Impact: Misleading architecture โ the contract name suggests actions build trust, but they don't. Action counts are self-reported and can be freely inflated by calling track-action repeatedly.
Recommendation: Either integrate actions into reputation scoring (e.g., verified actions earn reputation via an oracle) or remove the function to reduce contract surface area.
Location: increase-reputation, decrease-reputation
Description: Neither function emits a print event when reputation changes. Off-chain indexers and UIs cannot efficiently track reputation updates without scanning every transaction.
Recommendation: Add (print {event: "reputation-change", user: user, old: current, new: (+ current amount), caller: tx-sender}) to both functions.
Description: The contract does not specify a Clarity version, defaulting to pre-Clarity 4. While this contract has no token transfers (so as-contract? with asset allowances isn't relevant), specifying the Clarity version is best practice for deployment reproducibility.
This is a minimal reputation primitive with a fundamental design flaw: permissionless write access makes the entire scoring system meaningless. The contract is effectively a public key-value store where anyone can write any value for any key.
No funds are at risk (no token transfers of any kind), but any system that relies on these scores for trust or access decisions would be trivially exploitable.
Positive notes:
track-action correctly uses tx-sender for self-reporting (can't fake caller identity)decrease-reputation properly checks for underflow