Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 89 additions & 0 deletions contracts/predictify-hybrid/src/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -886,6 +886,46 @@ pub struct ManualResolutionRequiredEvent {
pub timestamp: u64,
}

/// Contract upgraded event - emitted when contract Wasm is upgraded
#[contracttype]
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct ContractUpgradedEvent {
/// Previous Wasm hash
pub old_wasm_hash: soroban_sdk::BytesN<32>,
/// New Wasm hash
pub new_wasm_hash: soroban_sdk::BytesN<32>,
/// Upgrade ID
pub upgrade_id: Symbol,
/// Upgrade timestamp
pub timestamp: u64,
}

/// Contract rollback event - emitted when contract is rolled back to previous version
#[contracttype]
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct ContractRollbackEvent {
/// Current Wasm hash (before rollback)
pub current_wasm_hash: soroban_sdk::BytesN<32>,
/// Rollback Wasm hash (after rollback)
pub rollback_wasm_hash: soroban_sdk::BytesN<32>,
/// Rollback timestamp
pub timestamp: u64,
}

/// Upgrade proposal created event - emitted when a new upgrade proposal is created
#[contracttype]
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct UpgradeProposalCreatedEvent {
/// Proposal ID
pub proposal_id: Symbol,
/// Proposer address
pub proposer: Address,
/// Target version
pub target_version: String,
/// Proposal timestamp
pub timestamp: u64,
}

/// Event emitted when circuit breaker state changes
///
/// This event provides comprehensive information about circuit breaker
Expand Down Expand Up @@ -1538,6 +1578,55 @@ impl EventEmitter {
Self::store_event(env, &symbol_short!("gov_exec"), &event);
}

/// Emit contract upgraded event when contract Wasm is upgraded
pub fn emit_contract_upgraded_event(
env: &Env,
old_wasm_hash: &soroban_sdk::BytesN<32>,
new_wasm_hash: &soroban_sdk::BytesN<32>,
upgrade_id: &Symbol,
) {
let event = ContractUpgradedEvent {
old_wasm_hash: old_wasm_hash.clone(),
new_wasm_hash: new_wasm_hash.clone(),
upgrade_id: upgrade_id.clone(),
timestamp: env.ledger().timestamp(),
};

Self::store_event(env, &symbol_short!("up_grade"), &event);
}

/// Emit contract rollback event when contract is rolled back
pub fn emit_contract_rollback_event(
env: &Env,
current_wasm_hash: &soroban_sdk::BytesN<32>,
rollback_wasm_hash: &soroban_sdk::BytesN<32>,
) {
let event = ContractRollbackEvent {
current_wasm_hash: current_wasm_hash.clone(),
rollback_wasm_hash: rollback_wasm_hash.clone(),
timestamp: env.ledger().timestamp(),
};

Self::store_event(env, &symbol_short!("rollback"), &event);
}

/// Emit upgrade proposal created event
pub fn emit_upgrade_proposal_created_event(
env: &Env,
proposal_id: &Symbol,
proposer: &Address,
target_version: &String,
) {
let event = UpgradeProposalCreatedEvent {
proposal_id: proposal_id.clone(),
proposer: proposer.clone(),
target_version: target_version.clone(),
timestamp: env.ledger().timestamp(),
};

Self::store_event(env, &symbol_short!("up_prop"), &event);
}

/// Store event in persistent storage
fn store_event<T>(env: &Env, event_key: &Symbol, event_data: &T)
where
Expand Down
160 changes: 160 additions & 0 deletions contracts/predictify-hybrid/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ mod reentrancy_guard;
mod resolution;
mod storage;
mod types;
mod upgrade_manager;
mod utils;
mod validation;
mod validation_tests;
Expand All @@ -53,6 +54,9 @@ mod recovery_tests;
#[cfg(test)]
mod property_based_tests;

#[cfg(test)]
mod upgrade_manager_tests;

// Re-export commonly used items
use admin::{AdminAnalyticsResult, AdminInitializer, AdminManager, AdminPermission, AdminRole};
pub use errors::Error;
Expand Down Expand Up @@ -1554,6 +1558,162 @@ impl PredictifyHybrid {
pub fn check_role_permissions(env: Env, role: AdminRole, permission: AdminPermission) -> bool {
AdminManager::check_role_permissions(&env, role, permission)
}

// ===== CONTRACT UPGRADE METHODS =====

/// Upgrade the contract to new Wasm bytecode
///
/// This function allows authorized admins to upgrade the contract to a new
/// version by replacing the Wasm bytecode. It includes comprehensive validation,
/// version checking, and event logging.
///
/// # Parameters
///
/// * `env` - The Soroban environment
/// * `admin` - The admin performing the upgrade (must be authorized)
/// * `new_wasm_hash` - Hash of the new Wasm bytecode to deploy
///
/// # Returns
///
/// * `Ok(())` if upgrade succeeds
/// * `Err(Error)` if authorization fails or upgrade is incompatible
///
/// # Security
///
/// - Requires admin authentication via `require_auth()`
/// - Validates version compatibility
/// - Performs safety checks before upgrade
/// - Logs all upgrade attempts for audit trail
///
/// # Example
///
/// ```rust
/// # use soroban_sdk::{Env, Address, BytesN};
/// # let env = Env::default();
/// # let admin = Address::generate(&env);
/// # let new_wasm_hash = BytesN::from_array(&env, &[0u8; 32]);
///
/// // Perform upgrade with admin authorization
/// admin.require_auth();
/// PredictifyHybrid::upgrade_contract(env, admin, new_wasm_hash)?;
/// # Ok::<(), predictify_hybrid::errors::Error>(())
/// ```
pub fn upgrade_contract(
env: Env,
admin: Address,
new_wasm_hash: soroban_sdk::BytesN<32>,
) -> Result<(), Error> {
admin.require_auth();
upgrade_manager::UpgradeManager::upgrade_contract(&env, &admin, new_wasm_hash)
}

/// Rollback contract to previous version
///
/// Reverts the contract to a previous Wasm version. This is a critical
/// recovery mechanism for failed upgrades.
///
/// # Parameters
///
/// * `env` - The Soroban environment
/// * `admin` - The admin performing the rollback (must be authorized)
/// * `rollback_wasm_hash` - Hash of the Wasm bytecode to rollback to
///
/// # Returns
///
/// * `Ok(())` if rollback succeeds
/// * `Err(Error)` if authorization fails or rollback is invalid
pub fn rollback_upgrade(
env: Env,
admin: Address,
rollback_wasm_hash: soroban_sdk::BytesN<32>,
) -> Result<(), Error> {
admin.require_auth();
upgrade_manager::UpgradeManager::rollback_upgrade(&env, &admin, rollback_wasm_hash)
}

/// Get current contract version
///
/// Returns the currently active contract version information.
///
/// # Returns
///
/// * `Ok(Version)` - Current contract version
/// * `Err(Error)` - If version cannot be retrieved
pub fn get_contract_version(env: Env) -> Result<versioning::Version, Error> {
upgrade_manager::UpgradeManager::get_contract_version(&env)
}

/// Check if upgrade is available
///
/// Checks if there are approved upgrade proposals ready for execution.
///
/// # Returns
///
/// * `Ok(bool)` - True if upgrade is available
pub fn check_upgrade_available(env: Env) -> Result<bool, Error> {
upgrade_manager::UpgradeManager::check_upgrade_available(&env)
}

/// Get upgrade history
///
/// Retrieves complete history of all contract upgrades.
///
/// # Returns
///
/// * `Ok(Vec<UpgradeRecord>)` - List of all upgrade records
pub fn get_upgrade_history(env: Env) -> Result<Vec<upgrade_manager::UpgradeRecord>, Error> {
upgrade_manager::UpgradeManager::get_upgrade_history(&env)
}

/// Get upgrade statistics
///
/// Calculates and returns comprehensive upgrade statistics.
///
/// # Returns
///
/// * `Ok(UpgradeStats)` - Upgrade statistics and analytics
pub fn get_upgrade_statistics(env: Env) -> Result<upgrade_manager::UpgradeStats, Error> {
upgrade_manager::UpgradeManager::get_upgrade_statistics(&env)
}

/// Validate upgrade compatibility
///
/// Performs comprehensive validation of an upgrade proposal without
/// executing the upgrade. Useful for testing and validation.
///
/// # Parameters
///
/// * `env` - The Soroban environment
/// * `proposal` - The upgrade proposal to validate
///
/// # Returns
///
/// * `Ok(CompatibilityCheckResult)` - Detailed compatibility analysis
pub fn validate_upgrade_compatibility(
env: Env,
proposal: upgrade_manager::UpgradeProposal,
) -> Result<upgrade_manager::CompatibilityCheckResult, Error> {
upgrade_manager::UpgradeManager::validate_upgrade_compatibility(&env, &proposal)
}

/// Test upgrade safety
///
/// Performs dry-run validation of an upgrade proposal without executing.
///
/// # Parameters
///
/// * `env` - The Soroban environment
/// * `proposal` - The upgrade proposal to test
///
/// # Returns
///
/// * `Ok(bool)` - True if upgrade would succeed
pub fn test_upgrade_safety(
env: Env,
proposal: upgrade_manager::UpgradeProposal,
) -> Result<bool, Error> {
upgrade_manager::UpgradeManager::test_upgrade_safety(&env, &proposal)
}
}

mod test;
Loading
Loading