Ошибка резолвинга 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 и оценим стоимость. Каждый проект требует индивидуального подхода: получите детальный расчёт.







