@@ -14,7 +14,6 @@ use crate::common::{
1414use crate :: config:: {
1515 _apply_protocol_fee_precision, _apply_protocol_fee_updown, _read_fee_model,
1616} ;
17- use crate :: config:: { _apply_protocol_fee_precision, _apply_protocol_fee_updown, _read_fee_model} ;
1817use crate :: errors:: ContractError ;
1918use crate :: settlement_math:: {
2019 classify_price_direction, compute_deviation_bps, compute_updown_winner_payout,
@@ -24,9 +23,9 @@ use crate::storage::clear_round_storage;
2423use crate :: types:: {
2524 ArchivedRoundSummary , BetSide , DataKeyCore , DataKeyScoped , DeviationReferenceMode ,
2625 HbGateConfig , LeaderboardEntry , MultiFeedPayload , OracleHeartbeatRecord , OraclePayload ,
27- OracleQuorumConfig , PendingWinningsUpdatedAtKey , PrecisionCommitment , PrecisionPayoutPolicy ,
28- PrecisionPrediction , PriceSample , Round , RoundArchiveStatus , RoundMode , TwapSamplesKey ,
29- UserOutcomeType , UserPosition , UserRoundOutcome , UserStats ,
26+ OracleQuorumConfig , OneSidedPolicy , PendingWinningsUpdatedAtKey , PrecisionCommitment ,
27+ PrecisionPayoutPolicy , PrecisionPrediction , PriceSample , Round , RoundArchiveStatus , RoundMode ,
28+ TwapSamplesKey , UserOutcomeType , UserPosition , UserRoundOutcome , UserStats ,
3029} ;
3130use soroban_sdk:: xdr:: ToXdr ;
3231use soroban_sdk:: { contracttype, symbol_short, Address , Bytes , Env , Map , Symbol , Vec } ;
@@ -2856,244 +2855,5 @@ pub fn _update_stats_loss(env: &Env, user: Address) -> Result<(), ContractError>
28562855 crate :: leaderboard:: _update_leaderboards ( env, user. clone ( ) ) ;
28572856 crate :: leaderboard:: _update_season_stats_loss ( env, user) ?;
28582857 Ok ( ( ) )
2859- }
2860-
2861- // ─── Dispute window (void / finalize) ───────────────────────────────────────
2862-
2863- fn _resolved_at_map_key ( ) -> Symbol {
2864- Symbol :: new ( & Env :: default ( ) , "RslvAtMap" )
2865- }
2866-
2867- fn _settlement_map_key ( ) -> Symbol {
2868- Symbol :: new ( & Env :: default ( ) , "SttlMap" )
2869- }
2870-
2871- fn _read_resolved_at ( env : & Env , round_id : u64 ) -> Option < u32 > {
2872- env. storage ( )
2873- . persistent ( )
2874- . get :: < _ , Map < u64 , u32 > > ( & _resolved_at_map_key ( ) )
2875- . and_then ( |m| m. get ( round_id) )
2876- }
2877-
2878- fn _remove_resolved_at ( env : & Env , round_id : u64 ) {
2879- let key = _resolved_at_map_key ( ) ;
2880- let mut m: Map < u64 , u32 > = env
2881- . storage ( )
2882- . persistent ( )
2883- . get ( & key)
2884- . unwrap_or ( Map :: new ( env) ) ;
2885- m. remove ( round_id) ;
2886- if m. len ( ) == 0 {
2887- env. storage ( ) . persistent ( ) . remove ( & key) ;
2888- } else {
2889- env. storage ( ) . persistent ( ) . set ( & key, & m) ;
2890- _extend_ttl_symbol ( env, & key) ;
2891- }
2892- }
2893-
2894- fn _read_settlement ( env : & Env , round_id : u64 ) -> Option < RoundSettlement > {
2895- env. storage ( )
2896- . persistent ( )
2897- . get :: < _ , Map < u64 , RoundSettlement > > ( & _settlement_map_key ( ) )
2898- . and_then ( |m| m. get ( round_id) )
2899- }
2900-
2901- fn _remove_settlement ( env : & Env , round_id : u64 ) {
2902- let key = _settlement_map_key ( ) ;
2903- let mut m: Map < u64 , RoundSettlement > = env
2904- . storage ( )
2905- . persistent ( )
2906- . get ( & key)
2907- . unwrap_or ( Map :: new ( env) ) ;
2908- m. remove ( round_id) ;
2909- if m. len ( ) == 0 {
2910- env. storage ( ) . persistent ( ) . remove ( & key) ;
2911- } else {
2912- env. storage ( ) . persistent ( ) . set ( & key, & m) ;
2913- _extend_ttl_symbol ( env, & key) ;
2914- }
2915- }
2916-
2917- fn _round_from_settlement ( stl : & RoundSettlement ) -> Round {
2918- Round {
2919- round_id : stl. round_id ,
2920- price_start : stl. price_start ,
2921- start_ledger : 0 ,
2922- start_timestamp : 0 ,
2923- bet_end_ledger : 0 ,
2924- end_ledger : 0 ,
2925- pool_up : stl. pool_up ,
2926- pool_down : stl. pool_down ,
2927- mode : if stl. mode == 0 {
2928- RoundMode :: UpDown
2929- } else {
2930- RoundMode :: Precision
2931- } ,
2932- }
2933- }
2934-
2935- pub fn void_round ( env : Env , round_id : u64 ) -> Result < ( ) , ContractError > {
2936- _require_supported_schema ( & env) ?;
2937- _ensure_not_paused ( & env) ?;
2938-
2939- let dispute_ledgers = crate :: config:: get_dispute_ledgers ( & env) ;
2940- if dispute_ledgers == 0 {
2941- return Err ( ContractError :: DisputeWindowExpired ) ;
2942- }
2943-
2944- let resolved_at: u32 = _read_resolved_at ( & env, round_id) . ok_or ( ContractError :: DisputeWindowExpired ) ?;
2945- if env. ledger ( ) . sequence ( ) >= resolved_at. saturating_add ( dispute_ledgers) {
2946- return Err ( ContractError :: DisputeWindowExpired ) ;
2947- }
2948-
2949- let participants: Vec < Address > = env
2950- . storage ( )
2951- . persistent ( )
2952- . get ( & DataKeyScoped :: RoundParticipants ( round_id) )
2953- . unwrap_or ( Vec :: new ( & env) ) ;
2954- if participants. is_empty ( ) {
2955- return Err ( ContractError :: NoActiveRound ) ;
2956- }
2957-
2958- let settlement: RoundSettlement =
2959- _read_settlement ( & env, round_id) . ok_or ( ContractError :: NoActiveRound ) ?;
2960-
2961- for i in 0 ..participants. len ( ) {
2962- if let Some ( user) = participants. get ( i) {
2963- let pos_key = DataKeyScoped :: Position ( round_id, user. clone ( ) ) ;
2964- if let Some ( pos) = env. storage ( ) . persistent ( ) . get :: < _ , UserPosition > ( & pos_key) {
2965- _accumulate_pending ( & env, user. clone ( ) , pos. amount ) ?;
2966- let side = match pos. side {
2967- BetSide :: Up => 0 ,
2968- BetSide :: Down => 1 ,
2969- } ;
2970- _persist_user_outcome (
2971- & env, round_id, 0 , & user, side, 0 , pos. amount , pos. amount ,
2972- UserOutcomeType :: Refund ,
2973- ) ;
2974- }
2975- let pred_key = DataKeyScoped :: PrecisionPosition ( round_id, user. clone ( ) ) ;
2976- let commit_key = DataKeyScoped :: PrecisionCommitment ( round_id, user. clone ( ) ) ;
2977- if let Some ( pred) = env. storage ( ) . persistent ( ) . get :: < _ , PrecisionPrediction > ( & pred_key) {
2978- _accumulate_pending ( & env, user. clone ( ) , pred. amount ) ?;
2979- _persist_user_outcome (
2980- & env, round_id, 1 , & user, 2 , pred. predicted_price , pred. amount , pred. amount ,
2981- UserOutcomeType :: Refund ,
2982- ) ;
2983- } else if let Some ( commit) =
2984- env. storage ( ) . persistent ( ) . get :: < _ , PrecisionCommitment > ( & commit_key)
2985- {
2986- _accumulate_pending ( & env, user. clone ( ) , commit. amount ) ?;
2987- _persist_user_outcome (
2988- & env, round_id, 1 , & user, 2 , 0 , commit. amount , commit. amount ,
2989- UserOutcomeType :: Refund ,
2990- ) ;
2991- }
2992- }
2993- }
2994-
2995- for i in 0 ..participants. len ( ) {
2996- if let Some ( user) = participants. get ( i) {
2997- env. storage ( ) . persistent ( ) . remove ( & DataKeyScoped :: Position ( round_id, user. clone ( ) ) ) ;
2998- env. storage ( ) . persistent ( ) . remove ( & DataKeyScoped :: PrecisionPosition ( round_id, user. clone ( ) ) ) ;
2999- env. storage ( ) . persistent ( ) . remove ( & DataKeyScoped :: PrecisionCommitment ( round_id, user) ) ;
3000- }
3001- }
3002- env. storage ( ) . persistent ( ) . remove ( & DataKeyScoped :: RoundParticipants ( round_id) ) ;
3003-
3004- let round = _round_from_settlement ( & settlement) ;
3005- _archive_round (
3006- & env,
3007- & round,
3008- RoundArchiveStatus :: Voided ,
3009- settlement. final_price ,
3010- & participants,
3011- settlement. fee_amount ,
3012- None ,
3013- ) ;
3014-
3015- _remove_settlement ( & env, round_id) ;
3016- _remove_resolved_at ( & env, round_id) ;
3017-
3018- #[ allow( deprecated) ]
3019- env. events ( ) . publish (
3020- ( symbol_short ! ( "round" ) , symbol_short ! ( "voided" ) ) ,
3021- ( round_id, settlement. final_price , participants. len ( ) as u32 , settlement. fee_amount ) ,
3022- ) ;
3023- Ok ( ( ) )
3024- }
3025-
3026- pub fn finalize_round ( env : Env , round_id : u64 ) -> Result < ( ) , ContractError > {
3027- _require_supported_schema ( & env) ?;
3028- _ensure_not_paused ( & env) ?;
3029-
3030- let dispute_ledgers = crate :: config:: get_dispute_ledgers ( & env) ;
3031- if dispute_ledgers == 0 {
3032- return Err ( ContractError :: DisputeWindowExpired ) ;
3033- }
3034-
3035- let resolved_at: u32 = _read_resolved_at ( & env, round_id) . ok_or ( ContractError :: DisputeWindowExpired ) ?;
3036- if env. ledger ( ) . sequence ( ) < resolved_at. saturating_add ( dispute_ledgers) {
3037- return Err ( ContractError :: ClaimLocked ) ;
3038- }
30392858
3040- let participants: Vec < Address > = env
3041- . storage ( )
3042- . persistent ( )
3043- . get ( & DataKeyScoped :: RoundParticipants ( round_id) )
3044- . unwrap_or ( Vec :: new ( & env) ) ;
3045- if participants. is_empty ( ) {
3046- return Err ( ContractError :: NoActiveRound ) ;
3047- }
3048-
3049- let settlement: RoundSettlement =
3050- _read_settlement ( & env, round_id) . ok_or ( ContractError :: NoActiveRound ) ?;
3051-
3052- for i in 0 ..settlement. participants . len ( ) {
3053- if let Some ( entry) = settlement. participants . get ( i) {
3054- match entry. outcome {
3055- UserOutcomeType :: Win => {
3056- _accumulate_pending ( & env, entry. user . clone ( ) , entry. payout ) ?;
3057- _update_stats_win ( & env, entry. user . clone ( ) ) ?;
3058- }
3059- UserOutcomeType :: Loss => {
3060- _update_stats_loss ( & env, entry. user . clone ( ) ) ?;
3061- }
3062- UserOutcomeType :: Refund => {
3063- _accumulate_pending ( & env, entry. user . clone ( ) , entry. payout ) ?;
3064- }
3065- _ => { }
3066- }
3067- }
3068- }
3069-
3070- for i in 0 ..participants. len ( ) {
3071- if let Some ( user) = participants. get ( i) {
3072- env. storage ( ) . persistent ( ) . remove ( & DataKeyScoped :: Position ( round_id, user. clone ( ) ) ) ;
3073- env. storage ( ) . persistent ( ) . remove ( & DataKeyScoped :: PrecisionPosition ( round_id, user. clone ( ) ) ) ;
3074- env. storage ( ) . persistent ( ) . remove ( & DataKeyScoped :: PrecisionCommitment ( round_id, user) ) ;
3075- }
3076- }
3077- env. storage ( ) . persistent ( ) . remove ( & DataKeyScoped :: RoundParticipants ( round_id) ) ;
3078-
3079- let round = _round_from_settlement ( & settlement) ;
3080- _archive_round (
3081- & env,
3082- & round,
3083- RoundArchiveStatus :: Resolved ,
3084- settlement. final_price ,
3085- & participants,
3086- settlement. fee_amount ,
3087- None ,
3088- ) ;
3089-
3090- _remove_settlement ( & env, round_id) ;
3091- _remove_resolved_at ( & env, round_id) ;
3092-
3093- #[ allow( deprecated) ]
3094- env. events ( ) . publish (
3095- ( symbol_short ! ( "round" ) , symbol_short ! ( "finalized" ) ) ,
3096- ( round_id, settlement. final_price , participants. len ( ) as u32 , settlement. fee_amount ) ,
3097- ) ;
3098- Ok ( ( ) )
30992859}
0 commit comments