This audit covers a 4-contract system deployed on Stacks mainnet for managing AI agent quests with STX bounty escrow, agent registration, oracle-based evaluation with Merkle proof verification, and subscription management. The system has critical issues โ all STX transfer logic is commented out in the deployed code, rendering the escrow mechanism entirely non-functional. Additionally, the subscription usage tracking is unrestricted, the Merkle proof verification has ordering issues, and the oracle admin has no safeguards.
Location: quest-escrow โ create-quest
The stx-transfer? call that should lock bounty STX in the escrow contract is commented out with a TODO about Clarity v4 tooling issues. The contract records bounty amounts but never receives STX.
;; Transfer bounty to escrow contract
;; TODO: Fix as-contract - clarinet v3.11 parser issue with Clarity v4
;; (try! (stx-transfer? bounty tx-sender (as-contract tx-sender)))
Impact: The entire escrow mechanism is non-functional. Quests are created with phantom bounties. There is no STX to release upon completion or refund upon dispute. The contract is a state machine with no financial backing.
Recommendation: Uncomment and fix the STX transfer. If Clarity v4 tooling is needed, use as-contract? with explicit with-stx allowance.
Location: quest-escrow โ complete-quest, resolve-dispute
All four stx-transfer? calls in the contract are commented out. Even if STX somehow existed in the contract, neither quest completion nor dispute resolution can move funds.
;; Release funds to the agent creator
;; TODO: Fix as-contract - clarinet v3.11 parser issue with Clarity v4
;; (try! (as-contract (stx-transfer? (get bounty quest) tx-sender (get agent-creator quest))))
Impact: Agents completing quests receive nothing. The dispute resolution refund and payment paths are both inoperable. The system cannot function as a payment mechanism.
Recommendation: Same as C-01. All four transfer paths must be restored before the system is usable.
Location: subscription-manager โ track-usage
Any principal can call track-usage for any user/agent pair. The code acknowledges this: "For now, any user can call this, but ideally restricted to the oracle/escrow."
;; For now, any user can call this, but ideally restricted to the oracle/escrow
(asserts! (<= new-usage (get cycles-limit sub)) err-quota-exceeded)
Impact: An attacker can exhaust any user's cycle quota by repeatedly calling track-usage, effectively denying service to all subscribers.
Recommendation: Add access control: (asserts! (or (is-eq tx-sender contract-owner) (is-eq contract-caller .quest-escrow)) err-unauthorized)
Location: agent-evaluator-oracle โ merkle-step
The Merkle proof step always concatenates current-hash || proof-element. Proper Merkle tree verification requires knowing whether the sibling is a left or right child at each level.
(define-private (merkle-step (proof-element (buff 32)) (current-hash (buff 32)))
(sha256 (concat current-hash proof-element))
)
Impact: Legitimate proofs at certain tree positions will compute incorrect roots and fail verification. Conversely, some invalid proofs may pass. The verification is unreliable.
Recommendation: Include left/right indicators in the proof elements, or use a sorted-pair approach: if (< current-hash proof-element) concat(current, proof) else concat(proof, current).
Location: agent-evaluator-oracle โ set-oracle-admin
Admin transfer is immediate with no timelock, multi-sig, or two-step confirmation. A compromised admin key can authorize malicious oracles that submit fraudulent evaluations.
Impact: Compromised admin โ fake evaluations โ fraudulent quest completions. Would enable fund theft if STX transfers were active.
Recommendation: Implement a two-step admin transfer (propose โ accept) with a timelock period.
Location: subscription-manager โ subscribe
Takes price and creator as parameters without cross-referencing agent-registry's actual price-per-cycle or creator fields. A malicious frontend could redirect payments.
Impact: STX payments could be sent to arbitrary addresses instead of the legitimate agent creator.
Recommendation: Read price and creator from agent-registry via contract-call? and validate inputs.
Location: quest-escrow โ mark-evaluating
Both quest creator and agent-creator can transition to EVALUATING state. The agent creator can advance their own quest without the quest creator's consent.
Impact: Bypasses the expected workflow where the quest creator initiates evaluation.
Location: quest-escrow โ create-quest
Only checks bounty > u0. No minimum threshold prevents dust-value quests from spamming the system.
quest-escrow accepts any agent-creator and agent-id without verifying against agent-registry.
Re-subscribing overwrites existing subscription state via map-set, losing remaining cycles and time without refund.
None of the 4 contracts emit print events for state changes, making off-chain indexing impractical.
Multiple TODO comments reference Clarity v4 tooling issues. All STX transfer logic is commented out in a deployed mainnet contract.
quest-escrow uses .agent-evaluator-oracle directly instead of a trait, preventing upgradeability.
No enumeration of quests, agents, or subscriptions โ only point lookups by ID.
| Contract | Purpose | Key Functions |
|---|---|---|
| quest-escrow | Escrow STX bounties for AI agent quests | create-quest, complete-quest, raise-dispute, resolve-dispute |
| agent-registry | Register and manage AI agents | register-agent, update-agent, toggle-agent-status |
| agent-evaluator-oracle | Oracle for verifying quest execution with Merkle proofs | submit-evaluation, verify-evaluation, authorize-oracle |
| subscription-manager | Track subscriptions and compute cycle quotas | subscribe, track-usage, has-cycles-available |
Independent audit by cocoa007.btc โ Full audit portfolio