고급 시장 모델 및 체인링크 오라클 통합
5개 결과가 각각 50%일 때: 합계 = 250% (거래를 통해 수렴)
5개 결과가 각각 20%일 때: 합계 = 100% (차익거래 기회 없음)
슈퍼볼 (NegRisk CTF): ┌────────────┬───────┬───────┬──────────┐ │ 팀 │ YES │ NO │ YES + NO │ ├────────────┼───────┼───────┼──────────┤ │ Chiefs │ 23¢ │ 77¢ │ 100¢ ✓ │ │ Eagles │ 19¢ │ 81¢ │ 100¢ ✓ │ └────────────┴───────┴───────┴──────────┘ CFP (Grouped Binary): ┌────────────┬───────┬───────┬──────────┐ │ 팀 │ YES │ NO │ YES + NO │ ├────────────┼───────┼───────┼──────────┤ │ Indiana │ 93.4¢ │ 99¢ │ 192.4¢ │ │ Ohio State │ 72¢ │ 98¢ │ 170¢ │ └────────────┴───────┴───────┴──────────┘
5개 결과가 각각 50%일 때: 합계 = 250% 차익거래자: - 모든 NO 토큰 매수 - 한 결과가 패배할 때 보장된 수익 - 제작자는 차익거래자에게 손실
Grouped Binary (5개 결과 × 50%): 시장 1: 팀 A YES (50¢) + NO (50¢) = $1 ✓ 시장 2: 팀 B YES (50¢) + NO (50¢) = $1 ✓ 시장 3: 팀 C YES (50¢) + NO (50¢) = $1 ✓ 시장 4: 팀 D YES (50¢) + NO (50¢) = $1 ✓ 시장 5: 팀 E YES (50¢) + NO (50¢) = $1 ✓ YES의 합 = 250%... 하지만 그래서요? 왜 차익거래가 아닌가? • 각 시장은 독립적입니다 • 다른 시장 간에 토큰을 병합할 수 없습니다 • 각 시장은 개별적으로 YES + NO = $1 ✓ 250% → 100% 수렴은 단지 가격 발견(Price Discovery)일 뿐, 차익거래가 아닙니다. 스마트 트레이더들이 이를 정상화합니다.
| 케이스 | 조건 | 행동 | 결과 |
|---|---|---|---|
| 단일 시장 | YES + NO < $1 | 둘 다 매수 | 보장된 수익 |
| 단일 시장 | YES + NO > $1 | 둘 다 발행 및 매도 | 보장된 수익 |
| CTF 다중 결과 | 합계 < $1 | 모두 매수, 병합 | 보장된 수익 |
| CTF 다중 결과 | 합계 > $1 | 분할 및 모두 매도 | 보장된 수익 |
| 크로스 플랫폼 | YES_A + NO_B < $1 | 양쪽 매수 | 보장된 수익 |
핵심: 차익거래는 무위험, 보장된 수익을 의미합니다. 250% 합계는 이에 해당하지 않습니다.
| 결과 | 초기 | 공정가 | 차이 |
|---|---|---|---|
| A (우승후보) | 50¢ | 60¢ | -10¢ |
| B | 50¢ | 15¢ | +35¢ |
| C | 50¢ | 10¢ | +40¢ |
| D | 50¢ | 10¢ | +40¢ |
| E | 50¢ | 5¢ | +45¢ |
우승후보: 약간 저평가 (-10¢)
언더독: 극심한 고평가 (+35~45¢)
| 결과 | 초기 | 공정가 | 차이 |
|---|---|---|---|
| A (우승후보) | 20¢ | 60¢ | -40¢ |
| B | 20¢ | 15¢ | +5¢ |
| C | 20¢ | 10¢ | +10¢ |
| D | 20¢ | 10¢ | +10¢ |
| E | 20¢ | 5¢ | +15¢ |
우승후보: 큰 저평가 (-40¢)
언더독: 약간 고평가 (+5~15¢)
우승후보가 이기면, 제작자는 가치 없는 80¢ NO 토큰만 보유하게 됩니다.
손실을 최소화하는지는 거래 패턴에 달려 있습니다.
| 공급자 | 현실 | 언제 |
|---|---|---|
| 무작위 트레이더 | 빈 시장에 오지 않음 | 초기에는 절대 없음 |
| 전문 MM | 검증된 고거래량 시장에만 참여 | 거래량이 확립된 후 |
| 플랫폼 자체 | 새로운 시장을 부트스트랩해야 함 | 첫날부터 |
$1000 유동성으로 5개 결과 시장의 경우: 균등 분할: 시장당 $200 각 시장에 대해 (20% YES / 80% NO): - 200 YES @ $0.20 = $40 - 200 NO @ $0.80 = $160 - 합계: $200 → 200 YES + 200 NO (균형) A가 이길 경우: - A: 200 YES × $1 = $200 - B: 200 NO × $1 = $200 - C: 200 NO × $1 = $200 - D: 200 NO × $1 = $200 - E: 200 NO × $1 = $200 반환: $1000 ✓ (균형 상태일 때 본전)
| 유동성 수준 | 거래 품질 | 사용자 경험 |
|---|---|---|
| 시장당 $500 | 나쁨 | 좌절스러움, 큰 슬리피지 |
| 시장당 $5,000 | 보통 | 소액 트레이더에게 허용 가능 |
| 시장당 $50,000+ | 좋음 | 전문가 수준 |
초기: 시장 A 20% YES / 80% NO 제작자 보유: 200 YES + 200 NO 시간 경과... A가 우승후보가 됨 (80% YES): 트레이더: "A의 YES를 사고 싶어!" 제작자: YES 매도, 행복 😊 트레이더: "A의 NO는 안 사, A가 이길 거니까!" 제작자: NO 매도 불가, 고립됨 😰 결과: - YES: 200 → 50 (150개 매도, 좋음!) - NO: 200 → 200 (아무도 안 삼, 고립!) A가 이길 경우: - 50 YES × $1 = $50 - 200 NO × $0 = $0 제작자 시작 $200, 종료 $50 손실: $150 ❌
패배하는 시장(B, C, D, E)에서 NO를 파는 것은 보상이 되지 않습니다:
B의 200 NO를 95¢에 매도 = $190 수취 하지만: A가 이기면, 구매자는 200 × $1 = $200를 받음 제작자는 $200 가치를 $190에 매도 = 손실 교차 시장 매도는 보상이 아니라 더 많은 손실을 추가합니다.
100 A + 100 B + 100 C + 100 D + 100 E → $100 USDC 상대방 불필요! 언제든지 병합을 통해 탈출 가능. 재고 고립 문제 없음.
| 시나리오 | 수수료 수입 | 재고 손실 | 총 손실 |
|---|---|---|---|
| 최상의 경우 | $500 | $100 | +$500 수익 |
| 평균 | $200 | $350 | -$150 (15%) |
| 나쁜 경우 | $75 | $400 | -$325 (32.5%) |
| 최악의 경우 | $75 | $860 | -$785 (78.5%) |
MM 주문 게시: YES 매수 @ 49¢ YES 매도 @ 51¢ 양쪽이 체결될 때: - 트레이더 A가 YES 매수 @ 51¢ → MM 51¢ 수취 - 트레이더 B가 YES 매도 @ 49¢ → MM 49¢ 지불 MM 수익: 51¢ - 49¢ = 주당 2¢ 10,000주 거래 시: 수익 =
Taker (주문 체결자): 2% 수수료 지불 Maker (주문 제공자): 0.5% 리베이트 수취 MM은 항상 주문을 제공함 → 모든 거래에서 리베이트 획득
가격이 오르는 중? → 매수 주문 취소 (비싸게 사는 것 방지) → 매도 가격 인상 (더 비싸게 팔기) 아마추어 LP: 매시간 업데이트 → 손해 봄 프로 MM: 매초 업데이트 → 스프레드 포착
상관관계가 있는 시장: - "Chiefs 슈퍼볼 우승" (YES @ 25¢) - "Mahomes MVP 수상" (YES @ 30¢) MM은 Chiefs YES 매도, Mahomes YES 매수 (헤지) 순 노출: ~0 하지만: 스프레드 수익은 유지!
MM 수익 = 스프레드 수입
+ 수수료 리베이트
+ 차익거래 이익
- 재고 손실
- 운영 비용
| 방법 | 설명 | 플랫폼 비용 |
|---|---|---|
| 월간 수수료 지급 | 유동성 공급에 월 -10K | 고정적, 예측 가능 |
| 수수료 리베이트 | MM이 거래의 0.5% 획득 | 수익 감소 |
| 수익 공유 | 거래 수수료의 50% | 가변적 |
| 토큰 인센티브 | 유동성에 대해 NOSTRA 토큰 지급 | 토큰 희석 |
유동성 출처:
일반 사용자는 그저 거래할 뿐입니다. UI를 통해 "유동성을 공급"하지 않습니다.
Nostra는 글로벌 선두 기업(예: Polymarket)의 오더북을 실시간으로 미러링하는 "브릿지 마켓 메이커(Bridge MM)" 봇을 운영합니다.
| 수수료 수준 | LP 수익률 | 거래 활동 |
|---|---|---|
| 높음 (3%+) | 높음 | 낮음 (거래 비용 비쌈) |
| 중간 (2%) | 중간 | 중간 |
| 낮음 (0.5%) | 낮음 | 높음 (거래 비용 저렴) |
거래량이 적고 시장이 한 방향으로 급격히 움직일 경우:
수수료는 도움이 되지만 수익을 보장하지는 않습니다.
| 플랫폼 | 수수료 모델 | 상세 내용 |
|---|---|---|
| Polymarket (글로벌/크립토) | 거래 수수료 없음 / 스프레드 |
|
| Polymarket US (규제/출시 예정) | 고정 거래 수수료 |
|
| Kalshi (미국 규제 준수) | 메이커-테이커 (Maker-Taker) |
|
매수-매도 스프레드는 매수 가격(Ask)과 매도 가격(Bid)의 차이로 발생하는 암묵적인 거래 비용입니다.
예측 시장의 결과는 0 또는 1입니다. AMM은 가격이 0이나 1에 가까워질수록 유동성을 제공하기 위해 막대한 자본을 요구합니다 (LSR - Logarithmic Scoring Rule 등 복잡한 수학 필요).
오더북은 사용자가 원하는 가격에 정확히 주문을 낼 수 있어 가격 발견이 더 효율적입니다.
고정소수점 연산이 예측 시장의 토큰 계산에 어떤 영향을 미치는지 이해합니다.
// 수학적 계산
$10 / $0.55 = 18.181818181818181818... (무한 반복)
// 18자리 소수점 정밀도 (블록체인 한계)
저장값: 18.181818181818181818 (잘림)
// 역으로 곱해서 검증
18.181818181818181818 × $0.55 = $9.99999999999999999990
// "더스트"
$10.00000000000000000000
-$9.99999999999999999990
─────────────────────────
$0.00000000000000000010 ← 정밀도 손실 (~0.00000000000000001 센트)
CTFExchange에서 컨트랙트는 정수 나눗셈을 사용하며 항상 내림(round DOWN)합니다:
| 작업 | 더스트가 남는 곳 |
|---|---|
| MINT (새 토큰 생성) | CTFExchange의 내부 balances 매핑 |
| COMPLEMENTARY (판매자와 매칭) | 판매자가 약간 적게 받거나, CTFExchange가 나머지 보유 |
| MERGE (토큰을 담보로 환매) | CTFExchange가 소수점 담보 보유 |
// CTFExchange 컨트랙트 - 더스트가 여기에 누적됨
mapping(address => uint256) public balances;
$10로 18.181818181818181818 shares를 구매할 때:
1/0.55, 1/0.33 등과 같은 무한 반복 소수에서는 유한한 소수점으로 완벽한 가역성이 불가능합니다. 이는 블록체인의 모든 고정소수점 연산 시스템에 내재된 특성입니다.
다중 결과 예측 시장을 위한 두 가지 주요 시장 모델 아키텍처를 이해합니다: Nostra의 현재 Grouped Binary 방식 vs Polymarket의 NegRisk 어댑터 솔루션.
| 특징 | Grouped Binary (Nostra) | Grouped Binary + NegRisk (Polymarket) |
|---|---|---|
| 초기 확률 | 유연함 (50% 또는 100/N%) | 유연함 (시장 결정) |
| YES 가격 합계 | 유연함 (연결 없음) | ~100% (차익거래로 강제) |
| 시장 연결 | 독립적 (연결 없음) | 어댑터 레이어 (NegRisk) |
| 재고 고립 | 있음 (심각한 문제) | 없음 (전환 가능) |
| conditionId | 다수 (결과당 하나) | 다수 + negRiskMarketId |
| 포지션 전환 | 불가능 | 어댑터로 가능 |
| 유동성 파편화 | 심각 (N개 시장) | 통합 |
| 구현 복잡도 | 단순 | 6-10주 |
Grouped Binary 모델은 Nostra의 현재 구현입니다. 다중 결과 질문의 각 결과는 독립적인 바이너리 시장으로 취급되며 자체 YES/NO 토큰을 가집니다.
각
결과 = 별도의 conditionId를 가진 독립적인 바이너리 시장
당신은 Spain YES 토큰 100개를 개당 $0.25에 보유하고 있습니다. Spain이 탈락했습니다. 이제 France YES를 원합니다:
결과: 이중 슬리피지, 상당한 가치 손실. 당신의 포지션은 사실상 "고립"되었습니다.
Nostra의 Grouped Binary 모델은 단순하지만, 다중 결과 마켓에서 심각한 유동성 문제가 발생합니다. 실제 시나리오를 통해 어떤 상황에서 문제가 생기는지 살펴보겠습니다.
Nostra에서 "2026 월드컵 우승팀" 마켓을 5개 팀으로 생성:
핵심: 각 팀은 독립된 마켓이며, 서로 연결되어 있지 않습니다.
Alice는 Spain이 우승할 것으로 예상하고 투자했습니다:
// Alice의 초기 투자 구매: Spain YES 1,000개 @ 20¢ 투자금: $200 예상 수익: Spain 우승 시 $1,000 (5배) // 1주일 후: Spain이 조별리그에서 탈락! Spain YES 가격: 20¢ → 3¢ (85% 하락) Alice의 포지션 가치: $200 → $30
Alice는 이제 France가 우승할 것 같아서 포지션을 바꾸고 싶습니다:
// Step 1: Spain YES 매도 매도: 1,000개 @ 3¢ 받는 금액: $30 슬리피지: -10% → 실제 $27 // Step 2: France YES 매수 France YES 가격: 25¢ 구매 가능: $27 / 0.25 = 108개 슬리피지: +8% → 실제 100개 결과: 1,000개 → 100개 (90% 손실)
// Direct Conversion via Adapter Spain YES → France YES 수학적 변환 (슬리피지 없음) 가치 기준 변환: $30 가치 → $30 가치 France @ 25¢ = 120개 결과: 가치 보존, 20% 더 많은 토큰
Bob은 $10,000를 Brazil YES에 투자하려 합니다:
// Nostra 오더북 상태 (Brazil YES) 총 마켓 유동성: $50,000 (5개 팀 전체) Brazil 마켓 유동성: $10,000 (1/5) 오더북 깊이: 15¢: 5,000 shares ($750) 16¢: 8,000 shares ($1,280) 17¢: 10,000 shares ($1,700) 18¢: 15,000 shares ($2,700) 19¢: 20,000 shares ($3,800) ───────────────────────────── 총 깊이: ~$10,230 // Bob이 $10,000 시장가 주문 실행 $750 @ 15¢ = 5,000 shares $1,280 @ 16¢ = 8,000 shares $1,700 @ 17¢ = 10,000 shares $2,700 @ 18¢ = 15,000 shares $3,570 @ 19¢ = 18,789 shares ───────────────────────────── 총: 56,789 shares @ 평균 17.6¢ 기대 가격 (15¢)으로 샀다면: 66,667 shares 슬리피지 손실: ~15% (9,878 shares)
독립된 마켓이기 때문에 모든 YES 가격의 합이 100%가 되지 않을 수 있습니다:
| 팀 | YES 가격 | 실제 확률 | 문제 |
|---|---|---|---|
| Spain | 25¢ | ~22% |
합계: 112¢ 12% 오버북 (Arbitrage 기회) |
| Brazil | 23¢ | ~20% | |
| France | 22¢ | ~19% | |
| Argentina | 21¢ | ~18% | |
| England | 21¢ | ~18% |
Nostra: 각 마켓이 독립적 → 가격 조정하는 메커니즘 없음 → 수동 차익거래에 의존
Polymarket: NegRisk 어댑터 → NO 토큰 동등성 → 자동 차익거래로 ~100% 유지
// Charlie가 Spain 마켓에 유동성 제공 제공: YES 측 $5,000, NO 측 $5,000 (총 $10,000) // 거래 발생: 사용자들이 Spain YES를 대량 매수 결과: Charlie는 Spain YES를 팔고 USDC를 받음 포지션: Spain NO $8,000 보유 (편향된 재고) // Spain 탈락 후 Spain NO = $1 (승리!) Charlie 수익: +$8,000 // 하지만 Spain이 우승했다면? Spain NO = $0 (패배) Charlie 손실: -$8,000 문제: 재고를 다른 팀으로 전환할 수 없음! Charlie가 France NO로 헤지하고 싶어도: 1. Spain NO 매도 (슬리피지) 2. France NO 매수 (슬리피지) = 이중 슬리피지로 헤지 비용 과다
| 상황 | Nostra (Grouped Binary) | Polymarket (NegRisk) |
|---|---|---|
| 포지션 전환 Spain → France |
불가능 매도 → 매수 (이중 슬리피지) |
가능 수학적 변환 (0% 슬리피지) |
| 대량 주문 $10K 시장가 |
10-20% 슬리피지 분산된 유동성 |
1-3% 슬리피지 통합 유동성 |
| 가격 일관성 Σ YES = ? |
90-120% 수동 차익거래 의존 |
~100% 자동 차익거래 |
| LP 헤지 재고 리밸런싱 |
고비용 이중 거래 필요 |
저비용 직접 변환 가능 |
핵심 아이디어: 담보가 상호 배타적인 YES 토큰들로 직접 분할됩니다. 이를 통해 유동성이 집중됩니다.
Sum(Price(YES)) = $1.00
Sum(Price(NO)) = $(N - 1).00
NegRisk는 각 결과를 위한 독립적인 바이너리 시장을 만드는 대신, 모든 결과를 하나로 연결합니다. $1의 담보(Collateral)가 모든 결과(Outcome)로 쪼개집니다.
5개 국가: Spain, Brazil, France, Argentina, England 초기 가격: 각 20¢ YES / 80¢ NO (20% 확률) 마켓 메이커: 국가당 $2,000 공급 → 2,000 (YES+NO) 쌍씩 총 유동성: $10,000
| 국가 | YES 잔량 | NO 잔량 | 상태 |
|---|---|---|---|
| Spain | 500 | 2,000 | 1,500 NO 고립! |
| Brazil | 1,600 | 2,000 | 400 과잉 NO |
| France | 1,800 | 2,000 | 200 과잉 NO |
| Argentina | 2,000 | 2,000 | 균형 |
| England | 2,000 | 2,000 | 균형 |
// 거래 6: Spain YES $100 추가 매수 Spain YES 500개만 남음 가격 급등: 20¢ → 30¢ → 40¢ $100로 250개만 매수 가능 (500개가 아님!) 반면: 1,500 Spain NO는 쓸모없이 방치됨 💀
// 마켓 메이커가 과잉 NO를 변환 5개 국가에서 각 200 NO 수집 = 200개의 완전한 NO 세트 (5개 토큰씩) = 200 × $4 = $800 USDC로 환원! → 400개의 새 Spain YES+NO 쌍 발행
핵심: NegRisk에서는 모든 NO 토큰을 결합하여 USDC로 환원할 수 있습니다 (그 중 하나는 반드시 승리하므로). 이것이 "고립된" 재고를 해제하여 마켓 메이커가 지속적으로 유동성을 가장 필요한 곳으로 재배치할 수 있게 합니다.
Polymarket의 NegRisk 구현은 오픈소스이며 ChainSecurity와 OpenZeppelin의 감사를 받았습니다.
GitHub: Polymarket/neg-risk-ctf-adapter →
포함: NegRiskAdapter, NegRiskOperator, NegRiskCtfExchange, WrappedCollateral, Vault, FeeModule
핵심: USDC ↔ NO 토큰 ↔ YES 토큰 변환
스페인 YES/NO | 프랑스 YES/NO | 브라질 YES/NO | ...
모두 negRiskMarketId로 연결됨
모든 토큰 작업의 기본 레이어
| 컨트랙트 | 목적 | Nostra 보유? |
|---|---|---|
| NegRiskAdapter | 핵심 변환 로직 (NO → YES) | 아니오 |
| NegRiskOperator | 관리자 기능, 오라클 통합 | 아니오 |
| WrappedCollateral | 내부 회계용 Wrapped USDC | 아니오 |
| ConditionalTokens (CTF) | 기본 토큰 프레임워크 | 예 |
| MarketFactory | 바이너리 시장 생성 | 예 |
| CTFExchange | 오더북 트레이딩 | 예 |
| 컴포넌트 | 시간 | 복잡도 |
|---|---|---|
| 스마트 컨트랙트 (1-3) | 2-3주 | 높음 (보안 중요) |
| 백엔드 API (4-5) | 3-5일 | 중간 |
| 프론트엔드 UI (6) | 3-5일 | 중간 |
| 테스트 및 감사 | 2-4주 | 매우 중요 |
| 총계 | 6-10주 |
NegRisk를 구현하기 전에, 정말 필요한지 고려해보세요. 현재의 차익거래 봇으로도 훨씬 간단한 구현으로 경제적 포지션 균형을 맞출 수 있습니다.
언제 NegRisk를 구현해야 할까요?
Nostra는 암호화폐 가격부터 틈새 지역 이벤트까지 다양한 시장 유형을 처리하기 위해 멀티 오라클 전략을 채택합니다. 우리는 하이브리드 AI와 낙관적 오라클을 사용하는 Opinion Labs 및 UMA를 사용하는 Polymarket과 같은 업계 선두주자들을 벤치마킹합니다.
| 오라클 유형 | 메커니즘 | 장점 | 단점 | 적합한 대상 |
|---|---|---|---|---|
| 수동 관리자 (Manual Admin) | 신뢰할 수 있는 관리자 키로 결과 해결 |
|
|
베타 출시, 테스트 시장, 비상 해결 |
| 체인링크 (Chainlink) (Functions / Feeds) |
탈중앙화 노드가 API/가격 데이터 가져옴 |
|
|
스포츠, 암호화폐 가격, 선거 결과 (API 존재 시) |
| UMA (낙관적 오라클) |
"이의 제기 전까지 진실" + 투표 배심원 |
|
|
롱테일 이벤트, "의견" 기반 시장 (예: "AI가 지배할까?") |
Opinion Labs는 정교한 하이브리드 오라클 접근 방식을 사용합니다:
Nostra는 비정형 시장을 위해 이 "낙관적 검증" 패턴을 채택할 것입니다.
목표: 시장 수요 및 UI/UX 검증.
방법: 관리자 키로 모든 시장 해결. 빠르고 무료지만 중앙화됨.
목표: 높은 거래량 시장 자동화.
방법: 스포츠 및 암호화폐 시장에 체인링크 도입. 롱테일 이벤트는 관리자가 유지.
목표: 무허가 시장 생성.
방법: UMA (낙관적 오라클) 통합. 관리자 키는 "거부권"만 허용 (비상 브레이크).
목표: 멈출 수 없는 프로토콜.
방법: 관리자 키 제거. 시장은 오직 체인링크, UMA 또는 DAO 거버넌스에 의해서만 해결됨.
검증 가능한 온체인 데이터나 API를 사용할 수 없는 시장(예: "이 유튜버가 구독자 100만 명을 달성할까?" 또는 매우 주관적인 "의견" 시장)의 경우, 우리는 UMA의 낙관적 오라클(Optimistic Oracle)을 활용합니다. 이를 통해 인간이 암호경제학적 보증을 바탕으로 시장을 해결할 수 있습니다.
비정형 시장의 해결을 확장하기 위해, 우리는 Opinion Labs와 유사한 하이브리드 AI 접근 방식을 채택합니다. 이는 AI의 속도와 낙관적 오라클의 보안성을 결합한 것입니다.
OptimisticOracleV3는 주장(assertion) 수명 주기를 관리하는 핵심 컨트랙트입니다. 이는 이의가 제기되지 않는 한 진실로 간주되는 에스컬레이션 게임(escalation game)을 활용합니다.
// Core OOv3 Interface interface IOptimisticOracleV3 { /** * @notice 세계 상태에 대한 진실을 주장합니다. * @param claim 진술을 나타내는 인코딩된 데이터 또는 문자열 (예: "BTC > 50k at block 100"). * @param asserter 정답일 경우 채권을 돌려받을 주소. * @param callbackRecipient 정산 시 알림을 받을 주소. * @return assertionId 이 주장의 고유 ID. */ function assertTruthWithDefaults( bytes calldata claim, address asserter ) external returns (bytes32 assertionId); /** * @notice 주장을 정산합니다. 활동 기간(Liveness Period) 이후에만 호출 가능합니다. * @return bool 주장이 '진실'로 해결되었으면 true를 반환합니다. */ function settleAndGetAssertionResult(bytes32 assertionId) external returns (bool); /** * @notice 상태 확인을 위한 View 함수. */ function getAssertionResult(bytes32 assertionId) external view returns (bool); }
assertTruthWithDefaults를 호출합니다. 이는 주장자로부터
최소 채권(Minimum
Bond)(보통 WETH 또는 USDC)을 예치하게 합니다.
settleAndGetAssertionResult를
호출합니다.
true가 반환되면 Nostra는 승자에게 지급을 처리합니다.
disputeAssertion을 호출합니다. 이 경우 판결은
UMA의 데이터 검증 메커니즘(DVM)으로 넘어갑니다.UMA 토큰은 DVM(데이터 검증 메커니즘) 작동에 필수적입니다:
낙관적 모델은 누군가 지켜보고 있을 때만 작동합니다. Nostra는 모든 활성 주장을 모니터링하는 감시견 봇을 운영(또는 장려)해야 합니다. 악의적인 사용자가 거짓 결과를 주장하면, 봇은 이를 감지하고 이의를 제기하여 시장 참여자를 보호해야 합니다.
체인링크를 통합하려면 다음 단계가 필요합니다:
| 제품 | 사용 사례 | 적합한 대상 | 비용 |
|---|---|---|---|
| Data Feeds | 가격 데이터 (BTC, ETH, 주식) | "BTC가 K를 넘을까?" | 무료 |
| Functions | 커스텀 API 호출 | 스포츠 점수, 선거 결과 | 요청당 ~0.25 LINK |
| Automation | 예약/조건부 실행 | 마감 시 자동 해결 | 실행당 ~0.1 LINK |
| VRF | 검증 가능한 무작위성 | 복권 스타일 시장 | 요청당 ~0.25 LINK |
암호화폐, 원자재, 외환을 위한 실시간 위변조 방지 가격 데이터.
노드 → 집계 → 온체인
↓
컨트랙트가 가격 읽기
↓
비교 → 해결
모든 API에서 데이터를 가져오기 위해 커스텀 자바스크립트 실행.
컨트랙트 → 요청 → DON
↓
자바스크립트 실행
↓
API 조회 → 반환
일정이나 조건에 따라 컨트랙트 함수 자동 호출.
Upkeep 등록 → 모니터링
↓
조건 충족?
↓
performUpkeep()
관리자가 수동으로 승자 결정
데이터 기반 자동 해결
// FunctionsClient.sol (우리 마켓 컨트랙트가 상속) import { FunctionsClient } from "@chainlink/.../FunctionsClient.sol"; import { FunctionsRequest } from "@chainlink/.../FunctionsRequest.sol"; contract NostraMarket is FunctionsClient { using FunctionsRequest for FunctionsRequest.Request; address router = 0x...; // 체인링크 라우터 (오라클 컨트랙트) bytes32 donId = 0x...; // DON ID (네트워크 식별자) uint64 subscriptionId = 1234; // 내 구독 ID (결제 계정) // 이 함수가 체인링크 라우터 컨트랙트를 호출합니다 function resolveMarket() external { // 1. 요청서 작성 (JavaScript 로직 포함) FunctionsRequest.Request memory req; req.initializeRequestForInlineJavaScript("const apiResponse = await Functions.makeHttpRequest(...)"); // 2. 체인링크 라우터로 전송 (그림의 Step 1 화살표) bytes32 requestId = _sendRequest( req.encodeCBOR(), subscriptionId, gasLimit, donId ); // 3. 요청 ID 저장 (나증에 검증용) pendingRequests[requestId] = true; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.19; import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol"; contract PriceFeedResolver { AggregatorV3Interface internal priceFeed; IConditionalTokens public ctf; struct PriceMarket { bytes32 questionId; uint256 threshold; // 8자리 소수점 가격 임계값 bool resolveAbove; // true = 가격 > 임계값이면 YES 승리 uint256 deadline; bool resolved; } mapping(bytes32 => PriceMarket) public markets; function resolveMarket(bytes32 questionId) external { PriceMarket storage market = markets[questionId]; require("이미 해결됨"); require(block.timestamp >= market.deadline, "너무 이름"); // 체인링크에서 최신 가격 가져오기 (, int256 price, , , ) = priceFeed.latestRoundData(); // 승자 결정 bool yesWins = market.resolveAbove ? price > int256(market.threshold) : price < int256(market.threshold); // CTF에 배당 보고 uint256[] memory payouts = new uint256[](2); payouts[0] = yesWins ? 1 : 0; // YES 결과 payouts[1] = yesWins ? 0 : 1; // NO 결과 ctf.reportPayouts(questionId, payouts); market.resolved = true; } }
// 이 코드는 Chainlink Functions DON에서 실행됩니다 const apiEndpoint = args[0]; // 예: "https://api.sportsdata.io/..."\ const jsonPath = args[1]; // 예: "Games[0].Winner" const response = await Functions.makeHttpRequest({ url: apiEndpoint, headers: { "Ocp-Apim-Subscription-Key": secrets.apiKey } }); if (response.error) { throw Error("API 요청 실패"); } // JSON 경로 탐색 및 결과 반환 const homeTeamWins = result === "HomeTeam" ? 1 : 0; return Functions.encodeUint256(homeTeamWins);
LINK: 0x84b9B910527Ad5C03A9Ca831909E21e236EA7b06 BTC/USD: 0x5741306c21795FdCBb9b265Ea0255F499DFe515C ETH/USD: 0x143db3CEEfbdfe5631aDD3E50f7614B6ba708BA7 BNB/USD: 0x2514895c72f50D8bd4B4F9b1110F0D6bD2c97526
Functions Router: 0xC22a79eBA640940ABB6dF0f7982cc119578E11De BTC/USD: 0xe7656e23fE8077D438aEfbec2fAbDf2D8e070C4f ETH/USD: 0xF0d50568e3A7e8259E16663972b11910F89BD8e7
| 컴포넌트 | 사용당 비용 | 월간 (100개 시장) |
|---|---|---|
| Data Feeds (읽기) | 무료 | /opt/homebrew/bin/zsh |
| Functions 요청 | ~0.25 LINK | 25 LINK (~) |
| Automation 확인 | ~0.01 LINK | 30 LINK (~) |
| Automation 실행 | ~0.1 LINK | 10 LINK (~) |
| 합계 | ~65 LINK (~) |
예측 시장은 빈번한 상호작용(구매, 판매, 청구)을 필요로 합니다. 가스비는 $0.01 미만이어야 합니다.
USDC 유동성이 존재하는 체인에 배포하면 사용자 온보딩 마찰을 줄일 수 있습니다.
기존 도구, 지갑(MetaMask), 체인링크 서비스를 지원하기 위해 필수적입니다.
트레이딩은 즉각적인 반응이 필수입니다. UX를 위해 2초 미만의 블록 타임(Polygon/BSC/Monad)이 선호됩니다.
우리는 시장 컨트랙트를 여러 체인에 동시에 배포해서는 안 됩니다. 예측 시장은 유동성 깊이에 크게 의존합니다.
최적의 UX를 제공하기 위해, 우리 서버는 사용자 작업을 배치 처리(Batch Processing)할 가능성이 높습니다 (예: 50개의 주문을 하나의 트랜잭션으로 매칭). 이렇게 하면 사용자에게 즉각적인 확인과 가스비 없는 경험을 제공할 수 있지만, 가스비는 플랫폼의 직접적인 운영 비용이 됩니다.
| 시나리오 | Polygon/BSC 비용 (~15원) | Arbitrum/Op 비용 (~200원) | 영향 |
|---|---|---|---|
| 1회 단일 거래 | 15원 ($0.01) | 200원 ($0.15) | 감당 가능 |
| 일일 배치 (10,000건) | 15만 원 / 일 ($100) | 200만 원 / 일 ($1,500) | 치명적인 차이 |
| 월간 비용 | 450만 원 ($3,000) | 6,000만 원 ($45,000) | 사업 지속성 위험 |
결론: 만약 우리가 가스비를 대납하거나 배치 프로세서를 운영한다면, Arbitrum과 같은 L2는 현재 규모에서 너무 비쌉니다. 경제적 생존을 위해 Polygon 또는 BSC는 필수입니다.
| 카테고리 | 네트워크 | 가스비 (Gas Fee) | 평균 블록 시간 | 파이널리티 (Finality) | 장점 | 단점 | 결론 |
|---|---|---|---|---|---|---|---|
| L1 / 사이드체인 | BNB Smart Chain (BSC) | 0.05 Gwei (약 15원) | 450ms (0.45초) | 확률적 (15 블록 × 0.45초 ≈ 7초) |
|
다소 중앙화된 검증자 세트 | 최고의 선택 |
| Polygon PoS | ~ $0.001 (약 1.5원) | ~ 2.1초 | 확률적 (~128 블록 × 2.1초 ≈ 5분) |
|
재구성(Reorg) 위험 (현재는 드묾) | 강력한 대안 | |
| 이더리움 (L1) | $2.00 - $50.00+ | ~ 12초 | 안전: ~12분 (2 에폭) |
|
|
정산 전용 | |
| 솔라나 (Solana) | ~ $0.00025 (약 0.3원) | ~ 400ms | 빠름 (~12초 확정) |
|
|
호환 불가 | |
| Monad | < $0.001 (약 1원 미만) | 1.0초 | 즉시 (1 블록 × 1초 = 1초) |
|
|
미래의 강자 | |
| Monero (XMR) | 낮음 | ~ 2분 | 느림 (10 블록 × 2분 ≈ 20분) |
|
|
호환 불가 | |
| Zcash (ZEC) | 낮음 | ~ 75초 | 느림 (24 블록 × 75초 ≈ 30분) |
|
|
호환 불가 | |
| 레이어 2 | Base | < $0.01 (약 15원 미만) | 즉시 (~2초) |
|
새로운 생태계 | 대안 | |
| Arbitrum One | ~ $0.10 (약 150원) | 즉시 (~0.25초) |
|
Polygon/BSC보다 약간 높은 수수료 | 대안 | ||
| zkSync Era | ~ $0.05 (약 70원) | 즉시 (~1초) |
|
생태계 파편화 | 좋은 대안 | ||
| Lighter | 낮음 | 즉시 |
|
|
호환 불가 |
Polygon은 낮은 수수료 덕분에 여전히 실행 가능한 백업이지만, BSC의 압도적인 퍼포먼스와 전략적 생태계 연계는 Nostra를 위한 최적의 런치패드가 됩니다.
Polygon과 BSC 모두 EVM (이더리움 가상 머신)과 완벽하게 호환되므로, 코드 분기에 대한 위험이 없습니다.
사용자들은 이더리움 메인넷, Optimism, Arbitrum 등에 자금을 가지고 있습니다. 복잡한 서드파티 브릿지를 사용하여 특정 체인으로 수동으로 브릿징하도록 강요하고 싶지 않습니다.
CCIP를 사용하면 지원되는 어느 체인에서든 입금을 받고 이를 우리의 특정 시장 구현으로 라우팅할 수 있습니다.
Nostra는 시장 생성자가 블록체인과 직접 상호작용하는 복잡성을 추상화합니다. 사용자가 "배치 생성 시작 (Start Batch Creation)" 버튼을 클릭하면, 서버가 모든 온체인 작업을 비동기적으로 처리합니다.
| 단계 | 동작 | 상태 메시지 |
|---|---|---|
| 1. 초기화 | 프로세서가 작업을 가져옴 | "Job started processing" |
| 2. createBinaryMarket | 각 결과에 대해 스마트 컨트랙트 호출 | "Creating market X/Y: [Name]" |
| 3. 영속성 | 그룹/마켓 정보를 PostgreSQL에 저장 | "Saving to database..." |
| 4. 유동성 | 담보 민팅 및 `splitPosition` 호출 | "Minting collateral for market inventory..." |
| 5. 시딩 | 초기 지정가 주문 배치 | "Seeding initial liquidity..." |
시장이 즉시 거래 가능하도록 보장하기 위해, 서버 지갑(Server Wallet)이 초기 유동성 공급자 역할을 수행합니다. 이는 다음과 같은 구체적인 토큰 전송 순서를 포함합니다:
splitPosition() 호출사용자들은 종종 당첨금 청구 시 지갑 확인이 두 번 필요한 이유를 묻습니다. 이는 조건부 토큰 프레임워크 (CTF)와 Nostra 거래소 컨트랙트 간의 아키텍처적 분리 때문입니다.
contract.redeemPositions(...)
exchange.deposit(...)
자주 묻는 질문 중 하나는 "왜 상환(Redemption) 단계에서 자금을 거래소로 자동 전송할 수 없는가?"입니다.
우리는 지속적인 거래를 최우선으로 합니다. 자동 입금을 통해 사용자가 당첨금을 재사용하기 위해 별도의 "입금" 페이지로 이동할 필요가 없게 합니다. 두 번째 확인은 자금이 다음 베팅을 위해 즉시 준비되도록 보장합니다.