> For the complete documentation index, see [llms.txt](https://docs.selcier.xyz/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.selcier.xyz/build-on-selcier/chain-events.md).

# Chain event catalog

Solidity event signatures for Selcier contracts on Robinhood Chain, grouped by contract, along with practical advice for building an indexer.

Selcier contracts write their activity to Robinhood Chain as events. Supply, transfers, rule changes, offerings, liquidity, corporate actions and disclosures all show up in these logs, which makes them the public record of a company. Both `GET /v1/events` and the [public Explorer](/the-platform/public-explorer.md) are derived from them, and any Robinhood Chain archive node will let you index them on your own.

Topic filters work on any parameter flagged `indexed`.

## Deployment events

Emitted by `SelcierFactory`.

```solidity
event CompanyDeployed(
    bytes32 indexed companyId,
    address identityRegistry,
    address trustedVerifiers,
    address offeringVault,
    address liquidityWindow,
    address rfqSettlement,
    address distributionVault,
    address governance,
    address disclosureRegistry,
    address issuerTimelock
);
event ShareClassDeployed(bytes32 indexed companyId, bytes32 indexed shareClass, address token, address ruleEngine, address valuationOracle);
event PoolGateDeployed(bytes32 indexed companyId, address indexed token, address poolGate);
```

## Share token events

Emitted by `SelcierShareToken`.

```solidity
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
event SharesIssued(address indexed to, uint256 amount, bytes32 indexed ref);
event SharesRedeemed(address indexed from, uint256 amount, bytes32 indexed ref);
event RecoveryApproved(address indexed lost, address indexed replacement, address indexed approver);
event RecoveryScheduled(address indexed lost, address indexed replacement, uint64 eta, bytes32 ref);
event RecoveryExecuted(address indexed lost, address indexed replacement, uint256 amount);
event RecoveryCancelled(address indexed lost);
event TokensFrozen(address indexed holder, uint256 amount, bytes32 reason);
event TokensUnfrozen(address indexed holder, uint256 amount);
event Paused(bytes32 reason);
event Unpaused();
event MultiplierScheduled(uint256 newMultiplier, uint64 effectiveAt);
event UIMultiplierUpdated(uint256 oldMultiplier, uint256 newMultiplier);
event AgentSet(address indexed agent, bool enabled);
event DocumentsRootUpdated(bytes32 documentsRoot);
```

How these combine in practice:

* Issuance and redemption: `SharesIssued` and `SharesRedeemed` pair with an ERC-20 `Transfer` whose other side is the zero address.
* Conversion between share classes: one token logs `SharesRedeemed`, another logs `SharesIssued`, and both share a transaction and a `ref`.
* Recovery: `RecoveryExecuted` comes with a `Transfer` moving the balance out of the lost wallet and into its replacement.

## Rule events

Emitted by `RuleEngine`.

```solidity
event ModuleAdded(address indexed module);
event ModuleRemoved(address indexed module);
event ModuleConfigured(address indexed module, bytes32 configHash);
```

The `configHash` value is a keccak256 over the encoded configuration of a module. To see that configuration decoded, read the module directly or look it up in the Explorer.

## Identity events

Emitted by `IdentityRegistry`.

```solidity
event IdentityRegistered(address indexed wallet, address indexed identity);
event IdentityRemoved(address indexed wallet);
event ClaimAdded(address indexed identity, bytes32 indexed topic, address verifier, uint64 expiry);
event ClaimRevoked(address indexed identity, bytes32 indexed topic);
```

No personal data ever appears in a claim event. All it captures is the fact that a trusted verifier attested to some topic for an identity, plus the time that attestation runs until.

## Primary raise events

Emitted by `OfferingVault`.

```solidity
event OfferingCreated(uint256 indexed offeringId);
event Subscribed(uint256 indexed offeringId, address indexed investor, uint256 amount);
event OfferingClosed(uint256 indexed offeringId, uint256 raised, uint256 sharesIssued);
event OfferingFailed(uint256 indexed offeringId);
event Refunded(uint256 indexed offeringId, address indexed investor, uint256 amount);
```

Stablecoin units apply to `raised` and `amount`, while `sharesIssued` uses raw token units at 18 decimals.

## Window events

Emitted by `LiquidityWindow`.

```solidity
event WindowOpened(uint256 indexed windowId, uint64 opensAt, uint64 closesAt);
event OrderPlaced(uint256 indexed windowId, uint256 indexed orderId, uint8 side, uint256 quantity, uint256 limitPrice);
event OrderCancelled(uint256 indexed windowId, uint256 indexed orderId);
event WindowCleared(uint256 indexed windowId, uint256 clearingPrice, uint256 volume);
event WindowCancelled(uint256 indexed windowId);
event RofrExercised(uint256 indexed windowId, address indexed holder, uint256 quantity, uint256 price);
event DeliveryDeferred(address indexed shareToken, address indexed owner, uint256 amount);
event DeferredClaimed(address indexed shareToken, address indexed owner, uint256 amount);
```

Bids (buy) have a `side` of `1`, while asks (sell) have `0`.

There is no dedicated fill event. Fills at clearing show up as `Transfer` events on the stablecoin and the share token, inside the transaction that carries `WindowCleared`.

Clearing does not revert when a token delivery fails the recipient's rules. The window holds those tokens for their owner and logs `DeliveryDeferred`, and a later `claimDeferred` call by the owner produces `DeferredClaimed`.

## Quote events

Emitted by `RFQSettlement`.

```solidity
event QuoteFilled(bytes32 indexed quoteHash, address indexed maker, address indexed taker, uint256 quantity, uint256 price);
event QuoteCancelled(address indexed maker, uint256 nonce);
```

## Payout events

Emitted by `DistributionVault`.

```solidity
event DistributionFunded(uint256 indexed distributionId, address asset, uint256 amount, uint256 recordBlock);
event DistributionClaimed(uint256 indexed distributionId, address indexed holder, uint256 amount);
event DistributionSwept(uint256 indexed distributionId, uint256 amount);
```

The `recordBlock` value is a Robinhood Chain L2 block number obtained from the ArbSys precompile. It is not what `block.number` gives you on Arbitrum chains, since that is an L1-derived value.

## Voting events

Emitted by `Governance`.

```solidity
event ProposalCreated(uint256 indexed proposalId, uint256 snapshotBlock, uint64 endsAt);
event VoteCast(uint256 indexed proposalId, address indexed voter, uint8 support, uint256 weight);
event ProposalFinalized(uint256 indexed proposalId, uint8 result);
event DelegateChanged(address indexed delegator, address indexed delegatee);
```

The multiplier of each share class is read when a proposal is created, and `weight` has it applied already. A `result` holds the index of the winning option, unless it is `255` (`NO_QUORUM`), which signals a missed quorum.

## Document events

Emitted by `DisclosureRegistry`.

```solidity
event DocumentAnchored(uint256 indexed documentId, bytes32 indexed kind, bytes32 hash, string uri);
```

The `kind` field is a string encoded as `bytes32`, and these are its allowed values:

* `SHARE_CLASS_TERMS`
* `OFFERING_DOCUMENT`
* `FINANCIAL_STATEMENT`
* `COMPANY_UPDATE`
* `BOARD_RESOLUTION`
* `VALUATION_REPORT`

The `hash` field is a SHA-256 over the file.

## Valuation events

Emitted by `ValuationOracle`.

```solidity
event ValuationPublished(int256 price, uint8 source, uint64 asOf, bytes32 documentHash);
```

## Configuration and signer logs

The next group tracks configuration. You will want these if your product displays how a company's rules and signers have changed over time.

```solidity
// IssuerTimelock
event ActionProposed(bytes32 indexed id, address indexed proposer, address target, uint256 value, bytes data);
event ActionApproved(bytes32 indexed id, address indexed signer);
event ActionQueued(bytes32 indexed id, uint64 eta);
event ActionExecuted(bytes32 indexed id);
event ActionCancelled(bytes32 indexed id);
event SignerAdded(address indexed signer);
event SignerRemoved(address indexed signer);
event ThresholdChanged(uint256 threshold);
event DelayChanged(bytes4 indexed selector, uint64 delay);

// TrustedVerifiers
event VerifierAdded(address indexed verifier, bytes32[] topics);
event VerifierRemoved(address indexed verifier);

// ROFRModule
event TransferProposed(address indexed from, address indexed to, uint256 amount, uint64 noticeEndsAt);
event RightWaived(address indexed from, address indexed to);
event RightExercised(address indexed from, address indexed to, uint256 amount);

// EmployeeVestingModule
event GrantAdded(address indexed identity, uint256 index, uint64 start, uint64 cliff, uint64 duration, uint256 total);
event GrantAccelerated(address indexed identity, uint256 index);

// PoolGate
event PoolRegistered(address indexed pool);
event PoolRemoved(address indexed pool);

// Fee and venue settings
event FeeUpdated(address recipient, uint16 feeBps);                              // OfferingVault
event FeesUpdated(address recipient, uint16 sellerFeeBps, uint16 buyerFeeBps);   // LiquidityWindow, RFQSettlement
event ShareClassEnabled(address indexed shareToken, bool enabled);               // RFQSettlement
```

## Building an indexer

**Begin at the factory.** Take the `SelcierFactory` address from `GET /v1/contracts`, index its `CompanyDeployed` and `ShareClassDeployed` events, and extend your watch list with each contract they announce. You stay complete, and no company address ever gets hardcoded.

**Run against archive data.** Backfills and historical reads require an archive node. Rate limits make the public Robinhood Chain RPC a poor fit for indexing, so go with a dedicated provider, as [The network underneath](/under-the-hood/network-foundation.md) describes.

**Follow finality.** A log can be read the moment the sequencer includes its transaction, and it turns final after the batch reaches Ethereum. When you serve data from sequencer-confirmed blocks, plan for the uncommon case of a block that differs from its soft confirmation. In Selcier's API, each event carries a label of `confirmation: "sequencer"` or `"l1"`.

**Deduplicate on transaction and log position.** The pair `(tx_hash, log_index)` is unique per event, which makes it the right key for idempotent writes.

**Keep raw balances.** Build holdings from `Transfer` events in raw units and bring in `uiMultiplier` when reading. A split leaves raw balances alone, so this design survives corporate actions intact. Store each `UIMultiplierUpdated` as well, since historical share counts need the multiplier that applied on that date.

**Process logs per transaction.** Offering closes, window clears, conversions and recoveries each produce several events in one transaction. Handle a transaction's logs as a unit, and your data will never display an atomic action half done.

**Fill gaps from the API.** Should you also receive [event deliveries over webhooks](/build-on-selcier/event-delivery.md), `GET /v1/events` with `from_block` makes for an easy backfill. It serves those same events decoded, with Selcier ids attached.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.selcier.xyz/build-on-selcier/chain-events.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
