Cosmic Bull

Rendered from pearl/r/subscriptions/README.md at commit 6a510c665a53 in the project repository. The committed file is the source of truth; this page is a rendering of it.

subscriptions

A multi-provider subscription hub on gno.land: providers publish plans priced per billing period; subscribers pay per period; renewal, grace, expiration and cancellation follow deterministic block-height rules; and any realm or service can gate access with one call.

The rules, in full

EventRule
Subscribepay exactly price; paidThrough = height + periodBlocks
Entitlementheight < paidThrough — status does not enter into it
Renewpay exactly price; accepted iff paidThrough − height ≤ periodBlocks (early bound: at most one unstarted period prepaid — the duplicate-payment guard) and height < paidThrough + periodBlocks (grace bound, exclusive — a renewal always buys at least one block); extends from paidThrough, so period boundaries never drift and a grace renewal back-pays the lapsed span. A lapsed subscriber who prefers a fresh full period may Cancel + Subscribe at the same total price
Cancelsubscriber only; terminal; no refund — entitlement already paid for runs to paidThrough; the subscription can never be renewed again
Expirepermissionless once height ≥ paidThrough + periodBlocks; no funds move; frees the plan/subscriber slot (Subscribe also collapses an expired incumbent itself). From paidThrough − periodBlocks onward, every height is exactly one of renewable or expirable; below that window a renewal is refused as too early
RetirePlanprovider only; no new subscriptions, no renewals; existing entitlements run out untouched

The on-chain obligation is explicit at every moment: the realm owes the subscriber exactly paidThrough − height blocks of entitlement (queryable by anyone via PaidThrough / Entitled / EntitledFor / RenewableFrom), and the subscriber owes nothing — there is no pull payment and no debt; a lapse simply ends entitlement.

Payments and custody

Payments settle immediately: price − fee to the provider's claimable balance, fee to the protocol pot, both in the composed feeledger. There is no escrow; the monetary invariant is H == U + F (holdings = provider balances + fee pot), with out-of-band surplus recoverable above the Liabilities() reserve. The protocol fee follows the portfolio pattern: compile-time cap MaxFeeBps = 1000, snapshotted into the plan at creation under the provider's own consent ceiling, immutable afterwards.

Unauthorized / duplicate / out-of-window payments

Integration

Gate anything on EntitledFor(planID, subscriber) — it follows the subscriber's most recent subscription to the plan and honors paid entitlement across cancellation. Subscribers are EOAs (coinio's receipt guard); providers may be realms but must expose their own crossing path to Claim — see the header caveat.

Composition

feeledger (balances, fees, conservation) + coinio (receive / payout / sweep) + avl (ordered state) + sanitize/v0 (Render). Discovery record: DISCOVERY.md.