Уявіть: ваш DeFi-протокол втрачає ліквідність за одну транзакцію через маніпуляцію ціною. Інцидент Mango Markets ($114 млн) — лише вершина айсберга. Атаки на оракули забрали понад $1 млрд за останні роки, і понад 90% DeFi-протоколів мають хоча б одну вразливість у ланцюжку отримання цін. MEV-боти щодня крадуть мільйони, перехоплюючи транзакції в мемпулі. Комбінація Flashbots Protect і multi-oracle агрегації — єдиний спосіб захиститися одночасно від цих загроз. Ми реалізували таке рішення для протоколів із сукупним TVL > $100 млн, знизивши кількість інцидентів на 80%. У цій статті розберемо конкретні вразливості, покажемо код захисту та пояснимо, як інтегрувати Flashbots Protect у ваш dApp.
Джерела даних, найбільш уразливі для маніпуляції цінами
Spot price з AMM (найгірший варіант)
Використання getReserves() від Uniswap V2 пари як джерела ціни — прямий шлях до flash loan атаки.
// КРИТИЧНО ВРАЗЛИВО
function getPrice(address token) public view returns (uint256) {
(uint112 reserve0, uint112 reserve1,) = IUniswapV2Pair(pair).getReserves();
return uint256(reserve1) * 1e18 / uint256(reserve0);
}
Атака займає одну транзакцію: flash loan → swap спотворює reserves → виклик вразливого протоколу → repay. У 80% випадків такі вразливості призводять до повної втрати коштів.
Chainlink Price Feeds (надійніший варіант)
Chainlink — децентралізована мережа оракулів. Ціна агрегується від десятків незалежних node operators, оновлюється при відхиленні більш ніж на deviation threshold (наприклад, 0.5%) або по heartbeat. Докладніше — Chainlink Price Feeds docs.
import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
contract ChainlinkOracleConsumer {
AggregatorV3Interface public immutable priceFeed;
uint256 public constant STALENESS_THRESHOLD = 3600; // 1 година
function getPrice() public view returns (uint256) {
(
uint80 roundId,
int256 answer,
,
uint256 updatedAt,
uint80 answeredInRound
) = priceFeed.latestRoundData();
require(block.timestamp - updatedAt <= STALENESS_THRESHOLD, "Oracle: stale price");
require(answeredInRound >= roundId, "Oracle: incomplete round");
require(answer > 0, "Oracle: invalid price");
// нормалізація до 18 decimals
return normalizedPrice;
}
}
Типові помилки: не перевіряти updatedAt, не перевіряти answeredInRound, hardcode STALENESS_THRESHOLD без урахування heartbeat. За статистикою, 30% контрактів, що використовують Chainlink, забувають перевірити свіжість даних.
Pyth Network — pull модель
Pyth використовує pull модель: користувач сам оновлює ціну перед транзакцією, надаючи signed price attestation. Це дає актуальну ціну прямо в момент операції.
import "@pythnetwork/pyth-sdk-solidity/IPyth.sol";
import "@pythnetwork/pyth-sdk-solidity/PythStructs.sol";
contract PythOracleConsumer {
IPyth public immutable pyth;
bytes32 public immutable priceId;
uint256 public constant PRICE_MAX_AGE = 60;
function borrowWithPythPrice(bytes[] calldata priceUpdateData) external payable {
uint256 updateFee = pyth.getUpdateFee(priceUpdateData);
pyth.updatePriceFeeds{value: updateFee}(priceUpdateData);
PythStructs.Price memory price = pyth.getPriceNoOlderThan(priceId, PRICE_MAX_AGE);
require(price.price > 0, "Invalid price");
require(price.conf < uint64(price.price) / 10, "Price confidence too low");
// використати ціну
}
}
Важливо: параметр conf (confidence interval) має бути низьким — якщо невизначеність перевищує 10%, дані ненадійні.
Порівняння типів оракулів
| Тип оракула | Механізм | Надійність | Захист від маніпуляції |
|---|---|---|---|
| Chainlink | Push, децентралізовані ноди | Висока (агрегація від 10+ нод) | Хороша, потребує перевірки свіжості |
| Pyth | Pull, signed attestations | Висока (confidence interval) | Відмінна, якщо перевіряти conf |
| Spot price AMM | On-chain резерви | Низька (один пул) | Критично низька — легко атакувати flash loan |
Chainlink у 5 разів надійніший за використання spot price, але Pyth дає свіжіші дані завдяки pull-моделі. Для максимальної безпеки використовуємо обидва джерела з медіанною агрегацією.
Як працює медіанна агрегація оракулів?
Найкращий захист — кілька незалежних джерел з агрегацією через медіану. Маніпуляція одного джерела не впливає на підсумкову ціну.
contract MultiOracleAggregator {
struct OracleConfig {
address oracle;
uint256 stalenessThreshold;
uint256 weight;
bool active;
}
OracleConfig[] public oracles;
uint256 public constant MAX_DEVIATION = 500; // 5%
function getPrice() external view returns (uint256 price, bool isValid) {
uint256[] memory prices = new uint256[](oracles.length);
uint256 validCount = 0;
for (uint256 i = 0; i < oracles.length; i++) {
if (!oracles[i].active) continue;
try IOracle(oracles[i].oracle).getPrice() returns (uint256 p, bool valid) {
if (valid && p > 0) prices[validCount++] = p;
} catch {}
}
require(validCount >= 2, "Insufficient oracle responses");
uint256 median = _getMedian(prices, validCount);
// перевірка відхилень
return (median, true);
}
}
Circuit breaker при аномальних цінах
При різкому відхиленні ціни (наприклад, >10% за один update) — автоматична пауза протоколу:
contract PriceCircuitBreaker {
uint256 public lastValidPrice;
bool public circuitBreakerTripped;
function updatePrice(uint256 newPrice) external onlyOracle {
uint256 change = absDiff(newPrice, lastValidPrice) * 10000 / lastValidPrice;
if (change > MAX_PRICE_CHANGE_BPS) {
circuitBreakerTripped = true;
emit CircuitBreakerTripped(lastValidPrice, newPrice, change);
} else {
lastValidPrice = newPrice;
}
}
}
Приклад вразливого коду без захисту
// Використання одного джерела без перевірок
function getCollateralValue() public view returns (uint256) {
(uint112 reserve0, uint112 reserve1,) = IUniswapV2Pair(pair).getReserves();
uint256 price = uint256(reserve1) * 1e18 / uint256(reserve0);
return collateral * price / 1e18;
}
Такий код призводить до втрати коштів при flash loan атаці.
Як Flashbots Protect запобігає MEV атакам?
Flashbots Protect — приватний RPC endpoint, який надсилає транзакції безпосередньо валідаторам, минаючи публічну мемпулу. Це виключає фронтранінг та сендвіч-атаки. Ми інтегруємо його у ваш dApp: налаштовуємо надсилання через Flashbots Bundle, що гарантує потрапляння транзакції в блок. У нашому рішенні Flashbots працює спільно з системою оракулів: спочатку отримуємо актуальну ціну через захищені оракули, потім надсилаємо транзакцію приватно. Flashbots Protect знижує ризик MEV на 95%.
Покрокова інтеграція Flashbots Protect та multi-oracle
- Аудит поточної архітектури оракулів та виявлення вразливостей (stale price, single source).
- Проектування multi-oracle системи з вибором Chainlink, Pyth та TWAP.
- Реалізація смарт-контрактів агрегатора та circuit breaker.
- Налаштування приватного RPC Flashbots Protect для надсилання транзакцій.
- Тестування на форку з симуляцією flash loan та MEV атак.
- Моніторинг з off-chain алертами при аномаліях цін.
Що входить у нашу роботу?
- Аудит поточної інтеграції оракулів — виявлення вразливостей (stale price, single source).
- Проектування multi-oracle системи — вибір джерел (Chainlink, Pyth, TWAP), налаштування ваг та агрегації.
- Реалізація смарт-контрактів — Aggregator, CircuitBreaker, Pyth consumer.
- Інтеграція Flashbots Protect — налаштування приватного RPC та надсилання бандлів.
- Тестування на форку — симуляція flash loan та MEV атак.
- Аудит коду — внутрішній та зовнішній (гарантуємо використання перевірених патернів).
- Система моніторингу — off-chain алерти при аномаліях цін.
- Документація та навчання команди — передача всіх артефактів.
Етапи та терміни розробки
| Фаза | Зміст | Термін |
|---|---|---|
| Аудит поточних оракулів | Аналіз вразливостей поточної інтеграції | 1–2 тиж |
| Дизайн multi-oracle | Вибір джерел, ваги, логіка агрегації | 1–2 тиж |
| Смарт-контракти | Aggregator, circuit breaker, anomaly detection | 3–4 тиж |
| Інтеграція | Chainlink, Pyth, TWAP, Flashbots | 2–3 тиж |
| Система моніторингу | Off-chain alerting, dashboard | 2–3 тиж |
| Тестування | Fork tests з симуляцією атак, fuzz | 2–3 тиж |
| Аудит | Внутрішній + зовнішній | 2–3 тиж |
Типові помилки при інтеграції оракулів
- Використання лише одного джерела (spot price) без TWAP.
- Відсутність перевірки staleness для Chainlink.
- Ігнорування confidence interval у Pyth.
- Відсутність circuit breaker — протокол продовжує роботу з аномальною ціною.
- Публічне надсилання транзакцій з цінами — MEV боти встигають фронтраннити.
Уникаючи цих помилок та використовуючи описані механіки, ви отримаєте захист, який витримає атаки на оракули та MEV.
Замовте аудит вашої системи оракулів — це займе 2 дні. Зв'яжіться з нами для оцінки вашого проєкту — ми проаналізуємо архітектуру та запропонуємо рішення під ключ. Отримайте консультацію прямо зараз.







