Transaction fee accounting
Explains how DALP records per-operation fee obligations for off-chain invoicing without collecting tokens on-chain. Covers rates, exemptions, reconciliation, and audit events.
Transaction fee accounting records a fee obligation when a token is minted, burned, transferred, or redeemed. It does not withhold or move tokens on-chain. The platform keeps the operation amount unchanged, increments the accrued fee total, and emits events you can use for invoicing, reporting, or off-chain settlement.
Use this feature when you need a reliable on-chain fee trail but want settlement to happen later through an operating process. Use Transaction Fee instead when the contract should collect the fee during the operation.
Related pages:
- Token Features Catalog
- Asset Contracts
- API reference for transaction fee accounting
- Operator how-to for transaction fee accounting
- Treasury Distribution
What the feature does
The feature stores three fee rates in basis points:
- Mint fee rate for mint operations.
- Burn fee rate for burn operations and redemption operations.
- Transfer fee rate for holder-to-holder transfers.
For each tracked operation, the platform calculates a fee from the operation amount and the relevant rate, rounding down. No accounting fee is recorded when the amount is zero, when either side of the movement is fee-exempt, or when either side is the configured fee recipient.
Interface
Unlike Transaction Fee, Transaction Fee Accounting tracks obligations without moving or withholding tokens.
| Capability | Who can call | Inputs | On-chain effect | Emits | Notes |
|---|---|---|---|---|---|
| Record fee on operation | Automatic hook | Triggered on mint, burn, transfer, redemption | Increments accrued counter; no token movement | FeeAccrued | Does not rewrite amounts |
| Reconcile accrued fees | GOVERNANCE_ROLE | None | Resets accrued counter; closes accounting period | FeesReconciled | Off-chain settlement trigger |
| Set fee rates | GOVERNANCE_ROLE | Mint, burn, and transfer rates in bps | Updates fee rate configuration | FeeRatesUpdated | Redemptions use the burn fee rate; blocked after freeze |
| Set fee recipient | GOVERNANCE_ROLE | Non-zero recipient address | Redirects future reconciliation target | FeeRecipientUpdated | Blocked after freeze |
| Set fee exemption | GOVERNANCE_ROLE | Account address + exempt flag | Marks address as exempt from tracking | FeeExemptionSet | Available from the Console capability card and API |
| Freeze fee rates | GOVERNANCE_ROLE | None | Permanently locks rates and recipient changes | FeeRatesFrozen | Irreversible |
Business impact
This feature does not rewrite token balances or operation amounts. The platform tracks fees as obligations; it does not collect them from the transfer path.
Issuers and platform operators must reconcile and settle accrued fees through an off-chain process: invoicing, ledger posting, or reporting. The platform can batch settlement periodically instead of collecting value on every transfer.
Use FeeAccrued and FeesReconciled events as an on-chain trail for each accounting period. The actual payment or settlement record remains outside the token contract.
Risks and abuse cases
If the operator does not call reconcileFees() on schedule, accrued fee obligations continue to build in accounting records. Define a reconciliation cadence and owner before enabling the feature.
setFeeExemption() can exclude a holder, system address, or the zero address from fee tracking. Exempting the zero address excludes mint-side or burn-side accounting because mint and burn use the zero address on one side of the token movement.
Fee obligations are advisory. Off-chain systems must act on emitted events to collect or settle them.
Movements involving the configured fee recipient are not tracked, so settlement and treasury transfers do not create new obligations against themselves.
Controls and guardrails
| Role | Operation | Recommended guardrail |
|---|---|---|
GOVERNANCE_ROLE | setFeeRates() - set mint, burn, and transfer rates | Document changes and freeze rates when they should no longer move |
GOVERNANCE_ROLE | reconcileFees() - mark accrued fees as reconciled for a period | Run on a scheduled off-chain cadence |
GOVERNANCE_ROLE | setFeeExemption(address, exempt) - exempt a holder, system address, or the zero address for mint/burn accounting paths | Audit the exemption list and keep exemptions narrow |
GOVERNANCE_ROLE | setFeeRecipient() - change the recipient recorded in reconciliation events | Use a non-zero operational recipient address |
GOVERNANCE_ROLE | freezeFeeRates() - permanently lock rates and recipient changes | Treat as irreversible |
Failure modes and edge cases
Recorded obligations that are never settled create audit discrepancies. Establish your settlement process before enabling the feature on production assets.
Fee accruals add to the current accrued total. Reconciliation resets that total to zero and emits the reconciled amount for the closed interval, so reporting jobs should treat FeeAccrued and FeesReconciled as period events.
If fee rates change during a billing interval, events reflect the rate at the time of each transaction. Off-chain systems must handle rate history in reconciliation logic.
High-frequency tokens produce large event logs. Ensure the indexer, reporting job, or subgraph can handle the expected volume.
Reconciliation requires a non-zero accrued amount. If no tracked fees have accrued, the reconciliation call is rejected.
Auditability and operational signals
FeeAccrued(payer, from, to, feeType, operationAmount, feeBps, feeAmount, timestamp)- emitted per tracked operation. UsefeeAmountfor the accrued obligation andfeeTypeto distinguish mint, burn, transfer, and redemption types.FeesReconciled(caller, recipient, amount, periodEnd)- emitted when accrued fees are reconciled. Use the recipient and reconciled amount fields to close the accounting interval in your off-chain records.FeeRatesUpdated(sender, oldRates, newRates)- signals when fee rates change.FeeRecipientUpdated(sender, oldRecipient, newRecipient)- signals when the fee destination changes.FeeRatesFrozen(sender)- signals when rate and recipient changes are permanently locked.FeeExemptionSet(sender, account, exempt)- signals when exemption status changes.
Dependencies
- No external ERC-20 is required.
- No other token feature is required.
- You must supply off-chain reconciliation infrastructure: an indexer, invoicing process, ledger job, or reporting system.
Compatibility and ordering notes
supportsRewriting = false- the feature does not modify transfer amounts. It runs without changing the operation path.- Mutually exclusive with Transaction Fee in asset templates and token creation requests. Use Transaction Fee for on-chain collection, or Transaction Fee Accounting for off-chain settlement records.
- Compatible with other token features that do not require fee collection within the operation itself.
Change impact
Enabling after launch: historical transactions before activation are not retroactively tracked.
Disabling: uncollected obligations in progress remain in off-chain records. Reconcile before disabling.
Rate change: effective immediately. Off-chain systems must preserve enough rate history to reconcile the interval correctly.
Freeze: permanently blocks future rate and recipient changes for this feature.
See also
- Token Features Catalog - return to the full feature catalog
- Transaction Fee - on-chain fee collection alternative
- External Transaction Fee - fee collection using an external fee token
- Treasury Distribution - distribution and settlement flows
Transaction Fee
Per-transaction token fee that deducts a basis-point fee from mint, burn, transfer, and redemption events before downstream checks and audit reads consume the final amount.
External Transaction Fee
Fixed mint, burn, and transfer fees collected in a separate ERC-20 token. Covers fee token approvals, governance controls, freeze behavior, and operational failure modes.