Protocol Deep Dive

Zest Protocol V2 employs a hub-and-spoke architecture where the Market contract serves as the central coordinator, orchestrating interactions between users, vaults, registries, and oracles. This design separates concerns while maintaining efficiency through direct integration patterns.

Architectural Overview

                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                    β”‚  Market Contract β”‚
                    β”‚  (Central Hub)   β”‚
                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                             β”‚
        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
        β”‚                    β”‚                  β”‚
   β”Œβ”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”          β”Œβ”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”        β”Œβ”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”
   β”‚ Assets  β”‚          β”‚ Egroups β”‚        β”‚ Market- β”‚
   β”‚Registry β”‚          β”‚Registry β”‚        β”‚ Vault   β”‚
   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜          β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜        β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
        β”‚                    β”‚                  β”‚
        β”‚                    β”‚                  β”‚
   β”Œβ”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”
   β”‚              Asset Vaults (6 types)               β”‚
   β”‚   vault-stx | vault-sbtc | vault-ststx | etc.     β”‚
   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Core Components

Market Contract (market.clar)

The Market contract is the protocol's central coordinator and largest component, consolidating multiple subsystems for optimal gas efficiency.

Integrated Systems:

  • Oracle Resolution: Direct integration with Pyth and DIA oracles, including callcode transformations for derivative assets (stSTX, zTokens)

  • Vault Routing: Embedded routing logic directing operations to appropriate vaults without intermediate router contracts

  • Lending Operations: All borrow, repay, collateral, and liquidation logic

  • Health Calculations: LTV ratio computation and position validation

  • Index Caching: Timestamp-based caching of vault state per block

Design Philosophy: The market contract is intentionally stateless for persistent dataβ€”it holds only ephemeral caches that invalidate each block. All permanent state (user positions, balances) resides in market-vault.clar. This separation allows the market logic to be upgraded without requiring state migration.

Key Functions:

  • collateral-add/remove: Manage user collateral positions

  • borrow: Allow users to borrow against collateral

  • repay: Reduce or eliminate debt positions

  • liquidate: Process unhealthy positions

  • Oracle price resolution (internal functions)

  • Vault routing (internal if-based dispatch)

Market-Vault Contract (market-vault.clar)

The market-vault serves as the persistent state layer, tracking all user positions and their associated obligations.

State Management:

  • Obligations: Each user with an active position has an obligation entry containing collateral and debt data

  • Bitmap Tracking: Uses 128-bit masks to efficiently track which assets a user has enabled (bits 0-63 for collateral, bits 64-127 for debt)

  • Position Registry: Maps user addresses to obligation data structures

Access Control: Only the market contract can modify market-vault state. This strict access control ensures all position changes go through proper validation and health checks in the market contract.

Asset Registry (contracts/registry/assets.clar)

The asset registry maps principal addresses (SIP-10 token contracts) to internal numeric asset IDs and stores oracle configuration for each asset.

Asset Configuration:

  • Asset ID mapping (e.g., STX = 0, zSTX = 1, sBTC = 2 etc.)

  • Oracle type and feed identifiers

  • Price staleness thresholds

  • Enabled status (active/inactive)

  • Collateral and debt enablement flags

Why Numeric IDs: Using numeric asset IDs (uint) rather than principals throughout the protocol significantly reduces gas costs. Bitmasks can efficiently represent sets of assets, and comparisons become simple integer operations.

Efficiency Groups (contracts/registry/egroup.clar)

The egroup registry stores risk parameters for asset combinations and implements the bucket-based lookup system for efficient resolution.

Risk Parameters Per Group:

  • Collateral and debt asset masks (defining which assets the group covers)

  • LTV ratios (borrow, partial liquidation, full liquidation)

  • Liquidation penalty bounds (minimum and maximum)

  • Liquidation curve exponent

Bucket Optimization: Groups are organized into buckets by population count (number of assets in the group). When resolving a user's risk group, the system only checks buckets with relevant population counts, achieving O(log n) lookups rather than O(n).

Asset Vaults

Each supported asset has its own vault contract implementing standardized interfaces:

Vault Types:

  • vault-stx: Wrapped STX (wSTX) lending

  • vault-sbtc: Synthetic Bitcoin (sBTC) lending

  • vault-ststx: Staked STX (stSTX) lending with dual yield

  • vault-usdc: USD Coin stablecoin lending

  • vault-usdh: Hermetica USD stablecoin lending

  • vault-ststxbtc: Staked STX (stSTXbtc) vault (collateral only)

Vault Responsibilities:

  • Issue zTokens (vault shares) to depositors

  • Manage underlying asset reserves

  • Accrue compound interest using index-based system

  • Execute system borrows/repays on behalf of market contract

  • Support whitelisted flash loans with callback mechanism

  • Mint protocol reserves to DAO treasury

ERC-4626 Style: Vaults follow the ERC-4626 pattern where shares (zTokens) represent proportional ownership of the vault's assets. As interest accrues, each share becomes redeemable for more underlying tokens, providing passive yield to depositors.

Integration Patterns

Oracle Integration

V2 embeds oracle logic directly in the market contract rather than using a separate oracle contract, eliminating one layer of cross-contract calls.

1

Price Resolution Flow

Market determines which oracles are needed for current operation and fetches prices directly from Pyth or DIA based on asset configuration.

2

Applies callcode transformations where necessary:

  • stSTX: Multiplies by Lido ratio from external protocol

  • zTokens: Multiplies by vault liquidity index

3

Validates timestamp freshness using block time.

4

Caches prices for remainder of operation.

Timestamp Validation: All oracle timestamps must be within the configured staleness threshold (typically 120 seconds). The protocol uses stacks-block-time for precise temporal validation rather than approximating time from block height.

Index Caching

The market implements a timestamp-keyed cache for vault indexes, ensuring each vault is accrued at most once per block.

Cache Mechanism:

  • Cache key: {timestamp: block-time, asset-id: uint}

  • First operation on a vault in a block triggers accrual and caches indexes

  • Subsequent operations in same block read from cache

  • Next block, timestamp changes, cache misses, fresh accrual occurs

Impact: For operations involving multiple collateral and debt assets, this caching reduces vault calls by 30-50%, significantly lowering transaction costs for complex positions.

Risk Group Resolution

When the market needs to determine risk parameters for a position, it queries the egroup registry with the user's asset mask.

1

Market reads user's collateral and debt bitmask from market-vault.

2

Calls egroup registry's resolve(mask) function.

3

Egroup registry:

  • Calculates minimum population count from mask

  • Checks only relevant buckets (optimization)

  • Returns first matching group (smallest superset)

4

Market uses returned LTV and liquidation parameters for operation.

Validation: The protocol validates that users can't transition to invalid egroups. When adding new collateral types, the future asset combination must map to a valid risk group before the operation is allowed.

State Flow Example

User Borrows 500 USDC Against sBTC Collateral:

1

User calls market.borrow(usdc-aid, 500, tx-sender, none).

2

Market validates USDC borrowing is enabled in asset registry.

3

Market accrues vault-usdc interest (or uses cached indexes).

4

Market reads user position from market-vault.

5

Market resolves user's risk group from egroup registry (e.g., sBTC β†’ USDC group).

6

Market calculates current health using oracle prices and LTV-BORROW threshold.

7

Market simulates post-borrow health (adding 500 USDC debt).

8

If healthy: market calls vault-usdc.system-borrow(500).

9

Market instructs market-vault to update user's scaled debt.

10

Market transfers borrowed USDC to user.

Cross-Contract Calls: Market β†’ Market-Vault (read), Market β†’ Egroup (read), Market β†’ Assets (read), Market β†’ Oracle (read), Market β†’ Vault-USDC (write), Market β†’ Market-Vault (write)

Security Architecture

Access Control Layers

Market Contract:

  • Only callable by users for their own positions

  • Validates all inputs before state changes

  • Enforces health checks pre and post operation

Market-Vault:

  • Only market contract can modify state

  • Implements authorization check on all writes

  • All reads are public (transparency)

Vaults:

  • System functions (system-borrow, system-repay) restricted to market contract

  • User functions (deposit, withdraw) publicly callable

  • Flash loan callbacks must repay before transaction ends

Health Check System

Every operation that could affect position health triggers validation:

Pre-Flight Checks:

  • Current position must be healthy (below LTV-BORROW)

  • Ensures operations aren't attempted on already-unhealthy positions

Post-Operation Simulation:

  • Calculate position health after proposed changes

  • Reject transaction if simulation shows unhealthy result

  • Prevents users from borrowing/withdrawing into liquidation

Liquidation Validation:

  • Only allow liquidations when position exceeds LTV-LIQ-PARTIAL

  • Validate liquidation amount is appropriate for position health

  • Ensure liquidator receives correct collateral with penalty

Emergency Controls

Liquidation Pause:

  • DAO can pause liquidations in case of oracle issues or market dislocations

  • Grace period prevents immediate liquidation cascade when unpausing

  • Borrowers can still repay during pause

Asset Disablement:

  • DAO can disable assets from being used as new collateral or debt

  • Existing positions unaffected (grandfathered)

  • Allows controlled asset offboarding

Upgrade Strategy

The market contract is designed to be upgradeable while preserving state:

Stateless Market Design: Since persistent state lives in market-vault (not market), deploying a new market version doesn't require state migration. The new market contract can read existing positions from the unchanged market-vault.

Registry Separation: Asset and egroup configurations live in separate registries. Parameters can be updated through governance without redeploying core contracts.

This modular approach allows targeted upgrades to specific subsystems while minimizing deployment complexity and risk.

Summary

Zest V2's architecture consolidates coordination logic in the market contract while separating concerns through specialized subsystems. Direct integration patterns for oracles and vault routing reduce gas costs, while stateless market design and registry separation enable upgradability. The hub-and-spoke topology with the market as central coordinator provides a clean, efficient, and maintainable foundation for the lending protocol.

Last updated