> 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/under-the-hood/security-model.md).

# Security model

Selcier's approach to protecting its contracts and infrastructure, covering audit policy, target invariants, role separation, pausing, keys, monitoring and incident handling.

The record of who owns a company lives in Selcier contracts, and the security model follows from that. A balance may change only when the change is authorized, checked against the rules and publicly visible. Ownership cannot be changed by any one party acting alone, and that includes Selcier.

## Audit policy and target invariants

The contracts have not been audited yet. Selcier's policy is for independent firms to audit each contract ahead of mainnet deployment, and each upgrade ahead of its proposal. Once audits exist, the reports are meant to appear unabridged, with a link on the Explorer page for whichever contract version they examine.

The properties below are the design targets for the `RuleEngine` and the transfer path of the share token. They are meant to hold across any possible sequence of calls. Formal verification of them is a goal and has not been completed.

| Invariant             | Statement                                                                                                                                                                                                                                          |
| --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| No unchecked transfer | Mints, burns and recoveries carry their own role checks. Any other change to a holder's balance has to go through the `RuleEngine`.                                                                                                                |
| Verified holders only | Shares can land only in wallets that the company's `IdentityRegistry` links to an identity. Agents are the exception: they are the contracts and venues set through `setAgent` or a valid `VENUE` claim, and identity checks are skipped for them. |
| Supply accounting     | The sum of all balances matches total supply at all times, and only `mint` and `burn` alter that supply.                                                                                                                                           |
| Lots are conserved    | With `HoldingPeriodModule` enabled, lots follow a holder's balance. Balance that predates the module has no lot and counts as the oldest, unlocked holding. A transfer has no way to shorten a holding period.                                     |
| Frozen means frozen   | Transfers by a holder are capped at `unlockedBalanceOf`, a figure that leaves out frozen and locked amounts.                                                                                                                                       |
| Pause blocks movement | No transfer or mint of a paused token can succeed, so settlement cannot move it. `burn` and `recover` are registrar actions that do not read the pause flag.                                                                                       |
| Atomic settlement     | Tokens and stablecoins share one transaction in `RFQSettlement`, `LiquidityWindow` and `OfferingVault`, so a failure leaves both sides in place.                                                                                                   |
| Recovery is delayed   | Executing a recovery takes two approvals out of the required three, followed by the entire timelock.                                                                                                                                               |

Unit tests sit alongside this work, and continuous integration runs them on each change.

## Reporting a vulnerability

Selcier offers a public bug bounty whose scope spans hosted applications, the API and the contracts. Send reports to **<security@selcier.xyz>**, with a description, reproduction steps and the contract addresses or endpoints involved. Expect an acknowledgement inside one business day.

Mainnet contracts and accounts belonging to other people are not to be used for testing. The sandbox on Robinhood Chain testnet is the place for that, and [Keys and environments](/build-on-selcier/keys-and-environments.md) describes it.

## Separated authority

Permissions are never concentrated in one party. Selcier's operator, the registrar and the company's admin multi-sig sign separately, using separate keys. Agreement among them is required for the highest-stakes actions:

* A wallet recovery takes two of those three parties, and a timelock after that.
* Upgrading a share token requires approval from the company's multi-sig and then a seven-day timelock.
* Transfer rules change only with approval from the company's multi-sig, again behind a timelock.

[Access control](/under-the-hood/access-control.md) has the complete matrix.

## Pausing a share class

`PAUSER` role holders, namely the company and the registrar, can pause any share token. The pause applies from the next block, halting transfers and settlements in that share class, although `burn` and `recover` do not check it. A `reason` code passed with the call goes out in the `Paused` event and appears in the Explorer. The `ValuationOracle` publishes nothing further for a paused token and keeps its last value, which gives integrations reading it a stable price.

The effect is limited to that one class. Other classes at the company, and other companies, carry on unaffected.

## Rehearsal before mainnet

Ahead of mainnet, each company deployment gets a rehearsal on Robinhood Chain testnet (chain ID `46630`). Its configuration matches exactly: modules, parameters, roles and timelocks are all the same. The script Selcier runs includes an offering close, a corporate action, the replayed cap table, and sample transfers chosen to pass and to fail. Nothing goes to mainnet until the company has accepted the outcome in the Console.

## Upgrades

A UUPS proxy fronts each share token, under the control of an `IssuerTimelock` whose signers include the company's multi-sig. Proposing an upgrade is something Selcier can do, but approval rests with the company alone, and execution comes seven days later. For that period the Explorer carries the proposed implementation, a diff and its audit report.

Replacing a transfer rule module requires no token upgrade, though the swap still goes through the timelock. No other Selcier contract can be upgraded: later versions are deployed next to earlier ones, and each company moves across when it decides to.

## Keys

| Key type               | Handling                                                                                                                                                                                                             |
| ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Operator keys**      | Created and stored in hardware security modules, or divided across an MPC cluster, so that no one machine ever has a whole key. Companies have separate operator signers, which contains any problem to one company. |
| **Claim-signing keys** | These write identity claims. They are kept apart from operator keys, subject to rate limits, and restricted to the claim topics `TrustedVerifiers` lists for them.                                                   |
| **Company keys**       | The company's multi-sig owns these, and they are never seen or held by Selcier.                                                                                                                                      |
| **Holder keys**        | Holders own these. Embedded wallets are non-custodial, with key shares that Selcier does not hold alone.                                                                                                             |

Rotation follows a fixed schedule, and happens at once whenever a compromise is suspected.

## Watching the system

Selcier's own contracts are under continuous observation:

* **On-chain invariant monitors** examine each block for states that ought to be impossible, such as an unverified wallet holding a balance, or total supply differing from the registrar's record.
* **Role and configuration watchers** raise an alert on any role change, module change, pause or scheduled recovery, Selcier-initiated or otherwise.
* **Infrastructure monitors** follow queue depth, webhook delivery, sequencer feed lag and the health of RPC providers.

Chain connectivity, API availability and other live status details are on the public status page linked from [selcier.xyz](https://selcier.xyz).

## Handling incidents

An on-call engineer triages straight away, whether the trigger is a monitor or an outside report. When holder assets may be in danger, these steps follow:

1. Selcier gets in touch with the affected company's `PAUSER` holders, since they can pause the share class immediately and Selcier has no ability to pause it unilaterally.
2. Containment and a fix come next. Changes to contract logic follow the usual audit and timelock process, and the timelock is not bypassed under any circumstances.
3. Selcier notifies affected companies directly, and a notice goes up in Portfolio for holders.
4. Afterwards, the status page links to a public write-up setting out what happened and when, why it happened, and how it was remedied.


---

# 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/under-the-hood/security-model.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.
