Smart Contracts
The core infrastructure powering Oyrade's prediction engine.
Oyrade is built on Solana using the Anchor Framework. Our programs are designed for speed, security, and composability.
Program Architecture
The system is composed of three interacting programs, ensuring separation of concerns between trading, settlement, and privacy.
| Program | ID | Purpose |
|---|---|---|
oyrade_markets | OYRD... | Manages liquidity pools, order matching, and share minting. |
oyrade_resolver | RSLV... | Bridges off-chain data from oracles (Switchboard/UMA) to on-chain markets. |
oyrade_privacy | PRIV... | Handles zero-knowledge proofs and shielded account interaction. |
The Market Structure
Every prediction market on Oyrade is its own independent account on Solana. This ensures that the state of one market (like listing price or liquidity) never impacts another.
Market Account
This account stores the fundamental rules of the market: the question, the deadline, and the tokens involved.
#[account]
pub struct Market {
pub authority: Pubkey, // The creator (DAO or whitelisted user)
pub question: String, // IPFS hash or plain text string
pub expiry: i64, // Unix timestamp when trading stops
pub resolved: bool, // Has the oracle spoken?
pub outcome: Option<bool>, // The final truth: YES (true) or NO (false)
pub collateral_vault: Pubkey, // Holds the total USDC backing all shares
pub total_yes: u64, // Total supply of YES tokens
pub total_no: u64, // Total supply of NO tokens
}
User Positions
Unlike standard AMMs where you hold an LP token, in Oyrade you hold Outcome Shares. A Position account tracks these for a specific user.
#[account]
pub struct Position {
pub owner: Pubkey, // User's wallet
pub market: Pubkey, // The market this position belongs to
pub yes_shares: u64, // Amount of YES outcome held
pub no_shares: u64, // Amount of NO outcome held
pub is_shielded: bool, // If true, this position is hidden in the anonymity set
}
Instructions
1. Creating a Prediction (place_prediction)
This is the primary entry point for traders. It swaps USDC for outcome shares.
Logic Flow:
- User sends USDC to the
collateral_vault. - Program calculates odds using the LMSR cost function.
- Program mints
YESorNOshares to the user.
pub fn place_prediction(
ctx: Context<PlacePrediction>,
amount: u64, // Amount of USDC to wager
side: Side, // Side::Yes or Side::No
shielded: bool, // Enable privacy shield?
) -> Result<()>
2. Market Resolution (resolve_market)
Once a market expires, the resolver program triggers this instruction. It relies on a verified oracle report.
pub fn resolve_market(
ctx: Context<ResolveMarket>,
outcome: bool, // The specific truth derived from the oracle
) -> Result<()>
Pricing Mechanism (LMSR)
We use the Logarithmic Market Scoring Rule (LMSR) to price shares. This ensures that prices always reflect the probabilities implied by the market's liquidity distribution.
The cost function to purchase quantity $q$ of shares is:
C(q) = b \cdot \ln(e^{q_{yes}/b} + e^{q_{no}/b})
Where $b$ is the liquidity parameter.
// On-chain implementation snippet
pub fn calculate_cost(yes_shares: u64, no_shares: u64, b: u64) -> u64 {
// Determines the USDC cost to move the market state
let current_state = lmsr_cost(yes_shares, no_shares, b);
let potential_state = lmsr_cost(yes_shares + quantity, no_shares, b);
potential_state - current_state
}