Skip to main content
Every privileged instruction delegates its authorization decision to the vault’s policy program through one uniform cross-program call. The contract is deliberately minimal, so any program that implements it can serve as a policy.

The wire contract

ElementValue
DiscriminatorHand-rolled 8-byte VALIDATE_DISCRIMINATOR = [60,252,90,66,246,253,232,139] (not an Anchor sighash)
Instruction dataVALIDATE_DISCRIMINATOR ‖ borsh(ValidateOperation) — a single-byte op code (0–12)
Accountsaccount[0] is always the read-only vault; the rest follow a fixed per-operation layout from hyro_sdk::get_context
InvocationThe core uses an unsigned invoke (never invoke_signed) — a policy can read and decide, but can never move funds
FailureIf the policy returns Err, the entire core instruction reverts — authorization is all-or-nothing
Policy state lives in a PDA seeded by the vault (seeds = [vault]) under the policy’s own program id, so each vault carries an isolated policy configuration. Operations a policy doesn’t constrain return Ok (pass-through).

The 13 operations

Thirteen core instructions each issue exactly one validate(ValidateOperation) CPI, with a 1:1 mapping between instruction and operation variant.
Core instructionvalidate(…)What it gates
create_txCreationPropose a CPI into a Transaction PDA
execute_txExecutionReplay the proposed CPI as the vault
request_depositRequestDepositOpen a deposit (escrow underlying)
process_depositsProcessDepositsSettle deposit → mint LP shares
approve_deposit_requestApproveDepositApprove a pending deposit
reject_deposit_requestRejectDepositReject / refund a deposit
request_withdrawalRequestWithdrawalOpen a withdrawal (escrow shares)
process_withdrawalsProcessWithdrawalsSettle withdrawal → burn shares, pay out
approve_withdrawal_requestApproveWithdrawalApprove a pending withdrawal
reject_withdrawal_requestRejectWithdrawalReject / return escrowed shares
use_fundsUseFundsMove capital out to the venue (e.g. Bybit)
return_fundsReturnFundsBring capital back on-chain
report_on_fundsReportWrite NAV / off-chain balance (oracle)

Failure semantics

Rejections surface as typed errors — TransactionAlreadyPending, NotEnoughSigners, AmountTooHigh / AmountTooLow, UnauthorizedSender — and either revert create_tx or leave did_execute false on execute_tx. Authorization leaves no partial state.

Build a custom policy

Implement this interface with a complete Rust skeleton.