Docs Técnicas
Consortium Agreement
TREA ships a ConsortiumAgreement template (contracts/products/consortium_agreement.trea) modeling a Brazilian-style *consórcio*: a group of participants who pool periodic contributions into a shared reserve, and take turns receiving the quota's credit value either by lottery (*sorteio*) or by bid (*lance*).
TREA ships a ConsortiumAgreement template (contracts/products/consortium_agreement.trea) modeling a Brazilian-style *consórcio*: a group of participants who pool periodic contributions into a shared reserve, and take turns receiving the quota's credit value either by lottery (*sorteio*) or by bid (*lance*).
Lifecycle
Group-level state:
Forming— administradora created the group; members join and are assigned sequential quota numbers.Active—start_group()was called; members contribute periodically and can be contemplated.Closed— every quota has been contemplated;close_group()was called.Cancelled— administradora cancelled the group before close; members recover funds viarefund_member.
Per-member tracking uses Map[Address, ...] storage rather than per-member state machines, since the runtime has no native loop over map keys: member_quota, member_next_due, contributions_paid, member_contribution, member_bid, contemplated, and defaulted are all keyed by the member's address.
Membership
join() assigns the next sequential quota number and a member_next_due timestamp derived from the group's fixed starts_at + period_seconds, so eligibility and due dates never require iterating over all members. Membership is tested as member_quota[addr] > 0 rather than a boolean map — a never-written map key in the IR runtime defaults to Integer(0), not Bool(false), so boolean "is member" flags would silently miscompare against False.
Contributions and Default
contribute(amount) transfers the caller-provided amount from the caller to the group's reserve_account, requires that amount to equal the fixed installment_amount, credits the member's internal member_contribution, and advances their member_next_due by one period_seconds. declare_default(member) lets the administradora flag a member as defaulted once their due date has passed without payment; a defaulted member can no longer be contemplated.
Contemplation
Two paths release the quota_value credit from the reserve to a member:
contemplate_by_draw(member)— sorteio; no extra payment required.place_bid(amount)+contemplate_by_bid(member)— lance; the member escrows a bid premium first, then the administradora settles the bid.
Both increment contemplated_count, which an @invariant guarantees never exceeds total_quotas.
Cancellation and Refunds
cancel_group() moves Forming/Active groups to Cancelled. refund_member(member) then returns the sum of that member's accumulated member_contribution and member_bid from the reserve, regardless of whether they had been contemplated or defaulted.
Product Template Child
For on-demand product issuance, TREA also ships ConsortiumAgreementChild (contracts/products/consortium_agreement_child.trea). It keeps the same lifecycle and accounting rules as the standalone contract, but adds set-once ProductTemplate lineage through bind_lineage(parent_template_id, origin_request_id, approved_terms_hash).
The intended flow is:
- the institution publishes a
ProductTemplatewithproduct_type = "consortium"and the allowlisted child artifact/hash limits; - a client requests a group within the configured value/term bounds;
- the institution approves the request and the backend deploys the child at the derived address;
- the child records
parent_template_id,origin_request_id, andapproved_terms_hash, so explorer, wallet, receipts, and audit tooling can explain which product template originated the group.
Receipts
Every state-changing call emits both a specific event (MemberJoined, ContributionPaid, MemberDefaulted, BidPlaced, MemberContemplated, MemberRefunded, ...) and a ConsortiumReceipt(group_id, member, action, amount, state) event, giving a uniform audit trail of who paid, who was contemplated, and the group's resulting state.