> For the complete documentation index, see [llms.txt](https://docs.trilobyte.finance/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.trilobyte.finance/technical-documentation/compliance-allowlist-contract.md).

# Compliance Allowlist Contract

A simple, admin-maintained implementation of the protocol's optional compliance-gate interface. See [Covenants, Exposure and Compliance](/protocol-mechanics/covenants-exposure-and-compliance.md) for how and where the gate is checked.

**Source:** `contracts/compliance-allowlist/`

## Overview

Globals can optionally hold a `compliance_gate: Option<Address>` pointing at any contract that implements a single function, `is_allowed(who: Address, action: u32) -> bool`. `ComplianceAllowlist` is the first, simplest such implementation — an admin grants or revokes each address's permission for each action directly. It is deployed standalone; Globals points at it via `set_compliance_gate` (or leaves the gate unset, in which case every check passes).

Because the interface is just one function, the allowlist can later be swapped for a different implementation — for example, a KYC-token contract minted on Sumsub approval — without touching the Vault or Factory. Only the address Globals points at changes.

## Actions

| Code | Action   | Checked by | When                                            |
| ---- | -------- | ---------- | ----------------------------------------------- |
| 0    | `Invest` | Vault      | Before `deposit`, for the investor              |
| 1    | `Borrow` | Vault      | Before `approve_and_disburse`, for the borrower |
| 2    | `Manage` | Factory    | Before `create_vault`, for the manager          |

`is_allowed` returns `false` for an out-of-range action rather than trapping, since it's called from other contracts as a plain boolean gate — a caller doesn't need to know every valid action code in advance to safely call it.

## Functions

| Function        | Signature                                                | Auth  | Description                                                                                            |
| --------------- | -------------------------------------------------------- | ----- | ------------------------------------------------------------------------------------------------------ |
| `set_allowed`   | `set_allowed(who, action, allowed) -> Result<(), Error>` | Admin | Grant or revoke `who`'s permission for `action`. Fails with `InvalidAction` on an out-of-range action. |
| `is_allowed`    | `is_allowed(who, action) -> bool`                        | —     | The compliance-gate interface itself.                                                                  |
| `upgrade`       | `upgrade(new_wasm_hash, operator)`                       | Admin | Standard OZ admin-authorised upgrade.                                                                  |
| `__constructor` | `__constructor(admin)`                                   | —     | Deploy with an admin who can grant/revoke entries.                                                     |

## Events

| Event              | Key Fields                 | When                           |
| ------------------ | -------------------------- | ------------------------------ |
| `AllowlistUpdated` | `who`, `action`, `allowed` | An entry is granted or revoked |

## Error Codes

| Code | Name            | Description                                                                  |
| ---- | --------------- | ---------------------------------------------------------------------------- |
| —    | `InvalidAction` | The action code is not one of `0` (`Invest`), `1` (`Borrow`), `2` (`Manage`) |

## Default-deny

Every `(who, action)` pair defaults to `false` (not allowed) until explicitly granted — there is no implicit allow, and no global "allow everyone" switch other than **unsetting** the gate entirely in Globals (which bypasses this contract altogether, not something it exposes itself).

{% hint style="info" %}
On testnet, `ComplianceAllowlist` is deployed but **not** wired into Globals — `Globals.set_compliance_gate` is left as a deliberate, separate governance action once the allowlist has real entries. See [Testnet Deployment](/technical-documentation/testnet-deployment.md).
{% endhint %}

*As of September 2026.*
