Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Templar Protocol User Guide

This is a comprehensive user guide for the Templar Protocol smart contracts.

Templar is an overcollateralized lending protocol. Each market is an isolated, immutable smart contract that pairs one collateral asset with one borrow asset. Collateral held on other chains (Bitcoin, Ethereum, Stellar, XRP, Solana, and more) reaches NEAR through NEAR Intents, and curated vaults on Stellar route depositor liquidity into markets.

For definitions of key terms and concepts, refer to the Glossary.

Quick Navigation

Market Operations

Additional Resources

Architecture Overview

Templar is an overcollateralized lending protocol whose markets run on NEAR. Collateral and borrow assets that live on other chains reach those markets through NEAR Intents, prices reach them through proxy oracles that aggregate independent providers, and depositors on Stellar reach them through curated vaults. This page shows how the pieces fit together and what each external dependency is trusted to do.

System Map

                 Users, wallets, integrators
                            |
          +-----------------+------------------+
          |                                    |
   app.templarfi.org                    Gateway (JSON-RPC)
   (frontend)                           Relayer (gasless txs)
          |                                    |
          +-----------------+------------------+
                            v
 NEAR ..........................................................................
 :                                                                            :
 :   intents.near  (NEP-245 multi-token balances of bridged assets)           :
 :        |  deposits / withdrawals via NEAR Intents                          :
 :        v                                                                   :
 :   Registry v1.tmplr.near --deploys--> Markets <pair>.v1.tmplr.near         :
 :        |                                  |  reads prices                  :
 :        |                                  v                                :
 :        +-------deploys-------> Proxy oracle proxy-oracle-<pair>            :
 :                                   ^   ^   |  owned by                      :
 :            Pyth Lazer adapter ----+   |   v                                :
 :            RedStone adapter ----------+  Governance proxy-gov-<pair>       :
 :            Pyth (classic) -------------+  (timelocked; Admin = DAO)        :
 :            LST oracle adapter ---------+         ^                         :
 :                                                  |                         :
 :                            DAO multisig templar.sputnik-dao.near (2-of-3)  :
 :............................................................................:

 Stellar .......................................................................
 :                                                                            :
 :   Depositor --> ERC-4626 proxy --> Vault runtime --> Adapters --> Markets   :
 :                                     |   ^              (Blend pool,        :
 :                          Share token |   | Governance    custodial route)   :
 :                          (SEP-41)    v   | + Sentinel                      :
 :                                   Curator proxy                            :
 :............................................................................:

 Off-chain services: liquidator, accumulator, market-monitor, redstone-bridge,
 relayer, gateway, funding-bridge, plus Hypernative and custom alerting.

Components

NEAR contracts

ComponentRoleMutabilityMore
Registry v1.tmplr.nearHolds audited contract versions and deploys markets and proxy oracles as its sub-accounts; records each deployment's version key and code hash.Owned by the DAO multisig; can register versions and upgrade itself, cannot touch deployed contracts.Governance
Markets <collateral>-<borrow>[-n].v1.tmplr.nearOne collateral asset, one borrow asset, one contract. Supply, borrow, repay, withdraw, liquidate; interest accrual through periodic snapshots.No admin methods, no upgrade, no pause. Parameters fixed at deployment.Risk Parameters, Security
Proxy oracles proxy-oracle-<market>Aggregate Pyth Lazer, Pyth classic, RedStone, and LST-transformer sources per feed with freshness filters, weighted medians, and circuit breakers; the market's only price input.Configurable and upgradeable through its governance contract.Oracles
Proxy oracle governance proxy-gov-<market>Timelocked owner of a proxy oracle; every configuration or code change is a maturing proposal. Breaker operation is immediate in both directions: ManualTripper can trip or untrip a feed and CircuitBreakerOperator can re-arm a breaker and enable or disable enforcement with no delay, so untripping, re-arming, and disabling enforcement are zero-delay risk-increasing actions, held by the DAO multisig and alerted.Admin role held by the DAO multisig.Governance
Oracle adapters pyth-lazer.v1.tmplr.near, redstone-adapter.v1.tmplr.near, lst.oracle.tmplr.nearVerify provider signatures and serve prices to proxy oracles. pyth-oracle.near is Pyth's own contract.Owned; signer sets are admin-managed by the DAO multisig.Oracle Addresses
DAO multisig templar.sputnik-dao.near2-of-3 Sputnik DAO that administers every mutable NEAR component.Signer changes are themselves DAO proposals.Administrative Multisig

Stellar vault stack

A curated vault is a set of Soroban contracts: the vault runtime (custody, accounting, withdrawal queue, roles), a share token (SEP-41), a governance contract (per-action timelocks, Sentinel), an ERC-4626 proxy (the depositor-facing interface), a curator proxy, and one adapter per market route (a Blend pool adapter or a custodial adapter). The runtime and the proxy oracle share chain-agnostic Rust kernels with their NEAR counterparts, so the accounting logic is written and verified once. See Stellar Curated Vaults and the Curator Guide.

Off-chain services

None of these hold a privileged key over a market. They provide liveness and convenience; if all of them stopped, users could still interact with every contract directly.

ServicePurpose
GatewayJSON-RPC API for integrators in front of the contracts; see API Reference.
RelayerRelays signed delegate actions and pays their gas, so accounts without NEAR can transact.
LiquidatorScans positions and liquidates undercollateralized ones. Liquidation is permissionless and is carried out primarily by third-party liquidation bots; this is Templar's own liquidator, one participant among them, not the only one.
AccumulatorApplies interest to borrow positions by triggering market snapshots.
Market monitorPosition-health scanning with alerts to the public channel; part of monitoring.
RedStone bridgeDelivers signed RedStone price payloads to the RedStone adapter.
Funding bridgeTreasury operations across chains through the NEAR Intents bridge API.

Flows

How cross-chain collateral reaches a market

  1. A user deposits an asset on its home chain (Bitcoin, Ethereum, Stellar, XRP Ledger, Solana, and others) through NEAR Intents. The bridged balance is credited to the user on intents.near as a NEP-245 multi-token.
  2. Native-chain assets are represented as <chain>.omft.near tokens (for example btc.omft.near, eth-0xa0b8….omft.near for USDC on Ethereum). The full identifiers for Stellar-origin assets (XLM, USDC on Stellar, PYUSD, deJAAA, deJTRSY, SolvBTC, CETES, USTRY) are on Risk Parameters.
  3. The user transfers the token from their intents.near balance to the market with a mt_transfer_call; the market records the collateral (or supply) position. Markets never custody assets on other chains; everything they hold is a NEP-245 balance on NEAR.
  4. Withdrawals reverse the path: the market transfers the token back to the user's intents.near balance, and NEAR Intents settles it to the destination chain.

Borrowing, repayment, and liquidation

  1. Before a price-dependent operation (borrow, collateral withdrawal against debt, liquidation), the caller or a bot refreshes the market's proxy oracle. The proxy pulls fresh prices from its sources, filters stale ones, aggregates, runs circuit-breaker checks, and caches the accepted price.
  2. The market reads the accepted price with a freshness bound (price_maximum_age) and applies its immutable collateralization rules; see Risk Parameters.
  3. If a position falls below the liquidation MCR, any account may repay part of its debt and receive collateral at up to the market's maximum liquidation spread.
  4. Supply withdrawals, repayments, and collateral withdrawals from debt-free positions never depend on the oracle, so user exits survive an oracle outage or a tripped breaker.

How Stellar deposits reach markets

  1. A depositor deposits USDC (or another supported asset) into a vault's ERC-4626 proxy on Stellar and receives shares.
  2. The curator's allocation policy, within governance-approved caps, directs allocators to supply pooled assets into market routes through the vault's adapters.
  3. Yield accrues to external_assets and is reflected in the share price. Withdrawals are paid from idle liquidity or, through the withdrawal queue, after allocators recall liquidity from markets. See Stellar Curated Vaults.

Trust Assumptions

DependencyWhat Templar relies on it forWhat it cannot doAssurance
NEAR Intents (intents.near)Chain Signatures MPC-based smart contract custody of collateral and borrow assets while they are on NEAR; settlement of deposits and withdrawals to other chains.It has no role in market logic; a market's balances are NEP-245 entries it cannot reprice.Audited independently (Hacken, Guvenkaya, zkSecurity, Aurora Labs); see Dependency Audits. Status: status.near-intents.org.
Omnibridge and Chain SignaturesThe bridging and MPC signing behind NEAR Intents transfers. Separately, the Chain Signatures contract (v1.signer) can hold a derived full-access key on an operational account whose owner has installed one; it signs for that account only when the administering DAO approves a proposal asking it to (see DAO-approved MPC signing).Cannot act on Templar contracts on its own: it never holds a market, registry, or vault key, and a derived key signs nothing without an executed DAO proposal naming the exact payload hash.Omnibridge and NEAR One MPC audits in the same folder.
Pyth (Lazer and classic)Signed price updates for most feeds; the higher-weighted source in the standard configuration.Cannot bypass the freshness filter or the circuit breakers; a single stale or blocked source reads as no price rather than a wrong one.Signer sets verified on chain by the adapter; provider status at status.pyth.network.
RedStoneSigned price updates; the second source in the standard configuration and the sole source for some fundamental-value feeds.As above.Signer threshold verified on chain by the adapter.
Blend (Stellar)Lending venue behind Blend-adapter vault routes.Cannot affect NEAR markets; exposure is limited by the vault's caps.Blend's own audits; Templar's adapter is in the Halborn vault audit scope.
Custodians (custodial adapter routes)Off-chain deployment of vault assets and reporting of their value.Reporting is bounded by nonce and expected-value checks; exposure is capped per route.Out of scope of the Halborn vault audit; each route's controls are documented by the curator.
Templar's own botsLiveness: price refreshes, interest accrual, alerts, and a backstop liquidator. Liquidations are permissionless and are run primarily by third-party bots, not only by Templar.Hold no privileged role; every action they take is permissionless and can be performed by anyone.Monitored; see Monitoring and Risk Management.
DAO multisig signersGovernance of proxy oracles, adapters, the registry, and retained deployer keys.Cannot change a market's parameters or move user funds through any contract method; storage patches are limited to accounts whose deployer key is still retained.2-of-3 threshold, timelocked proposals, alerted actions; see Governance.

Historical design diagrams and papers are available in the public Templar-Protocol/architecture repository. That repository is somewhat outdated; use this guide, the current contract source, and deployed configuration as the authoritative description of the current system.

Smart Contracts

Market

A single Templar market represents a pair of collateral and borrow assets, such as BTC/USDC for Bitcoin-collateralized USDC loans.

Suppliers may deposit borrow assets into the market, and their funds will earn yield from the protocol fees paid by borrowers. Borrowers may borrow available supply assets from the market, paying a variable interest rate based on the supply utilization rate.

Markets support NEAR fungible asset contracts implementing the NEP-141 standard or the NEP-245 standard. The borrow and collateral assets do not need to implement the same standard.

Storage Management

Before interacting with a market (supplying, borrowing, depositing collateral, etc.), accounts must first register with the market contract by making a storage deposit. This is required because the market contract implements NEP-145 (Storage Management) to cover the storage costs of maintaining user positions on-chain.

Making a Storage Deposit

To register with a market and deposit the required storage cost:

near contract call-function as-transaction \
    <market-id> storage_deposit \
    json-args '{}' \
    prepaid-gas '10.0 Tgas' \
    attached-deposit '0.00125 NEAR' \
    sign-as <account-id>

The minimum required deposit can be obtained by calling the storage_balance_bounds function:

near contract call-function as-read-only \
    <market-id> storage_balance_bounds \
    json-args '{}' \
    network-config mainnet \
    now

Note: This storage deposit step is handled automatically in the Templar frontend application, but must be done manually when interacting directly with the market contracts.

Interactions

Accounts can interact with markets in seven primary ways:

  1. Deposit supply
  2. Withdraw supply
  3. Deposit collateral
  4. Withdraw collateral
  5. Borrow supply
  6. Repay supply
  7. Liquidate borrow position

Configuration

A market's configuration is immutable after deployment. It can be obtained from the market contract by calling the get_configuration function.

Example

near contract \
    call-function as-read-only ibtc-usdc.v1.tmplr.near get_configuration \
    json-args {} \
    network-config mainnet \
    now
Output
{
  "borrow_asset": {
    "Nep141": "17208628f84f5d6ad33f0da3bbbeb27ffcb398eac501a31bd6ad2011e36133a1"
  },
  "borrow_asset_maximum_usage_ratio": "0.99000000000000000000000000000000000001",
  "borrow_interest_rate_strategy": {
    "Piecewise": {
      "base": "0",
      "optimal": "0.90000000000000000000000000000000000001",
      "rate_1": "0.08888888888888888888888888888888888889",
      "rate_2": "2.40000000000000000000000000000000000001"
    }
  },
  "borrow_maximum_duration_ms": null,
  "borrow_mcr_liquidation": "1.19999999999999999999999999999999999999",
  "borrow_mcr_maintenance": "1.25",
  "borrow_origination_fee": {
    "Proportional": "0.00099999999999999999999999999999999999"
  },
  "borrow_range": {
    "maximum": null,
    "minimum": "1"
  },
  "collateral_asset": {
    "Nep245": {
      "contract_id": "intents.near",
      "token_id": "nep141:btc.omft.near"
    }
  },
  "liquidation_maximum_spread": "0.05000000000000000000000000000000000001",
  "price_oracle_configuration": {
    "account_id": "pyth-oracle.near",
    "borrow_asset_decimals": 6,
    "borrow_asset_price_id": "eaa020c61cc479712813461ce153894a96a6c00b21ed0cfc2798d1f9a9e9c94a",
    "collateral_asset_decimals": 8,
    "collateral_asset_price_id": "e62df6c8b4a85fe1a67db44dc12de5db330f7ac66b72dc658afedf0f4a415b43",
    "price_maximum_age_s": 60
  },
  "protocol_account_id": "revenue.tmplr.near",
  "supply_range": {
    "maximum": null,
    "minimum": "40000"
  },
  "supply_withdrawal_fee": {
    "behavior": "Fixed",
    "duration": "0",
    "fee": {
      "Flat": "0"
    }
  },
  "supply_withdrawal_range": {
    "maximum": null,
    "minimum": "40000"
  },
  "time_chunk_configuration": {
    "BlockTimestampMs": {
      "divisor": "600000"
    }
  },
  "yield_weights": {
    "static": {
      "revenue.tmplr.near": 1,
      "rewards.tmplr.near": 1
    },
    "supply": 1
  }
}

Snapshots

Interest and yield on borrow and supply positions are calculated using a snapshot system.

After a "time chunk" (e.g. 1 hour) elapses, the contract takes a snapshot, recording such things as the total supply deposit, amount borrowed, timestamp, etc.

Whenever a borrow or supply position update requires, interest/yield calculations are triggered. (They can also be triggered explicitly using harvest_yield and apply_interest.) These calculations iterate from the snapshot at which the record was last updated until the most-recently-finalized snapshot unless a snapshot limit is provided.

Supply

Accounts may deposit assets to the market's supply to earn yield.

Deposit

To add funds to a market's supply, send the to the contract, specifying "Supply" as the transfer msg.

For example:

near contract call-function as-transaction \
    <borrow-asset-contract-id> ft_transfer_call \
    json-args '{
        "receiver_id": "<market-id>",
        "amount": "<amount>",
        "msg": "\"Supply\""
    }' \
    prepaid-gas '100.0 Tgas' \
    attached-deposit '1 yoctoNEAR' \
    sign-as <account-id>

Withdraw

Since borrowers borrow the assets that suppliers have supplied, when a supplier wishes to withdraw their supply, there might not be enough available to withdraw at that time. However, through fees, interest, etc., as time passes, borrow assets should become available to withdraw again.

Because the market may not have sufficient borrow asset liquidity when a supplier wishes to withdraw, the market uses a queue-based withdrawal system.

In order to withdraw supply from the market, a supplier must first enter the supply withdrawal queue with their withdrawal request:

near contract call-function as-transaction \
    <market-id> create_supply_withdrawal_request \
    json-args '{"amount": "<amount>"}' \
    prepaid-gas '100.0 Tgas' \
    attached-deposit '0 NEAR' \
    sign-as <account-id>

Now the account has a position in the queue. Should the account wish to update the amount of the request, it can call create_supply_withdrawal_request again, however, this will also reset its position to the end of the queue.

A supply withdrawal request can be cancelled via cancel_supply_withdrawal_request.

In order for an account's supply withdrawal request to be fulfilled, all of the requests that are ahead of it in the queue must be fulfilled first.

To execute the next withdrawal request, use the execute_next_supply_withdrawal_request function:

near contract call-function as-transaction \
    <market-id> execute_next_supply_withdrawal_request \
    json-args '{}' \
    prepaid-gas '100.0 Tgas' \
    attached-deposit '0 NEAR' \
    sign-as <account-id>

This function is not permissioned; anyone may call it to advance the withdrawal queue.

Borrow

Accounts may borrow assets from the market's supply.

Borrow positions must be collateralized with a minimum amount of collateral asset determined by the market's configuration.

Deposit collateral

To add collateral to an account's position, transfer-call the market tokens with a msg of "Collateralize":

near contract call-function as-transaction \
    <collateral-asset-contract-id> ft_transfer_call \
    json-args '{
        "receiver_id": "<market-id>",
        "amount": "<amount>",
        "msg": "\"Collateralize\""
    }' \
    prepaid-gas '100.0 Tgas' \
    attached-deposit '1 yoctoNEAR' \
    sign-as <account-id>

Withdraw collateral

The collateral withdrawal process is relatively straightforward as compared to the supply withdrawal process: simply call withdraw_collateral, passing the amount of collateral asset tokens you wish to withdraw:

near contract call-function as-transaction \
    <market-id> withdraw_collateral \
    json-args '{ "amount": "<amount>" }' \
    prepaid-gas '100.0 Tgas' \
    attached-deposit '0 NEAR' \
    sign-as <account-id>

While this process is simple, collateral can only be withdraw so long as the value of the remaining collateral continues to satisfy the market's borrow_mcr_maintenance requirement.

Borrow

Once an account's position is collateralized, borrow asset can be withdrawn.

near contract call-function as-transaction \
    <market-id> borrow \
    json-args '{ "amount": "<amount>" }' \
    prepaid-gas '100.0 Tgas' \
    attached-deposit '0 NEAR' \
    sign-as <account-id>

As long as the collateralization requirements are met, the borrow amount (minus fees) will be sent to the predecessor account.

Repay

As long as an account has a liability (principal + interest/fees), some or all of their collateral will be locked so that it cannot be withdrawn.

To unlock the collateral, the account must repay its liability to the market.

To perform a repayment, transfer-call tokens to the market with a msg of "Repay":

near contract call-function as-transaction \
    <borrow-asset-contract-id> ft_transfer_call \
    json-args '{
        "receiver_id": "<market-id>",
        "amount": "<amount>",
        "msg": "\"Repay\""
    }' \
    prepaid-gas '100.0 Tgas' \
    attached-deposit '1 yoctoNEAR' \
    sign-as <account-id>

Liquidate

Liquidation is the process by which the asset collateralizing certain positions may be reappropriated e.g. to recover assets for an undercollateralized position.

A liquidator is a third party willing to send a quantity of a market's borrow asset (usually a stablecoin) to the market in exchange for the amount of collateral asset supporting a specific account's position. As compensation for this service, the liquidator receives an exchange rate that is slightly better than the current rate. This difference in rates is called the "liquidator spread," and the maximum liquidator spread is configurable on a per-market basis.

  • The liquidator MUST ensure that its account is able to receive the collateral tokens. Usually this means opting-in to storage management (if the collateral token in question implements that standard). If the collateral transfer fails, the liquidator will not be refunded!
  • It is the responsibility of the liquidator to calculate the optimal amount of tokens to attach to a liquidation call. The market will either completely accept or completely reject the liquidation attempt—no refunds!

A liquidator will follow this high-level workflow:

  1. The liquidator obtains a list of accounts borrowing from the market by calling list_borrow_positions.
  2. The liquidator checks the status of each account by calling get_borrow_status.
  3. If an account's status is Liquidation, that means the liquidator can obtain a spread by sending an amount of borrow asset to the market. The maximum spread is liquidation_maximum_spread in the market configuration.
  4. To perform the liquidation, the liquidator transfer-calls the appropriate amount of borrow asset to the market. That is to say, the liquidator calls ft_transfer_call/mt_transfer_call on the borrow asset's smart contract, specifying the market as the receiver. The msg parameter indicates 1) that the transfer is for a liquidation, and 2) which account is to be liquidated.

Thus, the arguments to a liquidation call might look something like this:

{
  "amount": "<amount>",
  "msg": {
    "Liquidate": {
      "account_id": "<account-to-liquidate>"
    }
  },
  "receiver_id": "<market-id>"
}

Example

near contract call-function as-transaction \
    <borrow-asset-contract-id> ft_transfer_call \
    json-args '{
        "receiver_id": "<market-id>",
        "amount": "<amount>",
        "msg": "{ \"Liquidate\": { \"account_id\": \"<account-to-liquidate>\" } }"
    }' \
    prepaid-gas '100.0 Tgas' \
    attached-deposit '1 yoctoNEAR' \
    sign-as <account-id>

Registry

The registry is a contract that maintains a list of contract versions, deploys new contracts, and maintains a list of those deployments. It is the only way a production market or proxy oracle is created: every one is a sub-account of the registry, deployed from a registered, audited version.

The account ID of the mainnet market registry is v1.tmplr.near. Its owner is the DAO multisig; what the owner can and cannot do is described in Protocol Governance.

Interactions

Every example below is a read-only view call with near-cli-rs. The outputs are illustrative and abridged; the live call is authoritative.

List available versions

near contract call-function as-read-only \
    v1.tmplr.near list_versions \
    json-args '{"offset":0,"count":100}' \
    network-config mainnet \
    now

Illustrative output:

[
  "v20250811",
  "v1.1.0",
  "v1.2.1",
  "v1.3.0",
  "templar-proxy-oracle-near-contract@0.4.1#fb9b3b46bbedd16665dbc31f0efc605c8ef49acfa5ff17608fbc3b490b4a6cb3",
  "templar-proxy-oracle-near-governance-contract@0.3.1#40b1719a525dae7117a776ccefa281f97470e1213e83bbf054bd77eae5b0568a"
]

Most market versions are registered under vX.Y.Z keys; the legacy 1.0.0 build uses v20250811. Proxy oracle and governance builds use <package>@<version>#<sha256> keys. The mainnet deployment profile currently deploys new markets from v1.3.0 and pins the proxy oracle and governance builds shown above; other keys may exist. Released artifact hashes are recorded under contract/artifacts/releases/.

List deployments

near contract call-function as-read-only \
    v1.tmplr.near list_deployments \
    json-args '{"offset":0,"count":100}' \
    network-config mainnet \
    now

Illustrative output:

[
  "ibtc-iethusdc-1.v1.tmplr.near",
  "proxy-oracle-ibtc-iethusdc-1.v1.tmplr.near",
  "proxy-gov-ibtc-iethusdc-1.v1.tmplr.near",
  "ixlm-ixlmusdc-1.v1.tmplr.near",
  "proxy-oracle-ixlm-ixlmusdc-1.v1.tmplr.near",
  "proxy-gov-ixlm-ixlmusdc-1.v1.tmplr.near",
  "ixlmdejaaa-ixlmusdc-2.v1.tmplr.near",
  "..."
]

The list contains markets, proxy oracles, and proxy oracle governance contracts alike, since the registry deploys all three, and it includes deprecated markets that are still on chain. The call is paginated: count caps the page size, so if a page comes back full, request the next one with offset advanced by the page size and repeat until a page contains fewer than count entries. The markets currently offered in the app, and the deprecated ones, are listed on Smart Contract Addresses.

Read a deployment record

near contract call-function as-read-only \
    v1.tmplr.near get_deployment \
    json-args '{"account_id":"ixlmdejaaa-ixlmusdc-2.v1.tmplr.near"}' \
    network-config mainnet \
    now

Illustrative output:

{
  "version_key": "v1.3.0",
  "code_hash": "<base58 sha256 of the deployed WASM>",
  "block_height": "…"
}

version_key names the registered version the account was deployed from and code_hash is the hash of the bytes deployed. Compare the code hash with the released artifact manifests above, and use Contract Verification to verify the deployed bytes against their source. The record's types are documented in the API Reference.

LST Oracle

The LST oracle adapter enhances base oracle functionality by supporting a broader range of asset classes. The primary transformation supported by the LST oracle adapter is price normalization of a liquid staking token (LST).

Price normalization requires retrieving the price of the underlying asset and the conversion rate between the LST and the underlying asset and combining them to produce a price for the LST asset itself.

The same normalization is available inside the proxy oracle as a transformer source, which is the path new LST markets use. Method-level documentation for both is in the API Reference.

Example: stNEAR Price Calculation

Examine the transformer specification:

near contract call-function as-read-only \
    lst.oracle.tmplr.near get_transformer \
    json-args '{"price_identifier":"c23cb2430c81d475fbd1c235324d4987f2dd01431bf7ab3e7b9d69b9f6701470"}' \
    network-config mainnet \
    now

Output:

{
  "action": {
    "NormalizeNativeLstPrice": {
      "decimals": 24
    }
  },
  "call": {
    "account_id": "meta-pool.near",
    "args": "bnVsbA==",
    "gas": "3000000000000",
    "method_name": "get_st_near_price"
  },
  "price_id": "c415de8d2eba7db216527dff4b60e8f3a5311c740dadb233e13e12547e226750"
}

This specification describes the following flow:

  1. Retrieve the NEAR price from the Pyth oracle (asset ID c415de8d2eba7db216527dff4b60e8f3a5311c740dadb233e13e12547e226750).
  2. Retrieve the stNEAR redemption rate from the staking contract (meta-pool.near->get_st_near_price({})).
  3. Calculate price_stnear = price_near * redemption_rate / 10^24.

API Reference

Templar exposes three programmatic surfaces. The backend HTTP API is the main reference for applications and integrators; the gateway JSON-RPC service and direct contract calls are lower-level paths for those who need them. The generated Rust documentation covers the contract types every surface returns.

Backend HTTP API

The backend HTTP API is the primary way to read protocol data and prepare user flows without handling contract calls yourself: a conventional web API over HTTPS with JSON request and response bodies. Its interactive documentation is the authoritative catalogue of endpoints, parameters, schemas, examples, and error responses:

api.templarfi.org/docs

The live reference is split into eight OpenAPI documents:

APIUse it forLive reference
MarketsMarket configuration and metrics, positions, wallet balances, prices, and asset metadataMarkets, accounts, prices, assets
LendingPreparing borrow, repay, collateral, and supply transactionsBorrow, supply
SwapsSupported tokens, quotes, deposit confirmation, and swap statusGet a quote, check status
BridgePreparing and tracking NEAR Intents deposits and withdrawalsDeposits and withdrawals
AnalyticsWarehouse-backed views, protocol state, metrics, and indexed eventsViews, state, metrics, events
CampaignsCampaign periods, Merkl data and rewards, and NEAR-to-Stellar payout linksCampaigns
ComplianceAdvisory off-chain wallet screeningScreen a wallet
RelayerSponsored submissions, account history, and universal accountsSubmissions, accounts, universal accounts

The server base URL shown by the live specifications is https://api.templarfi.org/v1. Where an operation requires authentication, its specification marks that requirement and uses the X-API-Key header. Use the version displayed by the selected live specification and its downloadable OpenAPI document rather than copying schemas from this guide.

Use this guide for protocol semantics behind the responses: Risk Parameters explains market configuration fields, Oracles explains price provenance, and Stellar Curated Vaults explains vault behavior.

Rust API Documentation

The generated Rust API documentation, built from the contract sources with cargo doc, is the authoritative reference for every contract type, method, argument, and error. It is served under /doc/ on this site. Useful entry points:

CrateWhat it documentsEntry point
templar_commonTypes shared by every contract: market configuration and interface, asset and amount types, fees, interest-rate strategies, registry recordstemplar_common
Market configurationThe immutable per-market parameters listed on Risk ParametersMarketConfiguration
Market interfaceEvery method a market exposes, with argument and return typesMarketExternalInterface
Interest-rate strategiesThe Linear, Piecewise, and Exponential2 curvesInterestRateStrategy
Registry recordsThe Deployment record (version key, code hash, block height) returned by get_deploymentDeployment
templar_proxy_oracle_kernelThe chain-agnostic proxy oracle pipeline: sources, freshness filters, aggregation, circuit breakerstemplar_proxy_oracle_kernel
templar_vault_kernelThe chain-agnostic vault state machine, fee math, and withdrawal queuetemplar_vault_kernel
Contract cratesThe NEAR contract entry points themselvestemplar_market_contract, templar_registry_contract, templar_proxy_oracle_near_contract

The /doc/ links resolve on the published site (docs.templarfi.org). When serving this guide locally with mdbook serve they return 404, because the Rust documentation is built separately by script/build-docs.sh and copied next to the guide.

Gateway JSON-RPC

Integrators who need transaction-level control without signing NEAR transactions directly can use the gateway service, a JSON-RPC API in front of the contracts. Its method catalog, generated from the service's own method registry, is at gateway/METHODS.md.

Calling Contracts Directly

Examples throughout this guide use near-cli-rs view calls. The pages that catalogue them:

  • Market: configuration, positions, snapshots, and the supply, borrow, and liquidate flows.
  • Registry: versions and deployments.
  • Oracles: proxy oracle feeds, cached prices, and circuit-breaker state.
  • Monitoring and Risk Management: the health checks Templar's own monitoring runs.

templarfi.org links to the published guide. The app should also expose a guide/API documentation link; that implementation belongs in the frontend repository.

Smart Contract Addresses

Deployed Templar Protocol contracts, and how to verify them. For deploying a new market, see Deploying a market.

Deployments

Core

ContractAccount IDNotes
Registryv1.tmplr.nearDeploys markets and proxy oracles as sub-accounts; see Registry
Administrative multisigtemplar.sputnik-dao.nearSputnik DAO, 2-of-3 council; see Protocol Governance
Protocol revenue accountrevenue.tmplr.nearReceives the protocol's share of market yield

Oracles

ContractAccount IDNotes
Proxy oracle (per market)proxy-oracle-<market>.v1.tmplr.nearAggregated, circuit-breaker-protected feed for <market>.v1.tmplr.near
Proxy oracle governance (per market)proxy-gov-<market>.v1.tmplr.nearTimelocked governance for the matching proxy oracle. A market that reads a separately deployed proxy does not necessarily follow this pattern; the authoritative governance account is the proxy's owner, returned by its own_get_owner view
Pyth Lazer adapterpyth-lazer.v1.tmplr.nearVerifies and serves signed Pyth Lazer prices
RedStone adapterredstone-adapter.v1.tmplr.nearVerifies and serves signed RedStone prices
Pyth (classic)pyth-oracle.nearPyth's own contract; read directly by older markets
LST oracle adapterlst.oracle.tmplr.nearLegacy liquid-staking-token adapter

See Oracles for how these fit together.

Markets

Market contracts are deployed dynamically through the registry. Each market represents a single asset pair (COLLATERAL → BORROW) in its own contract account.

Market account names follow <collateral>-<borrow>[-<n>].v1.tmplr.near, where each asset name is built from up to three parts: i if the token is held through NEAR Intents, the host chain when the asset is not native to it (eth, xlm, sol), and the asset symbol. So iethwbtc is WBTC on Ethereum held through Intents, ixlmusdc is USDC on Stellar held through Intents, and ibtc is native BTC held through Intents. A numeric suffix distinguishes successive deployments of the same pair.

The authoritative list is on-chain:

near contract call-function as-read-only v1.tmplr.near list_deployments \
    json-args '{"offset": 0, "count": 100}' network-config mainnet now

The call is paginated: count caps the page size, so if a page comes back full, request the next one with offset advanced by the page size ({"offset": 100, "count": 100}) and repeat until a page contains fewer than count entries.

Markets listed on app.templarfi.org

The markets currently offered in the app. Their immutable parameters and oracle configuration are on Risk Parameters.

Account IDCollateral AssetBorrow Asset
iada-ixlmusdc.v1.tmplr.nearNative ADA (via NEAR Intents)USDC on Stellar (via NEAR Intents)
ibtc-iethusdc-1.v1.tmplr.nearNative BTC (via NEAR Intents)USDC on Ethereum (via NEAR Intents)
ibtc-ixlmusdc.v1.tmplr.nearNative BTC (via NEAR Intents)USDC on Stellar (via NEAR Intents)
idoge-ixlmusdc.v1.tmplr.nearNative DOGE (via NEAR Intents)USDC on Stellar (via NEAR Intents)
iethfxrp-ixlmusdc.v1.tmplr.nearFXRP on Ethereum (via NEAR Intents)USDC on Stellar (via NEAR Intents)
iethhemibtc-iethusdc.v1.tmplr.nearhemiBTC on Ethereum (via NEAR Intents)USDC on Ethereum (via NEAR Intents)
iethwbtc-ixlmusdc.v1.tmplr.nearWBTC on Ethereum (via NEAR Intents)USDC on Stellar (via NEAR Intents)
iltc-ixlmusdc.v1.tmplr.nearNative LTC (via NEAR Intents)USDC on Stellar (via NEAR Intents)
ixlm-ixlmpyusd.v1.tmplr.nearNative XLM (via NEAR Intents)PYUSD on Stellar (via NEAR Intents)
ixlm-ixlmusdc-1.v1.tmplr.nearNative XLM (via NEAR Intents)USDC on Stellar (via NEAR Intents)
ixlmcetes-ixlmusdc.v1.tmplr.nearCETES on Stellar (via NEAR Intents)USDC on Stellar (via NEAR Intents)
ixlmdejaaa-ixlmusdc-1.v1.tmplr.neardeJAAA on Stellar (via NEAR Intents)USDC on Stellar (via NEAR Intents)
ixlmdejaaa-ixlmusdc-2.v1.tmplr.neardeJAAA on Stellar (via NEAR Intents)USDC on Stellar (via NEAR Intents)
ixlmdejtrsy-ixlmusdc-1.v1.tmplr.neardeJTRSY on Stellar (via NEAR Intents)USDC on Stellar (via NEAR Intents)
ixlmsolvbtc-ixlmusdc.v1.tmplr.nearSolvBTC on Stellar (via NEAR Intents)USDC on Stellar (via NEAR Intents)
ixlmustry-ixlmusdc.v1.tmplr.nearUSTRY on Stellar (via NEAR Intents)USDC on Stellar (via NEAR Intents)
ixrp-ixlmusdc.v1.tmplr.nearNative XRP (via NEAR Intents)USDC on Stellar (via NEAR Intents)
izec-ixlmusdc.v1.tmplr.nearNative ZEC (via NEAR Intents)USDC on Stellar (via NEAR Intents)

Deprecated markets

These markets were retired from the app at the end of August 2026. Where the same pair was redeployed, the successor is the -1 or -2 market above. They remain on chain and fully functional (markets cannot be paused or removed), so existing positions can still be repaid and withdrawn, but the app no longer offers them and Templar's bots and monitoring focus on the listed markets. Users with positions in a deprecated market should migrate to its successor, or to another listed market for the same collateral.

Account IDCollateral AssetBorrow AssetSuccessor
ibtc-iethusdc.v1.tmplr.nearNative BTC (via NEAR Intents)USDC on Ethereum (via NEAR Intents)ibtc-iethusdc-1
ibtc-usdc.v1.tmplr.nearNative BTC (via NEAR Intents)USDC on NEARnone (same pair)
ibtc-usdc-1.v1.tmplr.nearNative BTC (via NEAR Intents)USDC on NEARnone (same pair)
iethwbtc-iethusdc.v1.tmplr.nearWBTC on Ethereum (via NEAR Intents)USDC on Ethereum (via NEAR Intents)none (same pair)
ixlm-ixlmusdc.v1.tmplr.nearNative XLM (via NEAR Intents)USDC on Stellar (via NEAR Intents)ixlm-ixlmusdc-1
ixlmdejaaa-ixlmusdc.v1.tmplr.neardeJAAA on Stellar (via NEAR Intents)USDC on Stellar (via NEAR Intents)ixlmdejaaa-ixlmusdc-1, ixlmdejaaa-ixlmusdc-2
ixlmdejtrsy-ixlmusdc.v1.tmplr.neardeJTRSY on Stellar (via NEAR Intents)USDC on Stellar (via NEAR Intents)ixlmdejtrsy-ixlmusdc-1
izec-isolusdc.v1.tmplr.nearNative ZEC (via NEAR Intents)USDC on Solana (via NEAR Intents)none (same pair)
stnear-usdc.v1.tmplr.nearstNEAR on NEARUSDC on NEARnone
stnear-usdc-1.v1.tmplr.nearstNEAR on NEARUSDC on NEARnone

Other active markets

The live Markets API classifies these markets as active, but they were not linked from the app navigation in a 2026-09-15 snapshot:

Account IDCollateral AssetBorrow Asset
linear-usdt.v1.tmplr.nearLiNEAR on NEARUSDT on NEAR
stnear-usdt.v1.tmplr.nearstNEAR on NEARUSDT on NEAR

Use the API's status field for the current operational classification. The registry's list_deployments output remains the complete deployment list and includes historical contracts as well as active markets.

Each market's oracle account, price identifiers, and risk parameters are available from its get_configuration view; see Market Configuration. The declarative specifications markets were deployed from are in deployments/v1/. The registry's get_deployment view identifies the version key and code hash used at deployment; see Registry.

A separate registry, templar-alpha.near, hosts pre-release and liquidation-test markets on mainnet. Markets under it are not production markets.

Contract Verification

All smart contracts use reproducible builds. To verify deployed code:

near contract verify deployed-at <contract-id> mainnet now

Example output:

INFO The code obtained from the contract account ID and the code calculated from the repository are the same.
|    Contract code hash: DaudmUa3nAym9dfQkn8mpNPZxkphSRGwEaTMgtymVhFE
|    Contract version:	1.0.0
|    Standards used by the contract:	[nep330:1.2.0]
|    View the contract's source code on:	https://github.com/Templar-Protocol/contracts/tree/1d736e62a86424dd947284cbd8e83bef803fa9fb
|    Build Environment:	sourcescan/cargo-near:0.13.4-rust-1.85.0@sha256:a9d8bee7b134856cc8baa142494a177f2ba9ecfededfcdd38f634e14cca8aae2
|    Build Command:	cargo near build non-reproducible-wasm --locked

The verification compares the on-chain code hash with a build from the commit recorded in the contract's NEP-330 metadata, so it establishes that the deployed bytecode matches the published source commit. Whether that commit is covered by an audit must be checked separately against the audit reports. Released contract artifacts and their SHA-256 digests are recorded under contract/artifacts/releases/.

Risk Parameters

Every Templar market is deployed with a fixed set of risk parameters that cannot be changed afterwards (see Immutable Markets). This page lists those parameters for the markets offered on app.templarfi.org, generated from the declarative specifications the markets were deployed from. Markets deprecated in the app, alpha markets under templar-alpha.near, and test markets are not listed; see Smart Contract Addresses for the full account list. Which markets count as offered is recorded in script/docs/listed-markets.toml, and the generator refuses to run if a deployed market is missing from it.

What the Parameters Mean

ParameterMeaningRust field
MCR (maintenance)Minimum collateralization ratio (collateral value ÷ debt value) a position must satisfy after any borrower action such as borrowing more or withdrawing collateral.borrow_mcr_maintenance
MCR (liquidation)A position whose ratio falls below this value is eligible for liquidation. Always at or below the maintenance MCR; the gap is the borrower's buffer.borrow_mcr_liquidation
Max usage ratioThe share of supplied principal that may be lent out. The remainder is held as a reserve that suppliers can withdraw against.borrow_asset_maximum_usage_ratio
Max liquidation spreadThe largest discount to market value at which a liquidator may buy collateral out of an undercollateralized position; effectively the liquidation penalty.liquidation_maximum_spread
Max price ageThe market rejects an oracle price older than this. Price-dependent operations fail until the oracle is refreshed.price_oracle_configuration
Interest rate curveThe annualized borrow rate as a function of usage (borrowed ÷ supplied). Piecewise curves are cheap below the kink and steep above it to pull usage back toward the optimum.borrow_interest_rate_strategy
Origination feeA one-time fee added to the principal of each borrow.borrow_origination_fee
Supply withdrawal feeA time-based fee on supply withdrawals, to discourage very short-lived positions.supply_withdrawal_fee
Yield splitHow interest paid by borrowers is divided between suppliers and static recipients such as the protocol revenue account.yield_weights
Borrow, supply, and withdrawal rangesBounds on the size of a position after any modification. atom is the smallest unit of the asset; tokens is a whole-token amount.borrow_range, supply_range, supply_withdrawal_range
Max borrow durationIf set, a borrow becomes liquidatable after this period regardless of collateralization.borrow_maximum_duration_ms
Time chunkThe period over which the market snapshots its state to accrue interest and yield.time_chunk_configuration

Oracle columns describe how each asset is priced: which proxy oracle the market reads, the underlying sources and their weights, the aggregation rule (median_low biases collateral valuations down, median_high biases liability valuations up), and the minimum number of fresh sources required. The Storage patched column links to the reviewed patch record for markets whose storage was modified after deployment (the August 2026 migration of legacy markets to proxy oracles; see Deployer Key Retention).

How to Read This Page

  • Source of truth: the tables are generated from deployments/v1/*.toml with the same profile-composition rules tmplrmgr applies at deployment, and CI fails if they drift from the specs. A spec is the reviewed deployment input; the on-chain configuration returned by a market's get_configuration view is authoritative. Nothing on this page was reconciled against the chain when it was generated.
  • Patched markets: for the storage-patched markets, the spec was updated to the post-patch oracle configuration, so it describes current intent rather than deployment-time state.
  • Rounding: ratios and rates are rounded to four decimal places; the on-chain values carry up to 38 decimal digits (a maintenance MCR of 1.3333 is 4/3 on chain).
  • Feed migration: Pyth's classic contract is being retired in favour of Pyth Lazer. A source list in a spec can lead what is on chain for a market whose proxy oracle has not been reconfigured yet; the proxy's get_proxy view shows the sources in force.

Collateralization and Liquidation

MarketCollateralBorrowMCR (maintenance)MCR (liquidation)Max usage ratioMax liquidation spreadMax price age
iada-ixlmusdc.v1.tmplr.nearADA (via NEAR Intents)USDC on Stellar (via NEAR Intents)1.25 (125%)1.2 (120%)99%10%60s
ibtc-iethusdc-1.v1.tmplr.nearBTC (via NEAR Intents)USDC on Ethereum (via NEAR Intents)1.25 (125%)1.2 (120%)99%8%60s
ibtc-ixlmusdc.v1.tmplr.nearBTC (via NEAR Intents)USDC on Stellar (via NEAR Intents)1.1765 (117.65%)1.1111 (111.11%)99%10%60s
idoge-ixlmusdc.v1.tmplr.nearDOGE (via NEAR Intents)USDC on Stellar (via NEAR Intents)1.25 (125%)1.2 (120%)99%10%60s
iethfxrp-ixlmusdc.v1.tmplr.nearFXRP on Ethereum (via NEAR Intents)USDC on Stellar (via NEAR Intents)1.25 (125%)1.2 (120%)99%10%120s
iethhemibtc-iethusdc.v1.tmplr.nearhemiBTC on Ethereum (via NEAR Intents)USDC on Ethereum (via NEAR Intents)1.2 (120%)1.15 (115%)99%10%60s
iethwbtc-ixlmusdc.v1.tmplr.nearWBTC on Ethereum (via NEAR Intents)USDC on Stellar (via NEAR Intents)1.2 (120%)1.15 (115%)99%10%120s
iltc-ixlmusdc.v1.tmplr.nearLTC (via NEAR Intents)USDC on Stellar (via NEAR Intents)1.3333 (133.33%)1.25 (125%)99%10%60s
ixlm-ixlmpyusd.v1.tmplr.nearXLM (via NEAR Intents)PYUSD on Stellar (via NEAR Intents)1.4 (140%)1.3333 (133.33%)99%10%60s
ixlm-ixlmusdc-1.v1.tmplr.nearXLM (via NEAR Intents)USDC on Stellar (via NEAR Intents)1.4286 (142.86%)1.3333 (133.33%)99%10%120s
ixlmcetes-ixlmusdc.v1.tmplr.nearCETES on Stellar (via NEAR Intents)USDC on Stellar (via NEAR Intents)1.25 (125%)1.1765 (117.65%)99%10%60s
ixlmdejaaa-ixlmusdc-1.v1.tmplr.neardeJAAA on Stellar (via NEAR Intents)USDC on Stellar (via NEAR Intents)1.07 (107%)1.05 (105%)99%2.5%120s
ixlmdejaaa-ixlmusdc-2.v1.tmplr.neardeJAAA on Stellar (via NEAR Intents)USDC on Stellar (via NEAR Intents)1.07 (107%)1.05 (105%)99%2.5%120s
ixlmdejtrsy-ixlmusdc-1.v1.tmplr.neardeJTRSY on Stellar (via NEAR Intents)USDC on Stellar (via NEAR Intents)1.07 (107%)1.05 (105%)99%2.5%120s
ixlmsolvbtc-ixlmusdc.v1.tmplr.nearSolvBTC on Stellar (via NEAR Intents)USDC on Stellar (via NEAR Intents)1.25 (125%)1.2 (120%)99%10%60s
ixlmustry-ixlmusdc.v1.tmplr.nearUSTRY on Stellar (via NEAR Intents)USDC on Stellar (via NEAR Intents)1.2 (120%)1.1111 (111.11%)99%10%60s
ixrp-ixlmusdc.v1.tmplr.nearXRP (via NEAR Intents)USDC on Stellar (via NEAR Intents)1.25 (125%)1.2 (120%)99%10%60s
izec-ixlmusdc.v1.tmplr.nearZEC (via NEAR Intents)USDC on Stellar (via NEAR Intents)1.6667 (166.67%)1.5385 (153.85%)99%10%60s

Interest and Fees

MarketInterest rate curve (annualized)Origination feeSupply withdrawal feeYield splitBorrow rangeSupply rangeSupply withdrawal rangeMax borrow durationTime chunk
iada-ixlmusdc.v1.tmplr.near0% at 0% usage, 6% at 90% usage (kink), 24% at 100% usageFlat 0 atomsNonesuppliers 4/5; revenue.tmplr.near 1/5min 1 atom, no maximummin 0.04 tokens, no maximummin 0.04 tokens, no maximumnone10m
ibtc-iethusdc-1.v1.tmplr.near0% at 0% usage, 8% at 90% usage (kink), 32% at 100% usageFlat 0 atomsNonesuppliers 4/5; revenue.tmplr.near 1/5min 1 atom, no maximummin 0.04 tokens, no maximummin 0.04 tokens, no maximumnone10m
ibtc-ixlmusdc.v1.tmplr.near0% at 0% usage, 6% at 90% usage (kink), 24% at 100% usageFlat 0 atomsNonesuppliers 4/5; revenue.tmplr.near 1/5min 1 atom, no maximummin 0.04 tokens, no maximummin 0.04 tokens, no maximumnone10m
idoge-ixlmusdc.v1.tmplr.near0% at 0% usage, 6% at 90% usage (kink), 24% at 100% usageFlat 0 atomsNonesuppliers 4/5; revenue.tmplr.near 1/5min 1 atom, no maximummin 0.04 tokens, no maximummin 0.04 tokens, no maximumnone10m
iethfxrp-ixlmusdc.v1.tmplr.near0% at 0% usage, 6% at 90% usage (kink), 24% at 100% usageFlat 0 atomsNonesuppliers 4/5; revenue.tmplr.near 1/5min 1 atom, no maximummin 0.04 tokens, no maximummin 0.04 tokens, no maximumnone10m
iethhemibtc-iethusdc.v1.tmplr.near0% at 0% usage, 6% at 90% usage (kink), 24% at 100% usageFlat 0 atomsNonesuppliers 4/5; revenue.tmplr.near 1/5min 1 atom, no maximummin 0.04 tokens, no maximummin 0.04 tokens, no maximumnone10m
iethwbtc-ixlmusdc.v1.tmplr.near0% at 0% usage, 6% at 90% usage (kink), 24% at 100% usageFlat 0 atomsNonesuppliers 4/5; revenue.tmplr.near 1/5min 1 atom, no maximummin 0.004 tokens, no maximummin 0.004 tokens, no maximumnone10m
iltc-ixlmusdc.v1.tmplr.near0% at 0% usage, 6% at 90% usage (kink), 24% at 100% usageFlat 0 atomsNonesuppliers 4/5; revenue.tmplr.near 1/5min 1 atom, no maximummin 0.04 tokens, no maximummin 0.04 tokens, no maximumnone10m
ixlm-ixlmpyusd.v1.tmplr.near0% at 0% usage, 8% at 90% usage (kink), 32% at 100% usageFlat 0 atomsNonesuppliers 4/5; revenue.tmplr.near 1/5min 1 atom, no maximummin 0.04 tokens, no maximummin 0.04 tokens, no maximumnone10m
ixlm-ixlmusdc-1.v1.tmplr.near0% at 0% usage, 8% at 90% usage (kink), 32% at 100% usageFlat 0 atomsNonesuppliers 4/5; revenue.tmplr.near 1/5min 1 atom, no maximummin 0.04 tokens, no maximummin 0.04 tokens, no maximumnone10m
ixlmcetes-ixlmusdc.v1.tmplr.near0% at 0% usage, 8% at 90% usage (kink), 32% at 100% usageFlat 0 atomsNonesuppliers 4/5; revenue.tmplr.near 1/5min 1 atom, no maximummin 0.04 tokens, no maximummin 0.04 tokens, no maximumnone10m
ixlmdejaaa-ixlmusdc-1.v1.tmplr.nearLinear from 3.3% at 0% usage to 3.3% at 100% usageFlat 0 atomsNonesuppliers 19/20; revenue.tmplr.near 1/20min 1 atom, no maximummin 0.04 tokens, no maximummin 0.04 tokens, no maximumnone10m
ixlmdejaaa-ixlmusdc-2.v1.tmplr.near3% at 0% usage, 3% at 90% usage (kink), 23% at 100% usageFlat 0 atomsNonesuppliers 19/20; revenue.tmplr.near 1/20min 1 atom, no maximummin 0.04 tokens, no maximummin 0.04 tokens, no maximumnone10m
ixlmdejtrsy-ixlmusdc-1.v1.tmplr.nearLinear from 3% at 0% usage to 3% at 100% usageFlat 0 atomsNonesuppliers 19/20; revenue.tmplr.near 1/20min 1 atom, no maximummin 0.04 tokens, no maximummin 0.04 tokens, no maximumnone10m
ixlmsolvbtc-ixlmusdc.v1.tmplr.near0% at 0% usage, 8% at 90% usage (kink), 32% at 100% usageFlat 0 atomsNonesuppliers 4/5; revenue.tmplr.near 1/5min 1 atom, no maximummin 0.04 tokens, no maximummin 0.04 tokens, no maximumnone10m
ixlmustry-ixlmusdc.v1.tmplr.near0% at 0% usage, 8% at 90% usage (kink), 32% at 100% usageFlat 0 atomsNonesuppliers 4/5; revenue.tmplr.near 1/5min 1 atom, no maximummin 0.04 tokens, no maximummin 0.04 tokens, no maximumnone10m
ixrp-ixlmusdc.v1.tmplr.near0% at 0% usage, 6% at 90% usage (kink), 24% at 100% usageFlat 0 atomsNonesuppliers 4/5; revenue.tmplr.near 1/5min 1 atom, no maximummin 0.04 tokens, no maximummin 0.04 tokens, no maximumnone10m
izec-ixlmusdc.v1.tmplr.near0% at 0% usage, 6% at 90% usage (kink), 24% at 100% usageFlat 0 atomsNonesuppliers 4/5; revenue.tmplr.near 1/5min 1 atom, no maximummin 0.04 tokens, no maximummin 0.04 tokens, no maximumnone10m

Oracle Configuration

MarketOracleCollateral price sourcesBorrow price sourcesOracle governanceStorage patched
iada-ixlmusdc.v1.tmplr.nearProxy oracle proxy-oracle-iada-ixlmusdc.v1.tmplr.nearPyth (classic) 2a01deae… via pyth-oracle.near, weight 8
RedStone ADA via redstone-adapter.v1.tmplr.near, weight 2
aggregator median_low, min sources 1
Pyth (classic) eaa020c6… via pyth-oracle.near, weight 8
RedStone USDC via redstone-adapter.v1.tmplr.near, weight 2
aggregator median_low, min sources 1
proxy-gov-iada-ixlmusdc.v1.tmplr.nearNo
ibtc-iethusdc-1.v1.tmplr.nearProxy oracle proxy-oracle-ibtc-iethusdc-1.v1.tmplr.nearPyth Lazer feed 1 via pyth-lazer.v1.tmplr.near, weight 8
RedStone BTC via redstone-adapter.v1.tmplr.near, weight 2
aggregator median_low, min sources 1
Pyth Lazer feed 7 via pyth-lazer.v1.tmplr.near, weight 8
RedStone USDC via redstone-adapter.v1.tmplr.near, weight 2
aggregator median_high, min sources 1
proxy-gov-ibtc-iethusdc-1.v1.tmplr.nearYes
ibtc-ixlmusdc.v1.tmplr.nearProxy oracle proxy-oracle-ibtc-ixlmusdc.v1.tmplr.nearPyth (classic) e62df6c8… via pyth-oracle.near, weight 8
RedStone BTC via redstone-adapter.v1.tmplr.near, weight 2
aggregator median_low, min sources 1
Pyth (classic) eaa020c6… via pyth-oracle.near, weight 8
RedStone USDC via redstone-adapter.v1.tmplr.near, weight 2
aggregator median_low, min sources 1
proxy-gov-ibtc-ixlmusdc.v1.tmplr.nearNo
idoge-ixlmusdc.v1.tmplr.nearProxy oracle proxy-oracle-idoge-ixlmusdc.v1.tmplr.nearPyth (classic) dcef50dd… via pyth-oracle.near, weight 8
RedStone DOGE via redstone-adapter.v1.tmplr.near, weight 2
aggregator median_low, min sources 1
Pyth (classic) eaa020c6… via pyth-oracle.near, weight 8
RedStone USDC via redstone-adapter.v1.tmplr.near, weight 2
aggregator median_low, min sources 1
proxy-gov-idoge-ixlmusdc.v1.tmplr.nearNo
iethfxrp-ixlmusdc.v1.tmplr.nearProxy oracle proxy-oracle-iethfxrp-ixlmusdc.v1.tmplr.nearPyth Lazer feed 14 via pyth-lazer.templar-alpha.near, weight 8
RedStone XRP via redstone-adapter.v1.tmplr.near, weight 2
aggregator median_low, min sources 1
Pyth Lazer feed 7 via pyth-lazer.v1.tmplr.near, weight 8
RedStone USDC via redstone-adapter.v1.tmplr.near, weight 2
aggregator median_high, min sources 1
proxy-gov-iethfxrp-ixlmusdc.v1.tmplr.nearNo
iethhemibtc-iethusdc.v1.tmplr.nearProxy oracle proxy-oracle-iethhemibtc-iethusdc.v1.tmplr.nearPyth (classic) e62df6c8… via pyth-oracle.near, weight 8
RedStone BTC via redstone-adapter.v1.tmplr.near, weight 2
aggregator median_low, min sources 1
Pyth (classic) eaa020c6… via pyth-oracle.near, weight 8
RedStone USDC via redstone-adapter.v1.tmplr.near, weight 2
aggregator median_low, min sources 1
proxy-gov-iethhemibtc-iethusdc.v1.tmplr.nearNo
iethwbtc-ixlmusdc.v1.tmplr.nearProxy oracle proxy-oracle-iethwbtc-ixlmusdc.v1.tmplr.nearPyth Lazer feed 103 via pyth-lazer.v1.tmplr.near, weight 8
RedStone WBTC via redstone-adapter.v1.tmplr.near, weight 2
aggregator median_low, min sources 1
Pyth Lazer feed 7 via pyth-lazer.v1.tmplr.near, weight 8
RedStone USDC via redstone-adapter.v1.tmplr.near, weight 2
aggregator median_high, min sources 1
proxy-gov-iethwbtc-ixlmusdc.v1.tmplr.nearNo
iltc-ixlmusdc.v1.tmplr.nearProxy oracle proxy-oracle-iltc-ixlmusdc.v1.tmplr.nearPyth (classic) 6e3f3fa8… via pyth-oracle.near, weight 8
RedStone LTC via redstone-adapter.v1.tmplr.near, weight 2
aggregator median_low, min sources 1
Pyth (classic) eaa020c6… via pyth-oracle.near, weight 8
RedStone USDC via redstone-adapter.v1.tmplr.near, weight 2
aggregator median_low, min sources 1
proxy-gov-iltc-ixlmusdc.v1.tmplr.nearNo
ixlm-ixlmpyusd.v1.tmplr.nearProxy oracle proxy-oracle-ixlm-ixlmpyusd.v1.tmplr.nearPyth Lazer feed 23 via pyth-lazer.v1.tmplr.near, weight 8
RedStone XLM via redstone-adapter.v1.tmplr.near, weight 2
aggregator median_low, min sources 1
Pyth Lazer feed 156 via pyth-lazer.v1.tmplr.near, weight 8
RedStone PYUSD via redstone-adapter.v1.tmplr.near, weight 2
aggregator median_high, min sources 1
proxy-gov-ixlm-ixlmpyusd.v1.tmplr.nearYes
ixlm-ixlmusdc-1.v1.tmplr.nearProxy oracle proxy-oracle-ixlm-ixlmusdc-1.v1.tmplr.nearPyth Lazer feed 23 via pyth-lazer.v1.tmplr.near, weight 8
RedStone XLM via redstone-adapter.v1.tmplr.near, weight 2
aggregator median_low, min sources 1
Pyth Lazer feed 7 via pyth-lazer.v1.tmplr.near, weight 8
RedStone USDC via redstone-adapter.v1.tmplr.near, weight 2
aggregator median_high, min sources 1
proxy-gov-ixlm-ixlmusdc-1.v1.tmplr.nearNo
ixlmcetes-ixlmusdc.v1.tmplr.nearDirect read of proxy-oracle-ixlmcetes-ixlmusdc.v1.tmplr.nearfeed 43455445… read directlyfeed 55534443… read directlyOwner of that oracle (own_get_owner)No
ixlmdejaaa-ixlmusdc-1.v1.tmplr.nearProxy oracle proxy-oracle-ixlmdejaaa-ixlmusdc-1.v1.tmplr.nearRedStone deJAAA_FUNDAMENTAL/USD via redstone-adapter.v1.tmplr.near, weight 5
aggregator median_low, min sources 1
Pyth Lazer feed 7 via pyth-lazer.v1.tmplr.near, weight 8
RedStone USDC via redstone-adapter.v1.tmplr.near, weight 2
aggregator median_high, min sources 1
proxy-gov-ixlmdejaaa-ixlmusdc-1.v1.tmplr.nearNo
ixlmdejaaa-ixlmusdc-2.v1.tmplr.nearProxy oracle proxy-oracle-ixlmdejaaa-ixlmusdc-2.v1.tmplr.nearRedStone deJAAA_FUNDAMENTAL/USD via redstone-adapter.v1.tmplr.near, weight 5
aggregator median_low, min sources 1
Pyth Lazer feed 7 via pyth-lazer.v1.tmplr.near, weight 8
RedStone USDC via redstone-adapter.v1.tmplr.near, weight 2
aggregator median_high, min sources 1
proxy-gov-ixlmdejaaa-ixlmusdc-2.v1.tmplr.nearNo
ixlmdejtrsy-ixlmusdc-1.v1.tmplr.nearProxy oracle proxy-oracle-ixlmdejtrsy-ixlmusdc-1.v1.tmplr.nearRedStone deJTRSY_FUNDAMENTAL/USD via redstone-adapter.v1.tmplr.near, weight 5
aggregator median_low, min sources 1
Pyth Lazer feed 7 via pyth-lazer.v1.tmplr.near, weight 8
RedStone USDC via redstone-adapter.v1.tmplr.near, weight 2
aggregator median_high, min sources 1
proxy-gov-ixlmdejtrsy-ixlmusdc-1.v1.tmplr.nearNo
ixlmsolvbtc-ixlmusdc.v1.tmplr.nearProxy oracle proxy-oracle-ixlmsolvbtc-ixlmusdc.v1.tmplr.nearRedStone SolvBTC_FUNDAMENTAL/USD via redstone-adapter.v1.tmplr.near, weight 1
aggregator median_low, min sources 1
Pyth Lazer feed 7 via pyth-lazer.v1.tmplr.near, weight 8
RedStone USDC via redstone-adapter.v1.tmplr.near, weight 2
aggregator median_high, min sources 1
proxy-gov-ixlmsolvbtc-ixlmusdc.v1.tmplr.nearYes
ixlmustry-ixlmusdc.v1.tmplr.nearDirect read of proxy-oracle-ixlmustry-ixlmusdc.v1.tmplr.nearfeed 55535452… read directlyfeed 55534443… read directlyOwner of that oracle (own_get_owner)No
ixrp-ixlmusdc.v1.tmplr.nearProxy oracle proxy-oracle-ixrp-ixlmusdc.v1.tmplr.nearPyth (classic) ec5d3998… via pyth-oracle.near, weight 8
RedStone XRP via redstone-adapter.v1.tmplr.near, weight 2
aggregator median_low, min sources 1
Pyth (classic) eaa020c6… via pyth-oracle.near, weight 8
RedStone USDC via redstone-adapter.v1.tmplr.near, weight 2
aggregator median_low, min sources 1
proxy-gov-ixrp-ixlmusdc.v1.tmplr.nearNo
izec-ixlmusdc.v1.tmplr.nearProxy oracle proxy-oracle-izec-ixlmusdc.v1.tmplr.nearPyth (classic) be9b59d1… via pyth-oracle.near, weight 8
RedStone ZEC via redstone-adapter.v1.tmplr.near, weight 2
aggregator median_low, min sources 1
Pyth (classic) eaa020c6… via pyth-oracle.near, weight 8
RedStone USDC via redstone-adapter.v1.tmplr.near, weight 2
aggregator median_low, min sources 1
proxy-gov-izec-ixlmusdc.v1.tmplr.nearNo

Asset Identifiers

MarketCollateral assetDecimalsBorrow assetDecimalsProfiles applied
iada-ixlmusdc.v1.tmplr.nearnep245:intents.near:nep141:cardano.omft.near6nep245:intents.near:nep245:v2_1.omni.hot.tg:1100_111bzQBB65GxAPAVoxqmMcgYo5oS3txhqs1Uh1cgahKQUeTUq1TJu7mainnet, v1, irs-stable
ibtc-iethusdc-1.v1.tmplr.nearnep245:intents.near:nep141:btc.omft.near8nep245:intents.near:nep141:eth-0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48.omft.near6mainnet, v1, v1-collateral-ibtc, v1-borrow-iethusdc
ibtc-ixlmusdc.v1.tmplr.nearnep245:intents.near:nep141:btc.omft.near8nep245:intents.near:nep245:v2_1.omni.hot.tg:1100_111bzQBB65GxAPAVoxqmMcgYo5oS3txhqs1Uh1cgahKQUeTUq1TJu7mainnet, v1, irs-stable
idoge-ixlmusdc.v1.tmplr.nearnep245:intents.near:nep141:doge.omft.near8nep245:intents.near:nep245:v2_1.omni.hot.tg:1100_111bzQBB65GxAPAVoxqmMcgYo5oS3txhqs1Uh1cgahKQUeTUq1TJu7mainnet, v1, irs-stable
iethfxrp-ixlmusdc.v1.tmplr.nearnep245:intents.near:nep141:eth-0xce6170ea245dc8d1f275a710a062b70f125f0110.omft.near6nep245:intents.near:nep245:v2_1.omni.hot.tg:1100_111bzQBB65GxAPAVoxqmMcgYo5oS3txhqs1Uh1cgahKQUeTUq1TJu7mainnet, v1, irs-stable, v1-borrow-ixlmusdc
iethhemibtc-iethusdc.v1.tmplr.nearnep245:intents.near:nep141:eth-0x06ea695b91700071b161a434fed42d1dcbad9f00.omft.near8nep245:intents.near:nep141:eth-0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48.omft.near6mainnet, v1, irs-stable
iethwbtc-ixlmusdc.v1.tmplr.nearnep245:intents.near:nep141:eth-0x2260fac5e5542a773aa44fbcfedf7c193bc2c599.omft.near8nep245:intents.near:nep245:v2_1.omni.hot.tg:1100_111bzQBB65GxAPAVoxqmMcgYo5oS3txhqs1Uh1cgahKQUeTUq1TJu7mainnet, v1, irs-stable
iltc-ixlmusdc.v1.tmplr.nearnep245:intents.near:nep141:ltc.omft.near8nep245:intents.near:nep245:v2_1.omni.hot.tg:1100_111bzQBB65GxAPAVoxqmMcgYo5oS3txhqs1Uh1cgahKQUeTUq1TJu7mainnet, v1, irs-stable
ixlm-ixlmpyusd.v1.tmplr.nearnep245:intents.near:nep245:v2_1.omni.hot.tg:1100_111bzQBB5v7AhLyPMDwS8uJgQV24KaAPXtwyVWu2KXbbfQU6NXRCz7nep245:intents.near:nep245:v2_1.omni.hot.tg:1100_111bzQBB62XZkuam1hPr5wsG54FvwhYaPvecKwgZo1ZoKMWEXcE2n7mainnet, v1, irs-standard, v1-collateral-ixlm, v1-borrow-ixlmpyusd
ixlm-ixlmusdc-1.v1.tmplr.nearnep245:intents.near:nep245:v2_1.omni.hot.tg:1100_111bzQBB5v7AhLyPMDwS8uJgQV24KaAPXtwyVWu2KXbbfQU6NXRCz7nep245:intents.near:nep245:v2_1.omni.hot.tg:1100_111bzQBB65GxAPAVoxqmMcgYo5oS3txhqs1Uh1cgahKQUeTUq1TJu7mainnet, v1, irs-standard
ixlmcetes-ixlmusdc.v1.tmplr.nearnep245:intents.near:nep245:v2_1.omni.hot.tg:1100_111bzQBB5uBD3Wrr7pthp8XhJsreEcwTVnmjQ1wpbzkvHLEQf3ygS7nep245:intents.near:nep245:v2_1.omni.hot.tg:1100_111bzQBB65GxAPAVoxqmMcgYo5oS3txhqs1Uh1cgahKQUeTUq1TJu7mainnet, v1, irs-standard
ixlmdejaaa-ixlmusdc-1.v1.tmplr.nearnep245:intents.near:nep245:v2_1.omni.hot.tg:1100_111bzQBB66Lr9d7WU1sDna78SqG5x1ZraFjkpPdiYXjHFRnZJUhuV18nep245:intents.near:nep245:v2_1.omni.hot.tg:1100_111bzQBB65GxAPAVoxqmMcgYo5oS3txhqs1Uh1cgahKQUeTUq1TJu7mainnet, v1, v1-borrow-ixlmusdc
ixlmdejaaa-ixlmusdc-2.v1.tmplr.nearnep245:intents.near:nep245:v2_1.omni.hot.tg:1100_111bzQBB66Lr9d7WU1sDna78SqG5x1ZraFjkpPdiYXjHFRnZJUhuV18nep245:intents.near:nep245:v2_1.omni.hot.tg:1100_111bzQBB65GxAPAVoxqmMcgYo5oS3txhqs1Uh1cgahKQUeTUq1TJu7mainnet, v1, v1-borrow-ixlmusdc
ixlmdejtrsy-ixlmusdc-1.v1.tmplr.nearnep245:intents.near:nep245:v2_1.omni.hot.tg:1100_111bzQBB5y5yhcUCbDKaCx4zNjEHQbwLAdvwucCecVzC5Ub7uNKEb18nep245:intents.near:nep245:v2_1.omni.hot.tg:1100_111bzQBB65GxAPAVoxqmMcgYo5oS3txhqs1Uh1cgahKQUeTUq1TJu7mainnet, v1, v1-borrow-ixlmusdc
ixlmsolvbtc-ixlmusdc.v1.tmplr.nearnep245:intents.near:nep245:v2_1.omni.hot.tg:1100_111bzQBB5xzU1EsXby4ckez2qjWFTBiPoqHzZpPkq1Gr9gB7FQpeZ8nep245:intents.near:nep245:v2_1.omni.hot.tg:1100_111bzQBB65GxAPAVoxqmMcgYo5oS3txhqs1Uh1cgahKQUeTUq1TJu7mainnet, v1, irs-standard, v1-collateral-ixlmsolvbtc, v1-borrow-ixlmusdc
ixlmustry-ixlmusdc.v1.tmplr.nearnep245:intents.near:nep245:v2_1.omni.hot.tg:1100_111bzQBB5yT2A5maKJqJQsuNg7BA6VG4S4ZATpqmKYLwYBsfEfh6e7nep245:intents.near:nep245:v2_1.omni.hot.tg:1100_111bzQBB65GxAPAVoxqmMcgYo5oS3txhqs1Uh1cgahKQUeTUq1TJu7mainnet, v1, irs-standard
ixrp-ixlmusdc.v1.tmplr.nearnep245:intents.near:nep141:xrp.omft.near6nep245:intents.near:nep245:v2_1.omni.hot.tg:1100_111bzQBB65GxAPAVoxqmMcgYo5oS3txhqs1Uh1cgahKQUeTUq1TJu7mainnet, v1, irs-stable
izec-ixlmusdc.v1.tmplr.nearnep245:intents.near:nep141:zec.omft.near8nep245:intents.near:nep245:v2_1.omni.hot.tg:1100_111bzQBB65GxAPAVoxqmMcgYo5oS3txhqs1Uh1cgahKQUeTUq1TJu7mainnet, v1, irs-stable

Verifying a Market

Read the immutable configuration straight from the market:

near contract call-function as-read-only <market-address> get_configuration json-args {} network-config mainnet now

borrow_mcr_maintenance, borrow_mcr_liquidation, borrow_asset_maximum_usage_ratio, liquidation_maximum_spread, and borrow_interest_rate_strategy in the output correspond to the columns above; price_oracle_configuration names the oracle account and price identifiers. For a proxy-backed market, list the sources and quorum behind each identifier:

near contract call-function as-read-only <proxy-oracle-address> get_proxy json-args '{"id": "<price-id>"}' network-config mainnet now

Further health checks (current snapshot, borrow-asset metrics, cached prices, circuit-breaker state) are in Monitoring and Risk Management.

Deployment specs and state patches

A market is described by one spec file and deployed in two commands. There is no shell script: the spec is the source of truth, and everything that used to live in env.sh, market-args.json and proxy-*.json is derived from it.

deployments/alpha targets a mainnet registry, so both commands need --network mainnet — the CLI defaults to testnet. NETWORK and SIGNER_ID work in place of the flags.

tmplrmgr market plan  deployments/alpha/<market>.toml --out plan.json \
    --network mainnet --signer-id "$REGISTRY_OWNER" --public-key ed25519:…
tmplrmgr market apply --plan plan.json \
    --network mainnet --signer-id "$REGISTRY_OWNER" --sign-with keychain

The signer is not a personal account: registry.deploy asserts the registry's owner, and a proxy spec additionally requires it to equal governance.admin, which the mainnet profiles set to the registry itself.

plan reads the chain and writes a file; it sends nothing and takes no credential. apply sends what the file says.

Why two steps

The plan is a reviewable artifact. It lists every transaction, decodes the market configuration for reading, names the keys each new account will grant, and carries the results of every preflight check. Reviewing a deployment no longer means reading a shell script and trusting it matches four JSON files.

It is a record of a derivation, not an input: the file carries the spec it came from, and apply re-derives the steps and refuses anything that does not match. Editing the plan is therefore not a way to change a deployment — change the spec and re-plan. For something no spec can express, run the transaction yourself with the command that performs it (registry deploy, proxy-oracle governance create-proposal, storage deposit); each is typed and validated on its own.

Writing a spec

Shared values live in deployments/profiles/. A market file names the profiles it extends and states only what differs. Abbreviated — a market also needs a [borrow] leg and the [market] parameters the profiles above do not set; see any file under deployments/ for a complete one:

extends = ["../profiles/alpha.toml", "../profiles/irs-standard.toml"]
name = "my-market"

[oracle.direct]                    # reads an oracle that already exists
account_id = "pyth-oracle.near"

[collateral]
asset = "nep141:usdc.near"
price_id = "eaa020c6…"             # the oracle's own identifier
decimals = 6

Omit [oracle.direct] to deploy a dedicated proxy oracle instead. A proxy market names sources per asset and the deployment creates a governance contract, the oracle it owns, and the market — seven transactions, plus one storage registration per NEP-141 asset, rather than one.

Amounts

Every amount states its unit, and the tool does the scaling:

[market]
borrow_range            = { minimum = "1 atom" }
supply_range            = { minimum = "0.04 tokens" }
supply_withdrawal_range = { minimum = "0.04 tokens", maximum = "1000 tokens" }
origination_fee         = { Flat = "0 atoms" }

tokens counts whole units of the borrow asset, scaled by its decimals when the plan is built — "0.04 tokens" is four cents of a stablecoin whether it carries 6 decimals or 7. atoms counts the indivisible base units the chain stores, so "1 atom" says "no real floor" in a way "0.0000001 tokens" does not. All three ranges and both fees are denominated in the borrow asset; nothing is stated in collateral.

The unit is mandatory. A bare number is refused rather than guessed at, as is a tokens value with more decimal places than the asset can hold, or a fractional atom. Both spellings parse (1 atom, 1 atoms); the tool writes the plural.

This is what schema 5 changed. A schema 4 file wrote the same amounts as bare base-unit integers, which are still well-formed numbers — read as whole units they would be 10^decimals too large — so such a file is refused by version and must be re-authored, not renumbered.

Checking before and after

tmplrmgr spec check   deployments/alpha/<market>.toml --network mainnet
tmplrmgr market verify <account-id> --network mainnet \
    --governance-admin <account-id> \
    --against deployments/alpha/<market>.toml

Both modes verify. A direct market reconstructs without proxies or governance, so the two governance checks are skipped and everything else runs; --governance-admin is still required and means nothing there.

verify re-runs the preflight against what is actually on chain and exits non-zero on failure, so it can run on a schedule. That matters because the governance call that configures a price feed is dispatched detached: it reports success even when the oracle rejected the proxy, so deployed state is the only witness that a market can price anything.

Reading the report

Checks are printed to stderr as they run, grouped by what is being read, then summarized. The summary leads with the failures, in full, and lists what was skipped separately — a check that did not run proves nothing, and must never be counted as one that passed.

→ registry versions
  ok   registry.version.market          v1.3.0
  FAIL registry.version.oracle          `0.5.9` is not registered in v1.tmplr.near; the depl…

5 check(s): 3 passed, 1 skipped, 1 FAILED

FAILED
  registry.version.oracle
    `0.5.9` is not registered in v1.tmplr.near; the deploy would fail partway

Colour is used only on a terminal, and NO_COLOR turns it off. -q silences the report. stdout stays the machine-readable channel throughout, so spec check … >/dev/null leaves the report alone and … 2>/dev/null | jq leaves the JSON alone.

--skip-check <id> suppresses one verdict — every other check still runs, and the report records what the skip suppressed, so an override stays reviewable rather than reading as a pass. An id that matches no check is an error, since a typo would otherwise silently suppress nothing. Available on spec check, market plan and market apply.

Resuming

apply journals each step beside the plan as it lands. If a run is interrupted, re-running it skips what completed and continues from the first incomplete step. A plan truncated to its completed prefix is refused rather than reported complete: the re-derivation runs before the journal is consulted.

Patching contract storage

tmplrmgr patch builds one atomic transaction for a contract whose full-access key is still held: deploy the pinned PatchState WASM, apply guarded storage operations, then restore the exact local code or global-contract linkage.

Export complete, block-pinned contract storage before authoring guards:

tmplrmgr patch export <account> --out deployments/patches/<account>/<date>-<slug>.toml \
  --network mainnet

The export writes every contract-storage entry as schema-3 TOML and a sibling <stem>.blobs/ directory. Values are stored as deterministic files named from the SHA-256 of their raw keys. Planning separately re-fetches the pinned account metadata, access keys, code, and contract linkage. Existing spec or blob paths are never overwritten. A patch.state_complete check reports whether the trie fit in one request or required widening one-byte prefixes; incomplete or conservatively unaccountable state aborts without creating output.

Review and build the plan:

tmplrmgr patch plan deployments/patches/<account>/<date>-<slug>.toml \
  --out patch-plan.json --network mainnet \
  --signer-id <account> --public-key ed25519:…
tmplrmgr patch dry-run --plan patch-plan.json --network mainnet

patch dry-run reconstructs the target under its literal account ID in a fresh sandbox, installs the fetched code and complete state, and executes the exact reviewed tx.batch. Each view [[check]] is called before and after. An expect compares only the after JSON; a check without expect passes after a successful call and still reports its observed value. Before failures and before/after differences are diagnostic; after failures and expectation mismatches fail the check. JSON Patch diffs are present when both calls return JSON.

The dry-run prints one machine-readable JSON report on stdout, including the transaction, target code hash, every before/after view result, JSON diff, and check verdict. Reporter output, progress, diagnostics, and the digest go to stderr. Keep stdout dedicated to the report when piping it to review tooling. The completed replay is stamped into the same plan when no replay check fails. An apply-valid stamp requires every replay check to be non-skipped and passed; apply rejects stamps with skipped checks. The stamp binds the plan digest, semantic complete-state digest, target code hash, and verdicts; it records the sandbox chain ID for review context.

Apply only after reviewing both the plan and stamped replay:

tmplrmgr patch apply --plan patch-plan.json \
  --network mainnet --signer-id <account> --sign-with keychain

Apply re-derives the spec, live code/linkage, complete-state digest, and batch; state drift invalidates the plan. Without an explicit override it refuses a missing, stale, digest-mismatched, or failed patch.dry_run stamp. --skip-check patch.dry_run and --skip-check patch.state_complete are rejected. If local replay is unavailable and the operator accepts that risk, use the dedicated override:

tmplrmgr patch apply --plan patch-plan.json --no-dry-run \
  --network mainnet --signer-id <account> --sign-with keychain

--no-dry-run records patch.dry_run as explicitly skipped; all other preflight checks still run. Prefix deletes are expanded from one verified full snapshot and retain an in-receipt expectation for every concrete removal. Accounts containing record kinds the accounting reader cannot enumerate are rejected rather than silently treated as complete.

The plan is not self-contained: apply re-reads its canonical source spec and referenced files at their original paths. Dry-run views are sandbox evidence; check the live account separately after apply.

Schema-2 storage-only specs are not accepted. Review the authored operations and checks, set schema = 3, then rerun tmplrmgr patch plan; alternatively, export a fresh schema-3 spec with the command above.

Authored set and single-key remove operations should state expect. Use expect = "absent" for a fresh key; it compiles to an in-receipt absence guard. Keys and values use utf8, hex, base64, file, concat, sha256, json, or borsh byte expressions. file is relative to the declaring spec.

This is a privileged authorization checklist:

  • Confirm the target account, full-access signer, and plan public key.
  • Inspect the released PatchState 0.1.0 artifact and pinned SHA-256.
  • Confirm the batch receiver, spec target, and PatchState payload account match.
  • Inspect all view before/after values and diffs, including no-expect checks.
  • Verify the apply-time stamp binding and resolved-state re-derivation checks.
  • Authorize only after the complete arbitrary-storage write is understood.

Oracles

Templar Protocol relies on external price oracles to determine asset valuations when calculating collateralization ratios and performing liquidations. Every market operation that needs a price (borrowing, withdrawing collateral from a position with outstanding debt, and liquidating) reads the market's configured oracle account and fails closed if no acceptably fresh price is available.

Oracle Providers

ProviderStatusHow Templar uses it
Pyth NetworkLivePrimary price source. Newer markets read Pyth Lazer (marketed by Pyth as Pyth Pro) through Templar's Lazer adapter contract; markets deployed before the proxy oracle read Pyth's on-chain pull oracle (pyth-oracle.near) directly.
RedStoneLiveIndependent second source through Templar's RedStone adapter contract. RedStone is also the sole source for some tokenized real-world-asset feeds (for example tokenized treasury and fund products) that Pyth does not yet publish.
ChainlinkPlanned by end of 2026Will be added as an additional proxy oracle source.
AtlasPlanned by end of 2026Will be added as an additional proxy oracle source.

Where a market reads more than one provider, the sources are combined by a proxy oracle rather than by the market itself. Source weights, quorum, freshness bounds, and circuit breakers are configured per market and can be adjusted through the proxy oracle's timelocked governance.

Adding a new provider does not require changes to the market contract: a new adapter is deployed and registered as a source on the relevant proxy oracles.

How Markets Read Prices

Every market is configured with a single oracle account and a price identifier for each of its two assets:

#![allow(unused)]
fn main() {
pub struct PriceOracleConfiguration {
    /// Account ID of the oracle contract.
    pub account_id: AccountId,
    /// Price identifier of the collateral asset in the oracle contract.
    pub collateral_asset_price_id: PriceIdentifier,
    /// Collateral asset decimals, to convert the oracle price.
    pub collateral_asset_decimals: i32,
    /// Price identifier of the borrow asset in the oracle contract.
    pub borrow_asset_price_id: PriceIdentifier,
    /// Borrow asset decimals, to convert the oracle price.
    pub borrow_asset_decimals: i32,
    /// Maximum price age to accept from the oracle, after which the price
    /// will be considered stale and rejected.
    pub price_maximum_age_s: u32,
}
}

The market calls list_ema_prices_no_older_than on that account, the same read interface exposed by Pyth's NEAR contract. Templar's proxy oracle implements the same interface, so a market can read a proxy oracle, the Pyth contract, or the LST adapter without any change to the market code. Which one a market uses is visible in its get_configuration output.

Because this configuration is immutable, an existing market cannot be repointed to a different oracle account by an administrator. Markets deployed before the proxy oracle existed were migrated to proxy oracles through a reviewed, dry-run-verified storage patch (see Deploying a market); new markets are deployed reading a proxy oracle from the start.

Proxy Oracle

The proxy oracle is Templar's oracle aggregation and safety layer. Each market typically has its own proxy oracle and governance contract, deployed alongside the market through the registry.

The logic is split between a chain-agnostic kernel (aggregation, freshness, circuit breakers) and per-chain runtimes. The NEAR runtime serves Templar markets; a Soroban runtime with the same kernel serves Stellar consumers through SEP-40 adapters.

Price Pipeline

For each proxied price identifier, an update runs through the following stages:

  1. Sources. The proxy fetches each configured source asynchronously. A source is a Pyth Lazer feed, a classic Pyth feed, a RedStone feed, or a transformer (for example, a liquid-staking-token normalization that multiplies an underlying price by an on-chain redemption rate).
  2. Freshness filter. Prices older than the configured max_age or timestamped further in the future than max_clock_drift are discarded before aggregation, so a stale or pre-manufactured price can never be replayed into the aggregate.
  3. Aggregation. Surviving prices are combined by the proxy's aggregator. The production configuration uses a weighted median: median_low for collateral assets and median_high for borrow assets, so that any tie or ambiguity resolves to the valuation that is safer for the protocol. A min_sources quorum is enforced; if fewer fresh sources than the quorum survive, the update fails and nothing is cached. A priority aggregator (first fresh source wins) is also available.
  4. Circuit breakers. The aggregated candidate is checked against the feed's circuit breaker set. An enforced breaker that trips blocks the feed; a breaker running in observe-only mode records the trip and emits an event without blocking.
  5. Cache. The accepted price is cached with its status. Markets read only accepted, fresh cached prices; a missing, blocked, failed, or stale cache entry reads as no price, and the market operation fails closed.

Standard mainnet feeds are configured with a Pyth Lazer source at weight 8 and a RedStone source at weight 2 with min_sources = 1. With that weighting the Pyth price determines the aggregate while both sources are fresh, and RedStone keeps the feed alive if Pyth is stale or unavailable. Because the quorum is one, a single fresh source can determine the price when the other is stale, and the higher-weighted source determines it while both are fresh: this quorum provides liveness, not manipulation resistance. For a feed configured this way, the freshness filter and the enforced circuit breakers are the defence against a compromised provider. Weights, quorum, and sources are governed per feed and can be raised (for example to a quorum of two once a third provider is live) as additional providers come online.

Circuit Breakers

Circuit breakers are the on-chain defence against oracle manipulation and runaway prices. They evaluate each candidate price against the feed's accepted history (not against the previous raw sample, which an attacker may already have manipulated). Four rule types are available and can be combined:

RuleTrips when
StepwiseChangeA single update moves more than max_relative_change from the last accepted price. Catches sudden jumps.
MonotonicRunAt least max_streak consecutive accepted updates move in the same direction by at least min_relative_step_change each. Catches staged ramps.
WindowedChangeDeltaThe mean of the most recent window_len observations differs from the mean of an earlier window by more than max_relative_mean_change.
CumulativeChangeThe price drifts more than max_relative_change from an immutable baseline captured when the rule was installed.

In addition to automatic rules, an operator holding the ManualTripper role can trip a feed manually with no timelock. Because market contracts have no pause function, the manual trip is the emergency brake for an immutable market: while a feed is blocked, borrowing, collateral withdrawal against debt, and liquidation on every market reading that feed stop, while supply withdrawals, repayments, and collateral withdrawal from debt-free positions continue.

Each feed keeps up to 32 accepted observations of history and up to 16 breakers. Breakers can be installed in observe-only mode (they trip and emit events but do not block) before being enforced. Re-arming a tripped breaker is a separate governed action, so a block cannot be lifted by the same automation that detected the problem.

Every configuration change, trip, re-arm, and enforcement change emits an on-chain event, which is what Templar's monitoring watches.

Governance and Timelocks

Each proxy oracle is owned by its own governance contract. Feed configuration (sources, weights, aggregator, freshness filter, circuit breaker rules) and contract upgrades change only through proposals that mature under a per-method timelock and can only be executed by an account holding the role that method requires. Circuit breaker operation is different: tripping and untripping a feed, re-arming a breaker, and switching enforcement on or off are role-gated actions with no delay.

Timelocks and roles are configured per governance contract. The table below is the typical production setup; it is not guaranteed to apply to every proxy oracle, so confirm the policy in force on a specific contract as shown at the end of this section.

ActionTimelockRequired role
Trip or untrip a feed manuallynone (immediate)ManualTripper
Re-arm a tripped breaker; enable or disable enforcementnone (immediate)CircuitBreakerOperator
Set or change a feed's sources, weights, aggregator, or freshness filter24 hoursProxyConfigurationManager
Add, remove, or reconfigure circuit breakers24 hoursProxyConfigurationManager
Any other proxy oracle method (conservative default)72 hoursAdmin
Upgrade the proxy oracle contract code72 hoursAdmin
Change the governance policy (timelocks, roles)48 hoursAdmin
Upgrade the governance contract itself168 hoursAdmin

The immediate actions include their risk-increasing inverses: a ManualTripper can untrip a feed and a CircuitBreakerOperator can disable enforcement without delay. Those roles are therefore held by the same multisig as Admin, every use emits an on-chain event that monitoring alerts on, and a change to a breaker's rules still waits out the configuration timelock. A proposal's timelock is fixed when it is created, and shortening any timelock must itself mature under the timelock being shortened, so governance cannot be weakened faster than it currently protects. The Admin role is held by Templar's 2-of-3 multisig; see Protocol Governance.

The policy in force on a specific proxy oracle can be read from its governance contract:

near contract call-function as-read-only \
    proxy-gov-<market>.v1.tmplr.near get_governance_policy \
    json-args '{}' network-config mainnet now

and pending proposals with list_proposals and get_proposal.

Updating Proxy Prices

The proxy oracle is a pull design: someone must refresh it before a price-dependent action.

  1. Push fresh data to the underlying adapters (a signed Pyth Lazer payload to the Lazer adapter, a signed RedStone data package to the RedStone adapter, or a Pyth proof to pyth-oracle.near).
  2. Call update_prices on the proxy oracle with the price identifiers the market uses. The proxy fetches the sources, runs the pipeline above, and caches the result.
  3. Perform the market action.

Templar's relayer and liquidation bots do this automatically ahead of the actions they submit, and the Templar gateway exposes oracle.updatePrices to perform every required update for a market in one call. Integrators submitting their own transactions must do the same. For a market configured with a proxy oracle, reading the underlying Pyth or RedStone contracts directly bypasses the aggregation and circuit-breaker guarantees and is not the price the market will use; for a legacy market that reads pyth-oracle.near or the LST adapter directly, that configured contract is the market price.

Inspecting a Proxy Oracle

# Which price identifiers this proxy serves
near contract call-function as-read-only \
    proxy-oracle-<market>.v1.tmplr.near list_proxies \
    json-args '{}' network-config mainnet now

# Sources, weights, aggregator, and freshness filter for one feed
near contract call-function as-read-only \
    proxy-oracle-<market>.v1.tmplr.near get_proxy \
    json-args '{"id":"<price-id>"}' network-config mainnet now

# Circuit breakers, their state, and accepted history for one feed
near contract call-function as-read-only \
    proxy-oracle-<market>.v1.tmplr.near get_proxy_circuit_breaker_set \
    json-args '{"id":"<price-id>"}' network-config mainnet now

# Latest cached result and its status (accepted, blocked, stale, failed)
near contract call-function as-read-only \
    proxy-oracle-<market>.v1.tmplr.near get_cached_proxy_price \
    json-args '{"id":"<price-id>"}' network-config mainnet now

Oracle Addresses

Mainnet

ContractAccount IDPurpose
Proxy oracle (one per market)proxy-oracle-<market>.v1.tmplr.nearAggregated, circuit-breaker-protected feed read by the market <market>.v1.tmplr.near. Example: proxy-oracle-ixlmdejaaa-ixlmusdc-2.v1.tmplr.near.
Proxy oracle governance (one per proxy)proxy-gov-<market>.v1.tmplr.nearTimelocked governance for the matching proxy oracle. Example: proxy-gov-ixlmdejaaa-ixlmusdc-2.v1.tmplr.near.
Pyth Lazer adapterpyth-lazer.v1.tmplr.nearVerifies signed Pyth Lazer payloads (ed25519, trusted signer set, freshness window, per-feed anti-replay) and serves them by Lazer feed ID. Updates are permissionless because authenticity is cryptographic.
RedStone adapterredstone-adapter.v1.tmplr.nearVerifies RedStone signed data packages against the configured signer threshold and serves them by feed ID.
Pyth (classic pull oracle)pyth-oracle.nearPyth's own contract. Read directly by markets deployed before the proxy oracle, and usable as a proxy source.
LST oracle adapterlst.oracle.tmplr.nearLegacy adapter deriving liquid-staking-token prices; see below.

The exact oracle account and price identifiers a market uses are always available from the market's get_configuration view; see Smart Contract Addresses for the market list. A market can also read a proxy oracle that was deployed separately from it (for example ixlmustry-ixlmusdc.v1.tmplr.near reads proxy-oracle-ixlmustry-ixlmusdc.v1.tmplr.near, deployed on its own), so the governance account is not always proxy-gov-<market>; the authoritative link is the proxy oracle's owner, returned by its own_get_owner view.

Testnet

ContractAccount ID
Pyth (classic pull oracle)pyth-oracle.testnet

Price Identifiers

  • Proxy oracle feeds use a 32-byte identifier chosen when the feed is configured. Use list_proxies on the proxy oracle to enumerate them, and get_proxy to see which underlying feeds each one aggregates.
  • Pyth price identifiers can be found on Pyth's documentation site. Pyth Lazer feeds are addressed by their numeric Lazer feed ID.
  • RedStone feeds are addressed by their feed ID (for example BTC, USDC, or a fundamental-value feed such as deJAAA_FUNDAMENTAL/USD).

LST Oracle Adapter

For Liquid Staking Tokens (LSTs), Templar uses a custom oracle adapter (lst.oracle.tmplr.near) to derive the LST price from the underlying asset price and the staking contract's redemption rate. The same normalization is available inside the proxy oracle as a transformer source, which is the path new LST markets use.

Update Frequency and Freshness

  • Update model: Pull. Prices are pushed on-chain as needed by relayers, bots, and users, and the proxy oracle is refreshed before price-dependent operations.
  • Source freshness: Enforced per feed by the proxy oracle's freshness filter before aggregation.
  • Market staleness bound: Each market rejects prices older than its configured price_maximum_age_s, typically 60 to 120 seconds.
  • Confidence and smoothing: Markets consume Pyth-style prices with a confidence interval and use exponentially-weighted moving average (EMA) prices where the source provides them.

Price Validation

Markets validate price freshness before use. If no fresh, accepted price is available, operations that require prices (borrow, collateral withdrawal against debt, liquidate) fail, and callers must refresh the oracle first. Supply deposits, supply withdrawals, repayments, and collateral withdrawals from positions with no liability do not depend on the oracle.

Oracle Security Measures

  • Multiple independent sources: Pyth and RedStone are aggregated per feed with a configurable quorum. With the standard quorum of one this guarantees liveness through a single-provider outage; raising the quorum trades liveness for manipulation resistance.
  • Freshness filters: Stale and future-dated source prices are discarded before aggregation.
  • Conservative aggregation: Weighted median, biased low for collateral and high for liabilities.
  • Confidence intervals: Pyth prices include confidence bands. The lower bound is used for collateral valuations and the upper bound for liability valuations.
  • Circuit breakers: Automatic rules against jumps, ramps, and drift, plus an instant manual trip. See Circuit Breakers.
  • Timelocked governance: No feed configuration can change without a maturing proposal; only risk-reducing actions are immediate.
  • Maximum age limits: Markets reject stale price data using a configurable expiration duration.
  • Fail-closed reads: A blocked, failed, or stale feed reads as no price, never as the last known price.
  • Monitoring: Oracle divergence and downtime alerts run continuously; see Monitoring and Risk Management.

Oracle Failure Scenarios

Temporary Outage of a Provider

  • If one provider is stale but the feed's quorum is still met, the aggregate continues from the remaining fresh sources.
  • If no fresh source meets the quorum, the feed reads as no price and price-dependent operations pause until data returns.
  • Users can still withdraw supply, repay debt, and withdraw collateral from positions with zero liability.

Circuit Breaker Trip

  • Automatic trips and manual trips have the same effect: the affected feed is blocked and every market reading it stops borrowing, collateral withdrawal against debt, and liquidations.
  • Positions are not liquidated on a blocked price. When the feed is re-armed, liquidations resume against the newly accepted price.
  • Trips are announced on the public alerts channel; see Monitoring and Risk Management.

Price Manipulation Attack

  • An attacker who controls a source must move the weighted median (with the standard weighting the Pyth feed determines it, and a lone fresh source determines it while the other is stale), survive the freshness filter, and pass every enforced breaker in the same update. The breakers compare against accepted history, so a manipulated prior sample does not weaken them.
  • Markets reject stale prices automatically, and defensive valuations (lower bound for collateral, upper bound for liabilities) protect solvency in most cases.
  • The required maintenance collateralization ratio protects borrowers from unexpected liquidation in most cases.

Roadmap

Templar plans to add a third and fourth independent provider by the end of 2026. The classic-Pyth migration is also planned but has no separate published completion date.

  • Add two providers and raise the per-feed quorum. Chainlink and Atlas are planned as the third and fourth providers. With Pyth and RedStone as the only sources, min_sources = 1 is what keeps a feed live through a single-provider outage. Once a third independent provider is configured on a feed, the quorum can be raised to two so that no single provider determines the price on its own. The change is a timelocked configuration proposal on each proxy oracle's governance contract.
  • Retire classic Pyth reads in favour of Pyth Lazer. Several proxy oracles still read pyth-oracle.near; the shared asset profiles in deployments/profiles/ already describe the Lazer configuration each feed migrates to. Each migration is a timelocked configuration proposal.

Protocol Governance

This document outlines the administrative structure and governance controls of Templar Protocol: what can and cannot be changed, by whom, and with what delay.

Summary

ComponentMutabilityControlled byTimelock
Market contracts (NEAR)No admin functions, no upgrade method, no pause. Storage can be patched only while the deployer's full-access key is retained (see below).Nobody through the contract; the Templar DAO multisig (2-of-3) while a deployer key is retainedn/a
Proxy oraclesFeed configuration and code upgradeable through a dedicated governance contract. Until the deployer's full-access key is deleted, the key holder can also change the account directly (see below).Either the vault curators or the Templar DAO multisig (2-of-3), per proxy oracle; retained deployer keys are also held by the DAO multisig24h to 168h by action; emergency trips immediate; not enforced against a retained deployer key
RegistryOwned. Owner can register versions, deploy new contracts, and upgrade the registry's own code. Cannot touch deployed markets.Templar DAO multisig (2-of-3)Two-step finalize
Curated vaults (Stellar)Governed; runtime upgradeable through the vault governance contractVault governance admin, curator, and Sentinel per vaultConfigurable per action; risk-reducing actions immediate

Administrative Multisig

Mutable Templar contracts on NEAR are by default administered by templar.sputnik-dao.near, a Sputnik DAO (v2) whose sole council role holds three signers at a 2-of-3 threshold. Administrative actions are executed as DAO function-call proposals against the target contract; no signer can act alone.

Changing the signer set is itself a governed policy change: a council member submits a ChangePolicy (or AddMemberToRole / RemoveMemberFromRole) proposal, the remaining members vote, and the DAO applies the change to itself when the threshold is reached. Signer additions and removals are announced on the official channels.

DAO-approved MPC signing

Some administrative actions are not function calls a DAO can make directly — adding or removing an account's access keys, deploying code, or a transaction that must originate from the account itself. For those, an operational account can hold a full-access key derived by the NEAR Chain Signatures contract (v1.signer) for the DAO. The key never leaves the MPC network: to use it, a council member proposes a sign call carrying the hash of the exact payload (a NEP-366 delegate action or a transaction), voters review the payload (carried in the proposal, or shared alongside it when it should not be public before execution) against that hash, and once the proposal executes the MPC returns a signature that anyone can relay. The DAO threshold therefore governs these actions exactly as it governs direct calls, with two additional dependencies: the MPC network's availability and its key derivation, both audited by NEAR One. Which accounts hold a derived key is part of the deployment records.

Market Contracts

Market contracts have no administrative functions:

  • They operate autonomously based on their initial configuration, which is immutable after deployment.
  • There is no method to pause, upgrade, or modify market parameters.
  • There is no privileged access to user funds.

At the account level, the registry adds the deployer's full-access key to each new market account. While that key is retained, contract storage can be modified through the reviewed, sandbox-replayed patch process in Deploying a market; this is how legacy markets were migrated to proxy oracles. A market account with no access keys cannot be changed by anyone. Check a market's keys with:

near account list-keys <market-address> network-config mainnet now

Deployer Key Retention

When the registry deploys a market (or a proxy oracle and its governance contract), it adds the deploying signer's full-access key to the new account and logs a warning that it has done so; tmplrmgr includes that key by default and lists every key each account will receive in the deployment plan. The key exists so that contract storage can be repaired through the reviewed patch process while a market is new; it was used in August 2026 to migrate legacy markets to proxy oracles. The key is an ordinary NEAR full-access key: the account enforces nothing beyond a valid signature, so the key can deploy code, patch storage, or change keys directly. While retained, these keys are held by templar.sputnik-dao.near, whose 2-of-3 council threshold prevents one signer from acting alone; DAO-approved MPC signing is how a DAO exercises a full-access key. The reviewed, sandbox-replayed patch process and DAO sign-off remain operational policy rather than controls enforced by the target account.

Policy: retained deployer keys are deleted after a bake-in period. This applies to every account the registry gives the key to: the market and, where one is deployed alongside it, its proxy oracle and governance contract. The bake-in period for a market ends once the curators allocating to it and the issuers of its assets have signed off on the deployment. The DAO then makes one key-removal call per contract account; each removal is reported in the public alerts channel. After its key is deleted, a market becomes immutable at the account level as well as at the contract level: no storage patch is possible and any fix requires a new market version and user migration. A proxy oracle or governance contract can still be changed, but only through the governance contract's timelocked proposals.

Anyone can check whether an account still carries an access key with the near account list-keys command above; an empty list means the key has been deleted.

New market versions are deployed to new account IDs through the registry; old versions cannot be overwritten. When a new version of the market contract is available, it is uploaded to the registry contract and new markets are deployed from it. Existing markets are not upgraded and funds are not automatically migrated, so users migrate their positions individually.

Because a market cannot be paused, the emergency control for a market that reads a proxy oracle is its oracle: tripping the circuit breaker on the feed freezes borrowing, collateral withdrawal against debt, and liquidations on that market, while supply withdrawals and repayments continue. Older markets that read Pyth's contract directly have no such control.

Proxy Oracle Governance

Each proxy oracle is owned by its own governance contract (proxy-gov-<market>.v1.tmplr.near). Every change is a proposal that matures under a per-method timelock and can only be created and executed by an account holding the required role. The policy is set per governance contract; the table below is the typical production setup, not a guarantee for every contract:

ActionTimelockRequired role
Trip or untrip a feed manuallynoneManualTripper
Re-arm a tripped breaker; enable or disable enforcementnoneCircuitBreakerOperator
Configure a feed's sources, weights, aggregator, freshness filter, or circuit breakers24 hoursProxyConfigurationManager
Any other proxy oracle method (default)72 hoursAdmin
Upgrade the proxy oracle contract72 hoursAdmin
Change governance policy (timelocks, roles)48 hoursAdmin
Upgrade the governance contract itself168 hoursAdmin

The immediate operator actions include their risk-increasing inverses (untripping a feed, disabling enforcement); those roles are held by the DAO multisig and every use is alerted. Shortening a timelock must itself mature under the timelock being shortened, so the policy cannot be weakened faster than it currently protects. The Admin role is held by the DAO multisig. Always confirm the policy in force on a specific proxy oracle with get_governance_policy on its governance contract, and pending proposals with list_proposals.

Registry Contract

The registry is an owned contract; its owner is the DAO multisig. The owner can:

  • Register a new contract version (add_version, finalized in a second step) from an audited release.
  • Remove a version so it can no longer be deployed.
  • Deploy new markets and proxy oracles from registered versions.
  • Upgrade the registry's own code.

The registry has no authority over contracts it has already deployed: it cannot modify, pause, or upgrade a live market. Registering a version does not change any existing deployment.

Curated Vault Governance

Stellar vaults are governed by a per-vault governance contract with per-action timelocks, a curator who sets allocation policy, and an independent Sentinel that can pause and tighten restrictions immediately but cannot unpause or accept proposals. Risk-increasing changes (cap increases, new markets, fee increases, unpause, role changes, upgrades) are timelocked; risk-reducing changes execute immediately. See the Stellar Vault Curator Guide for the full rules.

Emergency Procedures

Markets are immutable once deployed. If a bug is discovered:

  1. Price-dependent operations on affected markets that read a proxy oracle can be frozen immediately by tripping the circuit breaker, and Templar's bots are halted.
  2. A patched version of the code is audited, registered in the registry, and deployed to new market accounts.
  3. Users migrate their funds individually. Supply withdrawal requests and repayments on the old market remain available throughout.

Contract code changes follow the full audit-and-multisig path even during an incident; there is no hotfix bypass. To facilitate migration swiftly and securely, users are encouraged to monitor all official communication channels and the public alerts channel for announcements. The full procedure is documented in the emergency runbooks.

Transparency and Monitoring

Templar contracts are open-source, with the source code available on GitHub. All completed audit reports are available in the Templar audits folder and summarized on the Security page. Deployed contracts can be verified against the source; see Contract Verification. Governance events on proxy oracles, vaults, and the registry are monitored and alerted; see Monitoring and Risk Management.

Stellar Curated Vaults

Curated vaults let depositors earn lending yield without managing positions themselves. A depositor supplies one asset to a vault on Stellar and receives transferable shares; a professional curator decides which markets the pooled assets are lent into and under what limits, and an independent Sentinel can halt the vault at any time. This page explains how a vault works from the depositor's side. Operators should read the Stellar Vault Curator Guide; the governance model is summarized in Protocol Governance.

Overview

A vault accepts a single SEP-41 asset (for example USDC on Stellar) and issues SEP-41 vault shares in return. The vault exposes ERC-4626-style deposit, mint, withdraw, redeem, and preview methods through a Soroban proxy, so wallets and integrators can treat it like any tokenized vault.

The core accounting identity is:

total_assets = idle_assets + external_assets
  • Idle assets are tokens the vault holds directly. They pay out deposits, atomic withdrawals, and queued withdrawals.
  • External assets are the value of the vault's positions in markets, reported through one adapter per market route (a Blend pool adapter, or a custodial adapter for off-chain routes).
  • Share price is total_assets / total_shares (with small virtual offsets that make the first deposit's price manipulation-resistant). Yield from markets raises external_assets and therefore the share price; losses lower it.

Adapter values are refreshed by the vault's operators rather than read live on every call, so a preview can lag a market move until the next refresh.

Depositing

deposit takes assets and mints shares at the current share price; mint asks for an exact number of shares. Both are atomic. There is no configurable vault-wide deposit cap on chain: max_deposit and max_mint are bounded only by the vault's pause and operation state and by arithmetic headroom, so a headline deposit limit a curator publishes is an operational limit. Deposits can be gated by restrictions (a whitelist or blacklist of accounts) that governance or the Sentinel may apply; allocation caps apply to routes and cap groups, not to deposits. Preview methods (preview_deposit, preview_mint) return the expected outcome before signing.

Withdrawing

There are two exit paths, and the difference matters:

  • Atomic withdrawal (withdraw, redeem, and the slippage-protected atomic_withdraw / atomic_redeem) settles in one transaction from idle assets only. It never pulls liquidity back from a market. max_withdraw and max_redeem can therefore be zero while your shares are fully backed by assets deployed in markets.
  • Queued withdrawal (request_withdraw) escrows your shares and records a fixed asset claim at the share price at request time. After a cooldown (one hour by default; the vault's actual value is a governance parameter) an allocator recalls liquidity from markets if needed and executes the queue head. Requests are paid in order, in full or not at all; there is no partial payout and no user-side cancellation. The queue does not reserve idle assets against atomic exits, so curators are expected to keep enough idle liquidity for outstanding claims.

There is no forced exit mechanism: a vault cannot compel a market to return liquidity faster than the market's own withdrawal rules allow.

Fees

Vaults may charge two fees, both paid by minting new shares to a fee recipient (which dilutes existing holders rather than moving tokens):

FeeBasisMaximum
ManagementTime-weighted on assets under management, accrued regardless of performance5% per year
PerformanceGrowth in assets since the last fee checkpoint; zero in flat or losing periods50% of profit

Two details depositors should understand:

  • The performance fee is measured since the last checkpoint, not above an all-time high-water mark. After a loss, the recovery back to the previous level is chargeable.
  • A growth-rate cap can limit how quickly assets are allowed to count towards fee accrual, which bounds the fee impact of a sudden inflow or a mis-reported adapter value.

Fee increases and recipient changes are timelocked; decreases execute immediately.

Caps and Cap Groups

The curator sets a per-market cap on how much of the vault may be allocated to each route, and can group correlated routes under a shared cap group with an absolute limit, a relative limit (a share of total assets), or both. The effective ceiling for a group is the lower of the two. Raising a cap, adding a market, or changing group membership is timelocked; lowering a cap, including to zero, is immediate.

Roles and Addresses

Every vault has four roles. The addresses that hold them are specific to each vault and published in that vault's own documentation (see the live example below); verify them on chain before relying on them.

RoleCanCannotAddress
Governance adminSubmit and accept governance proposals: caps, fees, roles, restrictions, upgrades, timelock changes. May be a Stellar account or a multisig contract.Bypass a timelock; pause (only the Sentinel can).See the vault's documentation
CuratorSet allocation policy within governance-approved caps; act as an allocator.Raise a cap or add a market without the timelock.See the vault's documentation
AllocatorMove assets between the vault and its markets, refresh adapter values, execute ready queued withdrawals, abort a stuck operation.Change policy or fees.See the vault's documentation
SentinelPause the vault, tighten restrictions, revoke pending operational proposals, and use emergency recovery, all immediately.Unpause, relax restrictions, or accept proposals.See the vault's documentation

Timelocks are configured per action kind between 0 and 30 days, chosen at deployment. As a rule, risk-increasing changes are timelocked and risk-reducing changes are immediate: unpausing, fee increases, cap increases, new markets, role changes, and upgrades wait; pausing, fee decreases, cap decreases, and timelock increases do not. The governance admin can permanently disable an action kind (abdicate), which is irreversible. The full rules are in the curator guide's exact timing rules.

Risks

  • Market risk: the vault's assets are lent into markets; a market's bad debt or liquidity shortfall reduces external_assets and the share price.
  • Adapter and custody risk: a Blend adapter exposes the vault to the Blend pool it targets. A custodial adapter forwards assets to a custodian, and its reported value is set by that custodian, so the custodian's controls, reporting cadence, and liquidity-return procedure are inside the trust boundary. The custodial adapter was out of scope of the Halborn vault audit.
  • Liquidity risk: atomic exits depend on idle liquidity; queued exits depend on allocators recalling funds and on the markets' own withdrawal rules.
  • Governance and key risk: a vault deployed with zero-duration timelocks gives its admin immediate control over every parameter. Check the timelocks in force before depositing. Vault runtimes are upgradeable through governance under the upgrade timelock; verify the controlling addresses.
  • Fee risk: see the checkpoint note under Fees.

Checking a Vault

Anyone can read a vault's state through its ERC-4626 proxy with the Stellar CLI:

# Total assets under management and shares outstanding
stellar contract invoke --id <vault-4626-proxy-id> --network mainnet -- total_assets
stellar contract invoke --id <vault-4626-proxy-id> --network mainnet -- total_supply

# The underlying asset contract, and what one share is worth
stellar contract invoke --id <vault-4626-proxy-id> --network mainnet -- asset
stellar contract invoke --id <vault-4626-proxy-id> --network mainnet -- convert_to_assets --shares 10000000

# How much can be withdrawn atomically right now for an owner
stellar contract invoke --id <vault-4626-proxy-id> --network mainnet -- max_withdraw --owner <G...>

Governance state (the proposal queue, timelocks, and roles) is read from the vault's governance contract; the curator guide shows the tmplr-soroban-vault governance queue and governance explain commands for that. Vault events (deposits, withdrawals, allocations, fee accruals, pauses) are emitted on chain and are part of the monitoring coverage.

Live Example: Bizantine Labs tBizUSDC-CORE

Bizantine Labs publishes a complete specification for tBizUSDC-CORE, a USDC vault on Stellar built on Templar's Soroban vault framework. Its configuration illustrates useful vault controls: a separate Sentinel and NAV reporter, explicit withdrawal and refresh cooldowns, directional governance timelocks, and caps for every route.

The values below are the configuration Bizantine publishes. Verify the live contracts before depositing. Bizantine also discloses that the combined admin, curator, and adapter-admin role is currently a single Fordefi-custodied key, adapter upgrades have no on-chain timelock, and independent reconciliation of the full address set remains a pre-funding gate.

Configuration

ParameterPublished value
Deposit assetUSDC on Stellar
Management fee0%
Performance fee15%
Growth-rate cap10% per year
Queued-withdrawal cooldown1 hour
Idle-resync cooldown120 seconds
Governance timelock24 hours, directional: risk-increasing changes wait; risk-reducing changes are immediate
RestrictionsNone; deposits are open, so the $1 million pilot cap is an operational limit rather than an on-chain deposit cap
Target allocation10% idle, 20% Blend, 40% BTC, 25% XLM, 2.5% XRP, 2.5% ZEC
Aggregate Templar-market cap70% of NAV

Source: Bizantine's Core Parameters, Sleeve Design, and Operating Controls.

Roles

RoleStellar accountPublished control
Admin, curator, and adapter adminGAXHOW2QMS2R3OD6MPSWMBE3XVYZEL5BFGG2BBPTINP4D37MGF64IM2PSingle Fordefi-custodied key; governance proposals, allocation policy, and adapter administration
SentinelGAHJUZUQ6D3YUJTY4LPMMQCPNEJW46LA3GUNSOUWPDF5EZLDI3AMKPTWSeparately custodied; may pause and tighten restrictions, but cannot relax them or control adapter upgrades
Custodian and NAV reporterGBCF7WMYE6KUOKU5DHCZBIWHD6UANXI6XR25FNKPKSVKBDZUHV3MEBGKSeparate Fordefi vault; reports assets for the custodial routes
AllocatorGBZCCMTR4I3MOIQM4TOLDU3PNONUQLWXTIZGZ5FVOZDNMJ7UG7RMKTUEExecutes allocator and rebalancer transactions; shares the admin's Fordefi vault
TTL keeperGC4JT5SKX5MKDYMCXNPXQCTZ73FRCCBTKMQRUJ7MYZXJR46WFRDHDMD3Low-privilege account used only to extend contract TTLs

Source: Bizantine's Roles and Addresses.

Core Contracts

ContractStellar contract ID
VaultCBH7TKSKKYF2AXSMRUCM5RATSB22PVZPBVWN6ZDCHCH37TKR3DKE4XAA
Share tokenCCZF6EUIP2ZYSDX6SXMJCIYDQBXKJWMFJ6OJCYBGFZVT4RSK67JIQ2GW
GovernanceCBPN2FYGGUFUYL73NAIQOJTVGGDZLHW6D4L3M2ING4NPYPHPZS2QK3TU
ERC-4626 proxyCB6XEPVIX4GGQC7M7WU3JI4VCJEDH43SCIWZY6265S3LMZQGOXDUTGX5
Curator proxyCCBFW24W4K3D6M6IXE4PDYN262B3H4FKJ3YDGJVDQREGNFZ6ICCB7GGV
USDC asset contractCCW67TSZV3SSS2HXMBQ5JFGCKJNXKZM7UQUWUZPUTHXSTZLEO7SJMI75
Blend Capital USDC poolCAJJZSGMMM3PD7N33TAPHGBUGTB43OC73HVIK2L2G6BNGGGYOSSYBXBD

Routes and Caps

RouteAdapter contractTarget allocationPublished cap
Blend Capital USDCCDWB5P44ESHPS47F4USHICZ4O2IPKCBCRTDDWFXVZZDP7H43MTBQQQZO20%400,000 USDC and 40% of NAV
Templar BTC/USDCCBGZL4EHE77GJ23VD47WDRC4XBXTNFQPG3PSXTQJBGPVTK4WYPRWFVDP40%400,000 USDC and 40% of NAV
Templar XLM/USDCCC2WFNZPXZHKTPFCPWLFXGDLEV2YD344MEN72XGUUMXUHY7PDDTCA5TV25%250,000 USDC and 25% of NAV
Templar XRP/USDCCCWURNFYN4OHUYDKQGLOCBZ4ABX2ILMVFGT6V4UJ2SGF3FY7ZNPO7IWH2.5%25,000 USDC and 2.5% of NAV
Templar ZEC/USDCCAVFJ5AETBAC52ZNUGIWJSLOHPT43S2HPP4OAFWNBPYINOK4IOTFWR7K2.5%25,000 USDC and 2.5% of NAV

The four Templar routes use custodial adapters: assets away from Stellar are represented by signed NAV reports, so the custodian and reporting process remain inside the trust boundary. Source: Bizantine's Protocol Address Appendix and Sleeve Design.

Stellar Vault Curator Guide

This is the operator runbook for Templar vaults on Stellar/Soroban. The tmplr-soroban-vault CLI and its deployment manifest are the supported curator interface for deployment, governance, allocation, withdrawal servicing, accounting maintenance, and TTL renewal.

Scope

The separate NEAR vault executor is not a deployed or audited curator surface and is not an operations reference for this guide. A Stellar vault adapter may represent a route that ultimately leaves Stellar, but the vault, shares, governance, accounting, and curator actions described here remain on Stellar.

Authoritative references

What a curator operates

A Templar Stellar vault is a single-asset vault with ERC-4626-compatible deposit, mint, withdraw, redeem, conversion, and limit semantics exposed through a Soroban proxy. Depositors supply one SEP-41 asset and receive transferable SEP-41 vault shares. Curators configure adapter-backed markets; allocators move pooled assets between the vault's idle balance and those markets.

A deployed stack contains:

  • Vault runtime — canonical custody, accounting, state machine, RBAC, withdrawal queue, and applied policy state.
  • Share token — the SEP-41 receipt token. Only the vault can mint and burn shares for vault flows.
  • Governance contract — proposal submission, per-action timelocks, acceptance, revocation, and irreversible abdication.
  • ERC-4626 proxy — user-friendly deposit, mint, atomic withdraw, redeem, and preview methods.
  • Curator proxy — the typed curator-facing proxy included in a full stack.
  • Adapters — one contract per market route, such as a Blend pool adapter or a custodial adapter.

The runtime uses the shared templar-vault-kernel state machine, but all operational calls in this guide target the Stellar contracts through tmplr-soroban-vault or stellar contract invoke.

Accounting model

The core invariant is:

total_assets = idle_assets + external_assets
  • idle_assets are underlying tokens held by the vault. They fund deposits, atomic exits, and queued-withdrawal payouts.
  • external_assets are the aggregate market principals/NAV recorded from adapters. The vault does not create a per-user market position.
  • Direct transfers of the underlying asset to the vault are reconciled as idle assets for existing shareholders. They are not captured by the next depositor.
  • Adapter NAV is not live-read by every preview. Run curator refresh-markets before relying on share-rate or fee-accounting views after a route's value changes.

Roles and authority

IdentityAuthority
Governance adminSubmits and accepts governance actions. This is the address passed as --admin and may be a Stellar account or a contract/multisig.
Vault curatorRuntime policy authority and an implicit allocator. A new stack uses the deployment --admin as the initial curator; governance can later replace it.
AllocatorSupplies to markets, recalls liquidity, refreshes adapter NAV, executes ready queued withdrawals, and may abort a stale Withdrawing operation.
SentinelSeparate emergency backstop. It can pause, tighten restrictions, revoke specified operational/economic proposals, and use allocator-emergency recovery. It cannot unpause, relax restrictions, or accept proposals.

The governance contract is not implicitly the Sentinel. Production deployments should separate governance, allocator, and emergency keys or contracts according to their operational risk.

Curator economics (fees)

There are two fee types. Both are minted as new SEP-41 shares to a configurable recipient.

FeeBasisCap
ManagementTime-weighted on AUM (rate × AUM × elapsed / 1yr), accrues regardless of performance5% / year
PerformanceAUM growth since the last accrual checkpoint; zero on flat or down periods50% of profit

Rates are WAD-scaled (1e18 = 100%). Each fee has its own recipient, and they can differ.

Operational details:

  • Checkpoint, not all-time high-water mark. Stellar share-pricing paths (DepositWithMin, RefreshFees, ResyncIdleBalance) first reconcile idle_assets against the live asset-token balance, then reset the fee_anchor to the reconciled total at the current ledger time. Profit is measured as current_AUM − anchor_AUM; if AUM is flat or down, the performance fee is zero. Because the anchor resets after each interaction, a recovery following a loss is chargeable — this is "growth since the last checkpoint", not "above the all-time peak". When fees are active, a deposit first crystallizes elapsed fees before the post-deposit anchor is written, so deposit principal cannot erase accrued fees.
  • Growth-rate cap (max_total_assets_growth_rate internally and --max-growth-rate-wad in the CLI, optional). Caps how fast AUM is allowed to count for fee accrual: effective_AUM = min(current, last × (1 + max_rate × dt/yr)). Relaxing or removing this cap is timelocked.
  • Refresh order matters. curator refresh-fees reconciles the live idle token balance, but it does not query every adapter. Refresh changed markets first, then crystallize fees against the resulting aggregate NAV.
tmplr-soroban-vault curator refresh-markets \
  --caller GALLOCATOR... \
  --markets 0,1
tmplr-soroban-vault curator refresh-fees

Set up the operator CLI

The examples below assume tmplr-soroban-vault is on PATH. From a source checkout, run the same commands with:

cargo run -p templar-soroban-vault-cli -- <arguments>

The current stack uses stellar-cli v26 and Rust 1.92. Run the repository's Stellar CLI installer or enter its devenv before operating a vault.

Create a public profile for repeatable network, RPC, manifest, and address defaults:

tmplr-soroban-vault profile init testnet
tmplr-soroban-vault --profile testnet doctor

Profiles must not contain seeds or secret keys. Keep signing material in the Stellar keystore, select it with stellar keys use <identity>, or provide an ephemeral secret through STELLAR_ACCOUNT. Never place a seed phrase or secret key in --source-account.

The deployment manifest defaults to:

contract/vault/soroban/.deploy-state/manifest.json

It records contract IDs, constructor arguments, artifact hashes, initialization state, and successful transaction audit records. Treat it as operational state, back it up, and pass --state explicitly when operating more than one vault.

Deploy a Stellar vault stack

Plan the deployment before writing to the network:

tmplr-soroban-vault deploy plan stack \
  --admin GCURATOR_OR_MULTISIG... \
  --asset-token CASSET... \
  --governance-timelock-ns 86400000000000 \
  --blend-pool CBLENDPOOL...

Then deploy the same configuration:

tmplr-soroban-vault deploy stack \
  --admin GCURATOR_OR_MULTISIG... \
  --asset-token CASSET... \
  --governance-timelock-ns 86400000000000 \
  --blend-pool CBLENDPOOL...

tmplr-soroban-vault status
tmplr-soroban-vault reconcile --json

deploy stack checkpoints the manifest after each upload, deployment, import, and initialization step. Reruns reuse recorded contract IDs and remotely available WASM. Use --force-new only when fresh contract instances are the explicit intent.

If deployment stops after one or more transactions:

tmplr-soroban-vault reconcile --json
tmplr-soroban-vault deploy repair --json
tmplr-soroban-vault deploy resume \
  --governance-timelock-ns 86400000000000 \
  --blend-pool CBLENDPOOL...

Resume only when reconciliation reports safe_to_resume: true. status reads the manifest; reconcile compares it with chain state and is the stronger check.

Mainnet writes require the global --allow-mainnet-write flag. A zero governance timelock additionally requires --allow-zero-timelock and should be limited to explicit local/test configurations.

Governance lifecycle

The deployment --admin becomes both the governance admin and initial vault curator. Governance can later assign a different curator, Sentinel, and allocator set.

A submission always returns a proposal ID. Directionally safe actions may be executed during submission; timelocked actions remain in the pending queue. Do not assume every returned ID needs a later accept call.

Inspect queued proposals before accepting them:

tmplr-soroban-vault governance queue
tmplr-soroban-vault governance explain --proposal-id 7
tmplr-soroban-vault governance accept \
  --admin GCURATOR_OR_MULTISIG... \
  --proposal-id 7

governance accept-ready is useful for routine automation, but exact proposal IDs are safer for high-impact changes. In particular, inspect and accept market cap proposals by ID; a textual cap filter can also match cap-group actions.

Exact timing rules

Governance timelocks are configured per action kind between 0 and 30 days. The initial value is chosen at deployment; there is no universal production default.

ChangeContract behavior
PauseOnly the Sentinel can pause, and it is immediate. Governance submit-set-paused --paused is rejected.
UnpauseGovernance proposal; timelocked under Pause.
RestrictionsSentinel may apply only a tightening change immediately. Every governance-admin restrictions submission is timelocked.
FeesA proposal containing only fee decreases and/or a tighter growth cap executes immediately if recipients do not change. Any fee increase, recipient change, or growth-cap relaxation/removal is timelocked.
Market capLowering an existing cap, including setting it to 0, executes immediately. A new market or cap increase is timelocked.
Cap groupsA new group cap, a cap increase, and every membership change are timelocked. Decreasing a known absolute or relative group cap executes immediately. Relative caps cannot exceed 100%.
Supply queue, allowed adapters, allocatorsTimelocked.
Curator, governance, admin, market removal, skim, upgrade, migrationTimelocked.
Sentinel appointmentThe first appointment may execute immediately; replacing an existing Sentinel is timelocked.
Timelock configurationIncreasing a duration executes immediately. Decreasing one is queued under the TimelockConfig timelock.
Withdrawal and idle-resync cooldownsEvery change is timelocked.

The governance admin can permanently disable an action kind with abdicate. Abdication is irreversible; confirm the exact action kind and recovery implications before submitting it.

Fees example

Fee values are WAD-scaled integers: 1e18 = 100%.

tmplr-soroban-vault governance submit-set-fees \
  --admin GCURATOR_OR_MULTISIG... \
  --performance-fee-wad 200000000000000000 \
  --performance-recipient GPERFORMANCE... \
  --management-fee-wad 20000000000000000 \
  --management-recipient GMANAGEMENT...

The command prints a semantic old/new diff and requires interactive confirmation or --yes. Inspect whether the proposal executed immediately or entered the queue before running accept.

Cap groups

Cap groups limit correlated routes together. When both limits are configured, the effective ceiling is:

min(absolute_cap, relative_cap × total_assets)

Absolute caps use raw asset base units and relative caps use WAD:

tmplr-soroban-vault governance submit-set-group-cap \
  --admin GCURATOR_OR_MULTISIG... \
  --group blue-chip \
  --cap 50000000000000

tmplr-soroban-vault governance submit-set-group-rel-cap \
  --admin GCURATOR_OR_MULTISIG... \
  --group blue-chip \
  --relative-cap 400000000000000000

tmplr-soroban-vault governance submit-set-group-member \
  --admin GCURATOR_OR_MULTISIG... \
  --market-id 0 \
  --group blue-chip

New group limits and all membership assignments are timelocked. Inspect and accept each proposal ID before relying on the group.

Sentinel emergency actions

Sentinel pause and restriction tightening are direct governance-contract entrypoints, not queued CLI governance proposals:

stellar contract invoke \
  --id "$SOROBAN_GOVERNANCE" \
  --source-account sentinel \
  -- set_paused \
  --caller GSENTINEL... \
  --paused true

stellar contract invoke \
  --id "$SOROBAN_GOVERNANCE" \
  --source-account sentinel \
  -- set_restrictions \
  --caller GSENTINEL... \
  --mode 1 \
  --accounts '["GACCOUNT..."]'

Restriction modes are 0 = none, 1 = blacklist, and 2 = whitelist. The governance contract rejects a Sentinel restriction change that relaxes the current policy.

Restoring normal operation uses governance and waits for the configured timelock:

tmplr-soroban-vault governance submit-set-paused \
  --admin GCURATOR_OR_MULTISIG...
tmplr-soroban-vault governance queue --kind pause

The CLI's boolean --paused flag defaults to false when omitted. Supplying the flag requests true, which this governance submission path rejects.

Pausing also blocks ordinary allocation and refresh operations. If an incident requires liquidity recall, decide whether to lower market caps and unwind routes before a global pause. Allocator-emergency recovery such as abort-withdrawing remains available while paused.

Add and activate market routes

Deploying an adapter does not make it usable by the vault. An active market requires three accepted governance states:

  1. The adapter contract is in the allowed-adapter set.
  2. The market ID has a nonzero cap in raw asset base units.
  3. The supply queue binds that market ID to the adapter address.

Add adapters to an existing or imported stack:

tmplr-soroban-vault deploy adapters \
  --vault CVAULT... \
  --governance CGOVERNANCE... \
  --asset-token CASSET... \
  --blend-pool CBLENDPOOL... \
  --custodian GCUSTODIAN...

Then submit the policy in order:

tmplr-soroban-vault governance submit-set-allowed-adapters \
  --admin GCURATOR_OR_MULTISIG... \
  --adapters CBLENDADAPTER...,CCUSTODIALADAPTER...
# After the allowed-adapters proposal is ready:
tmplr-soroban-vault governance accept-ready \
  --admin GCURATOR_OR_MULTISIG... \
  --kind allowed-adapters

tmplr-soroban-vault governance submit-set-cap \
  --admin GCURATOR_OR_MULTISIG... \
  --market-id 0 \
  --cap 1000000000
# After the cap proposal is ready, verify and accept its exact ID:
tmplr-soroban-vault governance explain \
  --proposal-id CAP_MARKET_0_PROPOSAL_ID
tmplr-soroban-vault governance accept \
  --admin GCURATOR_OR_MULTISIG... \
  --proposal-id CAP_MARKET_0_PROPOSAL_ID

tmplr-soroban-vault governance submit-set-supply-queue \
  --admin GCURATOR_OR_MULTISIG... \
  --entry 0:CBLENDADAPTER... \
  --entry 1:CCUSTODIALADAPTER...
# After the supply-queue proposal is ready:
tmplr-soroban-vault governance accept-ready \
  --admin GCURATOR_OR_MULTISIG... \
  --kind supply-queue

Each --entry is market_id:adapter_address. Market IDs are stable identities, not queue positions:

  • Reordering the queue does not remap a market to another adapter.
  • An existing market ID cannot be rebound to a different adapter.
  • Supply requires the bound adapter to remain allowed.
  • Withdrawal keeps using the stored binding, so liquidity can be recovered after an adapter is removed from new supply.
  • Queue entries must be unique, enabled markets with nonzero caps. Practical queue size is also bounded by Soroban transaction resource limits.

Adapter trust boundaries

  • Blend adapter — queries and operates a configured Blend pool on Stellar.
  • Custodial adapter — forwards assets to a configured custodian or multisig. The off-chain route, custody controls, NAV reporting, and liquidity-return procedure are part of the vault's trust boundary.

A custodial withdrawal only releases assets already returned to the adapter on Stellar; it does not initiate or prove an external unwind. Reported NAV updates must match both the current stored amount and the exact next nonce:

stellar contract invoke \
  --id "$CUSTODIAL_ADAPTER_ID" \
  --source-account custodian \
  -- set_reported_assets \
  --caller GCUSTODIAN... \
  --asset CASSET... \
  --expected_current 800000000 \
  --amount 1000000000 \
  --report_nonce 42

Before using a custodial route, document signer recovery, NAV cadence, report approval, reconciliation, and delayed-liquidity procedures.

Day-to-day allocation and accounting

Routine allocation commands use a positive amount and a stable market ID. The allocator does not choose an adapter at execution time.

tmplr-soroban-vault curator refresh-markets \
  --caller GALLOCATOR... \
  --markets 0,1

tmplr-soroban-vault curator allocate-supply \
  --caller GALLOCATOR... \
  --market 0 \
  --amount 100 \
  --asset-decimals 7

tmplr-soroban-vault curator allocate-withdraw \
  --caller GALLOCATOR... \
  --market 0 \
  --amount 25 \
  --asset-decimals 7

Decimal flags are converted without floating point. Automation can use --amount-raw, --assets-raw, or --shares-raw for exact base units.

The accounting behavior differs by direction:

  • allocate-supply transfers assets to the bound adapter, calls its supply method, reads total_assets(asset), and stores the observed route NAV.
  • allocate-withdraw requests an amount from the adapter, verifies the actual vault token-balance delta matches the adapter's return value, and subtracts the realized amount. It does not refresh the adapter's remaining NAV.
  • refresh-markets reads total_assets(asset) for the selected routes and replaces their stored principals. Run it after yield, loss, or a custodial NAV report and before fee/share-rate decisions.

Two maintenance calls are permissionless even though they are grouped under curator in the CLI:

tmplr-soroban-vault curator resync-idle
tmplr-soroban-vault curator refresh-fees

resync-idle requires the vault to be idle and is rate-limited by the idle resync cooldown, which defaults to 120 seconds. refresh-fees reconciles the live idle balance and advances the fee checkpoint. Neither call substitutes for refresh-markets when adapter NAV has changed.

Withdrawal operations

The Stellar vault has two distinct exit paths.

Atomic idle-liquidity exit

user atomic-withdraw and user atomic-redeem use the ERC-4626 proxy's slippage-protected atomic exit methods when the deployment manifest contains proxy_4626. The CLI first verifies that the recorded proxy interface exposes both atomic entrypoints; legacy proxies must be replaced rather than bypassed. Proxy-less imported deployments fall back to the vault's equivalent atomic commands. Both routes complete in one transaction only when the vault has enough idle assets. They never pull liquidity from an adapter. As a result, maxWithdraw and maxRedeem can be zero while the user's shares still represent assets deployed to markets.

tmplr-soroban-vault user preview --owner GUSER...

tmplr-soroban-vault user atomic-withdraw \
  --operator GUSER... \
  --assets 25 \
  --asset-decimals 7 \
  --max-shares-burned 25 \
  --share-decimals manifest

Queued withdrawal

Use the queued path when idle liquidity is insufficient:

The proxy-facing user withdraw and user redeem commands preserve its asynchronous ERC-7540-style compatibility methods. Use request-withdraw for the lower-level vault request surface with explicit share and minimum-asset inputs.

tmplr-soroban-vault user request-withdraw \
  --owner GUSER... \
  --shares 10 \
  --share-decimals manifest \
  --min-assets-out 9.9 \
  --asset-decimals 7

# After cooldown, recall enough market liquidity if needed.
tmplr-soroban-vault curator allocate-withdraw \
  --caller GALLOCATOR... \
  --market 0 \
  --amount 10 \
  --asset-decimals 7

# The operator is an authorized allocator/curator, not the withdrawing user.
tmplr-soroban-vault user execute-withdraw \
  --operator GALLOCATOR...

The queued path has these mechanics:

  • request-withdraw escrows shares and records a fixed asset claim at request time. The default cooldown is one hour.
  • execute-withdraw services the queue head; it does not select a request ID.
  • The caller must have allocator authority. The command is under user because it completes a user flow, not because any user may execute it.
  • The head request must be cooled down and fully covered by idle assets. There is no partial payout.
  • Finishing an allocation does not automatically progress the withdrawal queue; call execute-withdraw separately.
  • The queue does not reserve idle assets against later atomic exits. Curators must monitor queued claims and maintain enough idle liquidity.
  • There is no user cancellation path. Monitor request and payout events by request ID and alert on stalled heads.

If execution is already stuck in Withdrawing, an allocator, Sentinel, or curator may abort the exact active operation:

tmplr-soroban-vault curator abort-withdrawing \
  --caller GALLOCATOR_OR_SENTINEL... \
  --op-id 42

This is an incident-recovery action, not a normal withdrawal tool. A successful abort validates the active operation ID, restores collected idle accounting, refunds escrowed shares, removes the affected queue head, emits a WithdrawalStopped event, and returns the vault to Idle.

TTL and archival operations

Soroban contract data is not permanent. Every vault needs an automated TTL job; ordinary transaction traffic is not a substitute for a keeper schedule.

tmplr-soroban-vault extend-ttl

The CLI attempts the vault runtime, governance, ERC-4626 proxy, curator proxy, share token, and every adapter recorded in the manifest. The asset token has no deployment-wide TTL entrypoint and is reported as skipped. Treat a failed or unexpectedly skipped component as an operational alert.

Vault, governance, proxy, and custodial-adapter maintenance uses permissionless contract entrypoints. Share-token and Blend-adapter TTL entrypoints are admin-gated, so the aggregate command does not invoke them. It instead uses Stellar protocol-level operations to extend each contract instance and its WASM code. The configured source account signs and pays for those operations; no vault or governance contract authorization is required. The legacy --caller option remains accepted for backward compatibility but is ignored.

Each contract owns its own TTL. Extending the vault runtime does not extend governance, proxies, share-token holder entries, adapter storage, or oracle storage. Run the aggregate command before archival: an extend operation cannot revive an archived entry. If a contract is already archived, restore both its instance with stellar contract restore --id ... and its WASM code with stellar contract restore --wasm-hash ... before rerunning extend-ttl. Contract-specific persistent entries may require separate restore or renewal operations.

Safety and automation

  • Use --dry-run to print redacted Stellar commands and manifest decisions without writes.
  • Every contract write is simulated before submission. Review auth, footprint, resource, fee, and contract-error output on stderr.
  • Use --json for stable machine-readable responses or --json-lines for long-running automation. The schema lives at tools/soroban-vault-cli/schema/output.schema.json.
  • Mainnet writes require --allow-mainnet-write.
  • Dangerous governance submissions print an old/new semantic diff and require --yes or interactive confirmation.
  • Successful writes append transaction metadata to the manifest. Preserve that audit trail alongside external monitoring and event indexing.
  • Run reconcile after interrupted deployment, unexpected RPC results, or any manual contract operation that may have diverged from the manifest.
  • Generate operator completions or a manpage with completions and man rather than copying stale command snippets into private runbooks.

Before a policy or allocation change, verify the manifest/network, refresh any changed adapter NAV, inspect the current proposal queue, and identify the exact role that must authorize the action. Afterward, verify the transaction result, runtime state, adapter accounting, relevant events, and the manifest audit record.

Security

Templar Protocol is built on a defence-in-depth model: immutable, isolated market contracts; multi-source oracles with circuit breakers; independent audits and formal verification; continuous monitoring with 24/7 human coverage; and timelocked, multisig-controlled governance for every component that can change. This page summarizes those measures for users, integrators, and liquidity providers performing due diligence. For vulnerability reporting, see Security Reporting.

At a Glance

  • Five independent audits plus formal verification by Guvenkaya, Thesis Defense, Certora, and Halborn (twice). All critical and high-severity findings remediated. Reports.
  • Immutable market contracts: no contract-level admin functions, upgrade method, pause function, or parameter mutators. Retained deployer keys on some market accounts are a separate, documented storage-patch exception (see Immutable Markets).
  • Isolated markets: one collateral asset and one borrow asset per contract; no cross-asset contagion.
  • Proxy oracles aggregating Pyth and RedStone with freshness filters and circuit breakers, the emergency brake for immutable markets.
  • Professional curators manage vault lending risk under timelocked governance with an independent Sentinel.
  • Real-time monitoring of markets, proxy oracles, and vaults with Hypernative and custom alerts, a public alerts channel, and a live risk dashboard.
  • AI security-focused code scanning (Octane, Almanax, GPT Cyber) alongside nightly formal proofs and fuzzing in CI.
  • 2-of-3 DAO multisig for every mutable NEAR component; timelocks and immediate actions follow each component's policy (proxy oracle governance is timelocked per method, the registry uses two-step finalization, and breaker operation is immediate). Stellar vaults are governed per vault by a governance admin, curator, and Sentinel under configurable timelocks. See Protocol Governance.
  • Hardened frontend and DNS.

Audits and Formal Verification

All audit reports and the formal verification report are available in the Templar audits folder.

EngagementAuditorScopeCompleted
NEAR smart contract security reviewGuvenkayaMarket contracts and shared protocol logicApril 2025
Smart contracts security auditThesis DefenseMarket contracts and shared protocol logicJuly 2025
Security assessment and formal verificationCertoraMarket contracts: manual audit plus formal verification of borrow-position health, collateralization, liquidation, and repayment integrity propertiesSeptember 2025
Curated vaults auditHalbornCurated vault stack (kernel, Stellar runtime, governance, share token, adapters)June 2026
Proxy oracle auditHalbornProxy oracle kernel, NEAR and Stellar runtimes, and governanceAugust 2026
  • Coverage of live code: market contracts 100%; proxy oracle 100%; curated vault stack approximately 85% (the custodial adapter was out of scope).
  • Remediation: every critical and high-severity finding across all engagements has been fully remediated. Medium findings are remediated within a release cycle or accepted with written rationale; the known-issues register records findings acknowledged after a report was issued.
  • Audit cadence: every material contract release (new contract, new external function, change to accounting or authorization semantics) is audited before it is deployed to mainnet. Auditor selection deliberately rotates so that no single firm owns every code path.
  • Bytecode verification: mainnet deployments use reproducible builds, and the on-chain code hash is checked against the audited commit before deployment. Anyone can verify a deployed contract; see Contract Verification.

Beyond the external engagements, verification runs continuously inside the repository:

  • Formal verification in CI: Kani model-checking proofs over the vault kernel (asset conservation across allocation, withdrawal, refresh, and emergency-recovery flows; fee accrual; withdrawal escrow) and the universal-account authentication and migration logic run nightly and on every relevant pull request (workflow).
  • Fuzzing: twenty libFuzzer targets covering borrow, supply, liquidation, interest and fee math, decimal arithmetic, snapshots, market creation, the vault state machine, and Stellar storage codecs run nightly, with committed regression seeds (fuzz targets).
  • Independent process review: DeFiSafety's Process Quality Review of Templar scored the protocol 94% (PASS).

Dependency Audits

Templar's cross-chain flows rely on NEAR infrastructure that is audited independently of Templar: NEAR Intents (deposits and withdrawals), the Omnibridge, Chain Signatures (the MPC network), and nearcore. Those reports are collected in the NEAR dependency audits folder: nearcore assessments by Trail of Bits and Sigma Prime; NEAR Intents reviews by Hacken, Guvenkaya, zkSecurity, and Aurora Labs; Omnibridge audit reports; and the NEAR One reports on the MPC Chain Signatures network. Contingency procedures for a dependency incident are part of the incident response runbooks.

Smart Contract Architecture

Immutable Markets

Market contracts have no administrative functions: no owner, no upgrade method, no pause switch, and no method to modify collateralization ratios, interest rate curves, fees, or oracle configuration after launch. Nothing in the contract's code lets anyone change the configured market parameters a user relied on when opening a position. (Interest rates move with utilization along the fixed curve, and valuations follow the oracle; the curve and the oracle configuration themselves cannot change.)

One qualification applies at the account level rather than the contract level. A market account whose deployer full-access key has been removed cannot be changed by anyone. Where that key is still held (by the multisig that deployed the market), contract storage can be modified through the reviewed, sandbox-replayed patch process described in Deploying a market; this is how legacy markets were migrated from direct Pyth reads to proxy oracles. Whether a market account holds any access keys is visible on-chain:

near account list-keys <market-address> network-config mainnet now

When a new market version is released, it is registered in the registry and deployed to a new account; existing markets keep running unchanged and users migrate voluntarily. This removes the largest single risk class in DeFi lending, a compromised or misused admin key draining or re-parameterizing live markets through the contract itself, at the cost of making incident response rely on the oracle layer and on migration rather than on in-place upgrades. See Protocol Governance.

Isolated Markets

Each market pairs exactly one collateral asset with one borrow asset in its own contract account, with its own supply pool, interest rate model, and risk parameters. There is no shared liquidity, no cross-collateralization, and no protocol-wide bad-debt socialization. A collateral asset that depegs, an oracle feed that fails, or a liquidation cascade in one market cannot spread to suppliers in any other market. Riskier or newer assets are onboarded in their own markets with their own conservative parameters, rather than added to a shared pool.

Circuit Breakers as the Emergency Brake

Because markets cannot be paused, Templar puts the emergency control where the risk enters: the price feed. Markets configured with a proxy oracle (every new market, and the legacy markets that have been migrated) read feeds that carry circuit breakers. Automatic rules block sudden jumps, staged ramps, and cumulative drift, and an operator can trip a feed manually with no timelock. While a feed is blocked, borrowing, collateral withdrawal against debt, and liquidations on that market stop; supply withdrawals, repayments, and collateral withdrawals from debt-free positions continue. This gives the team an immediate, reversible containment action that cannot be used to seize funds or change market terms.

A small number of older markets still read Pyth's contract directly and have no trip mechanism; for those, the containment options are halting Templar's bots and migrating users to a replacement market. Which oracle a market reads is visible in its get_configuration output.

Defensive Valuation and Conservative Parameters

  • Collateral is valued at the lower bound of the oracle confidence interval and liabilities at the upper bound.
  • Aggregated prices use a weighted median biased low for collateral and high for liabilities.
  • Every market enforces a maintenance collateralization ratio above its liquidation ratio, a maximum usage ratio that preserves withdrawal liquidity, bounded liquidation spreads, and partial liquidation that restores health rather than closing positions entirely.
  • Market parameters are deployed from reviewed, version-controlled specifications with automated preflight checks, including a cross-check of every oracle price against an independent reference before a market goes live. See Deploying a market.

Reproducible Builds and On-Chain Verification

All contracts are open source and built reproducibly. The deployed code hash of any Templar contract can be verified against the tagged source commit with a single command; see Contract Verification. Released contract artifacts are pinned by SHA-256 in the repository and are immutable once published.

Oracle Security

Oracle failure and manipulation is the dominant cause of lending-protocol losses. Templar's proxy oracles aggregate multiple independent oracles for redundancy and gate every price through freshness filters and circuit breakers:

  • Multiple sources: Pyth (Lazer and classic) and RedStone are live; Chainlink and Atlas are planned by the end of 2026. Sources, weights, and the fresh-source quorum are configured per feed.
  • Freshness filters drop stale and future-dated prices before aggregation.
  • Weighted-median aggregation across sources with a configurable fresh-source quorum. The standard production configuration uses a quorum of one with Pyth weighted above RedStone, so the higher-weighted source determines the price while both are fresh and a single fresh source carries the feed when the other is stale. That configuration favours liveness; the freshness filter and enforced circuit breakers, not the aggregation, are the primary defence against a single compromised provider, and quorum and weights can be raised per feed as more providers come online.
  • Circuit breakers compare against accepted history, so an attacker cannot first poison the reference sample and then pass a deviation check.
  • Fail-closed reads: a blocked, failed, or stale feed reads as no price, never as the last known price.
  • Timelocked governance on every feed configuration change and contract upgrade. Circuit breaker operation (trip and untrip, re-arm, enforcement on or off) is role-gated and immediate in both directions; those roles sit with the multisig and every use is alerted.
  • Independently audited by Halborn (August 2026).

Source: contract/proxy-oracle.

Curated Vaults and Professional Curators

Templar's curated vaults (currently on Stellar) let depositors hold a single vault share while professional curators manage lending risk on their behalf. Curators decide which markets a vault may allocate to, set per-market and per-group caps, and configure fees, under a governance model designed so that no single role can both take risk and escape oversight:

  • Timelocked governance: risk-increasing actions (cap increases, new markets, fee increases, unpause, role changes) must mature under a per-action timelock before they execute. Risk-reducing actions (cap decreases, fee decreases) execute immediately.
  • Independent Sentinel: a separate emergency role can pause the vault and tighten restrictions instantly, but cannot unpause, relax restrictions, or accept proposals.
  • Bounded exposure: absolute and relative caps per market and per correlated group.
  • Audited and formally verified: the vault stack was audited by Halborn, and the kernel's accounting invariants are proven with Kani in CI.
  • Continuously monitored by Hypernative for exploit patterns, invariant violations, and anomalous privileged calls.

See the Stellar Vault Curator Guide for the full operating model.

Monitoring, Alerting, and Risk Dashboard

  • Live risk dashboard: data.templarfi.org shows, in real time and per market, collateral coverage, liquidation proximity with drawdown scenarios, oracle health per feed, TVL and revenue, utilization and rates, borrower and supplier concentration, supply-side flows, positions by risk tier, a ledger of events, and post-withdrawal transfers through NEAR Intents, so anyone can assess the protocol's risk without relying on the team's reporting.
  • Alerting: Hypernative monitors the Stellar vaults for exploit detection, invariant checks, and privileged-call anomalies. Custom alerts cover the NEAR markets and proxy oracles. Together the alerting covers oracle failure or price deviation beyond threshold, positions approaching liquidation, liquidations executed, large position events (whale alerts), bad debt creation, utilization crossing critical thresholds, and smart contract pauses or emergency admin actions. Alerts are published to the public Templar alerts Telegram channel.
  • 24/7 coverage: Templar's written security policy defines an on-call rotation among the multisig signers, who are distributed across multiple time zones, so that a responder is within working hours at all times and alerts page the current on-call directly.
  • Compliance screening: on-chain sanctions and risk signals from Predicate and TRM Labs flag SEVERE-labelled accounts interacting with Templar contracts.

Details, including how to run the same health checks yourself, are on the Monitoring and Risk Management page.

Secure Development and AI-Assisted Code Scanning

  • Review and CI: every change to protocol code lands through a pull request with required approving reviews, signed commits, and a passing CI gate (unit, integration, and sandbox node tests, lint, formatting, coverage, and dependency vulnerability scanning). Toolchains and dependencies are pinned; new dependencies require a second reviewer and a written rationale.
  • AI security-focused code scans: in addition to human review and external audits, Templar runs AI-driven security analysis over the contracts using Octane, Almanax, and GPT Cyber (OpenAI's closed-access cybersecurity model). These scans are used to surface candidate issues for human triage; they complement rather than replace audits.
  • Formal proofs and fuzzing in CI: see Audits and Formal Verification.
  • Threat models: components ship with written threat models and audit boundaries (for example the Stellar vault STRIDE model and the proxy oracle audit boundary).
  • No hotfix bypass: even during an incident, contract code changes go through the full audit-and-multisig path. The incident toolkit (circuit breakers, Sentinel pauses, cap-to-zero, halting bots) exists to buy time so that fixes are never rushed.
  • Deployment discipline: mainnet deployments are planned from declarative specifications, reviewed as a plan artifact, preflighted against chain state, and applied with the multisig; see Deploying a market. Storage patches to live contracts are replayed in a sandbox and stamped before they can be applied.

Operational Security and Key Management

  • Multisig control: every mutable Templar contract on NEAR (the registry, proxy oracle governance, and adapters) is administered by templar.sputnik-dao.near, a Sputnik DAO with three signers on its council at a 2-of-3 threshold. Adding or removing a signer is itself a governed DAO proposal.
  • Timelocks: proxy oracle governance typically applies 24-hour to 168-hour timelocks to configuration and upgrades (the exact policy is set per contract), and vault governance applies configurable per-action timelocks. Circuit breaker operation (trip and untrip, re-arm, enforcement on or off) is immediate in both directions, so those operator roles are held as tightly as the admin role and every use is alerted. See Protocol Governance for the full table.
  • Least privilege: proxy oracle governance separates the ManualTripper, CircuitBreakerOperator, ProxyConfigurationManager, and Admin roles so that the account able to hit the emergency brake need not be able to reconfigure feeds or upgrade code.
  • Key hygiene: privileged keys are held on hardware devices with geographically distributed cold backups; infrastructure and vendor accounts require MFA and have at least two administrators for continuity.
  • Security policy: Templar maintains a written organizational security policy (access control, key management, SDLC, monitoring, incident response, vendor risk, business continuity) reviewed quarterly and shared with counterparties on request.

Incident Response

Templar maintains role-segmented emergency runbooks covering markets, vaults, oracles, NEAR Intents, bridges, and stablecoin issuers. The process from detection to resolution:

  1. Detect and page: a Hypernative or custom alert reaches the on-call responder.
  2. War room: the responder opens a war room, names an incident lead, communications lead, and scribe, and classifies severity.
  3. Contain with the smallest reversible action: halt Templar's own bots; trip the relevant proxy oracle feed to freeze price-dependent operations on markets that read a proxy oracle; on vaults, Sentinel pause or restriction tightening, allocator abort, and curator cap-to-zero, in that order of escalation.
  4. Preserve user exits: no role can disable supply withdrawal requests or repayments at the market boundary.
  5. Recover: a patched market version is audited, registered, and deployed through the registry; users migrate. There is no in-place hotfix.
  6. Stand down and learn: stand-down requires sign-off from at least two roles; every user-affecting incident produces a post-mortem, published where appropriate.

Templar coordinates with the NEAR Foundation and the Stellar Development Foundation security functions during ecosystem-level incidents.

Insurance and Recovery

Templar does not currently carry insurance cover for smart contract or oracle failure, there is no on-chain insurance fund that backstops bad debt, and there is no insurance-adoption timeline. Users with assets or positions in an exploited contract should assume that unrecovered exploit losses are borne by the users whose assets or positions are affected, including borrowers whose collateral is lost. Unrecoverable bad debt is borne by the affected market's suppliers and may reduce the share value of vaults allocated to that market. Markets are isolated, so neither kind of loss spreads to other markets.

Recovery from a protocol-level incident follows the incident response process: contain through the oracle layer and the bots, preserve user exits, and migrate to a patched, audited market version. For incidents at the infrastructure layer (NEAR Intents, bridges, stablecoin issuers), Templar coordinates with the NEAR Foundation and the Stellar Development Foundation security functions, following the recovery precedents those ecosystems have established. There is no treasury-backed remediation policy; users should not assume one applies.

Frontend Security

The application at app.templarfi.org is the interface most users sign transactions through, so it is hardened as a first-class attack surface.

Hosting and DDoS Protection

The frontend is deployed on Vercel's edge network, which provides distributed denial-of-service mitigation at the infrastructure level. The global CDN absorbs and filters volumetric attacks, rate-limits abusive traffic, and serves the application from geographically distributed edge nodes, providing resilience against Layer 3, 4, and 7 attacks.

DNS Hardening

The templarfi.org domain is protected by:

  • Registrar lock to prevent unauthorized transfers or modifications.
  • DNSSEC validation to ensure the authenticity of DNS responses and prevent cache poisoning.
  • Pinned records: DNS resolves exclusively to Vercel's verified edge infrastructure, minimizing the risk of hijacking or redirection.
  • Restricted access: DNS and registrar management is limited to authorized personnel with multi-factor authentication enforced on every account with domain-level permissions.

Integrity and Modification Detection

  • Immutable deployments: every deployment produces an immutable, content-addressed build; any unauthorized change can be identified and rolled back instantly.
  • Build verification: production deployments originate only from reviewed and approved changes in a branch-protected repository.
  • No third-party scripts: the application loads no scripts or stylesheets from external origins. Everything is bundled into content-hashed assets from the immutable build, so there is no external resource whose integrity would need to be pinned.
  • Framing protection: every response carries X-Frame-Options: SAMEORIGIN and a Content Security Policy of frame-ancestors 'none', so the application cannot be embedded in another site to trick users into signing (clickjacking). The policy does not currently restrict script or style sources; the absence of third-party scripts limits the injection surface such a restriction would cover. Restricting script-src and style-src to the application's own origin is planned, but no owner or delivery date is published; the frontend is maintained in a separate repository.

Intrusion Detection and Monitoring

  • Platform analytics and logging provide visibility into traffic patterns, error rates, and deployment activity.
  • Automated alerts fire on deployment failures, unusual traffic spikes, and error-rate thresholds.
  • Administrative access to the deployment platform and related accounts is role-based and protected by multi-factor authentication.

Client-Side Practices

  • No private key handling: the frontend never requests, stores, or transmits private keys; signing is delegated to the user's wallet.
  • Strict input validation before any contract interaction.
  • HTTPS enforced: all traffic is served over TLS and plain HTTP is redirected to HTTPS. HTTP Strict Transport Security is a deployment requirement satisfied by the hosting platform's configuration rather than by headers set in the application code.
  • Minimal, pinned dependencies to reduce supply-chain risk.
  • Transparent transactions: parameters are constructed so users can verify the contract call and arguments in their wallet before signing.

Frontend Incident Response

If a frontend compromise is detected or suspected: immediate rollback to the last known-good deployment; revocation and rotation of any affected credentials; communication on official channels advising users to verify the application URL and refrain from signing until the all-clear; and a post-incident review.

Responsible Disclosure

Report vulnerabilities to security@templarprotocol.com. See Security Reporting for the disclosure process.

Security Reporting

Templar Protocol takes security seriously and encourages responsible disclosure of security vulnerabilities.

All smart contracts are open-source and use reproducible builds for maximum transparency. For an overview of the protocol's security posture (audits, formal verification, oracle safeguards, monitoring, and operational controls), see the Security page.

Security Contact

Report security vulnerabilities and other sensitive issues by email to security@templarprotocol.com.

This is the single channel for responsible disclosure. Templar previously ran a public bug bounty program; that program has ended, and reports should no longer be submitted through third-party bounty platforms. Good-faith reports of genuine vulnerabilities may be rewarded at Templar's discretion.

Please do not disclose vulnerabilities publicly (on GitHub issues, social media, or community channels) before Templar has had the opportunity to investigate and remediate.

Responsible Disclosure

If you have discovered a security issue, please follow these steps:

  1. Report: Send vulnerability details to security@templarprotocol.com.
  2. Investigation: The security team will acknowledge the report and assess its severity and impact.
  3. Resolution: A fix is developed, reviewed, and deployed. Because market contracts are immutable, a fix to a market may involve deploying a patched version through the registry and coordinating user migration; see Protocol Governance.
  4. Public Disclosure: Coordinated disclosure after the fix is in place.

Security reports should include:

  • A clear description of the vulnerability and its impact.
  • The affected contract(s), account ID(s), or component(s).
  • Steps to reproduce the issue, ideally with a proof of concept.

Security Alerts

Important security notices will be posted on the official Discord server, Telegram channel, and X (Twitter) account. Real-time protocol alerts are also published to the public Templar alerts Telegram channel; see Monitoring and Risk Management.

Audit Information

Audit reports and the formal verification report are available in the Templar audits folder. A summary of each engagement is on the Security page.

The audits directory in the contracts repository contains auditor-facing notes and the known-issues register (findings acknowledged or fixed after a report was issued). Audits of the NEAR infrastructure Templar depends on (nearcore, NEAR Intents, Omnibridge, Chain Signatures) are in the NEAR dependency audits folder.

Monitoring and Risk Management

Templar Protocol runs real-time monitoring on its NEAR markets and proxy oracles and on its Stellar curated vaults, and publishes its risk data openly. This page describes the monitoring and alerting stack, the public risk dashboard, the operational bots, how to run protocol health checks yourself, and how risk is managed and contained.

Real-Time Monitoring and Alerting

Templar runs two complementary monitoring systems with 24/7 human coverage:

  • Hypernative monitors the Stellar curated vaults for exploit detection, invariant violations, anomalous privileged calls, and counterparty risk signals.
  • Custom alerts built by Templar monitor the NEAR markets and proxy oracles. Alert definitions are version-controlled in the templar-monitoring repository and changed only through reviewed pull requests.

Alerts from both systems are published to the public Templar alerts Telegram channel, so integrators and liquidity providers see the same signals the team does.

What Is Monitored

The alerting covers:

  • Oracle failure or price deviation beyond threshold
  • Position approaching liquidation
  • Liquidation executed
  • Large position events (whale alerts)
  • Bad debt creation
  • Utilization rate crossing critical thresholds
  • Smart contract pause or emergency admin action

Coverage and Escalation

Templar's security policy defines an on-call rotation among the multisig signers, who are distributed across multiple time zones, so that a responder is within working hours at all times. Every alert is classified by severity; critical alerts page all signers and open a war room following the emergency runbooks. See Incident Response below.

Compliance Screening

Separately from the protocol alerts above, Templar screens on-chain activity against sanctions and risk signals from Predicate and TRM Labs. SEVERE-labelled accounts interacting with Templar contracts trigger a Telegram notification. Details are in the templar-monitoring repository.

Live Risk Dashboard

data.templarfi.org is Templar's public, real-time risk dashboard. It is built directly from on-chain data (contract state over NEAR RPC, blocks and events from NEARData and FastNear) with USD prices from Pyth, Pyth Lazer, and RedStone, and it is the same tool the team uses for risk modeling. Every view can be filtered per market and viewed in aggregate.

Ops Console

  • Collateral Coverage: total collateral against outstanding borrows, a 90-day coverage trend, coverage by collateral asset, and a per-asset breakdown with each market classified as healthy, below target, or undercollateralized. Markets whose price feed was stale or missing at scan time are flagged rather than silently counted.
  • Liquidation Proximity (live): positions at risk (health factor at or below 1.2), aggregate coverage ratio, average health factor, the health-factor distribution ("collateral wall"), and scenario sliders showing how a price drawdown moves positions toward liquidation.
  • Oracle Health: assets scanned, stale feeds, and missing feeds; per-feed staleness, spread, and confidence; effective (protocol-side) versus raw price; and a per-asset oracle state table.
  • TVL & Revenue: total supply, total borrowed, and protocol TVL across day, week, month, and quarter; protocol fees and cumulative revenue.

Risk Committee

  • Utilization & Rates: current utilization against each market's kink, the interest rate curves, and 90-day history.
  • Concentration Risk: top-1 and top-5 borrower share, Herfindahl-Hirschman indices for borrowers, collateral providers, and suppliers, single-borrower and single-provider exposure, and the distributions and top lists behind them.

Strategic

  • Supply-Side Analytics: deposit and withdrawal flows, net supply flow, depositor count, average deposit age, accrued yield, and advertised supply APY; borrow and repay flows and net loan flow, with a market selector.
  • Positions at Risk: position counts by risk tier (liquidatable below 1.0 health factor, critical below 1.10, warning below 1.25, healthy) with an hourly trend.
  • Ledger Events: deposits, withdrawals, borrows, repays, and liquidations, newest first, filterable by market.
  • Intents Transfers: where value went after withdrawal, showing bridge-outs and NEAR transfers by account through the NEAR Intents settlement layer, which block explorers cannot show.

The same data drives the position and utilization alerts above. Total value locked is also tracked independently on DefiLlama.

Operational Services

The protocol runs the following off-chain services, all open source under service/:

  • Liquidator: monitors borrow positions across all registered markets, refreshes oracle prices, and executes liquidations of under-collateralized positions. Liquidation is permissionless and is performed primarily by third-party liquidation bots; Templar's bot is one participant among them, not a privileged one.
  • Accumulator: applies interest to borrow positions on a schedule so that accrued liability is always reflected on-chain.
  • Market monitor: scans every market and sends Telegram alerts for positions at risk of liquidation, classified into health zones by distance from the maintenance ratio.
  • Oracle updaters: the RedStone bridge service, together with the oracle-update paths built into the liquidator and relayer, fetch signed Pyth Lazer and RedStone payloads, submit them to the on-chain adapters, and refresh proxy oracle prices ahead of price-dependent actions.
  • Relayer: relays signed delegate actions so that accounts without NEAR can interact with the protocol, and refreshes oracle prices before the actions it relays.

Bots can be halted at any time as a containment step. They have no privileged access to markets: everything they do, anyone can do.

Gas Usage Monitoring

Gas analysis tools provide performance insights:

./script/gas-report.sh

This generates detailed reports on function execution costs, snapshot iteration limits, and performance bottlenecks.

Protocol Health Checks

Anyone can reproduce the core health checks with view calls. Examples use near-cli-rs.

Market Status

# Get market configuration (immutable after deployment)
near contract call-function as-read-only <market-address> get_configuration json-args {} network-config mainnet now

# Check current market snapshot
near contract call-function as-read-only <market-address> get_current_snapshot json-args {} network-config mainnet now

# Get borrow asset metrics (supplied, borrowed, available)
near contract call-function as-read-only <market-address> get_borrow_asset_metrics json-args {} network-config mainnet now

# List all deployed markets from the registry
near contract call-function as-read-only v1.tmplr.near list_deployments json-args '{"offset": 0, "count": 100}' network-config mainnet now

paid_to_fees is the decimal-string amount of repaid interest and fees currently available to pay supplier yield. It is a market-wide, first-come-first-served pool: it is not accrued yield, per-user reserved cash, or a guarantee that a withdrawal will execute. A raw JSON response that omits this field is from a legacy deployment and differs from an upgraded market explicitly reporting "0"; Rust consumers deserialize an omitted field as zero for compatibility and therefore lose that distinction. The field appears on live markets only after a released version containing it has been deployed or upgraded.

Oracle Health

Markets read prices from the oracle account in their configuration. Newer markets read a proxy oracle; some older markets still read pyth-oracle.near or lst.oracle.tmplr.near directly (for example ibtc-iethusdc.v1.tmplr.near and stnear-usdc-1.v1.tmplr.near), so check the market's get_configuration output first. For a proxy-backed market, check the proxy first, then the underlying adapters. The example below uses ixlmdejaaa-ixlmusdc-2.v1.tmplr.near, whose configuration points to proxy-oracle-ixlmdejaaa-ixlmusdc-2.v1.tmplr.near; take the price identifiers from that configuration.

# Latest cached price for a feed and its status (accepted, blocked, stale, failed)
near contract call-function as-read-only proxy-oracle-ixlmdejaaa-ixlmusdc-2.v1.tmplr.near get_cached_proxy_price json-args '{"id": "<price-id>"}' network-config mainnet now

# Circuit breaker state and accepted price history for a feed
near contract call-function as-read-only proxy-oracle-ixlmdejaaa-ixlmusdc-2.v1.tmplr.near get_proxy_circuit_breaker_set json-args '{"id": "<price-id>"}' network-config mainnet now

# What the market will actually see: accepted prices no older than <age> seconds
near contract call-function as-read-only proxy-oracle-ixlmdejaaa-ixlmusdc-2.v1.tmplr.near list_ema_prices_no_older_than json-args '{"price_ids": ["<price-id>"], "age": 60}' network-config mainnet now

# Underlying sources
near contract call-function as-read-only pyth-oracle.near get_price json-args '{"price_identifier": "<pyth-price-id>"}' network-config mainnet now
near contract call-function as-read-only redstone-adapter.v1.tmplr.near read_price_data_for_feed json-args '{"feed_id": "<feed-id>"}' network-config mainnet now

# Legacy LST oracle adapter
near contract call-function as-read-only lst.oracle.tmplr.near get_price_data json-args '{}' network-config mainnet now

Provider status pages: Pyth Network Price Feeds and Pyth Network Status; RedStone.

Market Data Analysis

  • Supply Positions: Monitor individual and aggregate supply positions

    near contract call-function as-read-only <market-address> list_supply_positions json-args '{"offset": 0, "count": 100}' network-config mainnet now
    
  • Withdrawal Queue: Check pending withdrawal requests

    near contract call-function as-read-only <market-address> get_supply_withdrawal_queue_status json-args {} network-config mainnet now
    
  • Historical Snapshots: Analyze market history

    near contract call-function as-read-only <market-address> list_finalized_snapshots json-args '{"offset": 0, "count": 10}' network-config mainnet now
    
  • Utilization Rate: Calculate from borrow asset metrics as borrowed / (borrowed + available)

    near contract call-function as-read-only <market-address> get_borrow_asset_metrics json-args {} network-config mainnet now
    
  • Supplier Yield Availability: min(accrued_yield, paid_to_fees) is the largest yield-only request that can be paid without consuming principal. Such a request meets the configured minimum only when min(accrued_yield, paid_to_fees) >= supply_withdrawal_range.minimum. This is not a general withdrawal-eligibility check: principal may cover the remainder of a larger request. Existing eligibility checks still apply, and other withdrawals can consume the shared pool before execution.

  • Last Yield Rate: get_last_yield_rate returns the most recently computed supply yield rate. It is an expected average over time, not a spot rate; supply positions earn yield the instant it is distributed.

    near contract call-function as-read-only <market-address> get_last_yield_rate json-args {} network-config mainnet now
    

    Note: Historical interest rate analysis requires an indexer for time-series data; the risk dashboard provides this.

Network Dependencies

Templar's cross-chain collateral and stablecoin flows depend on NEAR infrastructure: NEAR Intents, the Omnibridge, Chain Signatures (the MPC network), and nearcore itself. The security audits of those dependencies (nearcore assessments by Trail of Bits and Sigma Prime; NEAR Intents reviews by Hacken, Guvenkaya, zkSecurity, and Aurora Labs; Omnibridge audit reports; and the NEAR One reports on the MPC Chain Signatures network) are collected in the NEAR dependency audits folder. Contingency procedures for a dependency incident are in the emergency runbooks.

Risk Management

Economic Risk Assessment

  • Market parameters: every market's collateralization ratios, interest rate curve, usage ratio, and liquidation spread are immutable and readable via get_configuration. The specifications they were deployed from are version-controlled under deployments/.
  • Real-time risk modeling: coverage, liquidation proximity, positions by risk tier, concentration, and utilization analysis for every market is continuous on the risk dashboard, rather than a periodic simulation.
  • Oracle reliability: divergence and downtime are tracked per source and per proxy feed, and the dashboard's Oracle Health view shows staleness, spread, and confidence per feed; see Oracle Health.
  • Liquidation efficiency: executed liquidations and positions at risk are alerted in real time and visible in the dashboard's Liquidation Proximity, Positions at Risk, and Ledger Events views.
  • Individual positions: My Account in the Templar app.

Risk Mitigation Strategies

  • Isolated markets: one collateral and one borrow asset per market, so no cross-asset contagion.
  • Immutable markets: no parameter can be changed after deployment, by anyone.
  • Conservative parameters: maintenance ratios above liquidation ratios, bounded liquidation spreads, and usage-ratio caps that preserve withdrawal liquidity.
  • Multi-source oracles with circuit breakers: see Oracles.
  • Defensive valuation: collateral valued at the lower confidence bound and liabilities at the upper bound.
  • Liquidation incentives: permissionless, partially-liquidating liquidations with a configured spread so that positions are restored to health promptly.
  • Dynamic interest rates: utilization-driven curves that price liquidity scarcity and pull utilization back toward the optimum.
  • Curated vaults: professional curators manage vault allocations under caps, timelocks, and an independent Sentinel; see the Curator Guide.

Incident Response

Templar's response to an alert follows the public emergency runbooks:

  1. Whoever spots an alert opens a war room, classifies severity, and takes the smallest reversible mitigation for their role.
  2. Containment ladder: halt Templar's own bots; trip the affected proxy oracle feed (freezing borrows, collateral withdrawals against debt, and liquidations on markets that read a proxy oracle); on vaults, Sentinel pause or restriction tightening, allocator abort or rebalance, then curator cap-to-zero or market removal.
  3. User exits are preserved: no role can disable supply withdrawal requests or repayments.
  4. Recovery uses a patched market deployed through the registry and voluntary migration, never an in-place upgrade.
  5. Stand-down requires sign-off from at least two roles, and user-affecting incidents produce a post-mortem.

For the protocol's overall security posture, see Security.

Testing & Code Coverage

Test Execution

Run the complete local suite through the same entrypoints used by CI:

just test

Use just test-fast for the complete non-node gate, including non-node integration targets, or just test-sandbox for the node-backed gate. The sandbox recipe prebuilds NEAR contracts before starting its pooled neard instances; pass --stale to reuse the contracts already built into target/near.

Run the artifact drift check separately when validating the release catalog — pure in-memory invariant checks, no builds:

./script/check-artifact-drift.sh

Local Testing

Running Tests with Coverage

# Generate and open HTML coverage for the fast library-test cut
just coverage

# Generate coverage.lcov
just coverage-lcov

Test Categories

  • Unit tests: Module-level functionality
  • Integration tests: Cross-module interactions
  • Contract tests: Smart contract behavior
  • End-to-end tests: Full workflow validation

Performance Testing

Gas Usage Analysis

Gas usage analysis is available through existing tools:

./script/gas-report.sh

This generates a gas report for market operations, including average gas costs for individual operations and snapshot iteration limits.

Test-Gate Timing

The node gate is the slowest thing we run, so its cost is measured rather than guessed. Two tools:

# Time the harness primitives on a dedicated neard: block-latency floor,
# per-transaction and per-patch costs, fixture setup.
just bench-sandbox

# Compare two whole-suite runs. `just test-sandbox` writes per-test timings to
# target/nextest/sandbox/junit.xml (see [profile.sandbox.junit] in
# .config/nextest.toml); copy it aside before and after a change.
./script/bench/junit-diff.py before.xml after.xml

junit-diff.py totals are summed per-test durations. The gate runs several tests concurrently, so those intervals overlap: the totals measure work done, not gate wall clock. Its per-test breakdown is the point — a change that halves the suite can still make one test much worse.

What the measurements established, so it need not be re-derived:

  • Node round-trips dominate; WASM payload is ~free. 570KB of extra contract code adds ~18ms to a deploy. Installing contract code via sandbox_patch_state works but is not faster, and it forfeits batching deploy+init into one transaction. Same verdict rules out global contracts. Don't retry either.
  • sandbox_patch_state costs ~200ms per call, not per record. Minting N accounts in one patch therefore costs roughly what minting one does — hence the harness's batched create_accounts.
  • Block production delay is the other lever, and it is local-only. See the sandbox cadence note below.

Sandbox Block Cadence

Locally the harness runs neard at a 40ms min_block_production_delay instead of the stock 120ms, which roughly halves the node gate. CI pins the stock 120ms (NEAR_SANDBOX_BLOCK_MS in .github/workflows/test.yml): a 4-vCPU runner cannot sustain four nodes producing blocks 3× as often, and attempting it caused widespread transaction-finality failures. Reducing parallelism to compensate was measured and is slower than stock.

Override the cadence with NEAR_SANDBOX_BLOCK_MS=<ms>. max_block_production_delay is compensated in the opposite direction so that avg(min, max) stays fixed at 310ms — nearcore credits a sandbox_fast_forward as delta_height × avg(min, max), so holding that average keeps every time-sensitive test's simulated time unchanged whatever the real cadence.

Because local blocks are faster than CI's, a test that leans on incidental block cadence to cross a time boundary will pass in one place and fail in the other. Advance chain time explicitly with fast_forward rather than relying on how long some operations happen to take.

Glossary

This glossary provides definitions for key terms used throughout the Templar Protocol documentation and smart contracts.

A

APY (Annual Percentage Yield): The total return on an investment over one year. In Templar, this represents the effective yearly return for suppliers or the cost for borrowers.

Asset Pair: The combination of collateral asset and borrow asset that defines a market (e.g., BTC/USDC means Bitcoin collateral, USDC borrowing).

B

Borrow Asset: The token that users can borrow from the market. Typically a stablecoin like USDC, but can be any supported token.

Borrow Position: A user's borrowing account containing collateral deposits, borrowed amounts, accumulated interest, and current status.

Borrower: A user who deposits collateral and borrows assets from the market, paying interest on the borrowed amount.

C

Circuit Breaker: A rule on a proxy oracle price feed that trips when accepted prices move in a way the rule forbids (for example, a single step larger than a configured percentage). When an enforced breaker trips, the feed is blocked and fails closed: markets reading it cannot borrow, withdraw collateral against debt, or liquidate until an operator re-arms it. A breaker in observe-only mode records and alerts on a trip without blocking. Feeds can also be tripped manually with no timelock.

Collateral Asset: The token deposited by borrowers to secure their loans. Must be worth more than the borrowed amount due to over-collateralization requirements.

Collateralization Ratio (CR): The ratio of collateral value to borrowed value. A 150% ratio means $150 of collateral backs $100 of debt.

Compounding: The process of reinvesting earned yield to generate additional returns over time.

Curator: The party responsible for a curated vault's risk policy: which markets it may allocate to, per-market and per-group caps, and fees. Curators operate under timelocked governance and alongside an independent Sentinel that can pause the vault immediately.

D

Debt: The total amount owed by a borrower, including principal plus accumulated interest and fees.

E

EMA: Exponentially-weighted moving average. A time-series smoothing technique that favors recency.

F

FMV (Fair Market Value): The current market price of an asset as determined by oracle price feeds.

G

Gas: The computational cost for executing transactions on the NEAR blockchain.

H

Harvest Yield: The action of claiming accumulated yield from a supply position, which can then be withdrawn.

I

Interest Accumulation: The process of calculating and adding accrued interest to a borrower's total liability.

Isolated Market: A Templar market holds exactly one collateral asset and one borrow asset in its own contract account, with its own supply pool and risk parameters. Losses in one market cannot spread to another: there is no shared liquidity or cross-collateralization between markets.

L

Lending: The general practice of providing assets to borrowers in exchange for interest payments. In Templar, suppliers lend to the market pool.

Liability: The total debt owed by a borrower, including principal, accumulated interest, and fees.

Liquidation: The forced sale of a borrower's collateral when their position becomes undercollateralized or expires.

Liquidator: A third party who performs liquidations by repaying part of a borrower's debt in exchange for discounted collateral.

Liquidator Spread: The discount liquidators receive when purchasing collateral, serving as incentive for providing the liquidation service.

Liquidity: The availability of assets in the market for borrowing or withdrawal. When liquidity is low, withdrawal requests may need to wait in the queue.

Liquidity Pool: The combined supply of assets deposited by all suppliers in a market, available for borrowers to access.

M

Market: A smart contract managing lending and borrowing for a specific asset pair (e.g., BTC/USDC market).

Maximum Usage Ratio: The maximum percentage of supplied assets that can be borrowed from a market, preventing over-utilization and maintaining liquidity reserves.

MCR (Minimum Collateralization Ratio): The minimum ratio of collateral value to borrowed value required to maintain a position. Different MCR levels trigger maintenance requirements or liquidation.

MCR Liquidation: The minimum collateralization ratio below which a position becomes eligible for liquidation.

MCR Maintenance: The minimum collateralization ratio required for new borrows or collateral withdrawals.

N

NEAR Intents: A NEAR Protocol feature that allows users to express desired outcomes (intents) that can be fulfilled by solvers, enabling more flexible and efficient transaction execution. See the official NEAR Intents documentation.

NEP-141: The NEAR Protocol standard for fungible tokens, similar to Ethereum's ERC-20. See the official NEP-141 specification.

NEP-245: The NEAR Protocol standard for multi-token contracts, similar to Ethereum's ERC-1155. See the official NEP-245 specification.

O

Oracle: A service providing real-time price data for assets, essential for calculating collateralization ratios and liquidations.

Origination Fee: A fee charged when creating a new borrow position, can be flat amount or percentage-based.

Over-collateralization: The requirement for borrowers to deposit collateral worth more than the borrowed amount, providing a safety buffer against price volatility.

P

Partial Liquidation: Liquidating only enough collateral to bring a position back to the maintenance MCR, rather than liquidating the entire position.

Principal: The original amount borrowed or supplied, excluding accumulated interest and fees.

Protocol Revenue: Fees collected by the protocol from borrowers and suppliers, distributed to suppliers and other accounts according to configured yield weights.

Proxy Oracle: A Templar contract that reads several underlying oracle sources (Pyth, RedStone), filters out stale prices, aggregates the survivors (typically a weighted median), gates the result through circuit breakers, and serves the accepted price to markets through the same interface as the Pyth contract. See Oracles.

Pyth Lazer (Pyth Pro): Pyth's low-latency signed price feed product. Templar runs an on-chain adapter that verifies Lazer signatures and serves the prices to proxy oracles.

Pyth Network: A decentralized oracle network providing high-frequency price feeds for various assets.

R

RedStone: A modular oracle network that delivers signed price data packages verified on-chain. Templar runs a RedStone adapter contract and uses RedStone feeds as an independent source alongside Pyth in its proxy oracles.

Registry: A smart contract that manages deployment and versioning of market contracts within the Templar Protocol.

Repay: The action of returning borrowed assets plus interest to reduce or eliminate a borrower's debt.

S

Sentinel: An emergency role on a curated vault that can pause the vault and tighten restrictions immediately, without a timelock, but cannot unpause, relax restrictions, or accept proposals.

Snapshot: A point-in-time record of market state including interest rates, asset amounts, and yield distribution.

Stablecoin: A cryptocurrency designed to maintain stable value, typically pegged to a fiat currency like USD. Commonly used as borrow assets in lending protocols.

Static Yield: A fixed allocation of market revenue to specific accounts, independent of their supply activity. Defined in the market's yield_weights configuration, static yield is distributed proportionally to designated accounts and can be withdrawn using the withdraw_static_yield function.

Supply: The total amount of assets deposited by suppliers that are available for borrowing in a market.

Supplier: A user who deposits assets into the market to earn yield from borrower interest payments.

Supply Withdrawal Fee: A fee charged when suppliers withdraw their assets from the market, configured per market to manage liquidity.

T

Time Chunk: A configurable time period (based on blocks, epochs, or timestamps) that determines when new snapshots are created.

Timelock: A mandatory delay between proposing and executing a governance action, giving users and operators time to react. Templar's proxy oracle governance and vault governance apply per-action timelocks; risk-reducing emergency actions (circuit breaker trips, vault pauses) execute immediately.

Transfer Call: A token transfer that includes data, allowing the receiving contract to execute logic based on the transfer.

U

Undercollateralized: A borrow position where the collateral value falls below the required minimum ratio, making it eligible for liquidation.

Utilization Rate: The percentage of supplied assets currently borrowed. Calculated as: borrowed_amount / total_supplied_amount.

V

Vault: A curated, single-asset vault (currently on Stellar) that issues shares to depositors and allocates pooled liquidity into markets under a curator's policy. See Stellar Curated Vaults for depositors and the Stellar Vault Curator Guide for operators.

W

Withdrawal Queue: A first-in-first-out system for processing supply withdrawals when market liquidity is insufficient.

Y

Yield: The return earned by suppliers on their deposited assets, generated from borrower interest payments and fees.

Notes

Sending funds to the market contract

When sending funds to a contract, you must call the asset contract's *_transfer_call function with the market as the receiver_id. So, for a token contract that implements the NEP-141 (Fungible Token) standard, you must call ft_transfer_call, specifying the market account ID as the receiver_id argument. For a token contract that implements the NEP-245 (Multi Token) standard, you must call mt_transfer_call.

If the funds are not sent using a *_transfer_call function, the contract will not be able to respond to the transfer: the funds will not be tracked by the contract, they will not be added to the supply, and the funds cannot be returned or withdrawn.

Contract interaction syntax

Contract interactions will be shown using near-cli-rs syntax. It can be installed via:

cargo install near-cli-rs

Example

near contract call-function as-transaction \
    ibtc-usdc.v1.tmplr.near borrow \
    json-args '{ "amount": "1000" }' \
    prepaid-gas '100.0 Tgas' \
    attached-deposit '0 NEAR' \
    sign-as account.near \
    network-config mainnet \
    sign-with-keychain \
    send

This command calls the function borrow on the contract ibtc-usdc.v1.tmplr.near with the arguments payload:

{
  "amount": "1000"
}

Large numbers are serialized as strings instead of numerical literals to ensure that the precision limitations of JSON parsers do not affect the values. (See "Notes on Serialization" on docs.near.org.)

The command attaches 100 teragas units and 0 NEAR to the call, signs the transaction as account.near using a key saved to the local keychain, and sends the transaction to NEAR mainnet.

Please refer to the near-cli-rs user guide for more details.