Fees & Economics
Protocol fees, billing templates, and integrator economics for AURA treasuries.
AURA includes a comprehensive fee system that supports protocol-level revenue, integrator economics, and flexible billing models for treasury operators.
Fee Model Overview
AURA's current on-chain fee path accrues execution fees during finalize_execution when a FeeVault is supplied. Fee schedules also carry creation, subscription, AUM, discount, and integrator fields used by templates and off-chain billing surfaces.
| Surface | Stored in | Enforced on-chain |
|---|---|---|
| Execution fee | FeeSchedule / legacy ProtocolFees | finalize_execution when fee_vault is present |
| Protocol fee floor and integrator bounds | ProtocolConfigAccount | Fee schedule validation and fee computation |
| Creation fee / subscription / AUM fields | FeeSchedule and templates | Stored for billing policy; not charged by propose_transaction |
Fees are:
- Prepaid into a
FeeVaultattached to the treasury - Accrued into the vault's
accumulated_fees_lamportsbucket during finalization - Split according to a
FeeSplittable on collection
Fee Vault
Each treasury has an optional FeeVault PDA storing:
import { instructions } from "@aura-protocol/sdk-ts";
await instructions.fees.sendInitFeeVault(client, owner, initFeeVaultInput);
await instructions.fees.sendDepositFees(client, owner, depositFeesInput);Vault state:
fee_balance— prepaid lamports available for future feesaccumulated_fees_lamports— accrued fees not yet collectedfee_debt_usd— shortfall recorded when low-balance mode isDegrade
Low-balance mode:
Blockrejects finalization when prepaid balance cannot cover the feeDegradeaccrues the covered portion and records the shortfall infee_debt_usdWarnskips accrual when the vault is short
Fee enforcement
Finalization is rejected with InsufficientFeeBalance when the vault cannot cover the fee and low-balance mode is Block.
Fee Schedules
A FeeSchedule sidecar defines per-treasury fee rates:
await instructions.fees.sendInitFeeSchedule(client, owner, initFeeScheduleInput);Validation:
- Rates must fall within
ProtocolConfigbounds (integrator limits) - Sum of all fees cannot exceed protocol-defined cap
Updates:
await instructions.fees.sendUpdateFeeSchedule(client, owner, updateFeeScheduleInput);Billing Templates
Pre-defined fee structures that can be applied to multiple treasuries:
await instructions.fees.sendCreateBillingTemplate(client, owner, createTemplateInput);
await instructions.fees.sendApplyBillingTemplate(client, owner, applyTemplateInput);Built-in profiles:
PayrollTradingDeskDaoTreasuryGrantProgramVendorPaymentsColdStorageSpecialty
Forking: Templates can be forked from built-in profiles and customized:
await instructions.fees.sendCreateBillingTemplate(client, owner, forkTemplateInput);Fee Splits & Recipients
Revenue is split across multiple recipients via a FeeSplit table:
await instructions.fees.sendSetFeeSplits(client, owner, setFeeSplitsInput);Rules:
bpssum must equal 10,000 (100%)- Up to 4 recipients
- Split table applies to all fees accrued after it's set
Collection:
await instructions.fees.sendCollectFees(client, collector, collectFeesInput);Protocol Configuration
The ProtocolConfig singleton governs global fee economics:
await instructions.lifecycle.sendInitProtocolConfig(
client,
protocolAuthority,
initProtocolConfigInput,
);Staged updates: All economic changes are timelocked via a two-step process:
// 1. Stage change (48h timelock)
await instructions.lifecycle.sendUpdateProtocolConfig(
client,
protocolAuthority,
updateProtocolConfigInput,
);
// 2. Commit after timelock
await instructions.lifecycle.sendCommitProtocolConfig(
client,
protocolAuthority,
commitProtocolConfigInput,
);Protocol config changes affect all treasuries. The timelock gives integrators time to update billing templates or opt out.
Org Profiles
Combine policy templates and billing templates into a single "org profile":
await instructions.fees.sendApplyOrgProfile(client, owner, applyOrgProfileInput);Profiles are validated atomically — both templates must be compatible and within protocol bounds.
Withdrawing Prepaid Surplus
Treasury owners can withdraw unused prepaid balance:
await instructions.fees.sendWithdrawUnusedFees(client, owner, withdrawInput);Restrictions:
- Cannot withdraw accrued fees (only prepaid surplus)
- Must preserve rent and any accrued-fee bucket
Use Cases
Protocol operators:
- Set global fee floor to fund development
- Adjust integrator bounds to control ecosystem economics
- Collect protocol revenue periodically
Integrators (wallets, dashboards, APIs):
- Define custom billing tiers for their users
- Earn revenue share on execution fees
- Apply templates across customer treasuries
Treasury owners:
- Prepay fees to avoid per-proposal friction
- Switch between billing tiers as usage scales
- Monitor
accumulated_fees_lamportsto budget operational costs
Referral programs:
- Add referral address to fee split table
- Referrer earns bps on every execution
- Tracked on-chain with immutable split history
Related Instructions
init_fee_vault/close_fee_vault— Vault lifecycledeposit_fees/withdraw_unused_fees— Prepaid balanceinit_fee_schedule/update_fee_schedule/close_fee_schedule— Per-treasury ratescreate_billing_template/update_billing_template/close_billing_template— Template authoringapply_billing_template/apply_org_profile— Apply templatesset_fee_splits/collect_fees/update_fee_recipient— Revenue collectioninit_protocol_config/update_protocol_config/commit_protocol_config— Protocol governance