diff --git a/contracts/predictify-hybrid/src/balance_tests.rs b/contracts/predictify-hybrid/src/balance_tests.rs index d7553cfd..0a74a17d 100644 --- a/contracts/predictify-hybrid/src/balance_tests.rs +++ b/contracts/predictify-hybrid/src/balance_tests.rs @@ -34,7 +34,7 @@ impl BalanceTestSetup { // Register and initialize contract let contract_id = env.register(crate::PredictifyHybrid, ()); let client = crate::PredictifyHybridClient::new(&env, &contract_id); - client.initialize(&admin, &None); + client.initialize(&\1, &None, &None); // Set token for the contract (simulate what PredictifyTest::setup does) env.as_contract(&contract_id, || { diff --git a/contracts/predictify-hybrid/src/balances.rs b/contracts/predictify-hybrid/src/balances.rs index 75d8aa4e..a1f0851a 100644 --- a/contracts/predictify-hybrid/src/balances.rs +++ b/contracts/predictify-hybrid/src/balances.rs @@ -11,6 +11,7 @@ //! - **Security**: Implements the checks-effects-interactions pattern to prevent reentrancy and double-spending. use crate::errors::Error; +use crate::reentrancy_guard::{ReentrancyGuard, GuardError as ReentrancyError}; use crate::events::EventEmitter; use crate::markets::MarketUtils; use crate::storage::BalanceStorage; @@ -82,7 +83,12 @@ impl BalanceManager { // Transfer funds from user to contract // In Soroban, if this fails it will panic, rolling back the transaction. // This ensures the balance is NOT credited unless the transfer succeeds. - token_client.transfer(&user, &env.current_contract_address(), &amount); + // Guard the external transfer from user -> contract + ReentrancyGuard::with_external_call(env, || { + token_client.transfer(&user, &env.current_contract_address(), &amount); + Ok::<(), ReentrancyError>(()) + }) + .map_err(|_| Error::InvalidState)?; // Update balance - occurs only if transfer succeeded let balance = BalanceStorage::add_balance(env, &user, &asset, amount)?; diff --git a/contracts/predictify-hybrid/src/bet_cancellation_tests.rs b/contracts/predictify-hybrid/src/bet_cancellation_tests.rs index 1b834150..89d2187e 100644 --- a/contracts/predictify-hybrid/src/bet_cancellation_tests.rs +++ b/contracts/predictify-hybrid/src/bet_cancellation_tests.rs @@ -47,7 +47,7 @@ impl BetCancellationTestSetup { let contract_id = env.register(PredictifyHybrid, ()); let client = PredictifyHybridClient::new(&env, &contract_id); - client.initialize(&admin, &None); + client.initialize(&\1, &None, &None); let token_admin = Address::generate(&env); let token_contract = env.register_stellar_asset_contract_v2(token_admin.clone()); diff --git a/contracts/predictify-hybrid/src/bet_tests.rs b/contracts/predictify-hybrid/src/bet_tests.rs index f476b511..7a5f823e 100644 --- a/contracts/predictify-hybrid/src/bet_tests.rs +++ b/contracts/predictify-hybrid/src/bet_tests.rs @@ -144,7 +144,7 @@ impl BetTestSetup { // Register and initialize the contract let contract_id = env.register(PredictifyHybrid, ()); let client = PredictifyHybridClient::new(&env, &contract_id); - client.initialize(&admin, &None); + client.initialize(&\1, &None, &None); // Setup token for staking let token_admin = Address::generate(&env); diff --git a/contracts/predictify-hybrid/src/bets.rs b/contracts/predictify-hybrid/src/bets.rs index 9eceec7b..18feb18c 100644 --- a/contracts/predictify-hybrid/src/bets.rs +++ b/contracts/predictify-hybrid/src/bets.rs @@ -22,6 +22,7 @@ use soroban_sdk::{contracttype, symbol_short, Address, Env, Map, String, Symbol, Vec}; use crate::errors::Error; +use crate::reentrancy_guard::{ReentrancyGuard, GuardError as ReentrancyError}; use crate::events::EventEmitter; use crate::markets::{MarketStateManager, MarketUtils, MarketValidator}; use crate::types::{Bet, BetLimits, BetStats, BetStatus, Market, MarketState}; @@ -1067,8 +1068,13 @@ impl BetUtils { /// Returns `Ok(())` if transfer succeeds, `Err(Error)` otherwise. pub fn lock_funds(env: &Env, user: &Address, amount: i128) -> Result<(), Error> { let token_client = MarketUtils::get_token_client(env)?; - token_client.transfer(user, &env.current_contract_address(), &amount); - Ok(()) + // Protect the external transfer with the reentrancy guard. If the + // guard cannot be acquired the call fails with `InvalidState`. + ReentrancyGuard::with_external_call(env, || { + token_client.transfer(user, &env.current_contract_address(), &amount); + Ok::<(), ReentrancyError>(()) + }) + .map_err(|_| Error::InvalidState) } /// Unlock funds by transferring from contract to user. @@ -1091,8 +1097,11 @@ impl BetUtils { /// before_external_call/after_external_call here to allow batch refunds. pub fn unlock_funds(env: &Env, user: &Address, amount: i128) -> Result<(), Error> { let token_client = MarketUtils::get_token_client(env)?; - token_client.transfer(&env.current_contract_address(), user, &amount); - Ok(()) + ReentrancyGuard::with_external_call(env, || { + token_client.transfer(&env.current_contract_address(), user, &amount); + Ok::<(), ReentrancyError>(()) + }) + .map_err(|_| Error::InvalidState) } /// Get the contract's locked funds balance. diff --git a/contracts/predictify-hybrid/src/claim_idempotency_tests.rs b/contracts/predictify-hybrid/src/claim_idempotency_tests.rs index 994eb392..3414fb46 100644 --- a/contracts/predictify-hybrid/src/claim_idempotency_tests.rs +++ b/contracts/predictify-hybrid/src/claim_idempotency_tests.rs @@ -50,7 +50,7 @@ impl ClaimIdempotencyTestSetup { // Register and initialize the contract let contract_id = env.register(PredictifyHybrid, ()); let client = PredictifyHybridClient::new(&env, &contract_id); - client.initialize(&admin, &None); + client.initialize(&\1, &None, &None); // Setup token for staking let token_admin = Address::generate(&env); diff --git a/contracts/predictify-hybrid/src/custom_token_tests.rs b/contracts/predictify-hybrid/src/custom_token_tests.rs index aa6bb76e..34491680 100644 --- a/contracts/predictify-hybrid/src/custom_token_tests.rs +++ b/contracts/predictify-hybrid/src/custom_token_tests.rs @@ -29,7 +29,7 @@ impl CustomTokenTestSetup { // Register contract let contract_id = env.register(PredictifyHybrid, ()); let client = PredictifyHybridClient::new(&env, &contract_id); - client.initialize(&admin, &None); + client.initialize(&\1, &None, &None); // Setup custom token let token_admin = Address::generate(&env); diff --git a/contracts/predictify-hybrid/src/disputes.rs b/contracts/predictify-hybrid/src/disputes.rs index 65e343c0..31555b9b 100644 --- a/contracts/predictify-hybrid/src/disputes.rs +++ b/contracts/predictify-hybrid/src/disputes.rs @@ -2354,6 +2354,7 @@ pub struct DisputeUtils; impl DisputeUtils { /// Add dispute to market /// Records `dispute.stake` in `market.dispute_stakes` for the disputing user. + pub fn add_dispute_to_market(market: &mut Market, dispute: Dispute) -> Result<(), Error> { // Add dispute stake to market let current_stake = market.dispute_stakes.get(dispute.user.clone()).unwrap_or(0); market @@ -2368,6 +2369,7 @@ impl DisputeUtils { /// Extend market for dispute period /// Extends `market.end_time` by [`DISPUTE_EXTENSION_HOURS`] to allow voting. + pub fn extend_market_for_dispute(market: &mut Market, _env: &Env) -> Result<(), Error> { let extension_seconds = (DISPUTE_EXTENSION_HOURS as u64) * 3600; market.end_time += extension_seconds; Ok(()) @@ -2375,6 +2377,7 @@ impl DisputeUtils { /// Determine final outcome considering disputes /// Picks the final outcome, deferring to community consensus when dispute impact > 30%. + pub fn determine_final_outcome_with_disputes( env: &Env, market: &Market, ) -> Result { @@ -2402,6 +2405,7 @@ impl DisputeUtils { /// Finalize market with resolution /// Sets `market.winning_outcomes` to `[final_outcome]` after validating it is a known outcome. + pub fn finalize_market_with_resolution( market: &mut Market, final_outcome: String, ) -> Result<(), Error> { @@ -2418,6 +2422,7 @@ impl DisputeUtils { /// Extract disputes from market /// Builds a `Vec` from `market.dispute_stakes` entries with stake > 0. + pub fn extract_disputes_from_market( env: &Env, market: &Market, market_id: Symbol, @@ -2443,16 +2448,19 @@ impl DisputeUtils { /// Check if user has disputed /// Returns `true` if `user` has a non-zero stake in `market.dispute_stakes`. + pub fn has_user_disputed(market: &Market, user: &Address) -> bool { market.dispute_stakes.get(user.clone()).unwrap_or(0) > 0 } /// Get user's dispute stake /// Returns the dispute stake for `user`, or `0` if they have not disputed. + pub fn get_user_dispute_stake(market: &Market, user: &Address) -> i128 { market.dispute_stakes.get(user.clone()).unwrap_or(0) } /// Calculate dispute impact on market resolution /// Returns `total_dispute_stakes / total_staked` as a float, or `0.0` when `total_staked == 0`. + pub fn calculate_dispute_impact(market: &Market) -> f64 { let total_staked = market.total_staked; let total_disputes = market.total_dispute_stakes(); @@ -2465,6 +2473,7 @@ impl DisputeUtils { /// Add vote to dispute /// Appends `vote` to the dispute's voting record and updates aggregate stake counters. + pub fn add_vote_to_dispute( env: &Env, dispute_id: &Symbol, vote: DisputeVote, @@ -2493,6 +2502,7 @@ impl DisputeUtils { /// Get dispute voting data /// Loads the [`DisputeVoting`] record for `dispute_id`, creating a default if absent. + pub fn get_dispute_voting(env: &Env, dispute_id: &Symbol) -> Result { let key = (symbol_short!("dispute_v"), dispute_id.clone()); Ok(env .storage() @@ -2513,6 +2523,7 @@ impl DisputeUtils { /// Store dispute voting data /// Persists `voting` under the `dispute_v` storage key for `dispute_id`. + pub fn store_dispute_voting( env: &Env, dispute_id: &Symbol, voting: &DisputeVoting, @@ -2524,6 +2535,7 @@ impl DisputeUtils { /// Store dispute vote /// Persists an individual `vote` keyed by `(dispute_id, user)`. + pub fn store_dispute_vote( env: &Env, dispute_id: &Symbol, vote: &DisputeVote, @@ -2574,6 +2586,7 @@ impl DisputeUtils { /// Distribute fees based on outcome /// Builds and stores a [`DisputeFeeDistribution`] record based on `outcome`. + pub fn distribute_fees_based_on_outcome( env: &Env, dispute_id: &Symbol, voting_data: &DisputeVoting, @@ -2610,6 +2623,7 @@ impl DisputeUtils { /// Store dispute fee distribution /// Persists `distribution` under the `dispute_f` storage key for `dispute_id`. + pub fn store_dispute_fee_distribution( env: &Env, dispute_id: &Symbol, distribution: &DisputeFeeDistribution, @@ -2621,6 +2635,7 @@ impl DisputeUtils { /// Get dispute fee distribution /// Loads the [`DisputeFeeDistribution`] for `dispute_id`, returning a zeroed default if absent. + pub fn get_dispute_fee_distribution( env: &Env, dispute_id: &Symbol, ) -> Result { @@ -2642,6 +2657,7 @@ impl DisputeUtils { /// Store dispute escalation /// Persists `escalation` under the `dispute_e` storage key for `dispute_id`. + pub fn store_dispute_escalation( env: &Env, dispute_id: &Symbol, escalation: &DisputeEscalation, @@ -2653,6 +2669,7 @@ impl DisputeUtils { /// Get dispute escalation /// Returns the [`DisputeEscalation`] for `dispute_id`, or `None` if not escalated. + pub fn get_dispute_escalation(env: &Env, dispute_id: &Symbol) -> Option { let key = (symbol_short!("dispute_e"), dispute_id.clone()); env.storage().persistent().get(&key) } @@ -2709,6 +2726,7 @@ impl DisputeUtils { /// Store dispute timeout /// Persists `timeout` under the `timeout` storage key for `dispute_id`. + pub fn store_dispute_timeout( env: &Env, dispute_id: &Symbol, timeout: &DisputeTimeout, @@ -2720,6 +2738,7 @@ impl DisputeUtils { /// Get dispute timeout /// Loads the [`DisputeTimeout`] for `dispute_id`. + pub fn get_dispute_timeout(env: &Env, dispute_id: &Symbol) -> Result { let key = (symbol_short!("timeout"), dispute_id.clone()); env.storage() .persistent() @@ -2729,12 +2748,14 @@ impl DisputeUtils { /// Check if dispute timeout exists /// Returns `true` if a timeout has been configured for `dispute_id`. + pub fn has_dispute_timeout(env: &Env, dispute_id: &Symbol) -> bool { let key = (symbol_short!("timeout"), dispute_id.clone()); env.storage().persistent().has(&key) } /// Remove dispute timeout /// Removes the timeout record for `dispute_id` from persistent storage. + pub fn remove_dispute_timeout(env: &Env, dispute_id: &Symbol) -> Result<(), Error> { let key = (symbol_short!("timeout"), dispute_id.clone()); env.storage().persistent().remove(&key); Ok(()) @@ -2742,6 +2763,7 @@ impl DisputeUtils { /// Get all active timeouts /// Returns all active [`DisputeTimeout`] records (currently returns empty — index not yet implemented). + pub fn get_active_timeouts(env: &Env) -> Vec { // This is a simplified implementation // In a real system, you would maintain an index of active timeouts Vec::new(env) @@ -2749,6 +2771,7 @@ impl DisputeUtils { /// Check for expired timeouts /// Returns IDs of disputes whose timeout has expired (currently returns empty — index not yet implemented). + pub fn check_expired_timeouts(env: &Env) -> Vec { let _expired_disputes = Vec::new(env); let _current_time = env.ledger().timestamp(); diff --git a/contracts/predictify-hybrid/src/err.rs b/contracts/predictify-hybrid/src/err.rs index 11615b5d..f4ff7f12 100644 --- a/contracts/predictify-hybrid/src/err.rs +++ b/contracts/predictify-hybrid/src/err.rs @@ -123,6 +123,8 @@ pub enum Error { DisputeError = 410, /// Unclaimed winnings have already been swept for this market. Repeat sweeps are not allowed. SweepAlreadyDone = 411, + /// Fee arithmetic overflowed during calculation. No fee state is updated. + FeeArithmeticOverflow = 412, /// Platform fee has already been collected from this market. FeeAlreadyCollected = 413, /// No fees are available to collect from this market. @@ -1378,6 +1380,7 @@ impl Error { Error::DisputeCondNotMet => "Dispute resolution conditions not met", Error::DisputeFeeFailed => "Dispute fee distribution failed", Error::DisputeError => "Generic dispute subsystem error", + Error::SweepAlreadyDone => "Unclaimed winnings already swept for this market", Error::FeeArithmeticOverflow => "Fee arithmetic overflowed", Error::FeeAlreadyCollected => "Platform fee already collected", Error::NoFeesToCollect => "No fees available to collect", @@ -1471,6 +1474,7 @@ impl Error { Error::DisputeCondNotMet => "DISPUTE_RESOLUTION_CONDITIONS_NOT_MET", Error::DisputeFeeFailed => "DISPUTE_FEE_DISTRIBUTION_FAILED", Error::DisputeError => "DISPUTE_ERROR", + Error::SweepAlreadyDone => "SWEEP_ALREADY_DONE", Error::FeeArithmeticOverflow => "FEE_ARITHMETIC_OVERFLOW", Error::FeeAlreadyCollected => "FEE_ALREADY_COLLECTED", Error::NoFeesToCollect => "NO_FEES_TO_COLLECT", diff --git a/contracts/predictify-hybrid/src/event_creation_tests.rs b/contracts/predictify-hybrid/src/event_creation_tests.rs index e89ef1e2..6a6d4217 100644 --- a/contracts/predictify-hybrid/src/event_creation_tests.rs +++ b/contracts/predictify-hybrid/src/event_creation_tests.rs @@ -33,7 +33,7 @@ impl TestSetup { // Initialize the contract let client = PredictifyHybridClient::new(&env, &contract_id); - client.initialize(&admin, &None); + client.initialize(&\1, &None, &None); // Configure token used for creation fee collection and fund admin balance. env.as_contract(&contract_id, || { diff --git a/contracts/predictify-hybrid/src/event_management_tests.rs b/contracts/predictify-hybrid/src/event_management_tests.rs index c85ea35b..bc8f8fde 100644 --- a/contracts/predictify-hybrid/src/event_management_tests.rs +++ b/contracts/predictify-hybrid/src/event_management_tests.rs @@ -40,7 +40,7 @@ impl TestSetup { // Initialize the contract let client = PredictifyHybridClient::new(&env, &contract_id); - client.initialize(&admin, &None); + client.initialize(&\1, &None, &None); env.as_contract(&contract_id, || { crate::circuit_breaker::CircuitBreaker::initialize(&env) .expect("circuit breaker should initialize in tests"); diff --git a/contracts/predictify-hybrid/src/event_visibility_test.rs b/contracts/predictify-hybrid/src/event_visibility_test.rs index b4c9e7fa..b8a965a6 100644 --- a/contracts/predictify-hybrid/src/event_visibility_test.rs +++ b/contracts/predictify-hybrid/src/event_visibility_test.rs @@ -25,7 +25,7 @@ mod event_visibility_tests { let contract_id = env.register(PredictifyHybrid, ()); let client = PredictifyHybridClient::new(&env, &contract_id); - client.initialize(&admin, &None); + client.initialize(&\1, &None, &None); // Configure token used for fees and staking env.as_contract(&contract_id, || { diff --git a/contracts/predictify-hybrid/src/fees.rs b/contracts/predictify-hybrid/src/fees.rs index a79c4e3f..45c9c1a1 100644 --- a/contracts/predictify-hybrid/src/fees.rs +++ b/contracts/predictify-hybrid/src/fees.rs @@ -4,6 +4,7 @@ use crate::errors::Error; use crate::markets::{MarketStateManager, MarketUtils}; use crate::reentrancy_guard::ReentrancyGuard; use crate::types::Market; +use crate::reentrancy_guard::GuardError as ReentrancyError; /// Fee management system for Predictify Hybrid contract /// @@ -793,8 +794,12 @@ impl FeeManager { // Get token client let token_client = MarketUtils::get_token_client(env)?; - // Transfer creation fee from admin to contract - token_client.transfer(admin, &env.current_contract_address(), &creation_fee); + // Transfer creation fee from admin to contract under the reentrancy guard. + ReentrancyGuard::with_external_call(env, || { + token_client.transfer(admin, &env.current_contract_address(), &creation_fee); + Ok::<(), ReentrancyError>(()) + }) + .map_err(|_| Error::InvalidState)?; // Record creation fee FeeTracker::record_creation_fee(env, admin, creation_fee)?; @@ -1349,8 +1354,11 @@ impl FeeUtils { /// Transfer fees to admin pub fn transfer_fees_to_admin(env: &Env, admin: &Address, amount: i128) -> Result<(), Error> { let token_client = MarketUtils::get_token_client(env)?; - token_client.transfer(&env.current_contract_address(), admin, &amount); - Ok(()) + ReentrancyGuard::with_external_call(env, || { + token_client.transfer(&env.current_contract_address(), admin, &amount); + Ok::<(), ReentrancyError>(()) + }) + .map_err(|_| Error::InvalidState) } /// Get fee statistics for a market diff --git a/contracts/predictify-hybrid/src/gas_tracking_tests.rs b/contracts/predictify-hybrid/src/gas_tracking_tests.rs index d15e233f..b2c979c5 100644 --- a/contracts/predictify-hybrid/src/gas_tracking_tests.rs +++ b/contracts/predictify-hybrid/src/gas_tracking_tests.rs @@ -98,7 +98,7 @@ impl GasTestContext { let contract_id = env.register(PredictifyHybrid, ()); let client = PredictifyHybridClient::new(&env, &contract_id); - client.initialize(&admin, &None); + client.initialize(&\1, &None, &None); // Initialize configuration env.as_contract(&contract_id, || { @@ -179,7 +179,7 @@ fn test_gas_initialize_baseline() { let contract_id = env.register(PredictifyHybrid, ()); let client = PredictifyHybridClient::new(&env, &contract_id); - client.initialize(&admin, &None); + client.initialize(&\1, &None, &None); // Verify: Admin stored correctly let stored_admin = env.as_contract(&contract_id, || { diff --git a/contracts/predictify-hybrid/src/graceful_degradation.rs b/contracts/predictify-hybrid/src/graceful_degradation.rs index 788f66bb..9f437a43 100644 --- a/contracts/predictify-hybrid/src/graceful_degradation.rs +++ b/contracts/predictify-hybrid/src/graceful_degradation.rs @@ -96,6 +96,7 @@ impl OracleBackup { if backup_result.is_err() { let backup_msg = String::from_str(env, "Backup oracle failed"); EventEmitter::emit_oracle_degradation(env, &self.backup, &backup_msg); + return Err(Error::FallbackOracleUnavailable); } backup_result } diff --git a/contracts/predictify-hybrid/src/integration_test.rs b/contracts/predictify-hybrid/src/integration_test.rs index 1368acdf..364d1342 100644 --- a/contracts/predictify-hybrid/src/integration_test.rs +++ b/contracts/predictify-hybrid/src/integration_test.rs @@ -52,7 +52,7 @@ impl IntegrationTestSuite { // Initialize contract let contract_id = env.register(PredictifyHybrid, ()); let client = PredictifyHybridClient::new(&env, &contract_id); - client.initialize(&admin, &None); + client.initialize(&\1, &None, &None); // Set token for staking env.as_contract(&contract_id, || { diff --git a/contracts/predictify-hybrid/src/lib.rs b/contracts/predictify-hybrid/src/lib.rs index 882f0210..eb35d0cd 100644 --- a/contracts/predictify-hybrid/src/lib.rs +++ b/contracts/predictify-hybrid/src/lib.rs @@ -47,13 +47,6 @@ mod metadata_limits_tests; mod monitoring; #[cfg(test)] mod multi_admin_multisig_tests; -#[cfg(test)] -mod admin_auth_audit_tests; -#[cfg(any())] -mod metadata_limits_tests; -mod monitoring; -#[cfg(any())] -mod multi_admin_multisig_tests; mod oracles; mod performance_benchmarks; mod queries; diff --git a/contracts/predictify-hybrid/src/market_creation_validation_tests.rs b/contracts/predictify-hybrid/src/market_creation_validation_tests.rs index 85cfb0a0..a8f1d2de 100644 --- a/contracts/predictify-hybrid/src/market_creation_validation_tests.rs +++ b/contracts/predictify-hybrid/src/market_creation_validation_tests.rs @@ -41,7 +41,7 @@ impl TestSetup { }); let client = PredictifyHybridClient::new(&env, &contract_id); - client.initialize(&admin, &None); + client.initialize(&\1, &None, &None); env.as_contract(&contract_id, || { crate::circuit_breaker::CircuitBreaker::initialize(&env) .expect("circuit breaker should initialize in tests"); diff --git a/contracts/predictify-hybrid/src/metadata_validation_tests.rs b/contracts/predictify-hybrid/src/metadata_validation_tests.rs index 5d987e12..f1f3a9b2 100644 --- a/contracts/predictify-hybrid/src/metadata_validation_tests.rs +++ b/contracts/predictify-hybrid/src/metadata_validation_tests.rs @@ -41,7 +41,7 @@ impl MetadataTest { let contract_id = env.register(crate::PredictifyHybrid, ()); let client = PredictifyHybridClient::new(&env, &contract_id); - client.initialize(&admin, &None); + client.initialize(&\1, &None, &None); Self { env, diff --git a/contracts/predictify-hybrid/src/oracle_fallback_timeout_tests.rs b/contracts/predictify-hybrid/src/oracle_fallback_timeout_tests.rs index a9715d8a..4f487245 100644 --- a/contracts/predictify-hybrid/src/oracle_fallback_timeout_tests.rs +++ b/contracts/predictify-hybrid/src/oracle_fallback_timeout_tests.rs @@ -34,7 +34,7 @@ impl TestSetup { }); let client = PredictifyHybridClient::new(&env, &contract_id); - client.initialize(&admin, &None); + client.initialize(&\1, &None, &None); env.as_contract(&contract_id, || { crate::circuit_breaker::CircuitBreaker::initialize(&env) .expect("circuit breaker should initialize in tests"); diff --git a/contracts/predictify-hybrid/src/oracles.rs b/contracts/predictify-hybrid/src/oracles.rs index bdf2fdef..209bc58f 100644 --- a/contracts/predictify-hybrid/src/oracles.rs +++ b/contracts/predictify-hybrid/src/oracles.rs @@ -4,8 +4,6 @@ use alloc::format; use alloc::string::ToString; use crate::bandprotocol; use crate::errors::Error; -use alloc::format; -use alloc::string::ToString; use soroban_sdk::{ contracttype, symbol_short, vec, Address, Bytes, Env, IntoVal, String, Symbol, Vec, }; @@ -3352,7 +3350,7 @@ mod oracle_integration_tests { let default_fee_pct: Option = None; env.mock_all_auths(); - client.initialize(&admin, &default_fee_pct); + client.initialize(&admin, &default_fee_pct, &None); let unauthorized = client.try_set_oracle_val_cfg_global(&non_admin, &60, &500); assert!(unauthorized.is_err()); diff --git a/contracts/predictify-hybrid/src/queries.rs b/contracts/predictify-hybrid/src/queries.rs index 3940084b..7b865d37 100644 --- a/contracts/predictify-hybrid/src/queries.rs +++ b/contracts/predictify-hybrid/src/queries.rs @@ -32,12 +32,8 @@ use alloc::string::ToString; use crate::{ - errors::Error, - markets::{MarketAnalytics, MarketStateManager, MarketValidator}, - types::{Market, MarketState, PagedMarketIds, PagedUserBets}, - voting::VotingStats, admin::{AdminManager, AdminPermission, AdminRole, MultisigConfig}, - oracles::{OracleMetadata, OracleWhitelist}, + bets::BetManager, disputes::{Dispute, DisputeManager, DisputeStats, DisputeVote}, errors::Error, governance::{GovernanceContract, GovernanceProposal}, diff --git a/contracts/predictify-hybrid/src/recovery.rs b/contracts/predictify-hybrid/src/recovery.rs index 949fc89c..1c5b3e3a 100644 --- a/contracts/predictify-hybrid/src/recovery.rs +++ b/contracts/predictify-hybrid/src/recovery.rs @@ -13,7 +13,7 @@ const DEFAULT_UNCLAIMED_CLAIM_PERIOD_SECONDS: u64 = 90 * 24 * 60 * 60; /// Bounds persistent storage growth under repeated recovery events. Active /// (unresolved) recovery state is stored separately and is never counted toward /// this cap. -pub const MAX_RECOVERY_HISTORY_PER_MARKET: u32 = 100; +pub const MAX_RECOVERY_HISTORY_PER_MARKET: u32 = 10; /// Maximum entries removable in a single admin prune call (gas safety). pub const MAX_RECOVERY_PRUNE_BATCH: u32 = 30; diff --git a/contracts/predictify-hybrid/src/storage.rs b/contracts/predictify-hybrid/src/storage.rs index c60ef13d..fb63968d 100644 --- a/contracts/predictify-hybrid/src/storage.rs +++ b/contracts/predictify-hybrid/src/storage.rs @@ -954,7 +954,8 @@ impl StorageUtils { #[cfg(test)] mod tests { use super::*; - use soroban_sdk::testutils::{Address as _, EnvTestConfig}; + use soroban_sdk::testutils::{Address as _, EnvTestConfig, Ledger as _}; + use soroban_sdk::testutils::storage::Persistent as _; #[test] fn test_sub_balance_rejects_overdraw_without_mutation() { diff --git a/contracts/predictify-hybrid/src/test.rs b/contracts/predictify-hybrid/src/test.rs index 67907a03..1165162b 100644 --- a/contracts/predictify-hybrid/src/test.rs +++ b/contracts/predictify-hybrid/src/test.rs @@ -82,7 +82,7 @@ impl PredictifyTest { // Initialize contract let contract_id = env.register(PredictifyHybrid, ()); let client = PredictifyHybridClient::new(&env, &contract_id); - client.initialize(&admin, &None); + client.initialize(&\1, &None, &None); // Initialize configuration (required for VotingManager::process_claim) env.as_contract(&contract_id, || { @@ -1560,7 +1560,7 @@ fn test_initialize_with_default_fee() { let client = PredictifyHybridClient::new(&env, &contract_id); // Initialize with None (default 2% fee) - client.initialize(&admin, &None); + client.initialize(&\1, &None, &None); // Verify admin is set let stored_admin: Address = env.as_contract(&contract_id, || { @@ -1591,7 +1591,7 @@ fn test_initialize_with_custom_fee() { let client = PredictifyHybridClient::new(&env, &contract_id); // Initialize with custom 5% fee - client.initialize(&admin, &Some(5)); + client.initialize(&\1, &Some(\2), &None); // Verify platform fee is 5% let stored_fee: i128 = env.as_contract(&contract_id, || { @@ -1613,7 +1613,7 @@ fn test_reinitialize_prevention() { let client = PredictifyHybridClient::new(&env, &contract_id); // First initialization - should succeed - client.initialize(&admin, &None); + client.initialize(&\1, &None, &None); // Verify admin is set (proves initialization succeeded) let stored_admin: Address = env.as_contract(&contract_id, || { @@ -1658,7 +1658,7 @@ fn test_initialize_valid_fee_bounds() { let contract_id = env.register(PredictifyHybrid, ()); let client = PredictifyHybridClient::new(&env, &contract_id); - client.initialize(&admin, &Some(0)); + client.initialize(&\1, &Some(\2), &None); let stored_fee: i128 = env.as_contract(&contract_id, || { env.storage() @@ -1677,7 +1677,7 @@ fn test_initialize_valid_fee_bounds() { let contract_id = env.register(PredictifyHybrid, ()); let client = PredictifyHybridClient::new(&env, &contract_id); - client.initialize(&admin, &Some(10)); + client.initialize(&\1, &Some(\2), &None); let stored_fee: i128 = env.as_contract(&contract_id, || { env.storage() @@ -1698,7 +1698,7 @@ fn test_initialize_storage_verification() { let contract_id = env.register(PredictifyHybrid, ()); let client = PredictifyHybridClient::new(&env, &contract_id); - client.initialize(&admin, &Some(3)); + client.initialize(&\1, &Some(\2), &None); // Verify admin address is in persistent storage env.as_contract(&contract_id, || { diff --git a/contracts/predictify-hybrid/src/tests/security/executable_checklist_tests.rs b/contracts/predictify-hybrid/src/tests/security/executable_checklist_tests.rs index e80d78a8..10d6ffb3 100644 --- a/contracts/predictify-hybrid/src/tests/security/executable_checklist_tests.rs +++ b/contracts/predictify-hybrid/src/tests/security/executable_checklist_tests.rs @@ -32,7 +32,7 @@ fn setup_test(env: &Env) -> TestContext { .persistent() .set(&Symbol::new(env, "TokenID"), &token_id); - client.initialize(&admin, &None); + client.initialize(&\1, &None, &None); TestContext { env: env.clone(), diff --git a/contracts/predictify-hybrid/src/unclaimed_winnings_timeout_tests.rs b/contracts/predictify-hybrid/src/unclaimed_winnings_timeout_tests.rs index fb5ab923..ed5c7f03 100644 --- a/contracts/predictify-hybrid/src/unclaimed_winnings_timeout_tests.rs +++ b/contracts/predictify-hybrid/src/unclaimed_winnings_timeout_tests.rs @@ -31,7 +31,7 @@ impl TimeoutSweepSetup { let contract_id = env.register(PredictifyHybrid, ()); let client = PredictifyHybridClient::new(&env, &contract_id); - client.initialize(&admin, &None); + client.initialize(&\1, &None, &None); env.as_contract(&contract_id, || { let cfg = ConfigManager::get_development_config(&env);