Skip to main content
Policy builders are helper functions that construct PolicyConfig objects for common strategy execution scenarios. A policy must exist onchain before any strategy instruction can be executed by the vault.

What is a Policy?

A programInteraction policy defines exactly which instructions the vault’s smart account is permitted to execute. It is enforced onchain by the Squads program when executeTransactionSync is called. A policy consists of:
  • instructionsConstraints — a list of InstructionConstraint objects, each specifying:
    • programId — which program is allowed
    • dataConstraints — which instruction discriminators match (first 8 bytes of instruction data)
    • accountConstraints — which specific public keys must be present

Adding a Policy to a Vault

Policies are added by the vault manager role:
import {
  ExponentVault,
  createKaminoDepositPolicy,
  KAMINO_MARKETS,
  KAMINO_RESERVES,
  KaminoMarket,
} from "@exponent-labs/exponent-sdk";
import { Connection, Transaction, sendAndConfirmTransaction } from "@solana/web3.js";

const connection = new Connection("https://api.mainnet-beta.solana.com");
const vault = await ExponentVault.load({ connection, address: vaultAddress });

const solReserve = KAMINO_RESERVES[KaminoMarket.MAIN]["SOL"].pubkey;
const mainMarket = KAMINO_MARKETS[KaminoMarket.MAIN];

// Build the policy config
const policyConfig = createKaminoDepositPolicy({
  allowedReserves: [solReserve],
  allowedLendingMarkets: [mainMarket],
});

// Add it to the vault — requires payer, squads program, policy seed, and transaction index
const ix = vault.ixAddPolicy({
  payer: managerWallet.publicKey,
  policyConfig,
  squadsProgram: squadsProgram,
  nextPolicySeed: nextPolicySeed,
  nextTransactionIndex: nextTransactionIndex,
});
const tx = new Transaction().add(ix);
await sendAndConfirmTransaction(connection, tx, [managerWallet]);

Exponent Core Policy

createCorePolicy builds a policy that permits strip and merge operations on the Exponent Core program (ExponentnaRg3CQbW6dqQNZKXp7gtZ9DGMp1cwC4HAS7).
import { createCorePolicy } from "@exponent-labs/exponent-sdk";
import { PublicKey } from "@solana/web3.js";

const EXPONENT_VAULT = new PublicKey("...");

const policyConfig = createCorePolicy({
  allowedVaults: [EXPONENT_VAULT],
  actions: ["strip", "merge"],
});

Parameters

ParameterTypeDescription
allowedVaultsPublicKey[]Optional. Exponent Core vault addresses to constrain
allowedSyMintsPublicKey[]Optional. SY mint public keys — use with vaultsForSyMints
vaultsForSyMintsPublicKey[]Optional. Vault addresses corresponding to each SY mint (same order as allowedSyMints)
actionsCorePolicyAction[]Which actions to allow: "initializeYieldPosition", "strip", "merge"
spendingLimitsSpendingLimit[]Optional. Spending limits
thresholdnumberOptional. Number of signers required (default 1)
timeLocknumberOptional. Time lock in seconds (default 0)
You can constrain by vault address directly (allowedVaults) or by SY mint (allowedSyMints + vaultsForSyMints). If you omit both, any vault is allowed for the specified actions.
See Core Instructions for usage examples.

Exponent CLMM Policy

createClmmPolicy builds a policy that permits all CLMM operations on the Exponent CLMM program (XPC1MM4dYACDfykNuXYZ5una2DsMDWL24CrYubCvarC) — including providing liquidity, trading PT/YT, and claiming farm emissions.
import { createClmmPolicy } from "@exponent-labs/exponent-sdk";
import { PublicKey } from "@solana/web3.js";

const CLMM_MARKET = new PublicKey("...");

const policyConfig = createClmmPolicy({
  allowedMarkets: [CLMM_MARKET],
});

Parameters

ParameterTypeDescription
allowedMarketsPublicKey[]Optional. CLMM MarketThree addresses to constrain — omit to allow any market
thresholdnumberOptional. Number of signers required (default 1)
timeLocknumberOptional. Time lock in seconds (default 0)
Omitting allowedMarkets permits CLMM operations on any market. Specify market addresses to restrict the vault to specific pools.
See CLMM Instructions for usage examples.

Exponent Orderbook Policy

createOrderbookPolicy builds a policy that permits interacting with the Exponent Orderbook program (XPBookgQTN2p8Yw1C2La35XkPMmZTCEYH77AdReVvK1).
import { createOrderbookPolicy } from "@exponent-labs/exponent-sdk";
import { PublicKey } from "@solana/web3.js";

const SY_MINT = new PublicKey("...");

const policyConfig = createOrderbookPolicy({
  allowedSyMints: [SY_MINT],
  actions: ["postOffer", "marketOffer", "removeOffer", "withdrawFunds"],
});

Parameters

ParameterTypeDescription
allowedSyMintsPublicKey[]SY mint public keys that are allowed
actionsOrderbookPolicyAction[]Which actions to allow: "postOffer", "marketOffer", "removeOffer", "withdrawFunds"
spendingLimitsSpendingLimit[]Optional. Spending limits
thresholdnumberOptional. Number of signers required (default 1)
timeLocknumberOptional. Time lock in seconds (default 0)
See Orderbook Instructions for usage examples.

Kamino Lend Policies

Deposit Policy

createKaminoDepositPolicy builds a policy that permits calling depositReserveLiquidityAndObligationCollateral on the Kamino Lending program.
import { createKaminoDepositPolicy } from "@exponent-labs/exponent-sdk";

const policyConfig = createKaminoDepositPolicy({
  allowedReserves: [solReserve],
  allowedLendingMarkets: [mainMarket],
});

Parameters

ParameterTypeDescription
allowedReservesPublicKey[]Reserve public keys that can receive deposits
allowedLendingMarketsPublicKey[]Optional. Lending market public keys

Withdraw Policy

createKaminoWithdrawPolicy builds a policy that permits calling withdrawObligationCollateralAndRedeemReserveCollateral on the Kamino Lending program.
import { createKaminoWithdrawPolicy } from "@exponent-labs/exponent-sdk";

const policyConfig = createKaminoWithdrawPolicy({
  allowedReserves: [solReserve],
  allowedLendingMarkets: [mainMarket],
});

Parameters

ParameterTypeDescription
allowedReservesPublicKey[]Reserve public keys allowed as withdrawal sources
allowedLendingMarketsPublicKey[]Optional. Lending market public keys

Borrow Policy

createKaminoBorrowPolicy builds a policy that permits calling borrowObligationLiquidity on the Kamino Lending program.
import { createKaminoBorrowPolicy } from "@exponent-labs/exponent-sdk";

const policyConfig = createKaminoBorrowPolicy({
  allowedReserves: [solReserve],
  allowedLendingMarkets: [mainMarket],
});

Parameters

ParameterTypeDescription
allowedReservesPublicKey[]Reserve public keys allowed for borrowing
allowedLendingMarketsPublicKey[]Optional. Lending market public keys

Repay Policy

createKaminoRepayPolicy builds a policy that permits calling repayObligationLiquidity on the Kamino Lending program.
import { createKaminoRepayPolicy } from "@exponent-labs/exponent-sdk";

const policyConfig = createKaminoRepayPolicy({
  allowedReserves: [solReserve],
  allowedLendingMarkets: [mainMarket],
});

Parameters

ParameterTypeDescription
allowedReservesPublicKey[]Reserve public keys allowed for repayment
allowedLendingMarketsPublicKey[]Optional. Lending market public keys

Full Access Policy

createKaminoFullAccessPolicy creates a single policy covering multiple Kamino actions. This is useful when a strategy requires deposit, withdraw, borrow, and repay on the same reserves.
import {
  createKaminoFullAccessPolicy,
  KAMINO_MARKETS,
  KAMINO_RESERVES,
  KaminoMarket,
} from "@exponent-labs/exponent-sdk";

const solReserve = KAMINO_RESERVES[KaminoMarket.MAIN]["SOL"].pubkey;
const usdcReserve = KAMINO_RESERVES[KaminoMarket.MAIN]["USDC"].pubkey;
const mainMarket = KAMINO_MARKETS[KaminoMarket.MAIN];

const policyConfig = createKaminoFullAccessPolicy({
  allowedReserves: [solReserve, usdcReserve],
  allowedActions: ["deposit", "withdraw", "borrow", "repay"],
  allowedLendingMarkets: [mainMarket],
});

Parameters

ParameterTypeDescription
allowedReservesPublicKey[]Reserve public keys allowed for all specified actions
allowedActions`(“deposit""withdraw""borrow""repay”)[]`Which Kamino actions to permit
allowedLendingMarketsPublicKey[]Optional. Lending market public keys
Using a combined policy simplifies vault administration when a strategy requires multiple operations on the same reserves. The allocator passes the same policyPda to all Kamino calls.

Unified Kamino Policy

createKaminoPolicy is a unified API that supports both allowedReserves and allowedDepositMints as optional constraints. This provides finer-grained control than createKaminoFullAccessPolicy — you can constrain by the liquidity mint in addition to (or instead of) the reserve address.
import {
  createKaminoPolicy,
  KAMINO_MARKETS,
  KAMINO_RESERVES,
  KaminoMarket,
} from "@exponent-labs/exponent-sdk";

const usdcMint = KAMINO_RESERVES[KaminoMarket.MAIN]["USDC"].mint;
const mainMarket = KAMINO_MARKETS[KaminoMarket.MAIN];

const policyConfig = createKaminoPolicy({
  allowedDepositMints: [usdcMint],
  actions: ["deposit", "withdraw"],
  allowedLendingMarkets: [mainMarket],
});

Parameters

ParameterTypeDescription
allowedReservesPublicKey[]Optional. Reserve public keys to constrain
allowedDepositMintsPublicKey[]Optional. Liquidity mint public keys to constrain
actionsKaminoPolicyAction[]Which actions to allow: "deposit", "withdraw", "borrow", "repay"
allowedLendingMarketsPublicKey[]Optional. Lending market public keys
spendingLimitsSpendingLimit[]Optional. Spending limits
thresholdnumberOptional. Number of signers required (default 1)
timeLocknumberOptional. Time lock in seconds (default 0)
Both allowedReserves and allowedDepositMints are optional. Omit both to allow any reserve and mint for the specified actions.

Titan Swap Policy

createTitanSwapPolicy builds a policy that permits calling SwapRouteV2 on the Titan program (T1TANpTeScyeqVzzgNViGDNrkQ6qHz9KrSBS4aNXvGT).
import { createTitanSwapPolicy } from "@exponent-labs/exponent-sdk";
import { PublicKey } from "@solana/web3.js";

const USDC_MINT = new PublicKey("...");
const SOL_MINT = new PublicKey("...");

const policyConfig = createTitanSwapPolicy({
  allowedMints: [USDC_MINT, SOL_MINT],
});

Parameters

ParameterTypeDescription
allowedMintsPublicKey[]Optional. Token mints to constrain — applies to both input and output mints
thresholdnumberOptional. Number of signers required (default 1)
timeLocknumberOptional. Time lock in seconds (default 0)
The allowedMints constraint applies to both the input mint and the output mint of the swap. Omitting it permits swaps between any tokens.
See Titan Instructions for usage examples.