Hyro Protocol logo mark
Hyro Protocol
Explore vaults

Validation System

The HYRO Protocol validation system provides a unified approach for policy programs to validate vault operations. The system uses a single validate function with operation-specific contexts, enabling flexible and extensible validation logic across different policy types.

Validation Architecture

Unified Validation Function All policy programs implement a single validate function that accepts a ValidateOperation parameter. This approach simplifies policy implementation while providing operation-specific validation capabilities.

Operation Types The validation system supports four distinct operations:

  • Creation: Validates transaction creation requests
  • Execution: Validates transaction execution requests
  • UseFunds: Validates fund usage operations
  • ReturnFunds: Validates fund return operations

Validation Context System

Context Mapping The get_context function maps each operation type to a specific validation context that provides operation-specific account access:

1pub fn get_context(operation: ValidateOperation) -> ValidateContext {
2 match operation {
3 ValidateOperation::Creation => ValidateContext::Creation(CreationContext { ... }),
4 ValidateOperation::Execution => ValidateContext::Execution(ExecutionContext { ... }),
5 ValidateOperation::UseFunds => ValidateContext::UseFunds(UseFundsContext { ... }),
6 ValidateOperation::ReturnFunds => ValidateContext::ReturnFunds(ReturnFundsContext { ... }),
7 }
8}

Context Types Each context provides helper methods to access accounts from remaining_accounts:

  • CreationContext: Access to transaction, policy account, signer, and vault signer
  • ExecutionContext: Access to transaction, policy account, signer, and vault signer
  • UseFundsContext: Access to policy account
  • ReturnFundsContext: Access to policy account

Policy Implementation Pattern

Standard Validation Pattern Policy programs implement validation using a consistent pattern:

1pub fn validate(ctx: Context<Validate>, operation: ValidateOperation) -> Result<()> {
2 let validate_ctx = get_context(operation);
3 match validate_ctx {
4 ValidateContext::Creation(creation_ctx) => {
5 creation_ctx.validate_accounts(ctx.remaining_accounts)?;
6 // Policy-specific creation validation
7 Ok(())
8 }
9 ValidateContext::Execution(execution_ctx) => {
10 execution_ctx.validate_accounts(ctx.remaining_accounts)?;
11 // Policy-specific execution validation
12 Ok(())
13 }
14 ValidateContext::UseFunds(use_funds_ctx) => {
15 use_funds_ctx.validate_accounts(ctx.remaining_accounts)?;
16 // Policy-specific use funds validation
17 Ok(())
18 }
19 ValidateContext::ReturnFunds(return_funds_ctx) => {
20 return_funds_ctx.validate_accounts(ctx.remaining_accounts)?;
21 // Policy-specific return funds validation
22 Ok(())
23 }
24 }
25}

Account Validation Each context provides a validate_accounts method that ensures all required accounts are present in remaining_accounts before policy-specific validation logic executes.

Operation-Specific Validation

Creation Operation The Creation operation validates transaction creation requests:

  • Validates required accounts are present
  • Verifies policy account matches expected PDA
  • Performs policy-specific creation checks
  • Used when creating new transaction proposals

Execution Operation The Execution operation validates transaction execution requests:

  • Validates required accounts are present
  • Verifies policy account matches expected PDA
  • Validates transaction signer authorization
  • Performs policy-specific execution checks
  • Used when executing approved transactions

UseFunds Operation The UseFunds operation validates fund usage:

  • Validates policy account is present
  • Performs policy-specific fund usage checks
  • Used when funds are allocated or spent

ReturnFunds Operation The ReturnFunds operation validates fund returns:

  • Validates policy account is present
  • Performs policy-specific fund return checks
  • Used when funds are returned to the vault

Context Helper Methods

CreationContext and ExecutionContext Both contexts provide methods to access accounts:

  • transaction(): Returns transaction account and deserialized transaction data
  • policy_account(): Returns policy account reference
  • signer(): Returns signer account reference
  • vault_signer(): Returns vault signer account reference

UseFundsContext and ReturnFundsContext These contexts provide:

  • validate_accounts(): Ensures policy account is present

Policy Examples

Owners Policy The Owners policy validates that transaction signers are authorized owners:

1ValidateContext::Execution(execution_ctx) => {
2 execution_ctx.validate_accounts(ctx.remaining_accounts)?;
3 let policy_account = execution_ctx.policy_account(ctx.remaining_accounts);
4 let sender = execution_ctx.signer(ctx.remaining_accounts);
5
6 let policy = Owners::try_deserialize(&mut &policy_account.data.borrow()[..])?;
7 require!(policy.owners.contains(&sender.key()), ErrorCode::UnauthorizedSender);
8 Ok(())
9}

Multisig Policy The Multisig policy validates transaction signatures and approval thresholds:

1ValidateContext::Creation(creation_ctx) => {
2 creation_ctx.validate_accounts(ctx.remaining_accounts)?;
3 let policy_account = creation_ctx.policy_account(ctx.remaining_accounts);
4 let sender = creation_ctx.signer(ctx.remaining_accounts);
5
6 let mut multisig = MultiSig::try_deserialize(&mut &policy_account.data.borrow()[..])?;
7 // Check owner and mark signature
8 Ok(())
9}

Integration with Vault System

Vault Validation Flow When vaults perform operations, they invoke the associated policy program's validate function:

  1. Vault prepares operation-specific accounts
  2. Vault calls policy program's validate function with appropriate operation
  3. Policy program validates the operation using context helpers
  4. Validation result determines whether operation proceeds

Transaction Creation During transaction creation, vaults call:

1ValidateOperation::Creation

Transaction Execution During transaction execution, vaults call:

1ValidateOperation::Execution

Error Handling

Validation Errors The validation system provides specific error codes:

  • MissingTransaction: Required transaction account not found
  • MissingPolicyAccount: Required policy account not found
  • MissingSigner: Required signer account not found
  • MissingVaultSigner: Required vault signer account not found
  • InvalidAccountData: Account data format is invalid

Policy-Specific Errors Policy programs define additional error codes for policy-specific validation failures, such as unauthorized access or invalid parameters.

Security Considerations

Account Validation The context system ensures all required accounts are present before policy-specific validation, preventing runtime errors from missing accounts.

PDA Verification Policies verify that policy accounts match expected PDAs derived from vault addresses, ensuring correct policy association.

Authorization Checks Execution operations validate signer authorization, ensuring only authorized parties can execute transactions.

The validation system provides a robust, extensible framework for policy-based transaction validation while maintaining simplicity and consistency across different policy implementations.