> 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/factory-contract.md).

# Factory Contract

Deploys and registers vault contracts. Validates all parameters against the Globals contract before deployment.

**Source:** `contracts/factory/`

## Source Modules

| File          | Purpose                                                                                                  |
| ------------- | -------------------------------------------------------------------------------------------------------- |
| `contract.rs` | Constructor, `set_vault_wasm_hash`, `create_vault`, queries, inline `GlobalsClient` and mirrored structs |
| `storage.rs`  | Data keys (globals, wasm\_hash, 3-index vault registry), getters/setters, pagination                     |
| `errors.rs`   | `#[contracterror]` enum (11 variants)                                                                    |
| `events.rs`   | `VaultDeployed`, `WasmHashUpdated` events                                                                |
| `test.rs`     | 3 tests                                                                                                  |

## How It Works

1. Governor deploys the Factory with a Globals address and an initial vault WASM hash.
2. When a Pool Manager calls `create_vault(params, salt)`, the factory:
   * Validates the manager is approved and active (via `GlobalsClient::list_pool_managers`)
   * Checks the manager is **not delinquent** (`is_delinquent` — blocked if any vault defaulted)
   * Checks the manager's **credit limit** (`outstanding + principal ≤ max_credit`)
   * Validates the lending token is whitelisted (`get_supported_assets`)
   * Validates interest rate, loan term, principal, and split ratio against `get_global_settings`
   * Checks the manager has enough **available collateral** (`principal × default_collateral_ratio / 100`)
   * **Locks manager collateral** via `GlobalsClient::lock_collateral`
   * **Increments outstanding principal** via `GlobalsClient::increment_outstanding`
   * Deploys a new vault using `e.deployer().with_current_contract(salt).deploy_v2(wasm_hash, (globals, params))`
   * **Registers the vault in Globals** via `GlobalsClient::register_vault` (so the vault is authorised for cross-contract calls), then in three Factory indexes: all vaults, per-manager, per-borrower
3. The governor can update the vault WASM hash via `set_vault_wasm_hash` (for future vault template upgrades).

{% hint style="warning" %}
`create_vault` calls back into Globals (`lock_collateral`, `increment_outstanding`, `register_vault`). These require the Factory to be registered in Globals via `set_factory` first — otherwise the calls fail. See [Deployment](/technical-documentation/deployment.md).
{% endhint %}

## Functions

### Constructor

```
__constructor(governor, globals, vault_wasm_hash)
```

Initialise the factory with admin (`governor`), Globals reference, and the vault template hash.

### Admin Actions (`#[only_admin]`)

| Function                           | Description                                 |
| ---------------------------------- | ------------------------------------------- |
| `set_vault_wasm_hash(new_hash)`    | Update the vault WASM template              |
| `upgrade(new_wasm_hash, operator)` | Upgrade the Factory (auth via stored admin) |

### Vault Creation

| Function                                  | Description                                                          |
| ----------------------------------------- | -------------------------------------------------------------------- |
| `create_vault(params: VaultParams, salt)` | Deploy a new vault with full validation; returns the vault `Address` |

**VaultParams (15 fields):**

```rust
VaultParams {
    manager: Address,
    borrower: Address,
    lent_token: Address,
    principal: i128,
    interest_rate: u32,
    loan_term: u32,
    split_ratio: u32,
    permissioned: bool,
    grace_period: u64,
    funding_deadline: u64,
    approval_deadline: u64,
    collateral_escrow: Option<Address>,   // None = manager-collateral-only loan
    collateral_token: Option<Address>,    // asset the borrower must pledge
    collateral_recovery: Option<Address>, // receives the pledge on default
    collateral_min: i128,                 // on-chain floor the pledge must meet
}
```

{% hint style="info" %}
The four borrower-collateral fields are optional in effect: leave `collateral_escrow` as `None` (and the others empty / `0`) for a manager-collateral-only loan. If `collateral_escrow` is `Some`, the vault constructor asserts `collateral_token`, `collateral_recovery`, and a positive `collateral_min` are all present.
{% endhint %}

### Queries

| Function                                           | Returns                                             |
| -------------------------------------------------- | --------------------------------------------------- |
| `get_globals()`                                    | Globals contract address                            |
| `get_vault_wasm_hash()`                            | Current vault template hash                         |
| `get_vault_count()`                                | Total deployed vaults (O(1))                        |
| `get_all_vaults()`                                 | First 100 vault addresses (use pagination for more) |
| `get_vaults_page(start, limit)`                    | A page of vault addresses                           |
| `get_manager_vaults(manager)`                      | First 100 vaults for a manager                      |
| `get_manager_vaults_page(manager, start, limit)`   | A page of a manager's vaults                        |
| `get_manager_vault_count(manager)`                 | Number of vaults for a manager                      |
| `get_borrower_vaults(borrower)`                    | First 100 vaults for a borrower                     |
| `get_borrower_vaults_page(borrower, start, limit)` | A page of a borrower's vaults                       |
| `get_borrower_vault_count(borrower)`               | Number of vaults for a borrower                     |

{% hint style="info" %}
The registry is stored as indexed persistent entries with an O(1) count, avoiding Soroban's object-size limit. `get_all_vaults` / `get_manager_vaults` / `get_borrower_vaults` cap at **100**; use the `_page` variants for larger sets.
{% endhint %}

## Validation Checks

The Factory performs extensive validation before deploying a vault. Error codes are from the **Factory** error enum (`contracts/factory/src/errors.rs`):

| Check             | Error Code                   | Description                                   |
| ----------------- | ---------------------------- | --------------------------------------------- |
| Manager approved  | `ManagerNotApproved (1)`     | Manager must be active in Globals             |
| Asset whitelisted | `AssetNotSupported (2)`      | Token must be whitelisted in Globals          |
| Interest rate     | `InvalidRate (3)`            | Must be within global min/max                 |
| Loan term         | `InvalidTerm (4)`            | Must be within global min/max                 |
| Principal         | `InvalidPrincipal (5)`       | Must be `> 0` and within global min/max       |
| Split ratio       | `InvalidSplitRatio (6)`      | Must be 1–99                                  |
| WASM hash set     | `WasmHashNotSet (7)`         | Vault template hash must be configured        |
| Authorised        | `Unauthorized (8)`           | Caller not authorised                         |
| Collateral        | `InsufficientCollateral (9)` | Manager must have enough available collateral |
| Not delinquent    | `ManagerDelinquent (10)`     | Manager must have no uncleared defaults       |
| Credit limit      | `CreditLimitExceeded (11)`   | `outstanding + principal ≤ max_credit`        |

## Events

| Event             | Key Fields                                                                | When             |
| ----------------- | ------------------------------------------------------------------------- | ---------------- |
| `VaultDeployed`   | `vault`, `manager`, `borrower`, `principal`, `loan_term`, `interest_rate` | Vault created    |
| `WasmHashUpdated` | `old_hash`, `new_hash`                                                    | Template updated |
