Authorization PDAs: enforcing who can touch your RWA vault
A practical look at how STRATA uses Authorization PDAs and Anchor account constraints to enforce access rules for institutional RWA vaults.

Every RWA protocol that wants to serve institutional capital eventually has to answer a simple question in code: who is allowed to touch this vault, and under what conditions? For most DeFi systems, the answer is still “any wallet that calls the function”. For an institutional RWA vault, that is a non-starter.
On Solana, Program Derived Addresses (PDAs) give protocols a way to represent authority and policy without private keys. An Authorization PDA is a small account that encodes who is allowed to do what for a short period of time, and the program can refuse to execute any instruction that does not come with a valid authorization attached.
What an Authorization PDA actually represents
In STRATA, an Authorization PDA is the on-chain projection of an off-chain decision. Off-chain, the identity layer verifies verifiable credentials (KYC, jurisdiction, risk acknowledgments, etc.) and checks them against the protocol’s policies. If everything passes, the backend creates a PDA that encodes:
- the wallet that is allowed to act,
- which tranche or vault it can access,
- which operation is permitted (for example, deposit into senior or junior),
- and an expiry timestamp after which the authorization is no longer valid.
The PDA has no private key. It exists only because the program can derive it using its own program ID and a deterministic set of seeds. That is what makes it safe to treat as an authority on-chain.
A sketch of the PDA structure
In Anchor, the Authorization PDA might be modeled roughly like this:
#[account]
pub struct Authorization {
pub wallet: Pubkey,
pub vault: Pubkey,
pub tranche: u8, // 0 = senior, 1 = junior
pub operation: u8, // 0 = deposit, 1 = redeem, ...
pub expires_at: i64, // unix timestamp
pub bump: u8,
}
The account itself is derived from a stable set of seeds. For example:
// Seeds: ["auth", wallet, vault, tranche, operation]
#[derive(Accounts)]
pub struct DepositWithAuth<'info> {
#[account(
mut,
has_one = vault,
)]
pub authorization: Account<'info, Authorization>,
#[account(
seeds = [
b"auth",
authorization.wallet.as_ref(),
authorization.vault.as_ref(),
&[authorization.tranche],
&[authorization.operation],
],
bump = authorization.bump,
)]
/// CHECK: PDA derived and verified by seeds + bump
pub authorization_pda: UncheckedAccount<'info>,
// ... rest of the accounts (vault, user, token accounts, system)
}
This pattern ensures that only PDAs derived from the agreed seeds are accepted, and the Authorization account itself is tied to the expected wallet and vault.
Enforcing authorization inside the instruction
The instruction logic then does the actual enforcement. At a high level, the flow is:
- Check that
authorization.walletmatches the signer. - Check that
authorization.vaultmatches the vault being accessed. - Check that
authorization.trancheandauthorization.operationmatch the instruction being executed. - Check that
authorization.expires_atis in the future. - Only then proceed with the deposit or redemption logic.
In code, this could look like:
pub fn deposit_with_auth(ctx: Context<DepositWithAuth>, amount: u64) -> Result<()> {
let auth = &ctx.accounts.authorization;
let clock = Clock::get()?;
// 1. Wallet must match signer
require_keys_eq!(auth.wallet, ctx.accounts.user.key(), CustomError::UnauthorizedWallet);
// 2. Authorization must not be expired
require!(clock.unix_timestamp <= auth.expires_at, CustomError::AuthorizationExpired);
// 3. Operation and tranche must match this instruction
require!(auth.operation == OP_DEPOSIT, CustomError::InvalidOperation);
require!(auth.tranche == TRANCHE_SENIOR, CustomError::InvalidTranche);
// 4. If all good, proceed with the normal deposit logic
// (token transfers, share minting, vault accounting, etc.)
process_deposit_into_vault(ctx, amount)?;
Ok(())
}
The important part is that the access control logic lives next to the vault math, not in some external service. If the Authorization PDA is missing, malformed, or expired, the transaction fails at the protocol level, no matter what the frontend or backend tries to do.
Why this pattern matters for institutional RWA
From an institutional perspective, this pattern does three important things at once:
- It makes access rules explicit: auditors can inspect exactly which fields define who can access which tranches and under what conditions.
- It aligns on-chain behavior with off-chain policies: if the identity layer or policy engine refuses to issue an Authorization PDA, the vault is literally unreachable for that combination of wallet, tranche, and operation.
- It avoids long-lived “god whitelists”: authorizations can be short-lived, scoped, and revocable by simply refusing to refresh the PDA once it expires.
For STRATA, Authorization PDAs are the bridge between self-sovereign identity and vault mechanics. They let the protocol enforce complex rules about who can interact with RWA exposure, in a way that is transparent, testable, and as immutable as the rest of the program logic.
Knowledge Base / FAQ
Frequently Asked Questions
What is an Authorization PDA in Solana RWA protocols?
An Authorization PDA is a Program Derived Address that acts as an on-chain representation of off-chain compliance decisions. It encodes permissible wallets, specific vault tranches, allowed operations, and expiry timestamps directly on-chain without private keys.
How do Authorization PDAs enforce access control inside smart contracts?
Anchor instruction handlers verify the PDA's derived seeds, ensuring the transaction signer matches the authorized wallet, the target vault matches, the operation is valid, and the Unix timestamp has not surpassed the expiry limit before executing vault math.
Why are short-lived Authorization PDAs safer than static whitelists?
Short-lived PDAs require continuous off-chain policy verification. If a user's compliance status changes or risk policies update, the system stops issuing or refreshing the PDA, revoking access automatically without maintaining permanent admin privileges on-chain.
Where is access control executed in STRATA's architecture?
Access enforcement is embedded directly alongside vault math inside smart contract instructions. If an Authorization PDA is missing, expired, or invalid, the transaction fails deterministically on-chain regardless of frontend or API state.
Can Zanvexis help build custom PDA authorization architectures for RWA protocols?
Yes. Zanvexis specializes in engineering institutional Solana protocols, designing Anchor PDA constraints, structuring compliance-ready access control pipelines, and hardening vault architectures.
If you need help hardening your crypto project or designing custom Solana PDA access controls (wallets, backend, smart contracts, or incident response), you can request a security-focused engagement through the Services page or reach out directly via the Contact terminal.
Need help building secure technology?
Explore how Zanvexis helps teams build secure software, blockchain systems, intelligent platforms, and high-performance infrastructure.
Explore all services →Continue reading
Related articles
Trading infrastructure stops being resilient the moment incident response depends on heroics instead of architecture
Why serious trading platforms need incident response and operational resilience designed into architecture, tooling, and governance instead of relying on ad hoc fixes and individual effort during outages.
Crypto custody stops being security and becomes counterparty exposure when architecture depends on people behaving well
Why institutional-grade crypto custody has to enforce separation of duties, destination controls, cryptographic dual control, and operating model discipline in architecture instead of trusting operator conduct.
Trading bots become brittle when architecture pretends every market is the same
Why serious trading bot infrastructure needs clear separation between exchange adapters, strategy logic, execution paths, risk controls, and observability instead of one-size-fits-all bots.