> For the complete documentation index, see [llms.txt](https://docs.jaawle.xyz/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.jaawle.xyz/protocol/governance-and-roles.md).

# Governance and roles

One contract, the `AccessRegistry`, is the control plane for everything: roles, the KYC allowlist and pause flags. It is not upgradeable. Every other contract asks it `hasRole`, `isKyc` and `isPaused` and holds no permissions of its own. ADMIN is the timelock, so every parameter change, every role change and every upgrade waits out the timelock delay.

## Roles

| id | role              | held by                                                                                            | may                                                                                                                                                                                                                              |
| -- | ----------------- | -------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 0  | ADMIN             | the timelock, and on staging a separate offline key; the deployer ends the deployment with no role | grant roles, edit the allowlist, pause and unpause, configure every contract, upgrade every proxy, create pools, set index weights, set the treasury, withdraw from the insurance vault                                          |
| 1  | KEEPER            | the keeper's operator wallet                                                                       | `PriceFeed.refresh`; `MarketPool.executeRequests`, `placeIssuerOrder`, `sweepDividends`, `syncInventory`; `IndexVault.executeRequests`, `shift`; `PositionManager.liquidate` at any time; `TriggerBook.execute` at any time      |
| 2  | SETTLER           | the issuer adapter wallet                                                                          | `PriceFeed.setSession`; `MarketPool.settleIssuerOrder`, `refundStaleOrder`, `sweepUsdPlus`                                                                                                                                       |
| 3  | POSITION\_MANAGER | the PositionManager proxy                                                                          | `InsuranceVault.cover`                                                                                                                                                                                                           |
| 4  | GUARDIAN          | an operations key                                                                                  | pause a target or everything; never unpause                                                                                                                                                                                      |
| 5  | FACTORY           | the PoolFactory proxy                                                                              | `PositionManager.setMarket` and `setRisk` when registering a market                                                                                                                                                              |
| 6  | ROUTER            | the TradeRouter proxy and the TriggerBook proxy                                                    | the `...For(account, ...)` entry points: `increasePositionFor`, `decreasePositionFor`, `requestLiquidityFor`, `cancelRequestFor`, `requestDepositFor`, `requestRedeemFor`, `cancelRequestFor` on the index, `TriggerBook.setFor` |
| 7  | KYC               | the keeper's operator wallet                                                                       | `setKyc` and `setKycBatch`, nothing else: the keeper can admit a verified wallet but cannot change a role, a parameter or a pause                                                                                                |

Two authorisations are not roles: a pool accepts its counterparty hooks (`reserveInventory`, `releaseInventory`, `increaseShortOi`, `decreaseShortOi`, `settleTrader`) only from the PositionManager address it was wired with, and its parent hooks (`depositFromParent`, `withdrawToParent`) only from the IndexVault address.

The keeper is bounded on-chain. It supplies `minOut` and amounts; the contracts enforce the per-order cap, the deploy ratio, the reserve floor, the open-interest caps, the shift size and cooldown, and the session rules. The keeper cannot change a parameter, a weight or an implementation, and cannot move funds anywhere but between the pool, the issuer adapter and the accounts a request or a position belongs to.

The TriggerBook holds ROUTER so that `execute` can close a position through `decreasePositionFor`. The payout of that call goes to the position's account, never to the caller, which is the property that makes the ROUTER role safe to hold: a `...For` entry point can act for an account but can never be paid instead of it.

## The allowlist

`setKyc(account, allowed)` and `setKycBatch` are ADMIN or KYC calls; the KYC role exists so the keeper can admit a verified wallet without holding anything else. Every trading and liquidity entry point checks `isKyc(account)` on the account (not on the router or subaccount that submits). Revocation removes the account from the allowlist; open positions can still be closed because `decreasePosition` does not check it. How an account gets on the list is described in [Identity and access](/legal/eligibility-and-identity.md).

## Pause model

`setPaused(target, paused)` flags one contract; `setGlobalPause(paused)` flags all of them. `isPaused(target)` is true when either flag is set. ADMIN can set and clear both; GUARDIAN can only set them. Nothing can be unpaused without going through the timelock.

What a pause stops, per target:

| target                                 | paused entry points                                                                                | still works                                                                                                                                                  |
| -------------------------------------- | -------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| PositionManager                        | `increasePosition`, `decreasePosition`, `liquidate` and the `...For` variants                      | `flag`, views, `applyDividend` from a pool                                                                                                                   |
| a MarketPool                           | `requestLiquidity`, `executeRequests`, `placeIssuerOrder`, `depositFromParent`, `withdrawToParent` | `cancelRequest` of an expired request, `settleIssuerOrder`, `refundStaleOrder`, `sweepDividends`, `sweepUsdPlus`, `syncInventory`, counterparty hooks, views |
| IndexVault                             | requests, `executeRequests`, `shift`                                                               | `cancelRequest` of an expired request; a paused child is skipped for routing and still valued                                                                |
| TradeRouter                            | `execute`, `setSubaccount`, `setSubaccountWithSig`                                                 | `removeSubaccount`                                                                                                                                           |
| TriggerBook                            | `set`, `setFor`, `execute`                                                                         | `flag`, `check`                                                                                                                                              |
| PriceFeed, InsuranceVault, PoolFactory | no pause flag                                                                                      | everything (the InsuranceVault's `cover` is role-gated; the factory is ADMIN-only)                                                                           |

Settlement and refund paths stay open under a pause on purpose: an order in flight at the issuer must still be able to land, and escrow must always be recoverable.

## Upgrades

| contract                                                                                      | proxy                                                             | who upgrades                                                           |
| --------------------------------------------------------------------------------------------- | ----------------------------------------------------------------- | ---------------------------------------------------------------------- |
| PriceFeed, InsuranceVault, IndexVault, PositionManager, PoolFactory, TradeRouter, TriggerBook | UUPS behind an `ERC1967Proxy`; `_authorizeUpgrade` requires ADMIN | the timelock                                                           |
| every MarketPool                                                                              | `BeaconProxy` pointing at one `UpgradeableBeacon`                 | the beacon's owner, the timelock: one upgrade moves every pool at once |
| AccessRegistry, Timelock                                                                      | none                                                              | not upgradeable                                                        |

Every upgradeable contract uses ERC-7201 namespaced storage and disables its initialisers in the constructor; fields added after the first deployment are appended below a marked line (the pool's `treasury` and `priceAsset`, the feed's `maxMarkAge`, the router's `triggerBook`). `MarketPool` keeps its issuer-order, dividend and split accounting in the `PoolOrders` library, delegate-called on the pool's own storage, to stay under the contract size limit; access control and reentrancy guards stay in the pool.

Addresses are deterministic: every contract is deployed with CREATE2 from one salt, and each pool from the keccak of its symbol, so a fresh chain lands the same system at the same addresses.

## The timelock

The timelock is an OpenZeppelin `TimelockController`. The production deployment (`Deploy.s.sol`) sets a 24 hour delay, one proposer (the multisig) and open execution (anyone may execute a matured proposal). The deployer holds ADMIN only during bootstrap and renounces it in the same script; afterwards the timelock is the only ADMIN. Local forks and staging deploy with a zero delay and keep a developer EOA as a second ADMIN so they can be reconfigured from a laptop; that EOA is `address(0)` in production.

An admin action is therefore: the multisig schedules the call on the timelock, the delay elapses, anyone executes it. This covers `setRole`, `setKyc`, unpausing, `setConfig` and `setWiring` on a pool, `setMarket` and `setRisk` on the PositionManager, `configure` and `setMaxMarkAge` on the feed, `setLimits` and `withdraw` on the insurance vault, `addChild`, `setWeights` and `setParams` on the index, `setPriorityWindow` on the TriggerBook, `setTriggerBook` on the router, `createPool`, and every upgrade.

## Treasury and the protocol fee switch

The platform's on-chain revenue is the **protocol fee**: `RiskConfig.protocolFeeBps` per market (1 000, that is 10 %) of every taker fee and of every borrow and funding leg, transferred to `PositionManager.treasury` on each settlement and emitted as `ProtocolFeePaid(pool, usdc)`. It is the fee switch: the timelock can set it per market with `setRisk`, and setting it above zero without a treasury address makes settlements revert `TreasuryUnset`, so it can never be switched on into the void. `setTreasury` is ADMIN-only. In production the treasury defaults to the multisig.

Alongside it, `insuranceFeeBps` (also 10 %) routes the same base to the insurance vault, and the pool keeps the remaining 80 %.

The other revenue line, a 10 bps fee on dShare purchases made through the terminal, is charged off-chain by the platform's order flow with the issuer and does not pass through these contracts.

Dividends are not revenue. Each pool also carries a `treasury` and a `dividendFeeBps` (the share of the net dividend the sweep would route to the treasury), which exists as a governance lever and is deployed at 0 everywhere, so the whole net dividend is pool NAV. See [Dividends](/protocol/dividends.md).

The insurance vault is protocol-owned: only ADMIN can `withdraw` from it. A pool's `skim(token, to)` lets ADMIN rescue a token that is not part of the pool's accounting; it refuses USDC, USD+, the pool's shares and the LP token.

## What the roles cannot do

* The keeper cannot set a price the feed's guards refuse, cannot move a request's escrow anywhere but back to its owner or into the pool at NAV, cannot place an order above the cap or below the reserve, and cannot liquidate a healthy position.
* The settler cannot book a fill more than 3 % from the mid, and its only path to the pool's assets is the escrow of an order it is settling.
* The router and the TriggerBook can act for an account but every payout goes to the account.
* The guardian can stop the system but cannot restart it, take funds or change anything.
* The factory can register a market but cannot change one that exists.


---

# 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 dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.jaawle.xyz/protocol/governance-and-roles.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
