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
3 changes: 2 additions & 1 deletion bindings/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -551,14 +551,14 @@ export const ContractError = {
* No pending oracle rotation proposal to accept or cancel
*/
54: {message:"NoPendingRotation"},
55: {message:"RotationDelayNotElapsed"},
/**
* Invalid archive retention limit
*/
62: {message:"InvalidArchiveRetention"},
/**
* Commitment hash is malformed (e.g. the all-zero placeholder)
*/
61: {message:"PendingWinningsNotExpired"},
63: {message:"InvalidCommitment"},
64: {message:"InvalidSalt"},
65: {message:"NoRoundTemplate"},
Expand All @@ -579,6 +579,7 @@ export const ContractError = {
80: {message:"PositionNotFound"},
81: {message:"InvalidPhaseForCashout"},
82: {message:"WrongModeForCashout"},
83: {message:"PendingWinningsNotExpired"},
}

/**
Expand Down
5 changes: 5 additions & 0 deletions bindings/tests/contract-error-parity.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@ while ((entry = tsEntryRegex.exec(tsMapMatch[1])) !== null) {
const rustCodes = new Map(rustVariants.map(v => [v.code, v.name]));

describe("Contract Error Parity", () => {
it("has unique Rust discriminants", () => {
const codes = rustVariants.map(({ code }) => code);
expect(new Set(codes).size).toBe(codes.length);
});

it("has no missing error codes in TS", () => {
const missingInTS = [];
for (const [code, name] of rustCodes) {
Expand Down
208 changes: 104 additions & 104 deletions contracts/src/errors.rs
Original file line number Diff line number Diff line change
@@ -1,104 +1,104 @@
// SPDX-License-Identifier: MIT
//! Contract error types for the XLM Price Prediction Market.
use soroban_sdk::contracterror;
/// Contract error types
#[contracterror(export = false)]
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
#[repr(u32)]
pub enum ContractError {
AlreadyInitialized = 1,
AdminNotSet = 2,
OracleNotSet = 3,
InvalidBetAmount = 6,
NoActiveRound = 7,
RoundEnded = 8,
InsufficientBalance = 9,
AlreadyBet = 10,
Overflow = 11,
InvalidPrice = 12,
InvalidDuration = 13,
InvalidMode = 14,
WrongModeForPrediction = 15,
RoundNotEnded = 16,
StaleOracleData = 18,
InvalidOracleRound = 19,
RoundAlreadyActive = 20,
ContractPaused = 22,
WindowOutOfRange = 23,
FutureOracleData = 24,
PayoutOverflow = 25,
RoundNotCancellable = 27,
StakeExceedsMax = 28,
ExposureCapExceeded = 29,
PendingWinningsCapExceeded = 30,
InvalidStartPrice = 31,
OracleNonceReused = 33,
InvalidMinParticipants = 35,
InvalidPrecisionCap = 38,
PrecisionCapExceeded = 39,
OracleDeviationExceeded = 41,
UnsupportedSchemaVersion = 42,
MigrationActiveRound = 44,
CommitmentNotFound = 45,
AlreadyRevealed = 46,
InvalidRevealWindow = 47,
HashMismatch = 48,
OracleNetworkMismatch = 49,
InvalidProtocolFeeBps = 51,
MintLimitExceeded = 53,
NoPendingRotation = 54,
/// Oracle rotation delay has not elapsed yet (must wait MIN_ROTATION_DELAY_SECONDS)
RotationDelayNotElapsed = 55,
/// Invalid archive retention limit
InvalidArchiveRetention = 62,
InvalidCommitment = 63,
InvalidSalt = 64,
NoRoundTemplate = 65,
/// Oracle payload timestamp is outside the round-relative economic window
OracleTimestampOutsideWindow = 66,
/// Pending winnings entry exists but has not yet reached the configured
/// expiry threshold — caller must wait before reclaiming.
PendingWinningsNotExpired = 61,
/// Epoch mint budget has been fully consumed
EpochBudgetExceeded = 67,
/// Oracle heartbeat is not live and strict mode blocks settlement (Issue #264)
OracleNotLive = 68,
/// Invalid precision payout policy
InvalidPayoutPolicy = 69,
/// Stake amount is below the configured minimum bet (dust protection, Issue #269)
BelowMinBet = 70,
/// Multi-feed resolution: fewer observations survived outlier rejection
/// than the configured quorum threshold.
InsufficientOracleQuorum = 71,
/// Multi-feed resolution: payload contains fewer observations than the
/// configured minimum.
TooFewObservations = 72,
/// Multi-feed resolution: outlier observations would dominate the result
/// (too many rejected, cannot form quorum).
OracleOutlierRejected = 73,
/// Multi-feed payload contains duplicate source identifiers.
DuplicateOracleSource = 74,
/// Multi-feed payload has observations that are not sorted or sources
/// are out of expected range.
InvalidObservationOrder = 75,
/// The requested data key is not allowed for batch TTL touch operations.
UnsupportedDataKeyForTtlTouch = 76,
/// Pending winnings entry does not exist or expiry is not configured.
PendingWinningsNotFound = 77,
/// Pending winnings expiry is not configured (value is 0).
ExpiryNotConfigured = 78,
/// Early cash-out feature is disabled or not configured
EarlyCashoutDisabled = 79,
/// User does not have an active position to cash out
PositionNotFound = 80,
/// Early cash-out attempted outside the valid running phase
InvalidPhaseForCashout = 81,
/// Early cash-out is only supported for UpDown rounds
WrongModeForCashout = 82,
ProposalNotFound = 83,
ProposalExpired = 84,
GovInvalidState = 85,
GovUnauthorized = 86,
}
// SPDX-License-Identifier: MIT
//! Contract error types for the XLM Price Prediction Market.

use soroban_sdk::contracterror;

/// Contract error types
#[contracterror(export = false)]
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
#[repr(u32)]
pub enum ContractError {
AlreadyInitialized = 1,
AdminNotSet = 2,
OracleNotSet = 3,
InvalidBetAmount = 6,
NoActiveRound = 7,
RoundEnded = 8,
InsufficientBalance = 9,
AlreadyBet = 10,
Overflow = 11,
InvalidPrice = 12,
InvalidDuration = 13,
InvalidMode = 14,
WrongModeForPrediction = 15,
RoundNotEnded = 16,
StaleOracleData = 18,
InvalidOracleRound = 19,
RoundAlreadyActive = 20,
ContractPaused = 22,
WindowOutOfRange = 23,
FutureOracleData = 24,
PayoutOverflow = 25,
RoundNotCancellable = 27,
StakeExceedsMax = 28,
ExposureCapExceeded = 29,
PendingWinningsCapExceeded = 30,
InvalidStartPrice = 31,
OracleNonceReused = 33,
InvalidMinParticipants = 35,
InvalidPrecisionCap = 38,
PrecisionCapExceeded = 39,
OracleDeviationExceeded = 41,
UnsupportedSchemaVersion = 42,
MigrationActiveRound = 44,
CommitmentNotFound = 45,
AlreadyRevealed = 46,
InvalidRevealWindow = 47,
HashMismatch = 48,
OracleNetworkMismatch = 49,
InvalidProtocolFeeBps = 51,
MintLimitExceeded = 53,
NoPendingRotation = 54,
/// Oracle rotation delay has not elapsed yet (must wait MIN_ROTATION_DELAY_SECONDS)
RotationDelayNotElapsed = 55,
/// Invalid archive retention limit
InvalidArchiveRetention = 62,
InvalidCommitment = 63,
InvalidSalt = 64,
NoRoundTemplate = 65,
/// Oracle payload timestamp is outside the round-relative economic window
OracleTimestampOutsideWindow = 66,
/// Pending winnings entry exists but has not yet reached the configured
/// expiry threshold — caller must wait before reclaiming.
PendingWinningsNotExpired = 61,
/// Epoch mint budget has been fully consumed
EpochBudgetExceeded = 67,
/// Oracle heartbeat is not live and strict mode blocks settlement (Issue #264)
OracleNotLive = 68,
/// Invalid precision payout policy
InvalidPayoutPolicy = 69,
/// Stake amount is below the configured minimum bet (dust protection, Issue #269)
BelowMinBet = 70,
/// Multi-feed resolution: fewer observations survived outlier rejection
/// than the configured quorum threshold.
InsufficientOracleQuorum = 71,
/// Multi-feed resolution: payload contains fewer observations than the
/// configured minimum.
TooFewObservations = 72,
/// Multi-feed resolution: outlier observations would dominate the result
/// (too many rejected, cannot form quorum).
OracleOutlierRejected = 73,
/// Multi-feed payload contains duplicate source identifiers.
DuplicateOracleSource = 74,
/// Multi-feed payload has observations that are not sorted or sources
/// are out of expected range.
InvalidObservationOrder = 75,
/// The requested data key is not allowed for batch TTL touch operations.
UnsupportedDataKeyForTtlTouch = 76,
/// Pending winnings entry does not exist or expiry is not configured.
PendingWinningsNotFound = 77,
/// Pending winnings expiry is not configured (value is 0).
ExpiryNotConfigured = 78,
/// Early cash-out feature is disabled or not configured
EarlyCashoutDisabled = 79,
/// User does not have an active position to cash out
PositionNotFound = 80,
/// Early cash-out attempted outside the valid running phase
InvalidPhaseForCashout = 81,
/// Early cash-out is only supported for UpDown rounds
WrongModeForCashout = 82,
ProposalNotFound = 83,
ProposalExpired = 84,
GovInvalidState = 85,
GovUnauthorized = 86,
}
Loading