Developer

SpiritDAO: Tokens & Treasury (Developer Documentation)

Audience: developers, integrators, and technical evaluators. This document covers the SpiritDAO token economy and treasury system.

Scope note: This is public-safe documentation. Contract addresses below are already public on Base. It describes only shipped behavior; anything not yet built is marked Planned. It deliberately omits security-sensitive internals (row-level-security policies, admin-only flows, exact authorization-gate logic, and the backend attestation signer).


Two tokens, two purposes

The economy has exactly two tokens. They are deliberately different shapes:

$SYSTEM$SELF
StandardERC-20ERC-1155 (epoch ids)
Transferable?YesNo (soulbound)
Backed byCapital held by the nonprofit (~1:1 USD)Verified participation-hours
Created byStripe donation pipelineAttested platform actions
"Spending" meansTransferBurn
Decays?NoYes (expires)

The guiding idea (see 00-architecture-overview.md, "Soulbound-by-default"): $SYSTEM is money; $SELF is earned standing. You cannot buy $SELF, sell it, or gift it: you participate to earn it, and you burn it to use it.


$SYSTEM: the capital-backed utility token

A transferable ERC-20, backed roughly 1:1 by capital held by the SpiritDAO nonprofit (1 $SYSTEM ≈ $1 USD).

the donor, see Treasury below).

because the nonprofit holds matching capital.

Because $SYSTEM is freely transferable, it is the unit of account everywhere a real-money price is needed.


$SELF: the soulbound participation token

$SELF was redesigned in 2026 from a retired transferable ERC-20 into a soulbound ERC-1155. This is the most distinctive piece of the economy, so it is worth understanding in full.

(0x169760...)

Soulbound: mint and burn only

There are only two operations: mint and burn. There is no transfer. The contract overrides the ERC-1155 _update hook to revert any transfer between wallets. You earn it, you hold it, you burn it: it never moves sideways.

Token id encodes provenance

A $SELF token id packs (communityId, epoch):

id = (communityId << 32) | epoch

This means provenance and age are read directly off the id (no extra lookup table). A wallet's live balance is the sum of balanceOf over all of its non-expired ids.

Hour-anchored amounts

$SELF is denominated in verified participation-hours:

Decay / expiry

$SELF is time-bound. It is meant to reflect recent participation, so it fades:

$SELF grant is spendable for ~6 months, then expires.

V1's hard cliff (which dropped to zero all at once).

out of the live balance automatically; nothing has to be "swept."

Minting: attested, budget-bounded

Minting is performed by the SelfMinter contract:

holds MINTER_ROLE.

with dual-attest, bounty completion, and similar), submitted by a backend attestation signer.

pod_self_budgets, self_mint_queue, self_member_epoch_earned.

/api/admin/self.

Pods do NOT hold $SELF. A pod has a minting budget (capacity to award), not a balance. This is a direct consequence of soulbound: a token that cannot be transferred cannot be held-and-then-paid-out by a treasury.

Spending: burn-to-pay

"Paying" with $SELF means burning it. This is handled by a single shared primitive:

holds BURNER_ROLE.

src/features/shopping-cart/services/transaction/selfPayment.ts.

soon-to-expire $SELF is spent first.

NEXT_PUBLIC_SELF_RECEIPT (0x2aeB8C...), source src/contracts/SelfReceipt.sol.

there is no destination wallet, no treasury inflow. The value simply leaves circulation.

This one burn-to-pay primitive is reused across the marketplace, event ticketing, and access-gated bounties.

Tenure: permanent standing

Where $SELF decays (fading to zero roughly 6 months after each grant), Tenure is the permanent record of having earned it:

source src/contracts/SelfPrestige.sol.

decreases: it wires into the earn** path, not the burn path.

and images are frontend-only, in src/features/identity/config/tenureBands.ts.

The five bands:

TierBandLifetime hours
0Curious0–10h (membership floor)
1Resident10–50h
2Mainstay50–250h
3Pillar250–600h
4/5Elder600h+

Planned (not shipped)

These are designed but not yet built; do not assume them in integrations:

standing across communities.

but is not wired up.

Key files

src/contracts/SelfEpochsV2.sol
src/contracts/SelfPaymentV2.sol
src/contracts/SelfPrestige.sol
src/contracts/SelfReceipt.sol
src/features/self/services/selfEarnService.ts
src/features/shopping-cart/services/transaction/selfPayment.ts

Treasury

Pod treasuries: PodTreasuryV3

Each pod can hold $SYSTEM in a multi-sig, hat-gated treasury.

deploy tooling under src/contracts/treasury-deploy/.

04-governance-and-pods.md), not a hardcoded address list.

floor of 50.01%: a treasury can require more than a simple majority, but never less.

Where marketplace money goes

Marketplace $SYSTEM proceeds are routed by the PurchaseRouter to one of three destinations per listing:

BURN  |  WALLET  |  POD_TREASURY

$SELF always burns (see burn-to-pay above); it has no routable proceeds.

Stripe donations → $SYSTEM

The fiat on-ramp. A donation flows through Stripe and mints $SYSTEM:


Where to go next