Skip to main content
The ActionProposal account represents a governance proposal for a vault settings change or position update. It tracks the proposal status, voting results, and execution timeline. Program ID: HycecAnELpjL1pMp435nEKWkcr7aNZ2QGQGXpzK1VEdV

ActionProposal

#[account]
pub struct ActionProposal {
    /// The vault this proposal belongs to
    pub vault: Pubkey,

    /// Sequential proposal identifier
    pub proposal_id: u64,

    /// The manager who created this proposal
    pub proposer: Pubkey,

    /// Serialized ProposalAction data (VaultSettingsAction or PositionUpdate)
    pub action_data: Vec<u8>,

    /// Unix timestamp when the proposal was created
    pub created_at: i64,

    /// Unix timestamp when voting ends
    pub voting_ends_at: i64,

    /// Seconds to wait after approval before execution is allowed
    pub timelock_seconds: u32,

    /// Unix timestamp when the proposal becomes executable (after timelock)
    pub executable_at: i64,

    /// Current status of the proposal
    pub status: ProposalStatus,

    /// Total LP tokens staked to reject
    pub reject_votes: u64,

    /// Total LP tokens staked to opt-out
    pub opt_out_votes: u64,

    /// PDA bump seed
    pub bump: u8,

    /// Reserved bytes for future use
    pub reserved: [u8; 32],
}

ProposalStatus

pub enum ProposalStatus {
    /// Voting is active
    Active,
    /// Proposal was approved (rejection votes below threshold)
    Approved,
    /// Proposal was rejected (rejection votes exceeded threshold)
    Rejected,
    /// Proposal has been executed
    Executed,
    /// Proposal was cancelled by manager or sentinel
    Cancelled,
}

ProposalAction

The action_data field contains a serialized ProposalAction:
pub enum ProposalAction {
    /// A vault settings change (add/remove token entries, set withdrawal period, etc.)
    VaultSettingsAction(VaultSettingsAction),
    /// A strategy position update (add/remove positions)
    PositionUpdate(PositionUpdate),
}

Voting Model

Strategy Vaults use rejection-based voting:
  • Proposals pass by default unless sufficient LP is staked to reject
  • The rejection threshold is configured per-vault in ProposalVoteConfig.rejectionThresholdBps
  • LP holders can also vote OptOut — this doesn’t block the proposal but queues their LP for withdrawal if it passes

TypeScript

import { fetchActionProposalAccount } from "@exponent-labs/exponent-sdk/client/vaults";

const { data } = await fetchActionProposalAccount(connection, proposalAddress);
console.log(data.status);           // ProposalStatus
console.log(data.rejectVotes);      // bigint
console.log(data.optOutVotes);      // bigint
console.log(data.votingEndsAt);     // bigint (unix timestamp)
console.log(data.executableAt);     // bigint (unix timestamp)