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 validation7 Ok(())8 }9 ValidateContext::Execution(execution_ctx) => {10 execution_ctx.validate_accounts(ctx.remaining_accounts)?;11 // Policy-specific execution validation12 Ok(())13 }14 ValidateContext::UseFunds(use_funds_ctx) => {15 use_funds_ctx.validate_accounts(ctx.remaining_accounts)?;16 // Policy-specific use funds validation17 Ok(())18 }19 ValidateContext::ReturnFunds(return_funds_ctx) => {20 return_funds_ctx.validate_accounts(ctx.remaining_accounts)?;21 // Policy-specific return funds validation22 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 datapolicy_account(): Returns policy account referencesigner(): Returns signer account referencevault_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);56 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);56 let mut multisig = MultiSig::try_deserialize(&mut &policy_account.data.borrow()[..])?;7 // Check owner and mark signature8 Ok(())9}
Integration with Vault System
Vault Validation Flow
When vaults perform operations, they invoke the associated policy program's validate function:
- Vault prepares operation-specific accounts
- Vault calls policy program's
validatefunction with appropriate operation - Policy program validates the operation using context helpers
- 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 foundMissingPolicyAccount: Required policy account not foundMissingSigner: Required signer account not foundMissingVaultSigner: Required vault signer account not foundInvalidAccountData: 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.
