# Manager Contract

`contracts/Manager.sol` is the coordination hub for the exchange. It wires together access control, canonical OrderBook registration, taker-fee plumbing, token policy checks, and emergency tooling. When the contracts evolve, this is usually the first place that needs configuration tweaks.

## Contract Snapshot

* **Scope** – registers OrderBooks only after a normalized bytecode proof and parameter sanity checks, keeps a canonical pointer plus append-only pair history, and exposes discovery helpers.
* **Roles** – `DEFAULT_ADMIN_ROLE` manages admins, `ADMIN_ROLE` handles day-to-day ops, `PAUSER_ROLE` pauses books, and `FACTORY_ROLE` lets trusted factories register books. Admins implicitly inherit pauser powers.
* **Fees** – taker-only model with two layers: a global default and per-book rates. OrderBooks cache the rate pushed from Manager; there are no user-specific tiers.
* **Normalization** – expected normalized runtime hash and mask windows must be set; opcode spot checks and minimum runtime size are optional when configured. There is no bypass and no registration fee surface.
* **Token policies** – admin-gated token whitelist for registration plus a per-quote `minQuoteAmount` map that seeds OrderBooks.
* **Operations** – fee collector assignments, registry pagination, batch pause/unpause helpers, and an admin-facing `configureOrderBook` wrapper over `syncSettings`.

## Access Control

```
                    DEFAULT_ADMIN_ROLE 
                (role administration only)
                  /                     \
                 /                       \
         ADMIN_ROLE                     FACTORY_ROLE    
(ops, fee config, registry)    (register books when delegated)            
              |
              |
         PAUSER_ROLE
   (pause/unpause batches)
```

* `hasOrderBookRole(role, account)` remains the single source of truth for OrderBooks when they delegate access checks back to Manager.
* The constructor grants the deployer admin+pauser, gives `DEFAULT_ADMIN_ROLE` to the governance address, and grants `PAUSER_ROLE` to the Manager itself so it can batch pause books later.
* `FACTORY_ROLE` can register books but cannot mutate configuration and cannot replace an existing pair (only admins can upsert). Its admin is `DEFAULT_ADMIN_ROLE` (factories do not inherit from admin/pauser).

## Taker Fee Configuration

Only taker fees are charged across the protocol. The pricing surface is two layers, both expressed in parts-per-1e6 (`FEE_DENOM = 1_000_000`, max `MAX_FEE = 5,000` = 0.5%). Makers always pay zero; there are no user-specific tiers.

**Layer 1 – Default rate**

```solidity
uint256 public takerFee;
function setDefaultFees(uint256 takerFee_) external onlyAdminRole
```

* Constructor emits `DefaultFeesUpdated(0, initialTakerFee)`. The legacy `FeesUpdated` alias was removed.
* `setDefaultFees` is guarded by `MAX_FEE`.

**Layer 2 – Per-book override**

```solidity
mapping(address => uint256) public orderbookTakerFeeRates;
mapping(address => bool) private _orderbookFeesInitialized;

function setFees(address orderbook, uint256 takerFeeRate) external onlyAdminRole;
function setFeesBatch(address[] calldata orderbooks, uint256[] calldata takerFeeRates) external onlyAdminRole;
event OrderbookFeesSet(address indexed orderbook, uint256 takerFeeRate);
```

* Book must already be registered; `_setOrderbookFees` reverts otherwise. Registration seeds each new market with the current default and syncs it immediately.
* Batched updates revert if array lengths mismatch; clearing an override is just setting it back to the default.
* Every successful update calls `IOrderBookCore.syncSettings(4, 0, 0, rate)` so the runtime cache refreshes before the next taker fill.

**Retrieval and caching**

```solidity
// OrderBook constructor
uint256 takerFee = manager.getTakerFeeRate(address(this));

// Manager pushes updates
IOrderBookCore(orderbook).syncSettings(4, 0, 0, newRate);
```

`getTakerFeeRate` returns the per-book override when initialised, otherwise the default. There is no user parameter; SDKs should drop trader-specific fee lookups. Runtime matching uses the OrderBook’s cached `takerFeeRateCached`, which Manager refreshes via `syncSettings(4, ...)`.

**Worked examples (all under the 0.5% cap)**

* Single global rate: `setDefaultFees(4_000)` → 0.4% everywhere.
* Promo market: `setFees(BTC_USDC, 2_000)` while the default stays 4,000 → 0.2% for that pair only.
* Coordinated update: `setFeesBatch([BTC_USDC, ETH_USDC], [3_000, 4_500])` → 0.3% and 0.45%.

## Fee Configuration Helpers

* `setDefaultFees(uint256 takerFee)` – updates the protocol default (0–5,000 in the 1e6 denominator, i.e., up to 0.5%).
* `setFees(address orderbook, uint256 takerFee)` – pins a single market’s rate (validated against `MAX_FEE` = 5,000) after the book is registered.
* `setFeesBatch(address[] orderbooks, uint256[] takerFees)` – configure several books at once (lengths must match; each book must already be registered).
* `setFeeCollector(address feeCollector)` – updates the treasury sink that receives taker fees.
* `configureOrderBook(orderbook, mask, newTickSize, newMinQuote, newTakerFeeRate)` – admin helper that forwards directly to the OrderBook’s `syncSettings` bitmask.

## OrderBook Registration

OrderBook registration is always role-gated (admin or factory) and fully normalized:

1. **Access gate** – only `ADMIN_ROLE` or `FACTORY_ROLE` may call. Factories cannot replace an existing pair; admins can upsert.
2. **Payment guard** – `msg.value` must be zero. There is no registration fee surface.
3. **Input validation** – non-zero, distinct base/quote; non-zero candidate address; both base and quote must already be whitelisted via `whitelistToken`.
4. **Normalization proof** – `expectedNormalizedBytecodeHash` and a non-empty `normalizationMask` must be set. `normalizationOpcodeChecks` and `normalizationMinRuntimeBytecodeSize` are optional; they are enforced only when configured. The deployed runtime is normalized and hashed; mismatches revert. There is no bypass path.
5. **Parameter sanity** – the candidate OrderBook must report the expected base token, quote token, manager address, `pricePrecision` (`1e18`), and taker-fee denominator (`FEE_DENOM`).
6. **Registry update** – canonical pointer is updated, global catalogue dedupes entries, and per-pair history appends the deployment. `_setOrderbookFees` seeds the taker rate and immediately syncs it to the book.

Discovery helpers: `getOrderBookAddress`, `getPairOrderBooks`, `getPaginatedOrderBookAddresses`, `getAllOrderBooksLength`, and `getOrderBookId`.

## Token Policies

* `whitelistToken(address token)` / `revokeToken(address token)` (admin/default admin) gate which assets can be used as base/quote during registration. Both sides must be whitelisted or registration reverts with `Manager__TokenNotWhitelisted`.
* `setQuoteTokenMinAmount(address token, uint256 minQuoteAmount)` sets the dust floor that new OrderBooks cache for that quote asset.

## Emergency Controls

* `pauseOrderBooksBatch(startIndex, count)` and `unpauseOrderBooksBatch(...)` work over slices of `allOrderBooks`, swallowing per-book failures and returning the addresses that actually changed state.
* There is no admin bypass for normalization; register only canonical bytecode.

## Manager Events

```solidity
event DefaultFeesUpdated(uint256 oldTakerFee, uint256 newTakerFee);
event FeeCollectorUpdated(address oldCollector, address newCollector);
event ExpectedNormalizedBytecodeHashSet(bytes32 oldHash, bytes32 newHash);
event NormalizationMaskUpdated(uint32[] offsets, uint32[] lengths);
event NormalizationMinRuntimeBytecodeSizeSet(uint32 oldSize, uint32 newSize);
event NormalizationOpcodeChecksUpdated(uint32[] offsets, uint8[] opcodes);
event OrderbookFeesSet(address indexed orderbook, uint256 takerFee);
event OrderBookRegistered(bytes32 indexed pairHash, address indexed baseToken, address indexed quoteToken, address orderBook);
event OrderBookAdded(bytes32 indexed pairHash, address indexed orderBook);
event QuoteTokenMinAmountUpdated(address indexed token, uint256 oldAmount, uint256 newAmount);
event TokenWhitelisted(address indexed token);
event TokenUnwhitelisted(address indexed token);
event OrderBooksPausedBatch(address indexed pauser, uint256 startIndex, uint256 endIndex, address[] pausedAddresses);
event OrderBooksUnpausedBatch(address indexed pauser, uint256 startIndex, uint256 endIndex, address[] unpausedAddresses);
```

## Integration Points

* **OrderBooks** rely on `hasOrderBookRole`, `getTakerFeeRate`, pause helpers, and `getQuoteTokenMinAmount`.
* **Front-ends & indexers** usually:
  1. Subscribe to the events above (especially `DefaultFeesUpdated`, `OrderbookFeesSet`, whitelist changes, normalization updates, and pause events).
  2. Poll `getTakerFeeRate(orderbook)` to surface live fees.
  3. Mirror the registry using `getOrderBookAddress` / `getPairOrderBooks` for discovery.

### Removed Features

* Public registration, admin normalization bypasses, and fee-on-register flows are gone; every registration must prove the normalized runtime hash.
* User-specific fee tiers (percentage multipliers and absolute discounts) are absent. Only global and per-market rates remain.
* Maker fees, maker rebates, and maker-focused discount machinery are absent; makers always pay zero.
* There is no per-user self-trade prevention surface in the contracts; STP must be handled off-chain.


---

# Agent Instructions: 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:

```
GET https://dbookio.gitbook.io/dbook/technical-documentation/manager-contract.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
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.
