> 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 |


---

# 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.trilobyte.finance/technical-documentation/factory-contract.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.
