Разработка системы Oracle-based pricing для perpetuals
Perpetual DEX без правильного oracle pricing — это минное поле. GMX, dYdX, Synthetix — все они использовали oracle price для mark price контрактов, что принципиально отличается от spot order book ценообразования. Правильный oracle механизм определяет, можно ли манипулировать протоколом и насколько справедливы ликвидации.
Mark Price vs Index Price vs Oracle Price
Index Price: агрегированная цена с крупных централизованных бирж (Binance, OKX, Coinbase). Представляет "справедливую" рыночную цену.
Mark Price: цена используемая для расчёта unrealized PnL и определения ликвидаций. На perp DEX обычно = Oracle Price. Не может существенно отклоняться от Index Price (если отклоняется — funding rate это корректирует).
Oracle Price: конкретный смарт-контракт из которого читается цена.
Последствия неправильного oracle: если mark price отклоняется от справедливой цены — возможны unfair liquidations (ликвидация здоровой позиции при временном spike оракула) или oracle manipulation attacks.
Oracle выбор для perpetual DEX
GMX v1 подход: Chainlink + Keeper Network
GMX v1 использует Chainlink price feeds как primary и fast price feed (от GMX-specific keepers) как secondary для low-latency исполнения.
Проблема fast price: keepers могут быть атакованы или откажут. GMX имел spread control: если fast price отклоняется от Chainlink более чем на X% — используется только Chainlink.
GMX v2 подход: Chainlink Low-Latency
GMX v2 интегрировал Chainlink Data Streams — off-chain price reports подписанные Chainlink nodes, верифицируемые on-chain. Sub-second свежесть при криптографической надёжности.
// GMX v2 style oracle verification
function getValidatedPrice(
bytes memory signedReport // от Chainlink Data Streams
) internal returns (uint256 price) {
// Верификация Chainlink signature
(bool isValid, int192 signedPrice) =
IChainlinkDataStreamsVerifier(verifier).verify(signedReport);
require(isValid, "Invalid oracle report");
price = uint256(uint192(signedPrice));
require(price > 0, "Invalid price");
// Check against secondary oracle
uint256 secondaryPrice = getSecondaryPrice();
uint256 deviation = abs(price - secondaryPrice) * 10000 / secondaryPrice;
require(deviation < MAX_DEVIATION_BPS, "Oracle price deviation too large");
}
dYdX v4 подход: Cosmos-native oracle
dYdX v4 — appchain на Cosmos. Validators сами запускают oracle software и публикуют цены как часть блок-валидации. Decentralized на уровне consensus.
Защита от oracle manipulation
Spread-based protection
При крупном отклонении оракула от previous price — активировать защиту:
mapping(bytes32 => uint256) public lastOraclePrice;
function updateOraclePrice(bytes32 assetId, uint256 newPrice) internal {
uint256 lastPrice = lastOraclePrice[assetId];
if (lastPrice > 0) {
uint256 deviation = newPrice > lastPrice
? (newPrice - lastPrice) * 10000 / lastPrice
: (lastPrice - newPrice) * 10000 / lastPrice;
// Circuit breaker при слишком резком движении
if (deviation > MAX_PRICE_DEVIATION) {
emit PriceDeviationAlert(assetId, lastPrice, newPrice);
// Использовать защищённую цену вместо спайка
newPrice = lastPrice * (10000 + MAX_PRICE_DEVIATION) / 10000;
}
}
lastOraclePrice[assetId] = newPrice;
}
Multi-source validation
Читать цены из нескольких источников (Chainlink + Pyth + on-chain TWAP), брать медиану:
function getAggregatedPrice(bytes32 asset) public view returns (uint256) {
uint256[] memory prices = new uint256[](3);
prices[0] = getChainlinkPrice(asset);
prices[1] = getPythPrice(asset);
prices[2] = getUniswapTWAP(asset, 30 minutes);
return median(prices);
}
Если одна из цен сильно отличается от остальных — она выкидывается как outlier.
TWAP для ликвидаций
Для определения ликвидационного порога — использовать TWAP (Time-Weighted Average Price) за последние 15-30 минут, не spot price. Flash crash не триггерит массовые ликвидации.
| Операция | Рекомендуемый oracle |
|---|---|
| Открытие/закрытие позиции | Spot oracle (Chainlink/Pyth) |
| Unrealized PnL расчёт | Mark price (oracle) |
| Liquidation check | TWAP (15-30 min) |
| Funding rate расчёт | Index price (CEX aggregate) |
Funding Rate через оракул
Funding rate = механизм якорения perp цены к spot. Вычисляется на основе отклонения mark price от index price.
Oracle должен предоставлять index price надёжно — именно для этого расчёта. Ошибки в index price → неправильный funding rate → incentives для арбитражников нарушены.
Разработка oracle системы для perp DEX — 4-8 недель. Это критический компонент: большинство крупных атак на perp DEX (GMX, Synthetix) были именно oracle manipulation атаками.







