Skip to article
Daedalus Development Group
← More from this project

George Sarris (0xcircuitbreaker) · · 10 min read

Annuities On-Chain: How Lucrum's Annuitas Module Works

Annuitas is a later-phase Lucrum annuity specification with three proposed tiers, deferred accumulation, and an inactivity-triggered beneficiary mechanism.

In this article

Status note

Annuitas is a later-phase Lucrum module. This post describes behavior in the March 2026 specification; it does not establish a production deployment, an independent audit, regulatory approval, insurance coverage, or historical returns. V2 ideas — Guard coverage, dynamic premiums, multi-asset annuities, NFT receipts, and a secondary market — are roadmap items.

What is an annuity, minus the jargon

An annuity is a contract: you hand over a lump sum of capital, and in exchange you receive a stream of payments over time. The counterparty manages the capital so the stream is delivered. Payments can be fixed in amount, variable with market performance, or floored at a guaranteed minimum — each variant corresponds to how the counterparty structured the risk.

Annuities are an established traditional-finance primitive. Annuitas explores how some cash-flow rules might be expressed in smart contracts. That changes the risk model rather than removing it: contract bugs, strategy losses, governance, liquidity, custody, and legal treatment all require separate evaluation.

The three V1 tiers

Variable Annuity

Intended payment = yield attributed to this annuity for the period. The payment formula does not intentionally draw principal. If attributed yield is zero, the payment is zero; however, the current multi-annuity harvest-attribution gap described below must be fixed before this behavior can be relied on across shared routers.

  • Intended use: scheduled distribution of strategy yield without a designed principal drawdown
  • Risk: payment amounts fluctuate with market conditions
  • Principal: not intentionally drawn by the payment formula; still exposed to contract and strategy losses

Fixed-Term Annuity

Payment = target amount per period, principal amortized. You specify a target payment. The protocol funds each payment from a three-step waterfall:

  1. Yield earned this period
  2. Buffer reserve (accumulated surplus from prior periods when yield > target)
  3. Principal drawdown (when yield + buffer fall short)

The annuity moves to DEPLETED when currentValue + bufferReserve reaches zero (principal is the immutable initial deposit; currentValue is the drawable balance that amortizes over time).

  • Best for: predictable income; accepts principal depletion
  • Risk: principal is consumed; annuity has a finite lifespan
  • Principal: amortized over the annuity's term

Guaranteed Annuity

Payment = whatever yield, buffer, and principal can fund; minPayment is an accounting target. The V1 contract follows the Fixed-Term waterfall. If the resulting payment is below minPayment, it pays the lower available amount, adds the difference to guaranteedShortfall, and emits GuaranteedShortfall. The contract does not top the payment up to the minimum.

V1 behavior: the shortfall is tracked and emits a GuaranteedShortfall event but is not automatically covered. The Guard insurance pool integration is a V2 feature; V1 documents the shortfall so actuarial reserves can price forward and V2 can cover new shortfalls going forward.

V2 roadmap: the specification proposes drawing a shortfall from a Guard pool funded by a Tribunus-governed slice of protocol fees. That path is not implemented in V1. Its payout order, failure behavior, and solvency assumptions require implementation and review rather than being treated as a current guarantee.

  • Intended use: exploration of a future floor-backed tier; V1 does not deliver a funded floor
  • Risk (V1): shortfall tracked, not covered
  • Risk (V2 proposal): Guard pool solvency, implementation, governance, and pricing risk

How it's built — singleton architecture

Every Annuitas annuity is a uint256 ID inside one singleton contract (same pattern as Uniswap V4 and Lucrum's own Fideicommissum). No per-annuity contract deployment. This can make cross-annuity accounting cheaper, but it also makes correct attribution between positions essential.

V1 does not mint an NFT receipt per annuity. NFT wrapping (and the secondary market that enables) is V2 roadmap.

Share accounting and the current yield-attribution gap

Each annuity's deployed assets and withdrawals are tracked with internal shares per yield strategy, using an ERC-4626-style calculation with a virtual share offset (VIRTUAL_SHARE_OFFSET = 1e6). The offset is intended to reduce first-depositor inflation manipulation; it is not, by itself, proof of complete isolation.

The current harvest path has a separate attribution problem: _harvestFromStrategies(annuityId) calls each snapshotted router's global harvest(asset) function and credits the full returned amount to the annuity that triggered the call. It does not apportion that harvest using _annuityShares. Share accounting therefore scopes withdrawals but does not currently establish per-annuity yield isolation. Multi-annuity use needs proportional harvest attribution plus adversarial tests and review before the yield figures can be relied on.

IYieldRouter adapters

The design provides three strategy slots behind the IYieldRouter interface (shared with Fideicommissum). The names below describe the intended routes; they are not evidence that production adapters are registered or deployed:

StrategyRouterIllustrative design rangeRisk
ConservativeCreditum (lending)3–5% targetlower by design, not risk-free
BalancedFiscus (managed pools)5–8% targetmoderate by design
GrowthFRS (revenue-share staking)8–12% targethigher by design

These ranges are specification examples, not measured or promised yields.

Yield strategy presets

On creation, an annuity picks one of four allocation presets:

PresetCreditumFiscusFRS
Conservative100%0%0%
Balanced50%30%20%
Growth30%50%20%
Custom fallback33.34%33.33%33.33%

Router snapshot

The design snapshots router addresses at annuity creation time. That can reduce one governance-replacement risk, but it does not prevent a malicious or vulnerable snapshotted router, an implementation bug, or losses inside the selected strategy.

Payment frequencies

Four fixed intervals at V1:

FrequencyInterval
Monthly30 days
Quarterly90 days
Semi-Annual180 days
Annual365 days

The buffer reserve smooths volatility

For Fixed-Term and Guaranteed tiers, the buffer reserve absorbs yield shocks:

Period 1: yield = 500, target = 300 → payment = 300, buffer += 200
Period 2: yield = 100, target = 300 → payment = 300, buffer -= 200
Period 3: yield = 0,   target = 300 → payment = 300, buffer = 0, principal -= 300

High-yield periods build the buffer; low-yield periods consume it. The buffer is the first line of defense before principal is touched.

Deferred accumulation and the current activation edge case

An annuity can be created with a future payoutStartTime. Until that timestamp, it sits in the ACCUMULATING state, but no keeper loop runs automatically:

  • Yield compounds into currentValue only when an external caller successfully invokes harvestYield before the payout start. The function then redeploys that harvested amount. principal remains the immutable initial-deposit field.
  • No payments are made; the annuitant cannot claim.
  • State changes only when claimPayment or harvestYield calls the internal activation check after the timestamp.

The current activation path has an important edge case. claimPayment sets lastPaymentTime during activation and then checks whether a full payment interval has elapsed; that same transaction reverts as PaymentNotDue, rolling the activation back. A post-start harvestYield call can persist activation only when it actually harvests a nonzero amount; otherwise NothingToHarvest also reverts the transition. The contract therefore does not yet support a reliable autonomous “purchase today, retire later” flow without an activation fix and keeper/user-call design.

Inactivity benefit — the permissionless dead-man's-switch

Each annuity designates a beneficiary address and an inactivityTimeout period. The lastActivityTime is updated whenever the annuitant:

  • Claims a payment (claimPayment)
  • Records activity (recordActivity)
  • Changes the payment destination (setPaymentDestination)

If block.timestamp > lastActivityTime + inactivityTimeout:

  1. Anyone can call triggerInactivityBenefit(annuityId) — fully permissionless
  2. A final harvestYield runs, then currentValue + bufferReserve + freshly-harvested are withdrawn from strategies
  3. The total transfers to the designated beneficiary
  4. State transitions to TERMINATED

This is an inactivity-triggered transfer mechanism, not proof of death or incapacity and not a substitute for a will, trust, beneficiary designation, tax advice, or probate law. A timeout can fire while an annuitant is alive but unable to record activity, so production use would need careful recovery and legal design.

Payment routing — annuities as composable cash flow

Payments default to the annuitant's wallet, but any address works via setPaymentDestination(annuityId, destination):

DestinationUse case
Direct walletStandard income
Usura adapterRequires integration logic that calls Usura's deposit function
Fideicommissum adapterRequires a receiver/call path defined by that module
Any addressCharitable giving, DAO treasury, sub-account

The V1 setter changes only the address that receives a raw ERC-20 safeTransfer. It does not call a destination protocol. In particular, current Usura expects a registered source to call depositYield(routeId, amount) and then pulls tokens with transferFrom; simply transferring tokens to the Usura address does not perform that operation. The whitepaper's example structures are therefore integration concepts that need adapters and tests:

  • Annuity → Usura → Fiscus. Needs a registered adapter that receives or pulls the payment and invokes the correct Usura route.
  • Annuity → Fideicommissum. Needs a destination-specific deposit or accounting call; a bare token transfer is not proof that a trust position was funded correctly.
  • FRS → Annuity → Wallet. Needs an explicit creation/funding transaction because Annuitas does not pull an FRS distribution into a new position automatically.

Why on-chain annuities aren't just "DeFi in a costume"

Three areas where an on-chain design changes the operating model:

Contract transparency

Traditional annuity terms can be complex, and surrender charges, riders, fees, and withdrawal rules vary by product and jurisdiction. Buyers need to read the actual contract and applicable disclosure rather than assume a universal structure.

Annuitas specifies payment formulas and waterfall priorities in code that can be inspected. That can improve rule transparency, but readable source is not equivalent to safe execution: users would still need to verify deployed bytecode, upgrade authority, router behavior, tests, and audits.

Transparent accounting, with different risks

Traditional annuities expose buyers to insurer solvency and jurisdiction-specific protections. An on-chain design can make some balances and rules inspectable, but transparency does not ensure solvency or make complex strategy positions easy to value. Annuitas would add smart-contract, strategy, liquidity, governance, and key-management risks; the proposed V2 Guard pool is not equivalent to regulated insurance.

Additional intended safeguards and their limits:

  • The specification intends to restrict Tribunus from withdrawing annuity funds, changing core parameters, or terminating positions. Tests and an audit would need to verify that property in a release candidate.
  • The proposed pause scope blocks new creation while preserving existing claim paths. That is a design goal, not a guarantee that every failure mode leaves funds accessible.
  • Limited direct oracle use in the core formula. The current payment calculation is denominated in the deposited asset and does not directly query a price oracle. That does not eliminate oracle or market-manipulation exposure in selected routers, swaps, asset valuations, or other composed modules; each integration needs its own review.

Composable cash flow

Some traditional annuities restrict early access or impose surrender charges, but the amount and duration vary substantially and some products do not use that structure. Changing a payment destination also depends on the issuer's process and applicable controls.

Annuitas can change the ERC-20 payment recipient in one transaction. A wallet or treasury can receive that transfer directly; protocols such as Usura or Fideicommissum need adapter logic that invokes their own deposit/accounting methods. V2 proposes NFT receipts and a secondary market, but neither is implemented in V1.

Integration with the rest of the Lucrum ecosystem

The whitepaper sketches several neighboring integrations, but the current contracts do not wire all of them together:

  • Pensio has its own PAYING_OUT state and monthly claim path in the current contract; it neither imports nor calls Annuitas. Automatic conversion is a whitepaper concept, not current behavior.
  • Fiscus (managed pools) is a balanced-strategy backing route for annuity principal.
  • Creditum (lending) is the conservative-strategy backing route.
  • FRS pools (asset-class revenue shares) are the growth-strategy backing route; FRS pool yields can also fund annuity principal directly.
  • Guard (insurance) is proposed to backstop the Guaranteed tier's minimum payment floor in V2.
  • Administration can approve assets, register the three router slots, and pause new creation through onlyOwner functions. Those functions become DAO-controlled only if ownership is assigned accordingly. The preset allocations themselves are hard-coded in _getEffectiveAllocation; V1 has no setter for them.
  • Fideicommissum integration is conceptual until an explicit adapter or compatible deposit receiver is implemented in both directions.
  • Usura integration needs a registered source and a call to depositYield; a payment-destination address alone is insufficient.

When an Annuitas position makes sense

Honest framing of the three variants:

Variable Annuitas is most useful when:

  • You want yield exposure but prefer scheduled disbursements over manual claiming
  • You want to avoid any principal drawdown
  • You're matching a liability that can tolerate payment-amount variance

Fixed-Term Annuitas is most useful when:

  • You need known nominal cash flow for a specific future window
  • You're matching a defined liability schedule (child's tuition, property purchase, runway)
  • You accept that the target schedule is not a locked yield rate and remains dependent on strategy results and available capital
  • You're comfortable with principal amortization over the annuity's lifespan

Guaranteed Annuitas is most useful when:

  • You are evaluating the proposed V2 floor-backed design rather than treating V1 as a guaranteed-income product
  • You understand that V1 records a payment gap but does not make the recipient whole
  • You are willing to evaluate Guard solvency, pricing, governance, and implementation risk if the V2 path is built

The proposed trade-off is inspectable rules and composable routing in exchange for smart-contract and strategy risk without the protections automatically associated with a regulated annuity. Tax, securities, insurance, and estate treatment are jurisdiction-specific and require qualified advice.

What's next

  • Lucrum Architecture — the full module map (FOLLIS, FRS, Vestibulum, Tribunus, the yield engine)
  • Pensio: Retirement Planning On-Chain with Automatic Annuity Conversion — upcoming
  • Fideicommissum: Irrevocable Trusts and the Annuitas Integration — upcoming
  • Guard Insurance: The V2 Roadmap for Guaranteed Annuitas Coverage — upcoming

Or browse the Lucrum product page for current development status. The public source is the Lucrum monorepo; treat the whitepaper and this article as specifications until versioned contracts, tests, audits, and deployment addresses are published.

Continue reading