diff --git a/contracts/disputes/Cargo.toml b/contracts/disputes/Cargo.toml new file mode 100644 index 00000000..987db91f --- /dev/null +++ b/contracts/disputes/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "disputes" +version = "0.0.0" +edition = "2021" +publish = false + +[lib] +crate-type = ["lib", "cdylib"] +doctest = false + +[dependencies] +soroban-sdk = { workspace = true } +predictify-hybrid = { path = "../predictify-hybrid" } + +[dev-dependencies] +soroban-sdk = { workspace = true, features = ["testutils"] } + +[[test]] +name = "err_stab" +path = "tests/err_stab.rs" diff --git a/contracts/disputes/src/lib.rs b/contracts/disputes/src/lib.rs new file mode 100644 index 00000000..3e7d85a7 --- /dev/null +++ b/contracts/disputes/src/lib.rs @@ -0,0 +1,2 @@ +#![no_std] +// Disputes package library to satisfy cargo workspace structure diff --git a/contracts/disputes/tests/err_stab.rs b/contracts/disputes/tests/err_stab.rs new file mode 100644 index 00000000..6476d1de --- /dev/null +++ b/contracts/disputes/tests/err_stab.rs @@ -0,0 +1,31 @@ +//! Disputes client-facing error-code stability tests. +//! +//! These assertions intentionally freeze the numeric values exposed by the +//! contract's dispute-related errors. Client applications may persist or branch on +//! these values, so changing one is a visible API change. + +use predictify_hybrid::Error; + +/// Dispute error codes are frozen to prevent accidental modifications or shifts. +#[test] +fn dispute_error_codes_are_stable() { + let dispute_errors = [ + (Error::AlreadyDisputed, 404u32), + (Error::DisputeVoteExpired, 405u32), + (Error::DisputeVoteDenied, 406u32), + (Error::DisputeAlreadyVoted, 407u32), + (Error::DisputeCondNotMet, 408u32), + (Error::DisputeFeeFailed, 409u32), + (Error::DisputeError, 410u32), + (Error::DisputerCannotVote, 438u32), + (Error::DisputeStakeCapExceeded, 522u32), + ]; + + for (error, expected_code) in dispute_errors { + assert_eq!( + error as u32, + expected_code, + "dispute error code changed for {error:?}; this is a client-facing API change" + ); + } +} diff --git a/contracts/predictify-hybrid/tests/err_stability.rs b/contracts/predictify-hybrid/tests/err_stability.rs index 1194a926..f1f6d59f 100644 --- a/contracts/predictify-hybrid/tests/err_stability.rs +++ b/contracts/predictify-hybrid/tests/err_stability.rs @@ -74,13 +74,6 @@ fn general_errors() { assert_eq!(Error::InvalidInput as u32, 401); assert_eq!(Error::InvalidFeeConfig as u32, 402); assert_eq!(Error::ConfigNotFound as u32, 403); - assert_eq!(Error::AlreadyDisputed as u32, 404); - assert_eq!(Error::DisputeVoteExpired as u32, 405); - assert_eq!(Error::DisputeVoteDenied as u32, 406); - assert_eq!(Error::DisputeAlreadyVoted as u32, 407); - assert_eq!(Error::DisputeCondNotMet as u32, 408); - assert_eq!(Error::DisputeFeeFailed as u32, 409); - assert_eq!(Error::DisputeError as u32, 410); assert_eq!(Error::SweepAlreadyDone as u32, 411); assert_eq!(Error::FeeArithmeticOverflow as u32, 412); assert_eq!(Error::FeeAlreadyCollected as u32, 413); @@ -106,11 +99,26 @@ fn general_errors() { assert_eq!(Error::TooManyWinningOutcomes as u32, 434); assert_eq!(Error::CategoryTooShort as u32, 436); assert_eq!(Error::TagTooShort as u32, 437); - assert_eq!(Error::DisputerCannotVote as u32, 438); assert_eq!(Error::ArchiveFull as u32, 440); assert_eq!(Error::DuplicateMarketId as u32, 441); } +// ===== Dispute Errors (404-410, 438, 522) ===== + +#[test] +fn dispute_errors() { + assert_eq!(Error::AlreadyDisputed as u32, 404); + assert_eq!(Error::DisputeVoteExpired as u32, 405); + assert_eq!(Error::DisputeVoteDenied as u32, 406); + assert_eq!(Error::DisputeAlreadyVoted as u32, 407); + assert_eq!(Error::DisputeCondNotMet as u32, 408); + assert_eq!(Error::DisputeFeeFailed as u32, 409); + assert_eq!(Error::DisputeError as u32, 410); + assert_eq!(Error::DisputerCannotVote as u32, 438); + assert_eq!(Error::DisputeStakeCapExceeded as u32, 522); +} + + // ===== Circuit Breaker Errors (500-508) ===== #[test]