Skip to content
Merged
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
145 changes: 144 additions & 1 deletion contracts/predict-iq/src/test_resolution_state_machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,8 @@ fn test_stage3_dispute_filed_within_24h() {

let market = client.get_market(&market_id).unwrap();
assert_eq!(market.status, types::MarketStatus::Disputed);
assert!(market.dispute_timestamp.is_some());
// dispute window is tracked via pending_resolution_timestamp (set at oracle resolution)
assert!(market.pending_resolution_timestamp.is_some());
}

#[test]
Expand Down Expand Up @@ -339,3 +340,145 @@ fn test_payouts_blocked_until_resolved() {
let payout = client.claim_winnings(&bettor, &market_id);
assert!(payout > 0);
}

#[test]
fn test_resolved_at_populated_after_oracle_finalization() {
let (e, _admin, _, client) = setup_test_env();

let resolution_deadline = 2000;
let market_id = create_test_market(&client, &e, resolution_deadline);

client.set_oracle_result(&market_id, &0);

e.ledger().with_mut(|li| {
li.timestamp = resolution_deadline;
});

client.attempt_oracle_resolution(&market_id);

let finalize_time = resolution_deadline + 86400; // T+24h
e.ledger().with_mut(|li| {
li.timestamp = finalize_time;
});

client.finalize_resolution(&market_id);

let market = client.get_market(&market_id).unwrap();
assert_eq!(market.status, types::MarketStatus::Resolved);
// resolved_at must be set so prune_market can enforce the 30-day grace period
assert_eq!(market.resolved_at, Some(finalize_time));
}

#[test]
fn test_prune_market_succeeds_after_30_days() {
let (e, _admin, _, client) = setup_test_env();

let resolution_deadline = 2000;
let market_id = create_test_market(&client, &e, resolution_deadline);

client.set_oracle_result(&market_id, &0);

e.ledger().with_mut(|li| {
li.timestamp = resolution_deadline;
});

client.attempt_oracle_resolution(&market_id);

let finalize_time = resolution_deadline + 86400;
e.ledger().with_mut(|li| {
li.timestamp = finalize_time;
});

client.finalize_resolution(&market_id);

// Advance to exactly 30 days after resolution
let prune_time = finalize_time + 2_592_000; // PRUNE_GRACE_PERIOD
e.ledger().with_mut(|li| {
li.timestamp = prune_time;
});

// Should succeed β€” 30-day grace period has elapsed
client.prune_market(&market_id);

// Market must no longer exist in storage
assert!(client.get_market(&market_id).is_none());
}

#[test]
#[should_panic]
fn test_prune_market_fails_before_30_days() {
let (e, _admin, _, client) = setup_test_env();

let resolution_deadline = 2000;
let market_id = create_test_market(&client, &e, resolution_deadline);

client.set_oracle_result(&market_id, &0);

e.ledger().with_mut(|li| {
li.timestamp = resolution_deadline;
});

client.attempt_oracle_resolution(&market_id);

let finalize_time = resolution_deadline + 86400;
e.ledger().with_mut(|li| {
li.timestamp = finalize_time;
});

client.finalize_resolution(&market_id);

// Only 15 days after resolution β€” should fail
e.ledger().with_mut(|li| {
li.timestamp = finalize_time + 1_296_000; // 15 days
});

client.prune_market(&market_id);
}

#[test]
fn test_resolved_at_populated_after_dispute_resolution() {
let (e, _admin, contract_id, client) = setup_test_env();

let token_admin = Address::generate(&e);
let token_id = e.register_stellar_asset_contract_v2(token_admin.clone());
let token_address = token_id.address();
let token_client = token::StellarAssetClient::new(&e, &token_address);

client.set_governance_token(&token_address);

let resolution_deadline = 2000;
let market_id = create_test_market(&client, &e, resolution_deadline);

client.set_oracle_result(&market_id, &0);

e.ledger().with_mut(|li| {
li.timestamp = resolution_deadline;
});

client.attempt_oracle_resolution(&market_id);

// File dispute within 24h
let disputer = Address::generate(&e);
e.ledger().with_mut(|li| {
li.timestamp = resolution_deadline + 10000;
});
client.file_dispute(&disputer, &market_id);

// Cast votes with clear majority
let voter = Address::generate(&e);
token_client.mint(&voter, &7000);
client.cast_vote(&voter, &market_id, &1, &7000);

// Advance past 24h dispute window + 72h voting period
let finalize_time = resolution_deadline + 86400 + 259200;
e.ledger().with_mut(|li| {
li.timestamp = finalize_time;
});

client.finalize_resolution(&market_id);

let market = client.get_market(&market_id).unwrap();
assert_eq!(market.status, types::MarketStatus::Resolved);
// resolved_at must be set on the dispute path too
assert_eq!(market.resolved_at, Some(finalize_time));
}
Loading