> ## Documentation Index
> Fetch the complete documentation index at: https://docs.trusset.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Best Practices

> Operational guidance for deploying and managing stock tokens in production.

This page covers operational patterns, security considerations, and common pitfalls when running the Stock Token suite in production.

## Key Management

**Use a multi-sig for `DEFAULT_ADMIN_ROLE`.** The admin role controls all other role assignments. A compromised admin key means full control over the token. Deploy a Gnosis Safe with an appropriate threshold (e.g. 3-of-5) and assign it as the admin during initialization.

**Separate the legal operator.** `LEGAL_OPERATOR_ROLE` authorizes contract upgrades. Under eWpG, this must be a named legal entity. Use a dedicated multi-sig or institutional custody solution for this role - do not combine it with the issuer key.

**Rotate sub-issuer keys periodically.** Sub-issuers have minting authority. Even with caps in place, a compromised sub-issuer key can mint up to the cap limit. Rotate keys on a schedule that matches your risk tolerance, and set caps as tight as operationally feasible.

**Controller keys need strict access controls.** Controllers can freeze tokens and execute force transfers. These are high-impact regulatory actions. Store controller keys in hardware security modules (HSMs) or institutional custody with multi-party authorization.

## Sub-issuer Cap Strategy

Sub-issuer caps track *net outstanding* supply - tokens minted minus tokens redeemed by that sub-issuer. This means a sub-issuer who mints 1,000 and redeems 500 has 500 outstanding against their cap.

Set caps based on the sub-issuer's authorized issuance volume, not on total supply targets. If a sub-issuer needs to exceed their cap, the issuer must explicitly raise it via `setSubIssuerCap()`. This creates an auditable on-chain record of cap changes.

For multi-tranche offerings, assign each tranche a separate sub-issuer with a cap matching the tranche size. This prevents one tranche from accidentally over-issuing into another's allocation.

## Transfer Compliance Patterns

**Always pre-check with `canTransfer` in your frontend.** The function is a free `view` call off-chain and prevents users from submitting transactions that will revert. Display the human-readable `reason` string to the user so they understand why a transfer was blocked.

**Handle `SOFT_EXPIRED` KYC status proactively.** `SOFT_EXPIRED` does not block transfers, but it signals that the KYC provider should schedule a refresh. Monitor `KYCStatusChanged` events and trigger renewal workflows before the hard expiry blocks transfers entirely.

**Authorized contracts bypass all identity checks.** When you whitelist a contract via `addAuthorizedContract`, that contract can send and receive tokens without identity verification. Only whitelist contracts you control and have audited. Monitor the `AuthorizedContractAdded` event and maintain an inventory of authorized contracts with their purposes.

## Stock Split Operations

Stock splits are operationally complex because they require a complete holder list and affect dependent systems.

**Maintain an off-chain holder registry.** The contract does not store a list of holders. You must track this via `Transfer` events or your backend database. If any holder is omitted from the split call, their balance will not be adjusted, creating an inconsistency that requires manual correction.

**Pause dependent contracts before splitting.** Orderbooks, lending pools, and AMM pools that reference this token must be paused or notified before the split executes. After the split, update any cached price data, collateral valuations, or order quantities in those systems. Listen for the `StockSplit(numerator, denominator, newTotalSupply)` event as the coordination signal.

**Floor division creates dust.** The split calculation uses `(balance * numerator) / denominator` with floor division. For non-evenly-divisible balances, this means some holders may receive slightly less than the exact ratio. The issuer is responsible for handling these remainders off-chain if precision matters for the use case.

**Only forward splits are supported.** Reverse splits (where `numerator < denominator`) would destroy fractional shares due to integer division. If you need a reverse split, redeem all tokens and re-issue at the new ratio, or implement a custom migration contract.

## Freezing Tokens vs. Freezing Addresses

The suite provides two distinct freezing mechanisms that serve different purposes.

**Token-level freezing** (`StockToken.freezeTokens`) locks a specific amount of tokens on an account for a specific token. The holder retains their remaining transferable balance. Use this for partial holds, pledged collateral, or regulatory liens on specific positions.

**Address-level freezing** (`IdentityRegistry.freezeAddress`) blocks all transfers for that identity across every token using the same registry. Use this for full compliance freezes, AML investigations, or sanctions enforcement.

Both mechanisms can be active simultaneously. A holder can have 500 tokens frozen at the token level and still be unfrozen at the identity level - or vice versa. Your compliance workflow should account for both states when determining what actions a holder can take.

## Force Transfer Considerations

Force transfers (`forceTransfer`) are regulatory-grade actions. The recipient must be identity-verified even for forced transfers - this prevents using force transfer as a backdoor to move tokens to unverified addresses.

If the sender has frozen tokens, the frozen amount is reduced by the transfer amount (or to zero if the transfer exceeds the frozen amount). This means a force transfer can "consume" a regulatory hold. Document this behavior in your compliance procedures so auditors understand the interaction.

## Upgrade Safety

Contract upgrades require `LEGAL_OPERATOR_ROLE` authorization. Before upgrading:

1. Deploy the new implementation to a test environment and run your full test suite.
2. Verify the storage layout is compatible with the existing proxy. UUPS proxies will brick if the storage layout changes incompatibly.
3. Have the upgrade reviewed by your security auditor.
4. Execute the upgrade through the legal operator multi-sig with appropriate governance approval.

<Warning>
  A bricked proxy (from an incompatible storage layout) permanently locks all tokens. Use OpenZeppelin's upgrade safety tooling to validate storage compatibility before every upgrade.
</Warning>

## Compliance Module Deployment

The `BasicComplianceModule` is controlled by the token contract address via the `onlyToken` modifier. This means compliance configuration calls must originate from the token contract itself. If your deployment needs the issuer to configure compliance rules directly, you will need either a governance proxy pattern or wrapper functions on the token contract that forward calls to the module.

When setting holding limits, consider that the maximum holding check applies to the recipient's balance *after* the transfer. A recipient at 99,000 tokens with a 100,000 cap can only receive 1,000 more tokens. Set limits with headroom for operational flexibility.

Lockup periods are absolute timestamps, not durations. When setting a lockup, calculate the Unix timestamp for the desired expiry. A lockup set to a timestamp in the past will revert.

## Monitoring and Alerting

At minimum, monitor these events in production:

| Event                                           | Alert priority | Action                                                     |
| ----------------------------------------------- | -------------- | ---------------------------------------------------------- |
| `StockSplit`                                    | High           | Notify dependent systems, verify all holders were included |
| `ForceTransfer`                                 | High           | Log for regulatory audit trail, notify compliance team     |
| `TokensFrozen` / `TokensUnfrozen`               | Medium         | Update compliance dashboard                                |
| `AddressFrozen` / `AddressUnfrozen`             | Medium         | Update compliance dashboard, notify affected holder        |
| `IdentityRevoked`                               | Medium         | Check for outstanding token positions that need resolution |
| `KYCStatusChanged` to `SOFT_EXPIRED`            | Low            | Trigger KYC renewal workflow                               |
| `KYCStatusChanged` to `HARD_EXPIRED`            | Medium         | Holder can no longer transfer, escalate to KYC provider    |
| `SubIssuerCapUpdated`                           | Low            | Audit trail for cap changes                                |
| `BatchIssueCompleted` where `processed < total` | Medium         | Retry remaining recipients                                 |

## Gas Optimization

Batch operations (`batchIssue`, `batchVerifyIdentities`) include gas-aware early termination. If gas drops below the minimum threshold per item, processing stops and the function returns the count of successfully processed entries. Always check the return value and retry remaining items in a follow-up transaction.

For `batchIssue`, the maximum batch size is 200 recipients with a minimum gas reserve of 80,000 per item. For `batchVerifyIdentities`, the maximum is 500 entries with 50,000 per item. Size your batches based on your target chain's block gas limit.
