> ## Documentation Index
> Fetch the complete documentation index at: https://docs.testnet.dev.adipredictstreet.com/llms.txt
> Use this file to discover all available pages before exploring further.

# PredictStreetOracle

> On-chain outcome proposal, challenge, and finalise contract.

`PredictStreetOracle` is the **only** contract authorised to call
`ConditionalTokens.reportPayouts` for PredictStreet markets.

## Key constants (testnet defaults)

| Parameter                | Default          | SOP reference |
| ------------------------ | ---------------- | ------------- |
| `bondAmount`             | 10 USDC          | §8.1          |
| `challengeWindow`        | 7200s (2 hours)  | §8.1          |
| `rewardAmount`           | 0 USDC           | §8.3          |
| `revenueWallet`          | Set at deploy    | §8.3          |
| `emergencyClearTimelock` | 604800s (7 days) | §8.4          |

## Write surface (oracle-service is the sole caller)

| Function                                             | Purpose                               |
| ---------------------------------------------------- | ------------------------------------- |
| `proposeOutcome(questionId, payouts[])`              | Start challenge window                |
| `finalizeOutcome(questionId)`                        | After window, call `reportPayouts`    |
| `resolveChallengeConfirm(questionId)`                | On dispute: confirm original          |
| `resolveChallengeOverride(questionId, newPayouts[])` | On dispute: corrected                 |
| `voidMarket(questionId)`                             | CO+CTO joint: all collateral refunded |
| `voidUnproposedMarket(questionId, outcomeSlotCount)` | Void before proposeOutcome            |
| `markDelayed(questionId)` / `undelay(questionId)`    | Pause-while-waiting                   |
| `initiateProposalClear(questionId)`                  | Start 7d timelock for emergency clear |
| `executeProposalClear(questionId)`                   | Execute after 7d                      |

## Read surface (anyone)

| Function                          | Returns                                           |
| --------------------------------- | ------------------------------------------------- |
| `getProposal(questionId)`         | `(questionId, payouts, proposedAt, bondSnapshot)` |
| `getChallenge(questionId)`        | `(challenger, bondSnapshot, note)`                |
| `getState(questionId)`            | `uint8` state enum                                |
| `isInChallengeWindow(questionId)` | `bool`                                            |

## Events

```solidity theme={null}
event OutcomeProposed(uint64 seq, bytes32 indexed questionId, uint256[] payouts);
event OutcomeChallenged(uint64 seq, bytes32 indexed questionId, address challenger, uint256 bondAmount);
event ChallengeResolvedConfirm(uint64 seq, bytes32 indexed questionId);
event ChallengeResolvedOverride(uint64 seq, bytes32 indexed questionId, uint256[] newPayouts);
event MarketVoided(uint64 seq, bytes32 indexed questionId);
event MarketDelayed(uint64 seq, bytes32 indexed questionId, bool delayed);
event BondAmountSet(uint64 seq, uint256 bondAmount);
event ChallengeWindowSet(uint64 seq, uint256 challengeWindow);
event ProposalClearInitiated(uint64 seq, bytes32 indexed questionId, uint256 unlockAt);
event ProposalClearExecuted(uint64 seq, bytes32 indexed questionId);
```

## Challenging from a partner integration

### Direct on-chain

```typescript theme={null}
import { Contract, parseUnits } from 'ethers';

const oracle = new Contract(ORACLE_ADDRESS, ORACLE_ABI, signer);
await usdc.approve(ORACLE_ADDRESS, parseUnits('10', 6));
const bondSnapshot = await oracle.bondAmount();
const note = keccak256(toUtf8Bytes('your-free-text-reason'));
await oracle.challengeOutcome(questionId, bondSnapshot, note);
```

## Source

`0x346f4065f9aA3CE51F06bAfff3e657bc2FbD209b` on
[Blockscout](https://blockscout.ab.testnet.adifoundation.ai/address/0x346f4065f9aA3CE51F06bAfff3e657bc2FbD209b)
(testnet).
