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
2 changes: 2 additions & 0 deletions contracts/predictify-hybrid/src/err.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ pub enum Error {
Overflow = 672,
MaxBetCapExceeded = 673,
InvalidCap = 674,
/// The cool-off period is still active. Cannot unpause/resume the market.
CoolOffPeriodActive = 675,
// ===== USER OPERATION ERRORS (100-112) =====
/// User is not authorized to perform the requested action. Typically returned when
/// a non-admin attempts to call admin-only functions.
Expand Down
7 changes: 7 additions & 0 deletions contracts/predictify-hybrid/src/markets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3445,6 +3445,13 @@ impl MarketPauseManager {
return Err(Error::InvalidState);
}

// Enforce 7-day cool-off period before manual unpausing/resuming
let current_time = env.ledger().timestamp();
let cool_off_seconds = 7 * 24 * 3600; // 7 days in seconds
if current_time < pause_info.paused_at.saturating_add(cool_off_seconds) {
return Err(Error::CoolOffPeriodActive);
}

env.storage().persistent().remove(&market_id);
Self::emit_resume_event(env, market_id, &admin);

Expand Down
37 changes: 37 additions & 0 deletions contracts/predictify-hybrid/src/tests/oracle_validation_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,43 @@ fn test_auto_pause_already_paused_is_noop() {
});
}

#[test]
fn test_market_unpause_cool_off() {
let env = Env::default();
let contract_id = env.register_contract(None, crate::PredictifyHybrid);
let market_id = setup_auto_pause_env(&env, &contract_id);

env.as_contract(&contract_id, || {
let admin: Address = env.storage().persistent().get(&Symbol::new(&env, "Admin")).unwrap();

// Initial state: not paused
assert!(!MarketPauseManager::is_market_paused(&env, &market_id).unwrap());

// Set initial ledger timestamp
env.ledger().with_mut(|li| li.timestamp = 10_000);

// Pause the market for 24 hours
MarketPauseManager::pause_market(&env, admin.clone(), &market_id, 24).unwrap();
assert!(MarketPauseManager::is_market_paused(&env, &market_id).unwrap());

// Attempting to resume immediately (0 seconds passed) should fail with CoolOffPeriodActive
let err = MarketPauseManager::resume_market(&env, admin.clone(), &market_id).unwrap_err();
assert_eq!(err, Error::CoolOffPeriodActive);

// Fast forward 6 days (518,400 seconds passed)
env.ledger().with_mut(|li| li.timestamp = 10_000 + 6 * 24 * 3600);
let err = MarketPauseManager::resume_market(&env, admin.clone(), &market_id).unwrap_err();
assert_eq!(err, Error::CoolOffPeriodActive);

// Fast forward to exactly 7 days (604,800 seconds passed)
env.ledger().with_mut(|li| li.timestamp = 10_000 + 7 * 24 * 3600);
MarketPauseManager::resume_market(&env, admin.clone(), &market_id).unwrap();

// Resumed successfully
assert!(!MarketPauseManager::is_market_paused(&env, &market_id).unwrap());
});
}

#[test]
fn test_auto_pause_config_per_event_override() {
let env = Env::default();
Expand Down