Oracle3
Oracle3: 예측시장 거래 엔진·MCP 서버
Robinhood 체인 메인넷에서 파라뮤추얼 주식 예측 시장, 네이티브 주식 토큰과 실시간 체인링크 데이터 제공
Parimutuel stock prediction market on Robinhood Chain Mainnet · Native Stock Tokens (TSLA/AMZN/PLTR/AMD/NVDA) · Live Chainlink Data Feeds · Deployed day 2 of mainnet launch
금융JavaScript · PythonGitHub @pplmaverick온라인운영자 미확인
써 보셨어요? 한 번만 눌러 주세요. 로그인은 필요 없어요.
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
A parimutuel stock prediction market built on Robinhood Chain Mainnet, using native Stock Tokens (TSLA, AMZN, PLTR, AMD, NVDA) and live Chainlink Data Feeds as the price oracle.
Live Demo · Network: Robinhood Chain Mainnet (Chain ID 4663)README 전문 보기 ↗
A parimutuel stock prediction market built on Robinhood Chain Mainnet, using native Stock Tokens (TSLA, AMZN, PLTR, AMD, NVDA) and live Chainlink Data Feeds as the price oracle.
Live Demo · Network: Robinhood Chain Mainnet (Chain ID 4663)
b7b2071, d45fb8e). Real on-chain
history to date: 29 createMarket, 27 lockMarket, 27 settleMarket,
3 placeBet, 2 claimWinnings (independently counted, da13c80; second
claimWinnings on market 14 appeared on-chain 2026-09-08).f40f9a1, 0e2688d,
through subsequent fixes to 17c4ba9).lockMarket/settleMarket operation (664d535,
b4748f6, and other maint: commits).da13c80, added
September 3, 2026 ahead of Continuity Track submission): a Python
reference model derived from the contract's external spec/ABI, cross-checked
against all 27 real settleMarket transactions and both real
claimWinnings transactions pulled directly from chain. 29/29 match; trace
sealed via SHA-256 (verification/settlement/commitments.sha256).
Findings: no decimals-normalization in the price-read path (dormant to
date); README's claimed no-winner refund path has no implementation
(never triggered); all real settlements to date resolved via
tie-defaults-to-BULL rather than genuine price movement. A follow-up check
(1db88b1) found genesis-era rounds on all 5 price feeds report answers
scaled at 18 decimals instead of the 8 decimals() reports — 222
anomalous rounds total, non-uniform cutoffs per feed, confirmed one level
below the proxy via .aggregator(). To our knowledge this is undocumented
elsewhere. No real settlement has touched an anomalous round to date
(~9.9-day buffer). Full detail in
verification/settlement/comparison_report.md.relayer/), gates fund-committing
agent actions on AgentBook human-verification. StockPredictionMarketV2.placeAgentBet()
validates and consumes the attestation on-chain; broadcasting that transaction is still a
manually-triggered step, and the live agent wallet currently reads unbacked on AgentBook.
See Honest Disclosure below.subgraph/, PriceRangeIndex rolling-window stats, verified
against a Python reference model on 89 real on-chain events (verification/graph-computation/).decision-engine/, BULL/BEAR/NO_TRADE over
PriceRangeIndex + relayer attestation status, verified against a Python reference model on
the same 89 real snapshots (verification/decision/). See
Honest Disclosure and docs/spec.md for the momentum
vs. mean-reversion signal-direction choice./agent-activity (AgentDecisionPanel component,
backed by frontend/api/agent-status.js), a read-only visualization of the live agent decision
pipeline. Reuses decision-engine/ and relayer/ modules directly rather than reimplementing
any logic; never calls placeBet() or placeAgentBet(). This is currently the only place a
user can actually observe the pipeline described in
Honest Disclosure below, rather than just read about it.Chain-Native Stock Token Integration
Each market is anchored to a Robinhood Chain native stock token address. createMarket() accepts address stockToken directly, creating an on-chain verifiable link between the prediction market and the actual tokenized equity — something only possible on a chain purpose-built for RWA.
Live Chainlink Data Feeds
The contract reads real-time stock prices via Chainlink AggregatorV3Interface. Each stock has a dedicated ChainlinkPriceFeed wrapper deployed on Robinhood Chain Mainnet, connected to Chainlink's official price feed proxies live from day one of mainnet launch.
Parimutuel Settlement No order book, no counterparty risk. BULL and BEAR pools accumulate independently. At settlement, the winning side splits the total pool proportional to their stake, minus a 2% protocol fee.
Full Market Lifecycle
OPEN → LOCKED → SETTLED. lockMarket() snapshots the opening price from the oracle. settleMarket() reads the closing price and determines the winning direction.
Source: docs/architecture-source.html (rendered via Puppeteer — see the comment at the top of
that file before editing either one).
*Fixed 2026-09-22 per ADR-12 (
prompts/15-refund-tie-openprice-fix.md):openPriceis now snapshotted insidecreateMarket(), at the moment the market is opened, so bettors always have an on-chain reference price to bet against for the entire OPEN window.lockMarket()is now a pure state transition — it no longer reads the price feed at all. If a Chainlink round hasn't updated between open and settle andclosePrice == openPrice,settleMarket()now puts the market into aREFUNDstate instead of defaulting to a BULL win: every bettor on both sides reclaims their exact original stake viaclaimWinnings(), with no fee deducted.settleMarket()also falls back to the sameREFUNDstate if the price-implied winning side's pool is empty (nobody actually bet on the direction the price moved) — this closes a fund-lock gap an independent security review found, where the losing side's entire pool would otherwise become permanently unclaimable. This is tested behavior (test_12_tieSettlement_refundBothSides,test_19_tieDirectionOnly_noBets_matchesTC09,test_22_refundState_bothSidesClaimFullPrincipal_skewedPools,test_23_settleMarket_emptyWinningSideBull_refunds,test_24_settleMarket_emptyWinningSideBear_refundsintest/StockPredictionMarketV2.t.sol). Both price reads (createMarket()'sopenPrice,settleMarket()'sclosePrice) also now validate the oracle response itself — the price must be positive, the round must be complete (answeredInRound >= roundId), and the update must be no older thanSTALENESS_THRESHOLD(4 hours) — before it's trusted for any market logic. The originalStockPredictionMarketV2deployment (0x59DF30E22bdaC70764a5DbF8bBa51BC5a595759C, now deprecated) carried this limitation as documented, intentional-but-unfixed behavior — see ADR-12 for the full before/after context.
| Contract | Address |
|---|---|
| StockPredictionMarketV2 (V3 fix) | 0x06897Ce6A2492BE99B59a7c023A64A6C0Af37849 — deployed 2026-09-22 per ADR-12 (prompts/15-refund-tie-openprice-fix.md), fixing the openPrice-snapshot-timing and default-BULL-tie bugs described below, plus three follow-up fixes from an independent security review (empty-winning-side REFUND, Chainlink oracle staleness/round/timestamp validation) |
| StockPredictionMarketV2 (original) | 0x59DF30E22bdaC70764a5DbF8bBa51BC5a595759C — deprecated 2026-09-22, superseded by the V3 fix above; no longer referenced by frontend, decision-engine, or any new code |
| StockPredictionMarket | 0x72DAb8B1B53b3CF028e9A0d1E21178981f264245 — deprecated, no longer referenced by frontend or any new code |
| AgentStockMarket | 0xE8b3916Ea16AD2F2C0910bB94005e30F5CC341D3 — deployed 2026-09-05, superseded one day later when ADR-10 merged its attestation-verification logic into StockPredictionMarketV2.placeAgentBet(); no longer referenced by any frontend, decision-engine, or relayer code |
| TSLA ChainlinkPriceFeed | 0x072A3A0C04Cf8CDcaf5B4A73a4Ed4fF5A841531f |
| AMZN ChainlinkPriceFeed | 0xcAC5B9d2817325E78090E3Ce4b9C299C819cF953 |
| PLTR ChainlinkPriceFeed | 0xBdC53E50b1167cE1199bFaD54A034f7ab1741051 |
| AMD ChainlinkPriceFeed |
| Ticker | Feed Address |
|---|---|
| TSLA/USD | 0x4A1166a659A55625345e9515b32adECea5547C38 |
| AMZN/USD | 0xD5a1508ceD74c084eBf3cBe853e2C968fB2a651C |
| PLTR/USD | 0x820ABedFF239034956B7A9d2F0a331f9F075eB4c |
| AMD/USD | 0x943A29E7ae51A4798823ca9eEd2ed533B2A22C72 |
| NVDA/USD | 0x379EC4f7C378F34a1B47E4F3cbeBCbAC3E8E9F15 |
| Contract | Address |
|---|---|
| StockPredictionMarket | 0x15636CE4C0EdE55335f84E6386f8F49C897c077d |
# 1. Install dependencies
npm install
# 2. Configure environment
cp .env.example .env
| Variable | Description |
|---|---|
PRIVATE_KEY | Deployer wallet private key (no 0x prefix) |
# 3. Compile
npx hardhat compile
# 4. Deploy to mainnet
npx hardhat run scripts/deploy.js --network robinhoodMainnet
// Create a new prediction round
createMarket(address stockToken, address priceFeed, string symbol, uint256 duration) returns (uint256 marketId)
// Place a bet (send ETH as value)
placeBet(uint256 marketId, Direction direction) // Direction: 0 = BULL, 1 = BEAR
// Lock market and snapshot opening price
lockMarket(uint256 marketId)
// Settle market and determine winner
settleMarket(uint256 marketId)
// Claim winnings after settlement
claimWinnings(uint256 marketId)
Fees
Security
Live Chainlink Integration
Robinhood Chain launched mainnet on July 1, 2026 with Chainlink as the official oracle layer from block zero. This contract integrates Chainlink Data Feeds via a ChainlinkPriceFeed wrapper that implements IPriceFeed (mirrors AggregatorV3Interface). Replacing or upgrading feeds requires only a constructor argument change — zero contract modifications.
Stock Token as Market Identifier On most chains, a prediction market would use an arbitrary string or uint to identify a market. On Robinhood Chain, we use the native stock token contract address directly, creating an on-chain verifiable link between the prediction market and the actual tokenized equity.
The relayer/ service is a trusted-signer relayer bridge, not a trust-minimized one. It
verifies a World AgentKit-signed agent request, checks the agent's wallet against World Chain's
AgentBook for a registered humanId, enforces its own replay-nonce, and signs an attestation
with a relayer-held private key. StockPredictionMarketV2.placeAgentBet()
(contracts/StockPredictionMarketV2.sol) does verify and consume that attestation on-chain: it
ecrecovers the signature against relayerAddress, checks expiresAt and usedAttestations,
and credits the bet into the same bullPool/bearPool a human's placeBet() uses.
decision-engine/src/agent-tx.js builds, simulates, and can broadcast that transaction from the
agent's own wallet — the agent pays its own gas, the relayer never funds or broadcasts anything
— but its own code comment is explicit that the broadcast step is never invoked automatically
and is meant to be wired up only behind an explicit human confirmation. Nothing in this pipeline
runs unattended end-to-end today.
Separately: the agent wallet this project actually uses currently reads unbacked on AgentBook
(57/57 live reads against real, freshly generated addresses returned unbacked — see
prompts/08-world-id-orb-availability-constraint.md), because obtaining a real Orb-verified
World ID is blocked by an external constraint: Taiwan has no stably operating Orb location, and
a possible World ID Sandbox workaround was never confirmed compatible with AgentBook's on-chain
groupId=1 check. Concretely, this means the relayer currently refuses to sign an attestation
for this agent at all (agent_not_human_backed), so placeAgentBet() can never be reached with
a validly-signed attestation through the real pipeline as it stands — the backed branch's
correctness has been verified by code review and unit tests only (relayer/src/agent-book.js,
exercised in relayer/test/replay.test.js and decision-engine/test/), not by a live on-chain
bet.
Separately, and identified after the fact during design: World ID (and therefore AgentBook)
proves an agent maps to one distinct real human — uniqueness — not that the human authorized
this specific spend or amount, and not a post-hoc auditable record of that authorization. The
current design only blocks agent bets with no real human behind them at all; it does not yet
cover spend limits, scoped authorization, or accountability after the fact. See
prompts/03-calibrated-autonomy-boundary.md for the full reasoning.
The lookupHuman three-state read (backed / unbacked / unknown, so an AgentBook RPC
failure is never reported as "not registered") follows the pattern documented in
poh-aggregator's
lookupHumanBacking —
credited here as prior art this implementation deliberately follows, not independently arrived at.
| Layer | Technology |
|---|---|
| Smart contract | Solidity ^0.8.20 |
| Development | Hardhat 3 + ethers.js |
| Oracle | Chainlink Data Feeds (AggregatorV3Interface) |
| Stock tokens | Robinhood Chain native (TSLA, AMZN, PLTR, AMD, NVDA) |
| Frontend | React + wagmi v2 + Vite |
| Deployment | Vercel |
✅ M1 — Contract Deployment
✅ M2 — Frontend
✅ M3 — Mainnet
⬜ W3 — Keeper Automation
⬜ W4 — Architecture Diagram
⬜ W5 — NatSpec Documentation
GitHub: pplmaverick
Wallet: 0xed2B5717c9b936ecC76d75401026A99143e278F5
MIT
| NVDA ChainlinkPriceFeed | 0x914c40a644493b47336de847b0404E729e06C68d |