For the complete documentation index, see llms.txt. This page is also available as Markdown.

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

Example response

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 instead

429

rate_limited

API key rate limit exceeded


Fetch a pending tree by root hash

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

Example response

Same shape as Fetch a tree by root hashdata.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} 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 instead

429

rate_limited

API key rate limit exceeded

Last updated