Skip to Content
ReferenceEvents

Events

The typed events every Aeva module emits — the change log the indexer derives its tables from (the contract as written in docs/spec/events.md, reproduced below). Every event is also a transaction log entry the explorer shows on the tx page (Logs & Events).

Status: v1 FROZEN as of M0.3 (+ the two M0.4 additive fields); frozen at the ceremony commit (decision 83). v2 (M1.1) is a post-genesis additive section: new events and additive fields only. Fields may be added with new field numbers; no field may be renamed, retyped, renumbered or removed; no event may be removed or have its emission conditions changed. Any change to this file is a consensus-API change and needs an ADR.

Consumers: the M0.4 indexer ([ADR-005]) derives the whole rights graph from these events alone; the chain’s own queries are used for reconciliation only. Wallets and explorers should read the indexer, not raw events.

Encoding

  • Every event is a typed event (EventManager.EmitTypedEvent): the ABCI event type is the full proto message name (e.g. aeva.rights.v1.EventIssued) and every attribute is one top-level field, key = proto JSON field name, value = the field’s proto-JSON encoding as a JSON literal (strings are quoted: "400", messages are objects, enums are their names, bytes are base64, timestamps RFC3339). sdk.ParseTypedEvent reverses this.
  • Baseapp appends two non-field attributes that decoders must ignore: msg_index (tx events; the index of the message in the tx) and mode (BeginBlock | EndBlock, block-level events).
  • Amount fields (units, new_supply, encumbered, amount) are cosmossdk.io/math.Int → decimal strings, 0 < v ≤ 2^128 − 1. There are no floats anywhere.
  • Addresses are bech32 aeva1… account strings.
  • Failed transactions revert their state; their typed events are not part of the change log (a failed tx’s TxResult.events carries only ante events). Consumers must skip events of txs with code != 0.

Attribution

where an event appearsattributed to
block_results.txs_results[i].events(height, tx_index = i, tx_hash, msg_index)
block_results.finalize_block_events(height) only; mode says BeginBlock/EndBlock

Aeva emits block-level events only from EndBlock (settlement expiry sweep).

Ordering within a block

BeginBlock events → tx events in tx order, msg order, emission order → EndBlock events. The indexer derives state in exactly this order.

Catalogue

Int = math.Int decimal string. Timestamp = RFC3339 (google.protobuf.Timestamp). bytes = base64 in JSON.

aeva.asset.v1

event#fieldtypenotes
EventAssetCreated1asset_idstring (64 lower-case hex)
2issueraddress
3nonceuint64issuer nonce consumed
4kind_countuint32
5assetaeva.asset.v1.AssetM0.4 additive. Full asset as stored at creation: id, issuer, roles{custodian, transfer_agent, operator}, meta_hash, settlement_denom, kinds[]{kind_id, class, supply="0", decimals, bundle, term, transferable, policy_override}, policy, status=ASSET_STATUS_ACTIVE
EventPolicySet1asset_idstring
2targetenum PolicyTargetPOLICY_TARGET_ASSET | POLICY_TARGET_KIND
3kind_iduint32meaningful when target == KIND
4policyaeva.policy.v1.Policythe new policy (oneof rule: open, all, any, credential, allowlist, max_holders)
EventStatusSet1asset_idstring
2statusenum AssetStatusASSET_STATUS_ACTIVE | ASSET_STATUS_FROZEN

Emitted by: MsgCreateAsset, MsgSetPolicy, MsgSetStatus (one each).

aeva.rights.v1

event#fieldtypenotes
EventIssued1asset_idstring
2kind_iduint32
3issueraddress
4toaddress
5unitsInt
6new_supplyIntpost-value
EventRedeemed1asset_idstring
2kind_iduint32
3holderaddress
4unitsInt
5new_supplyIntpost-value
EventTransferred1asset_idstring
2fromaddress
3toaddress
4legs[]TransferLeg{kind_id uint32, units Int}every leg of the message
EventParamsUpdated1paramsParams{invariant_check_period uint64}
EventLocked1asset_idstring
2kind_iduint32
3holderaddress
4refstring"<module>/<id>", e.g. settlement/42
5unitsIntunits locked by this call
6encumberedIntpost-value of the position
EventUnlocked1asset_idstring
2kind_iduint32
3holderaddress
4refstring
5unitsIntunits released
6encumberedIntpost-value of the position
EventLockedTransferred1asset_idstring
2kind_iduint32
3fromaddresslock holder
4toaddressreceives free units
5refstring
6unitsInt

Emitted by: MsgIssueEventIssued; MsgRedeemEventRedeemed; MsgTransferEventTransferred; MsgUpdateParamsEventParamsUpdated; keeper LockEventLocked (today: inside settlement.MsgPropose); keeper UnlockEventUnlocked (inside settlement.MsgCancel, and in the EndBlock expiry sweep); keeper TransferLockedEventLockedTransferred (inside settlement.MsgAccept). A lock event is always accompanied by the caller’s own event in the same tx / block.

aeva.credential.v1

event#fieldtypenotes
EventAttested1subjectaddress
2typestring^[a-z0-9]+(\.[a-z0-9]+)*$, ≤ 64
3attesteraddress
4expiryTimestamp
5evidence_hashbytesempty or 32 bytes
EventRevoked1subjectaddress
2typestring
3attesteraddress

Emitted by: MsgAttest (upsert: re-attesting a revoked or expired record emits EventAttested again with revoked implicitly reset to false), MsgRevoke. No personal data is ever carried.

aeva.settlement.v1

Leg = {direction enum Direction, oneof kind: right{asset_id, kind_id, units Int} | coin{denom, amount Int}}, Direction ∈ {DIRECTION_PROPOSER_TO_COUNTERPARTY, DIRECTION_COUNTERPARTY_TO_PROPOSER}.

event#fieldtypenotes
EventProposed1iduint64
2proposeraddress
3counterpartyaddress
4legs[]Leg
5expiryTimestamp
6memo_hashbytesM0.4 additive. empty or 32 bytes
EventSettled1iduint64
2proposeraddress
3counterpartyaddress
4legs[]Legevery executed leg
EventCancelled1iduint64
2cancelleraddressproposer or counterparty
EventExpired1iduint64
EventParamsUpdated1paramsParams{max_ttl Duration, max_legs uint32, max_expirations_per_block uint32}

Emitted by: MsgProposeEventProposed (+ EventLocked per proposer right leg); MsgAcceptEventSettled (+ EventLockedTransferred per proposer right leg); MsgCancel before expiry → EventCancelled (+ EventUnlocked per proposer right leg); MsgCancel at/after expiry → EventExpired (+ EventUnlocked…) in the tx; EndBlock sweep → EventExpired (+ EventUnlocked…) as block-level events; MsgUpdateParamsEventParamsUpdated.

v2 — post-genesis additive (M1.1, decision 92)

New events (all typed, same encoding and attribution rules). Existing events are unchanged; EventAssetCreated.asset now carries Asset.liens_allowed (9) by virtue of embedding the full Asset message, and KindInvariantStatus (a query type, not an event) gains encumbrances_ok (8).

aeva.asset.v1 (v2)

event#fieldtypenotes
EventRolesSet1asset_idstring
2issueraddresssigner
3rolesRolesnew roles (custodian, transfer_agent, operator; empty = unset)
EventLiensAllowedSet1asset_idstring
2liens_allowedbool
EventKindPolicyCleared1asset_idstring
2kind_iduint32the kind whose policy_override was removed (inherits the asset policy)

Emitted by: MsgSetRolesEventRolesSet; MsgSetLiensAllowedEventLiensAllowedSet; MsgSetPolicy{clear_kind}EventKindPolicyCleared (a MsgSetPolicy with asset / kind_id still emits EventPolicySet).

aeva.encumbrance.v1 (v2)

Encumbrances lock disjoint units under the lock ref encumbrance/<id>; every creation is accompanied by aeva.rights.v1.EventLocked with that ref, every release / expiry by EventUnlocked, every exercise by EventLockedTransferred (holder → beneficiary) in the same tx / block.

event#fieldtypenotes
EventPledged1iduint64
2asset_idstring
3kind_iduint32
4holderaddresssigner
5unitsInt
6beneficiaryaddress
7holder_release_aftertimestampoptional; absent = the holder may never release
8exercisablebool
9expirytimestampoptional
10evidence_hashbytesempty or 32 bytes
EventLienCreated1iduint64
2asset_idstring
3kind_iduint32
4holderaddressthe encumbered position’s holder
5unitsInt
6beneficiaryaddress
7operatoraddresssigner; the asset’s operator role
8exercisablebool
9expirytimestampoptional
10evidence_hashbytesexactly 32 bytes
EventLockupCreated1iduint64
2asset_idstring
3kind_iduint32
4holderaddressthe recipient of MsgIssue
5unitsIntthe issued units
6issueraddress
7holder_release_aftertimestampMsgIssue.lockup_until
EventEncumbranceReleased1iduint64
2releaseraddressbeneficiary, holder, operator or issuer per decision 85
3unitsIntunits returned to the holder
EventEncumbranceExercised1iduint64
2unitsIntunits moved to the beneficiary
3remainingIntpost-value; 0 = EXERCISED
4beneficiaryaddress
EventEncumbranceExpired1iduint64block-level (EndBlock sweep)
EventParamsUpdated1paramsParamsaudit only

Emitted by: MsgPledgeEventPledged; MsgLienEventLienCreated; MsgIssue{lockup_until}EventLockupCreated (after EventIssued, same tx); MsgReleaseEventEncumbranceReleased; MsgExerciseEventEncumbranceExercised; EndBlock sweep → EventEncumbranceExpired; MsgUpdateParamsEventParamsUpdated. A lazy expiry inside a failing MsgRelease / MsgExercise is rolled back with the tx: the sweep is the authoritative expiry path (same caveat as settlements).

aeva.asset.v1 (v2, M1.2)

event#fieldtypenotes
EventDistributionDenomsSet1asset_idstring
2denomsstring[]the new allowlist (1..8); governs new distributions only

Asset.distribution_denoms (10) is carried by EventAssetCreated.asset. Emitted by: MsgSetDistributionDenomsEventDistributionDenomsSet.

aeva.asset.v1 (v3, overnight phase 2 — issuance lock)

event#fieldtypenotes
EventIssuanceLocked1asset_idstringemitted once per asset, ever
2issuerstringthe signer

Asset.issuance_locked (11) is false in every EventAssetCreated.asset (a MsgCreateAsset with the flag set is rejected). Emitted by: MsgLockIssuanceEventIssuanceLocked. A second lock fails with ErrAlreadyLocked and emits nothing; MsgIssue on a locked asset fails with ErrIssuanceLocked (asset codespace 18) and emits nothing.

aeva.payout.v1 (v2, M1.2, decision 103)

event#fieldtypenotes
EventDistributed1asset_idstring
2kind_iduint32
3denomstring
4payeraddressany signer
5amountIntbase units deposited in the payout module account
6new_indexIntpost-value; scaled by 10^18
7carry_scaledIntpost-value; < supply
8supplyIntthe kind supply at this instant (the ex-date is this block)
EventPendingSettled1holderaddress
2asset_idstring
3kind_iduint32
4denomstring
5amountIntaccrued moved into pending (units·(index − checkpoint) div 10^18)
6new_checkpointIntpost-value = the accrual index
EventClaimed1holderaddress
2asset_idstring
3kind_iduint32
4denomstring
5amountIntpaid from the module account; pending is 0 afterwards
EventParamsUpdated1paramsParamsaudit only

Emitted by: MsgDistributeEventDistributed; the x/rights units-change hook (Issue recipient, Redeem, Transfer both parties, TransferLocked both parties — never Lock / Unlock) → EventPendingSettled for every accrual of the (asset, kind) whose index moved since the holder’s checkpoint, before the position event of the same tx; MsgClaim / MsgClaimAllEventPendingSettled (when accrued > 0) then EventClaimed per paid (asset, kind, denom); MsgUpdateParamsEventParamsUpdated.

v3 — EVM facade (M5, decision 114): no new Aeva events

The AE-20 precompiles emit the same typed events as the native path: a right or bundle transfer / transferFrom is one aeva.rights.v1.EventTransferred (one leg per kind moved) inside a /cosmos.evm.vm.v1.MsgEthereumTx; the payout hook’s EventPendingSettled precede it exactly as for MsgTransfer. The ERC-20 Transfer / Approval logs live in cosmos/evm’s tx_log attributes and are not part of this contract — the indexer derives from typed events only (ADR-005, ADR-011). cosmos/evm’s own events (ethereum_tx, tx_log, block_bloom, fee market events) are stored raw like any other module’s; block_bloom carries a raw 256-byte value, which the indexer stores hex-encoded. The indexer’s txs table gains the EVM metadata of a MsgEthereumTx (eth hash, 0x from / to, value, status, gas, revert reason) from the tx body and result, not from events.

Not events

Coin movements of settlement legs are ordinary x/bank events (coin_spent, coin_received, transfer) and are not part of this contract; the settlement legs in EventProposed / EventSettled are authoritative for what moved. Module parameters are consensus state readable through the chain’s Params queries; the EventParamsUpdated events exist for audit, not derivation.

Change log of this contract

datechange
2026-09-19 (M0.3)catalogue frozen: 3 asset, 7 rights, 2 credential, 5 settlement events
2026-09-19 (M0.4)additive: EventAssetCreated.asset (5), EventProposed.memo_hash (6)
2026-09-20 (M1.1)v2 section: 3 asset + 7 encumbrance events; Asset.liens_allowed inside EventAssetCreated.asset
2026-09-20 (M1.2)v2: EventDistributionDenomsSet; 4 payout events; Asset.distribution_denoms inside EventAssetCreated.asset
2026-09-21 (RH-2)v5 section: 5 aeva.bridge.v1 events; I8
2026-09-21 (v0.12.0)v6 section: aeva.fee.v1.EventParamsUpdated; the settlement denom is aeusd in every event payload (pre-genesis rename, ADR-016 §1)

aeva.settlement.v1 (v3, M2)

EventCancelled gains reason (3): empty for a party’s cancel, "LIQUIDATION" when x/waterfall cancelled the PENDING settlement of a liquidating asset; canceller (2) is empty in that case.

aeva.waterfall.v1 (v3, M2, overnight phase 3)

event#fieldtypenotes
EventWaterfallSet1asset_idstring
2tiersTier[]the whole new list (≤ 16)
EventLiquidated1asset_idstringpreceded by EventStatusSet{LIQUIDATING}
2bystringissuer or operator
3window_endTimestamp
4cancelled_settlementsuint32one EventCancelled{reason: LIQUIDATION} each, earlier in the tx
EventLiquidationSwept1asset_idstringblock-level (EndBlocker); preceded by EventStatusSet{LIQUIDATED}
EventProceedsDeposited1–3asset_id, payer, coin{denom, amount}
EventTierPaid1asset_idstringone per tier that received something in a run
2tier_indexuint32
3typeTierTypeFIXED or PRO_RATA
4claimantstringFIXED only
5kind_iduint32PRO_RATA only (its EventDistributed precedes)
6amountDenomAmountthis payment
7cumulativeIntthe tier’s total after it
EventWaterfallRun1–5asset_id, caller, paid_fixed[], routed_pro_rata[], leftover[]per denom, this run
EventRedemptionFunded1–8asset_id, kind_id, denom, issuer, price_per_unit, amount, funded, untilfunded is cumulative
EventRedeemedForPool1–7asset_id, kind_id, denom, holder, units (raw), paid, pool_paidthe EventRedeemed of x/rights precedes it in the tx
EventRedemptionWithdrawn1–5asset_id, kind_id, denom, issuer, amount
EventSplit1–4asset_id, kind_id, factor, multiplierthe new multiplier = old × factor; raw events elsewhere are unchanged

RightKind.multiplier (9) is carried by EventAssetCreated.asset (always 0 at creation).

aeva.payout.v1 (v3, M3, overnight phase 4)

event#fieldtypenotes
EventRouteCreated1–6asset_id, kind_id, ref, holder, recipient, unitspreceded by the holder’s EventPendingSettled (units before the route)
EventRouteSettled1–6asset_id, kind_id, ref, denom, amount, new_checkpointthe route’s accrued moved into its pending
EventRouteRemoved1–5asset_id, kind_id, ref, recipient, moved[]{denom, amount}each moved went into the recipient’s own checkpoint pending; followed by EventUnlocked / the units move
EventClaimed6refstringset when the claim paid a routed entry

aeva.payout.v1 (v4, v0.10.1 — P4)

event#fieldtypenotes
EventRouteReduced1–8asset_id, kind_id, ref, holder, recipient, units_removed, units, moved[]{denom, amount}a partial exercise of a routed pledge: both parties settled (each moved went into the recipient’s own checkpoint pending), the route continues on units (> 0) with a fresh checkpoint at the current index; preceded by the holder’s / recipient’s EventPendingSettled and the route’s EventRouteSettled, followed by EventLockedTransferred. A full exercise emits EventRouteRemoved instead

EventPendingSettled.amount for a holder with routes is (units − routed) × Δindex.

aeva.delegation.v1 (v3, M3)

event#fieldtypenotes
EventDelegated1delegationDelegationthe full record (ended unset); EventLocked (ref delegation/<id>) and, for INCOME, EventRouteCreated in the same tx
EventDelegationEnded1iduint64
2reasonEndReasonEXPIRED (block-level, sweep) · REVOKED · RETURNED; EventRouteRemoved (INCOME) and EventUnlocked follow

aeva.encumbrance.v1 (v3, M3)

EventPledged gains income_to_beneficiary (11).

v5 — the Robinhood Chain bridge (RH-2, ADR-015)

aeva.bridge.v1 (v5)

The bridge modules are hyperlane-cosmos’ x/core (mailbox, ISMs, hooks) and x/warp (tokens) behind Aeva’s own x/bridge route registry. The five Aeva events below are the change-log contract; hyperlane’s own events (hyperlane.core.v1.EventDispatch / EventProcess, hyperlane.warp.v1.EventSendRemoteTransfer / EventReceiveRemoteTransfer, the ISM / mailbox / token events) are emitted alongside them in the same tx and are not part of the contract — consumers derive from aeva.bridge.v1.

event#fieldtypenotes
EventRouteSet1routeRoutethe stored route: route_id, remote_domain, remote_contract (0x bytes32), direction (NATIVE_OUT · SYNTHETIC_IN), local_denom (native denom · hyperlane/<token id>), status, caps{window_seconds, outbound_limit, inbound_limit}, warp_token_id, display, exponent, outbound, inbound
2createdbooltrue on creation (the warp token was created and the remote router enrolled in the same tx), false on an update
EventRoutePaused1route_idstring
2pausedbooltrue: both directions rejected from now on; false: resumed
EventBridgedOut1route_idstring
2senderaddressthe local account debited (escrow for NATIVE_OUT, burn for SYNTHETIC_IN)
3remote_recipientstring0x bytes32
4amountIntin local_denom
5message_idstringthe Hyperlane message id (0x bytes32); matches the remote process
EventBridgedIn1route_idstring
2recipientaddressthe local account credited (release for NATIVE_OUT, mint for SYNTHETIC_IN)
3amountIntin local_denom
4message_idstringthe Hyperlane message id of the delivered message
EventCapExceeded1route_idstring
2flowFlowOUT · IN
3amountIntthe rejected amount
4usedIntthe window total before the transfer
5limitIntthe window limit

Emission: EventRouteSet / EventRoutePaused from the governance messages (MsgSetRoute, MsgPauseRoute); EventBridgedOut from MsgBridgeOut, the only outbound path (hyperlane.warp’s MsgRemoteTransfer is rejected by the bank restriction on the warp account); EventBridgedIn from the relayer’s hyperlane.core.v1.MsgProcessMessage through the wrapped warp app handler. EventCapExceeded is emitted in a failing execution: the message returns ErrCapExceeded (codespace bridge, code 5) and the tx fails, so the event is visible in simulation / CheckTx results and in the failing tx’s error, never in a committed block’s events (the SDK discards a failed tx’s message events). The indexer derives rejected transfers from the failed MsgBridgeOut tx code instead. Inbound cap rejections fail the relayer’s tx; the relayer retries when the window has room — nothing is queued on chain. (Restated under v6.)

Invariant I8 (introduced 0.11.0): per NATIVE_OUT route, the warp collateral escrowed for the route’s token == outbound − inbound; per native denom the sum of those escrows == the warp module account’s balance; per SYNTHETIC_IN route the synthetic’s bank supply == inbound − outbound.

v6 — v0.12.0 (ADR-016)

aeva.fee.v1 (v6)

event#fieldtypenotes
EventParamsUpdated1paramsParams{accept_aeusd}; governance (block-level, EndBlock)

Not a derivation source (Conventions: params are read from the chain).

aeva.asset.v1 (v6 additions — RH-3)

event#fieldtypenotes
EventKindBridgeableSet1asset_idstring
2kind_iduint32
3bridgeableboolthe issuer’s flag (MsgSetKindBridgeable); a RIGHT_OUT route needs it and an OPEN effective policy

Derives right_kinds.bridgeable.

aeva.bridge.v1 (v6 additions — RH-3, ADR-017)

Route gains asset_id, kind_id, bundle, escrow_address (set on DIRECTION_RIGHT_OUT routes; local_denom is the pseudo denom right/<asset>/<kind> or bundle/<asset>). EventRouteSet carries them.

event#fieldtypenotes
EventRightBridgedOut1route_idstring
2asset_idstring
3kind_iduint32ignored when bundle
4bundleboolwhole bundles
5senderaddressthe local holder debited (policy-checked transfer to the escrow)
6remote_recipient0x bytes32
7unitsIntraw units (bundle: whole bundles)
8message_id0x hex
EventRightBridgedIn1route_idstring
2asset_idstring
3kind_iduint32
4bundlebool
5recipientaddressthe local account credited (policy-checked transfer from the escrow)
6unitsInt
7message_id0x hex
EventEscrowIncomeSwept1route_idstringgovernance (MsgSweepEscrowIncome), block-level
2recipientaddress
3swept[]DenomAmountthe escrow’s claimed income, per denom

Derives bridge_routes.outbound / inbound (I8b: escrow units == outbound − inbound), bridge_transfers rows with asset_id / kind_id / bundle, and bridge_routes.income_swept. Nothing is minted on Aeva: a right transfer never touches supply.

A note on EventCapExceeded

aeva.bridge.v1.EventCapExceeded is a CheckTx-level reason: it is emitted in the execution that fails with bridge/5, so it shows up in simulation and CheckTx results and in the failing tx’s error, and never appears in a committed block. Consumers derive rejected transfers from the failed tx’s code, not from this event.

Last updated