Skip to content
Open
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
1 change: 1 addition & 0 deletions contract/contracts/predifi-contract/src/benchmark_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ mod benchmark_tests {
max_total_stake: 0,
initial_liquidity: 0,
required_resolutions: 1,
delay: 0u64,
private: false,
whitelist_key: None,
outcome_descriptions,
Expand Down
3 changes: 3 additions & 0 deletions contract/contracts/predifi-contract/src/fee_tiers_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ fn test_dynamic_fee_tiers_application() {
max_total_stake: 0,
initial_liquidity: 0i128,
required_resolutions: 1u32,
delay: 0u64,
private: false,
whitelist_key: None,
outcome_descriptions: vec![
Expand Down Expand Up @@ -98,6 +99,7 @@ fn test_dynamic_fee_tiers_application() {
max_total_stake: 0,
initial_liquidity: 0i128,
required_resolutions: 1u32,
delay: 0u64,
private: false,
whitelist_key: None,
outcome_descriptions: vec![
Expand Down Expand Up @@ -141,6 +143,7 @@ fn test_dynamic_fee_tiers_application() {
max_total_stake: 0,
initial_liquidity: 0i128,
required_resolutions: 1u32,
delay: 0u64,
private: false,
whitelist_key: None,
outcome_descriptions: vec![
Expand Down
3 changes: 3 additions & 0 deletions contract/contracts/predifi-contract/src/integration_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ fn test_full_market_lifecycle() {
max_total_stake: 0,
initial_liquidity: 0i128,
required_resolutions: 1u32,
delay: 0u64,
private: false,
whitelist_key: None,
outcome_descriptions: vec![
Expand Down Expand Up @@ -186,6 +187,7 @@ fn test_multi_user_betting_and_balance_verification() {
max_total_stake: 0,
initial_liquidity: 0i128,
required_resolutions: 1u32,
delay: 0u64,
private: false,
whitelist_key: None,
outcome_descriptions: vec![
Expand Down Expand Up @@ -268,6 +270,7 @@ fn test_market_resolution_multiple_winners() {
max_total_stake: 0,
initial_liquidity: 0i128,
required_resolutions: 1u32,
delay: 0u64,
private: false,
whitelist_key: None,
outcome_descriptions: vec![
Expand Down
37 changes: 26 additions & 11 deletions contract/contracts/predifi-contract/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,8 @@ pub struct CreatePoolParams {
pub initial_liquidity: i128,
/// Market category for classification (e.g., Sports, Finance, Crypto).
pub category: Symbol,
/// Delay in seconds after `end_time` before this pool can be resolved.
pub delay: u64,
/// Whether the pool is private (invite-only).
pub private: bool,
/// Optional symbol used as an invite key for private pools.
Expand Down Expand Up @@ -277,6 +279,8 @@ pub struct Pool {
pub creator: Address,
/// Number of authorized oracle resolutions required to finalize the pool.
pub required_resolutions: u32,
/// Delay in seconds after `end_time` before this pool can be resolved.
pub delay: u64,
/// Whether the pool is private (invite-only).
pub private: bool,
/// Optional symbol used as an invite key for private pools.
Expand Down Expand Up @@ -308,6 +312,9 @@ pub struct PoolConfig {
pub initial_liquidity: i128,
/// Number of authorized oracle resolutions required to finalize the pool (must be >= 1).
pub required_resolutions: u32,
/// Delay in seconds after `end_time` before this pool can be resolved.
/// A value of `0` inherits the current global `resolution_delay`.
pub delay: u64,
/// Whether the pool is private (invite-only). If true, users must be whitelisted.
pub private: bool,
/// Optional symbol used as an invite key for private pools.
Expand Down Expand Up @@ -1596,12 +1603,23 @@ impl PredifiContract {
// Validate: end_time must be in the future
assert!(end_time > current_time, "end_time must be in the future");

let min_pool_duration = env
let protocol_config = env
.storage()
.instance()
.get::<DataKey, Config>(&DataKey::Config)
.map(|c| c.min_pool_duration)
.unwrap_or(DEFAULT_MIN_POOL_DURATION);
.unwrap_or_else(|| Config {
fee_bps: 0,
treasury: env.current_contract_address(),
access_control: env.current_contract_address(),
resolution_delay: 0,
min_pool_duration: DEFAULT_MIN_POOL_DURATION,
});
let min_pool_duration = protocol_config.min_pool_duration;
let pool_delay = if config.delay == 0 {
protocol_config.resolution_delay
} else {
config.delay
};

// Validate: minimum pool duration
assert!(
Expand Down Expand Up @@ -1687,6 +1705,7 @@ impl PredifiContract {
initial_liquidity: config.initial_liquidity,
creator: creator.clone(),
required_resolutions: config.required_resolutions,
delay: pool_delay,
private: config.private,
whitelist_key: config.whitelist_key.clone(),
outcome_descriptions: config.outcome_descriptions.clone(),
Expand Down Expand Up @@ -1863,9 +1882,8 @@ impl PredifiContract {
}

let current_time = env.ledger().timestamp();
let config = Self::get_config(&env);

if current_time < pool.end_time.saturating_add(config.resolution_delay) {
if current_time < pool.end_time.saturating_add(pool.delay) {
return Err(PredifiError::ResolutionDelayNotMet);
}

Expand Down Expand Up @@ -1982,10 +2000,9 @@ impl PredifiContract {
return Err(PredifiError::InvalidPoolState);
}

let config = Self::get_config(&env);
let current_time = env.ledger().timestamp();

if current_time >= pool.end_time.saturating_add(config.resolution_delay) {
if current_time >= pool.end_time.saturating_add(pool.delay) {
PoolReadyForResolutionEvent {
pool_id,
timestamp: current_time,
Expand Down Expand Up @@ -2999,9 +3016,8 @@ impl PredifiContract {
}

let current_time = env.ledger().timestamp();
let config = Self::get_config(&env);

if current_time < pool.end_time.saturating_add(config.resolution_delay) {
if current_time < pool.end_time.saturating_add(pool.delay) {
return Err(PredifiError::ResolutionDelayNotMet);
}

Expand Down Expand Up @@ -3109,9 +3125,8 @@ impl OracleCallback for PredifiContract {
}

let current_time = env.ledger().timestamp();
let config = Self::get_config(&env);

if current_time < pool.end_time.saturating_add(config.resolution_delay) {
if current_time < pool.end_time.saturating_add(pool.delay) {
return Err(PredifiError::ResolutionDelayNotMet);
}

Expand Down
6 changes: 6 additions & 0 deletions contract/contracts/predifi-contract/src/stress_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ fn test_high_volume_predictions_single_pool() {
max_total_stake: 0,
initial_liquidity: 0,
required_resolutions: 1u32,
delay: 0u64,
private: false,
whitelist_key: None,
outcome_descriptions: vec![
Expand Down Expand Up @@ -150,6 +151,7 @@ fn test_bulk_claim_winnings() {
max_total_stake: 0,
initial_liquidity: 0,
required_resolutions: 1u32,
delay: 0u64,
private: false,
whitelist_key: None,
outcome_descriptions: vec![
Expand Down Expand Up @@ -204,6 +206,7 @@ fn test_sequential_pool_creation_stress() {
max_total_stake: 0,
initial_liquidity: 0,
required_resolutions: 1u32,
delay: 0u64,
private: false,
whitelist_key: None,
outcome_descriptions: vec![
Expand Down Expand Up @@ -239,6 +242,7 @@ fn test_max_outcomes_high_volume() {
max_total_stake: 0,
initial_liquidity: 0,
required_resolutions: 1u32,
delay: 0u64,
private: false,
whitelist_key: None,
outcome_descriptions: vec![
Expand Down Expand Up @@ -294,6 +298,7 @@ fn test_prediction_throughput_measurement() {
max_total_stake: 0,
initial_liquidity: 0,
required_resolutions: 1u32,
delay: 0u64,
private: false,
whitelist_key: None,
outcome_descriptions: vec![
Expand Down Expand Up @@ -343,6 +348,7 @@ fn test_resolution_under_load() {
max_total_stake: 0,
initial_liquidity: 0,
required_resolutions: 1u32,
delay: 0u64,
private: false,
whitelist_key: None,
outcome_descriptions: vec![
Expand Down
Loading