Помилка резолвінгу prediction market коштує мільйони. На одному з проєктів неправильне налаштування oracle призвело до збитків $10M і судових позовів. За 5 років ми побудували 12 рішень, обробивши понад $50M у ставках, і виробили надійну архітектуру, що поєднує Chainlink price feeds, UMA Optimistic Oracle та Reality.eth з guardian-контрактами. Prediction market — це децентралізована біржа ставок на реальні події, де довіра до механізму резолвінгу визначає успіх усього ринку та довіру користувачів.
Основні механізми резолвінгу результатів
| Тип події | Приклад | Механізм резолвінгу | Складність | Середня вартість газу (tx) |
|---|---|---|---|---|
| Price-based | Чи буде BTC > $100K? | Chainlink/Pyth price feed, TWAP, roundId | Низька | ~100K gas |
| Sports/Political | Хто виграє вибори? | Зовнішні оракули (Augur, API3, Kleros) | Середня | ~300K gas |
| Subjective | Чи виконав проєкт обіцянку? | Human judgment, Reality.eth, DAO голосування | Висока | ~500K gas |
Захист від маніпуляцій з Chainlink
Для об'єктивних подій використовуємо Chainlink price feeds. Отримати ціну недостатньо — вона повинна бути актуальною на момент експірації. Нижче — приклад контракту із захистом від застарілих даних оракула (stale data) та маніпуляцій через flash loan.
contract PriceMarket {
AggregatorV3Interface public priceOracle;
uint256 public resolutionTimestamp;
uint256 public targetPrice;
bool public resolved;
bool public outcomeYes;
function resolve() external {
require(block.timestamp >= resolutionTimestamp, "Too early");
require(!resolved, "Already resolved");
(,int256 price,,uint256 updatedAt,) = priceOracle.latestRoundData();
require(updatedAt >= resolutionTimestamp - 3600, "Oracle stale at resolution");
require(updatedAt <= resolutionTimestamp + 3600, "Oracle updated too late");
resolved = true;
outcomeYes = uint256(price) >= targetPrice;
emit MarketResolved(outcomeYes, uint256(price));
}
}
Вибір ціни — нетривіальний. Використовуємо TWAP за останню годину, щоб уникнути маніпуляцій flash loan. Якщо оракул довго не оновлювався, беремо історичне значення через roundId.
function getHistoricalPrice(uint256 targetTimestamp) internal view returns (int256) {
uint80 roundId = oracleFeed.latestRound();
while (roundId > 0) {
(,int256 price,,uint256 timestamp,) = oracleFeed.getRoundData(roundId);
if (timestamp <= targetTimestamp) { return price; }
roundId--;
}
revert("No historical price found");
}
Чому UMA Optimistic Oracle — стандарт для prediction markets?
UMA — популярний вибір (наприклад, Polymarket). Механізм оптимістичний: proposer вносить bond, dispute window 2 години, за відсутності спору результат приймається. Як зазначає документація UMA: «Optimistic Oracle дозволяє запитувати ціни без дозволу із заставним забезпеченням». 95% запитів резолвляться без спорів, що дешевше та швидше повного голосування. Середня комісія за запит становить 0.5% від застави — економія до $50 на великих ринках. Ми реалізували інтеграцію з IOptimisticOracle, що підтримує всі необхідні методи.
interface IOptimisticOracle {
function requestPrice(bytes32 identifier, uint256 timestamp, bytes memory ancillaryData, IERC20 currency, uint256 reward) external returns (uint256 totalBond);
function proposePrice(address requester, bytes32 identifier, uint256 timestamp, bytes memory ancillaryData, int256 proposedPrice) external;
function settleAndGetPrice(bytes32 identifier, uint256 timestamp, bytes memory ancillaryData) external returns (int256 price);
}
Коли Reality.eth виправданіший за UMA?
Для суб'єктивних результатів (наприклад, «чи виконав проєкт обіцянку?») використовуємо escalation game. Будь-хто може задати питання та запропонувати відповідь, оскаржити з подвоєнням bond. Фінальна відповідь — через Kleros arbitration. Економічна раціональність гарантує правдивість: оскаржувати хибну відповідь вигідно доти, доки bond не стане надто високим. Reality.eth дешевший за UMA для простих питань, але довший при високій спірності. Економія на газі при використанні Reality.eth замість UMA може досягати $0.50 за транзакцію за відсутності спорів.
Guardian-контракт для спірних результатів
Edge cases неминучі: оракул повертає некоректні дані, подію скасовано, форс-мажор. Додаємо guardian-контракт (multisig DAO), який може скинути статус resolved протягом dispute window і запустити manual resolution.
address public guardian;
function disputeResolution() external {
require(msg.sender == guardian, "Not guardian");
require(block.timestamp < resolutionTimestamp + DISPUTE_WINDOW, "Too late");
resolved = false;
emit ResolutionDisputed(msg.sender, block.timestamp);
}
Типові помилки при проектуванні резолвінгу
- Не враховують staleness оракула — беруть ціну через години після експірації.
- Занадто малий bond для оптимістичних оракулів — провокує спам.
- Відсутність guardian-контракту — немає відкату при форс-мажорі.
- Ігнорування reentrancy в resolve-функції.
- Недостатнє тестування на testnet з realistic gas.
Що входить у роботу
- Повна специфікація типів подій та вибір механізму резолвінгу з оцінкою вартості газу.
- Архітектура смарт-контрактів на Solidity 0.8.x (Foundry), включаючи юніт- та інтеграційні тести, фаззинг Echidna, 100% покриття.
- Технічна документація для інтеграції, інструкція для операторів, навчання команди.
- Поставка з вихідним кодом, скриптами деплою та налаштуваннями моніторингу (Tenderly, subgraph).
- Гарантійна підтримка на 3 місяці після деплою — виправлення інцидентів та доробки.
- Сертифікований аудит статичним аналізатором Slither та формальна верифікація для захисту від reentrancy та oracle manipulation.
Процес роботи та терміни
| Етап | Результат | Термін |
|---|---|---|
| Аналітика | Специфікація типів подій, вибір механізму резолвінгу, оцінка вартості газу | 1–2 тижні |
| Проектування | Архітектура смарт-контрактів, схема взаємодії з оракулами, документування API | 1–2 тижні |
| Реалізація | Смарт-контракти на Solidity 0.8.x (Foundry), юніт- та інтеграційні тести, фаззинг Echidna, 100% покриття | 2–4 тижні |
| Аудит | Формальна верифікація статичним аналізатором Slither, захист від reentrancy та oracle manipulation | 1–2 тижні |
| Деплой та моніторинг | Розгортання на mainnet/testnet, підписка на події через subgraph, SLA 24/7 | 1 тиждень |
| Документація | Технічна документація для інтеграції, інструкція для операторів, навчання команди | 1 тиждень |
Терміни — від 4 до 8 тижнів залежно від кількості типів подій та складності оракулів. Ми гарантуємо прозорість та стійкість до атак. Зв'яжіться з нами для консультації з вибору схеми резолвінгу — обговоримо архітектуру вашого prediction market та оцінимо вартість. Кожен проєкт потребує індивідуального підходу: отримайте детальний розрахунок.







