Мы разрабатываем децентрализованные системы ставок на блокчейне: от простых тотализаторов до полноценных CLOB-маркетов с conditional tokens. Polymarket уже обрабатывает сотни миллионов долларов в объёме ставок на политические события через Polygon с USDC в качестве расчётной валюты — и вся эта система держится на смарт-контрактах с условным исходом. Ключевой вызов при построении любой такой платформы — не механизм приёма ставок, а детерминированная и безопасная резолюция исходов. Наш опыт — более 30 реализованных контрактов в продакшене на Ethereum, Polygon и Arbitrum.
Оракульный вопрос — центральный инженерный вызов
Исход события «Байден выиграет выборы» нельзя получить из Chainlink Price Feed. Это не числовое значение с децентрализованным консенсусом — это суждение. Для систем предсказаний это означает один из нескольких подходов к резолюции.
UMA Optimistic Oracle
UMA использует optimistic модель: любой может предложить исход, другой участник оспорить. Оспаривание запускает dispute resolution через голосование держателей UMA. Экономическая безопасность держится на bond: предлагающий вносит залог USDC или UMA, который теряет при неверной резолюции. UMA Optimistic Oracle обеспечивает безопасность через экономические стимулы — как описано в официальной документации.
Интеграция с UMA:
import "@uma/core/contracts/optimistic-oracle-v3/interfaces/OptimisticOracleV3Interface.sol";
contract EventBettingMarket {
OptimisticOracleV3Interface immutable oracle;
bytes32 public assertionId;
function resolveMarket(bytes memory claim) external {
assertionId = oracle.assertTruth(
claim,
address(this),
address(0),
address(0),
7200,
IERC20(currency),
bond,
identifier,
bytes32(0)
);
}
function assertionResolvedCallback(bytes32 _assertionId, bool assertedTruthfully) external {
require(msg.sender == address(oracle));
if (assertedTruthfully) {
_settleWinners();
} else {
_refundBettors();
}
}
}
Преимущество UMA: дёшево для большинства рынков (никакого голосования при отсутствии dispute), но медленнее Chainlink в 10 раз при оспаривании.
Chainlink для числовых исходов
Отметим: когда исход числовой, Chainlink AggregatorV3Interface — правильный выбор: детерминированный, без dispute window.
function resolveNumericMarket() external {
(, int256 price, , uint256 updatedAt, ) = priceFeed.latestRoundData();
require(updatedAt >= marketEndTime, "Price data too old");
require(block.timestamp >= marketEndTime, "Market not ended");
bool outcomeA = price >= int256(targetPrice);
_settleMarket(outcomeA);
}
Критическая проблема: Chainlink апдейтит данные по deviation threshold или heartbeat — не на конкретную секунду. Нужно явно проверять updatedAt и иметь fallback на Pyth или UMA.
Мультиоракульный подход для продакшн
Для критически важных рынков с объёмами от $1M — агрегация нескольких источников:
| Оракул | Тип исхода | Latency | Стоимость |
|---|---|---|---|
| Chainlink | Числовой (price) | ~1 час | Низкая |
| Pyth Network | Числовой (price) | Секунды | Низкая |
| UMA Optimistic | Произвольный | 2+ часа | Средняя |
| API3 dAPI | Числовой (первый класс данных) | Минуты | Низкая |
| Кастомный multisig | Любой | Мгновенно | 0 (доверие) |
Для спортивных результатов оптимален UMA + резервный multisig с timelock — как последняя линия.
Как выбрать модель распределения выигрыша?
Fixed odds — устарела для DeFi
Коэффициенты фиксируются при создании рынка. Букмекер несёт риск при неправильной оценке. Сложно реализовать on-chain без централизованной переоценки.
Parimutuel — стандарт для блокчейн-ставок
Все ставки попадают в пул. Выигравшие делят пул пропорционально. Коэффициент определяется итоговым распределением. Parimutuel дешевле CLOB в 2-3 раза по газу на операцию.
mapping(uint8 => uint256) public totalBets;
mapping(address => mapping(uint8 => uint256)) public userBets;
function claimWinnings(uint8 outcome) external {
require(resolvedOutcome == outcome, "Wrong outcome");
uint256 userBet = userBets[msg.sender][outcome];
require(userBet > 0, "No bet");
uint256 totalPool = totalBets[0] + totalBets[1];
uint256 protocolFee = totalPool * feeBps / 10000;
uint256 winnerPool = totalPool - protocolFee;
uint256 payout = (userBet * winnerPool) / totalBets[outcome];
userBets[msg.sender][outcome] = 0;
IERC20(currency).transfer(msg.sender, payout);
}
CLOB — продвинутый подход
Polymarket использует conditional tokens (ERC-1155). Каждый исход — токен, рынок торгуется через CLOB с лимитными ордерами. Преимущество: настоящий price discovery, ликвидность агрегируется. Сложность: off-chain orderbook + on-chain settlement.
| Характеристика | Parimutuel | CLOB |
|---|---|---|
| Price discovery | Нет (коэффициенты после пула) | Да (реальный рынок) |
| Ликвидность | Один пул | Агрегация ордеров |
| Сложность контрактов | Низкая | Высокая (matching engine) |
| Газ на одну ставку | 50k–100k gas | 150k–300k gas |
Как защитить ставки от front-running?
Используем commit-reveal scheme: сначала хеш ставки, через N блоков раскрытие. Для спортивных ставок — блокировка за 5 минут до старта через endBettingTime = eventStartTime - 5 minutes. Это предотвращает манипуляции с последней секундой.
Почему UMA Optimistic Oracle лучше для спортивных исходов?
UMA поддерживает произвольные утверждения, что идеально для спорта и политики. Chainlink Price Feed даёт только числовые данные. UMA дешевле для рынков без споров, а bond защищает от нечестных резолюций. Средняя стоимость разрешения — $50-$200 при отсутствии dispute.
Создание и управление рынком: Factory pattern
Каждый рынок — отдельный контракт, деплоированный через фабрику. Это изолирует риски.
contract MarketFactory {
mapping(bytes32 => address) public markets;
function createMarket(
string calldata question,
uint256 endTime,
address oracle,
bytes calldata oracleData
) external returns (address marketAddress) {
bytes32 marketId = keccak256(abi.encode(question, endTime, oracle));
require(markets[marketId] == address(0), "Market exists");
BettingMarket market = new BettingMarket(
question, endTime, oracle, oracleData, feeBps
);
markets[marketId] = address(market);
emit MarketCreated(marketId, address(market), question, endTime);
return address(market);
}
}
Emergency pause и refund
Если оракул не может резолвировать исход (событие отменено), emergency admin (multisig) вызывает cancelMarket(), все участники забирают депозиты. Timelock на отмену — минимум 24 часа.
Стек разработки
Контракты: Solidity 0.8.24 + OpenZeppelin (AccessControl, Pausable, ReentrancyGuard) + Foundry для тестирования. Тесты включают fork-тест с реальным UMA и Chainlink на Polygon mainnet. Для conditional tokens — Gnosis Conditional Tokens Framework. Off-chain: The Graph субграф, GraphQL API.
Процесс работы
- Аналитика (2–3 дня). Тип событий, модель выигрыша, оракулы, compliance, чейны.
- Проектирование (3–5 дней). Архитектура контрактов, интеграция, резолюция, emergency.
- Разработка (3–8 недель). От parimutuel MVP до CLOB с conditional tokens.
- Аудит. Ставочные контракты — высокоприоритетный аудит из-за управления деньгами. Стоимость аудита от $15,000 в зависимости от сложности.
Ориентиры по срокам
- Parimutuel с Chainlink — 1–2 недели (бюджет от $5,000).
- UMA + Factory + The Graph — 6–10 недель.
- CLOB с conditional tokens — 3–5 месяцев (от $50,000).
Что входит в результат
- Исходный код контрактов с полным покрытием тестами (Foundry).
- Интеграция с выбранными оракулами (Chainlink, UMA, Pyth).
- Документация API и субграф The Graph.
- Отчёт аудита от партнёров (HashEx или Certik).
- Обучение вашей команды и поддержка 3 месяца.
Мультиоракульный подход с комбинированием Chainlink (числовые данные) и UMA (исходы) снижает вероятность ошибочной резолюции до 0.01%. Свяжитесь для консультации — оценим ваш проект за 2 дня. Закажите разработку системы ставок на блокчейне и получите демо-доступ к нашим контрактам.







