> ## Documentation Index
> Fetch the complete documentation index at: https://docs.canopy.deal/llms.txt
> Use this file to discover all available pages before exploring further.

# Canopy Protocol Security Model and Design Principles

Defense-in-depth: multiple independently verifiable guarantees, each addressing a distinct class of vulnerability.

## Core Design Principles

<Steps>
  <Step title="Checks-Effects-Interactions (CEI)">
    Every state-modifying function in the OTCVenue updates internal state — balances, fill records, offer status — **before** making any external token transfer calls. `assetRemaining` is decremented and `assetFilled` is incremented before any `safeTransfer` or `safeTransferFrom`. This strict ordering means that even if an external call triggers a reentrant callback, the contract's internal state already reflects the outcome of the current operation.
  </Step>

  <Step title="Reentrancy Protection">
    All state-modifying functions carry explicit reentrancy guards via OpenZeppelin's `ReentrancyGuard`. This dual-layer defense (CEI + guard) ensures safety even when interacting with ERC-777 tokens or other callback-capable token contracts whose hooks might attempt to call back into the venue mid-execution. The guard causes the transaction to revert immediately rather than proceeding with corrupted state.
  </Step>

  <Step title="Full Collateralization">
    An offer is not visible or fillable until the seller's assets are fully escrowed in the contract. Canopy does not support speculative or credit-based offers of any kind. Every fillable order represents real, on-chain collateral that has already been transferred and verified. Buyers face no counterparty risk on the asset leg — the tokens they expect to receive are already locked.
  </Step>

  <Step title="Cumulative Precision Arithmetic">
    Fill costs are computed using a cumulative `mulDiv` approach: `quoteCost = mulDiv(newFilledTotal, pricePerUnit, 10^assetDecimals) - previousQuotePaid`. This means split fills produce exactly the same aggregate cost as a single fill of the same total size. An attacker cannot craft fill sequences that exploit rounding to extract more assets than they paid for.
  </Step>

  <Step title="Measured Escrow Deposits">
    When a seller deposits collateral, the venue records the **actual received balance** — the difference in the contract's token balance before and after the transfer — rather than the nominal amount the seller declared. This protects the protocol against fee-on-transfer tokens and other transfer mechanics that deliver less than the stated amount. The escrow record always reflects what is truly held.
  </Step>

  <Step title="Measured Outbound Transfers">
    Outbound transfers (to buyers at fill time, to sellers at cancellation, and to redeemers) are also measured. The venue verifies that its own balance decreased by exactly the stated amount and that the recipient's balance increased. If these checks fail — indicating a token with unsupported transfer behavior — the transaction reverts with `UnsupportedTransferBehavior()`.
  </Step>

  <Step title="Cumulative Fill Accounting">
    Partial fills are tracked cumulatively per offer (`assetFilled`, `quotePaid`) rather than computed as running deltas. The contract validates that `assetUnits <= assetRemaining` on every fill. When `assetRemaining` reaches zero, the offer is deactivated. This prevents double-counting and makes it structurally impossible for aggregate fills to overdraw the escrow.
  </Step>

  <Step title="Fee Snapshotting">
    Each offer captures `feeBps` and `feeRecipient` at creation time. This means the fee terms for an offer are immutable once created — an admin changing the venue's fee rate cannot retroactively affect existing offers.
  </Step>

  <Step title="Permissionless and Unpausable Redemption">
    No single party — including the protocol owner, the original seller, or any other privileged address — can block or gate claim redemptions after the unlock time. The `redeem` and `redeemWithMinimum` functions carry the `nonReentrant` modifier but not the `whenEntryOpen` modifier. Even when the entry pause is active, redemption remains fully operational.
  </Step>
</Steps>

## Series Isolation

Each series in Canopy maintains its own independent `backing` counter. The backing and claim supply for one series are entirely separate from every other series. A bug, an accounting imbalance, or an unexpected token behavior in one series has no access to and no effect on the collateral held in any other series. This isolation is structural — there are no shared balance pools or cross-series accounting entries — so you can reason about each series as a self-contained unit.

## Trust Model Summary

Understanding what Canopy does and does not hold in trust is essential for integrating or auditing the protocol.

| Property                | Detail                                                                                                                                                 |
| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **Quote token custody** | The venue does **not** custody quote tokens. Quote payments flow directly from buyer to seller (and fee recipient) at fill time.                       |
| **Fund flow**           | Assets move directly between counterparties at the moment of fill; there is no intermediate holding period for quote tokens.                           |
| **Escrowed assets**     | Only the asset being sold is held in escrow, and only for the duration between offer creation and fill/cancel/redemption.                              |
| **Administration**      | Owner permissions are intentionally limited to fee configuration and entry pause. See [Admin Controls](/protocol/admin-controls) for a full breakdown. |
| **Ownership model**     | The venue uses OpenZeppelin's `Ownable2Step`, requiring a two-step ownership transfer for safety.                                                      |

<Warning>
  Canopy's security guarantees apply only to the OTCVenue contract itself. The protocol cannot verify that a token contract behaves correctly, that an RPC endpoint is returning accurate data, or that the contract address you are interacting with is the canonical deployment. Always verify contract addresses against official sources before depositing assets or executing fills.
</Warning>
