> For the complete documentation index, see [llms.txt](https://docs.veda.tech/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.veda.tech/api/policy-manager-and-merkle-trees.md).

# Policy Manager & Merkle Trees

Veda vaults enforce an **allowlist-only** policy: a vault's strategist can only perform pre-approved actions. Nothing else is callable through the vault, regardless of who initiates the call. This page covers how that policy is represented and committed onchain (aka the Merkle Tree), and how to fetch the underlying data via the API.

## Allowlist-only policy

A Veda vault generates yield by allocating depositor funds, per the curator's instructions, to trusted DeFi protocols using predefined yield strategies. The vault's Manager contract enforces this by maintaining a strict list of actions the strategist is allowed to take, encoded as a **merkle tree** — supply USDC to Aave V3 core, swap MORPHO into USDT via 1Inch, bridge USDC from Ethereum to Base via CCTP, and so on.

Actions outside the list cannot be executed through the vault. This is the core security property — the surface area of the vault is exactly the set of pre-approved actions, and that surface is verifiable by anyone reading onchain.

## How merkle trees encode the allowlist

The allowlist is materialized off-chain as a **merkle tree**: each permitted action is one **leaf**, and leaves are hashed together pairwise up the tree to a single root hash at the top. A tree can have thousands of leaves; its root is one 32-byte value.

To execute an action, the strategist sends the call to the Manager along with a **merkle proof** — the small set of sibling hashes needed to reconstruct the path from that action's leaf up to the root. The Manager hashes the action, walks the proof, and accepts the call only if the result matches the root it has stored. If the action isn't in the tree, or its parameters fall outside what the leaf permits, the Manager reverts.

The [Transaction Builder](/api/transaction-builder.md) does this leaf lookup and proof construction for you — its responses contain calldata that already embeds the correct proof. Fetching the raw tree is rarely necessary in normal use; it's exposed here for callers who want to verify proofs themselves, audit the allowlist offline, or build alternative tooling.

## How roots fit in

Each vault has a **current root** stored on its Manager contract. Updating the allowlist — adding a new protocol, tightening a constraint, removing an action — means computing a new tree off-chain, taking its root, and setting that root on the Manager.

***

## Fetch a tree by root hash

```
GET /v1/trees/{root_hash}
```

Returns the merkle tree for a root hash. Globally addressable and content-cacheable.

### Path parameters

| Name        | Type   | Notes                                                       |
| ----------- | ------ | ----------------------------------------------------------- |
| `root_hash` | string | 64-character hex string. A leading `0x` prefix is optional. |

### Example request

```bash
curl https://api.veda.tech/v1/trees/0xb8b546c6ea05423782d5dcdf55f0153dbdbb7b9877c72b8d06ae689db9751a68 \
  -H "Authorization: Bearer $VEDA_API_KEY"
```

### Example response

```json
{
  "data": {
    "root_hash":  "0xb8b546c6ea05423782d5dcdf55f0153dbdbb7b9877c72b8d06ae689db9751a68",
    "format":     "solidity",
    "leaf_count": 9,
    "depth":      4,
    "tree":       { "metadata": { "...": "..." }, "merkle_tree": [], "leaves": [] }
  }
}
```

Common metadata (`root_hash`, `format`, `leaf_count`, `depth`) is hoisted above the format-specific `tree` payload so clients don't have to branch on `format` to read it. The shape of `tree` itself depends on `format`:

* `solidity` trees have keys `metadata`, `merkle_tree`, `leaves`.
* `rust` trees have keys `leaves`, `root`, `layers`.

### Errors

| Status | Code                | Cause                                                                                                                                                                                |
| ------ | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `400`  | `invalid_root_hash` | `root_hash` is not 64 hex characters (with or without `0x` prefix)                                                                                                                   |
| `401`  | `unauthenticated`   | Missing, expired, or revoked API key                                                                                                                                                 |
| `404`  | `tree_not_found`    | No tree for this root, no vault in your tenant uses this root, or the root is pending — fetch it via [Fetch a pending tree by root hash](#fetch-a-pending-tree-by-root-hash) instead |
| `429`  | `rate_limited`      | API key rate limit exceeded                                                                                                                                                          |

***

## Fetch a pending tree by root hash

```
GET /v1/trees/{root_hash}/pending
```

Returns a **pending** merkle tree — one that has been generated off-chain but has not yet been set on the vault's Manager contract. Use this to review a tree before the onchain root rotation and confirm it matches what you expect.

### Path parameters

| Name        | Type   | Notes                                                       |
| ----------- | ------ | ----------------------------------------------------------- |
| `root_hash` | string | 64-character hex string. A leading `0x` prefix is optional. |

### Example request

```bash
curl https://api.veda.tech/v1/trees/0xabc1230000000000000000000000000000000000000000000000000000000000/pending \
  -H "Authorization: Bearer $VEDA_API_KEY"
```

### Example response

Same shape as [Fetch a tree by root hash](#fetch-a-tree-by-root-hash) — `data.root_hash`, `data.format`, `data.leaf_count`, `data.depth`, and the format-specific `data.tree` payload.

### Pending vs onchain

A root is either pending or onchain, never both — the two endpoints partition the tree namespace by state, so they return mirror-image `200` / `404` responses:

| Request                             | Root's current state            | Response             |
| ----------------------------------- | ------------------------------- | -------------------- |
| `GET /v1/trees/{root_hash}`         | Onchain (current or historical) | `200` with the tree  |
| `GET /v1/trees/{root_hash}`         | Pending, not yet onchain        | `404 tree_not_found` |
| `GET /v1/trees/{root_hash}/pending` | Pending, not yet onchain        | `200` with the tree  |
| `GET /v1/trees/{root_hash}/pending` | Onchain (current or historical) | `404 tree_not_found` |

Once a pending root is set onchain (typically via a rebalance-window rotation), `/pending` starts returning `404` for that root and the base [`/v1/trees/{root_hash}`](#fetch-a-tree-by-root-hash) starts returning `200`.

### Errors

| Status | Code                | Cause                                                                                                                                                                                |
| ------ | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `400`  | `invalid_root_hash` | `root_hash` is not 64 hex characters (with or without `0x` prefix)                                                                                                                   |
| `401`  | `unauthenticated`   | Missing, expired, or revoked API key                                                                                                                                                 |
| `404`  | `tree_not_found`    | No pending tree for this root, no vault in your tenant uses this root, or the root is already onchain — fetch it via [Fetch a tree by root hash](#fetch-a-tree-by-root-hash) instead |
| `429`  | `rate_limited`      | API key rate limit exceeded                                                                                                                                                          |
