Voltar para Documentação

Docs Técnicas

Category Cards

TREA ships a category-card pattern for products where an institution funds a beneficiary, but the beneficiary can only use the value inside declared policy categories such as food, mobility, health, education, cashback, or travel.

O conteúdo abaixo vem das fontes técnicas do repositório e é prerenderizado no site para leitura direta por pessoas, crawlers e agentes.

TREA ships a category-card pattern for products where an institution funds a beneficiary, but the beneficiary can only use the value inside declared policy categories such as food, mobility, health, education, cashback, or travel.

The pattern is split in two layers:

text
CategoryAllowanceProgram  -> issuer-owned funding pool and category policy
BenefitsCardVault         -> beneficiary spends benefits by category
LoyaltyCardVault          -> beneficiary redeems rewards/points by category

The parent program controls issuance and funding policy. The child vault controls per-beneficiary balances, lifecycle, category limits, refunds, expiry, and the final payment or redemption transfer.

CategoryAllowanceProgram

std.factory.CategoryAllowanceProgram is the governed parent. It holds the issuer's pool balance and moves funds to a deterministic child address through issue_card(request_id, beneficiary, category, requested_amount).

Before issuing cards, the issuer configures:

  • set_category_cap(category, max_per_period) for each allowed category;
  • set_cap_policy(mode, period_seconds) to decide how caps accumulate;
  • the child artifact identity (artifact_id, code hash, ABI hash, IR hash,

and storage layout hash) during initialize.

Cap mode defines what category_cap means:

| Mode | Meaning | |------|---------| | 0 | Per-request ceiling. Each issue_card must be at or below the category cap. | | 1 | Per-beneficiary, per-period ceiling. Repeated funding for the same beneficiary and category accumulates inside the period. | | 2 | Program-wide, per-period ceiling. Funding across all beneficiaries accumulates inside the period. |

The program does not deploy the child itself. It derives the expected child address, transfers the approved amount there, and later binds the deployed child through register_child_instance(...), checking the artifact identity. This keeps free-text product labels out of the trust boundary.

BenefitsCardVault

contracts/products/benefits_card_vault.trea models a benefits card funded in real tokens. The issuer registers category limits with set_category_limit(category, period_limit). The beneficiary calls spend(category, merchant, amount).

A spend succeeds only when:

  • the caller is the beneficiary;
  • the card is active and not expired;
  • the category has a configured limit;
  • the category has enough funded balance;
  • the category's period spend stays within the limit.

The contract authorizes by declared category, not by merchant credentialing. There is no merchant allowlist in this template. A gateway, acquiring network, or higher-level product can still do merchant classification before submitting the call, but the on-chain proof is category policy plus ledger movement.

Standalone cards use allocate(category, amount), which transfers issuer funds into the vault and credits the category. Governed cards disable allocate(). They are funded only by the parent program: the issuer calls receive_program_funding(amount) to acknowledge funds already transferred by the program, then fund_category(category, amount) to attribute them.

LoyaltyCardVault

contracts/products/loyalty_card_vault.trea uses the same structure for points, rewards, or cashback products. The issuer configures allowed reward categories, and the beneficiary calls redeem(category, partner, amount).

Standalone cards use accrue(category, amount). Governed cards disable accrue() and use the same receive_program_funding() plus fund_category() flow as benefits cards. That makes the parent program's cap policy the funding boundary for every governed point the beneficiary can redeem.

Receipts And Lifecycle

Both child vaults emit product-level receipts:

  • BenefitsCardReceipt(category, beneficiary, merchant, amount, state)
  • LoyaltyReceipt(category, beneficiary, partner, amount, state)

Approved use emits state = "approved", refunds emit "refunded", and issuer forfeiture emits "expired". Rejections use normal require(...) aborts, so they do not create a successful receipt event.

Cards can be paused, unpaused, or permanently revoked by the issuer. Unused category balances and points roll over by default; they are forfeited only when the issuer explicitly calls expire_period(category).

Product Demo

The brand-site TREA gallery includes Moxie-style demos for both products:

  • Benefits card: program setup, category cap, card issuance, child binding,

funding attribution, and spend.

  • Loyalty card: rewards program setup, point issuance, child binding, funding

attribution, and redemption.

These demos intentionally present the product flow without requiring the user to understand contract deployment, artifact hashes, or ledger internals.