Інтеграція з MEV Blocker

Проєктуємо та розробляємо блокчейн-рішення повного циклу: від архітектури смарт-контрактів до запуску DeFi-протоколів, NFT-маркетплейсів та криптобірж. Аудит безпеки, токеноміка, інтеграція з наявною інфраструктурою.
Показано 1 з 1Усі 1306 послуг
Інтеграція з MEV Blocker
Простий
~1 день
Часті запитання

Напрямки блокчейн-розробки

Етапи блокчейн-розробки

Останні роботи

  • image_website-b2b-advance_0.webp
    Розробка сайту компанії B2B ADVANCE
    1306
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1218
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    920
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1147
  • image_logo-advance_0.webp
    Розробка логотипу компанії B2B Advance
    610
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    885

Розробка системи захисту від flash loan атак

Flash loan—це необеспечений займ, який повинен бути повернений в тій же транзакції. Якщо не повернений—вся транзакція реверсується. З точки зору протоколу, що видає flash loan (Aave, Uniswap V3), це безрисикова операція: або гроші повернулися, або транзакція не сталася.

Проблема не у flash loan як таких—це легітимний інструмент для арбітражу, ліквідацій, рефінансування. Проблема в тому, що вони дають зловмиснику тимчасовий доступ до величезного капіталу (сотень мільйонів доларів) без забезпечення. Якщо протокол приймає економічні рішення на основі легко маніпулюючих даних (spot price DEX, не-TWAP oracle)—одна транзакція з flash loan може принести зловмиснику мільйони.

Beanstalk ($182M, 2022), Cream Finance ($130M, 2021), Mango Markets ($114M, 2022)—усі взломи використовували тимчасовий контроль над капіталом. Спільна ознака: протоколи використовували дані, які можна було зсунути однією транзакцією.

Анатомія flash loan атаки

Розуміння вектора атаки необхідне для побудови захисту. Типова атака складається з чотирьох кроків:

1. Взяти flash loan (наприклад, 100M USDC від Aave)
2. Маніпулювати станом (pump/dump ціни в DEX пулі)
3. Експлойтити протокол (який читає маніпульовані дані)
4. Повернути flash loan + fee, залишити прибуток

Конкретний приклад—маніпуляція цінового оракула:

1. Flash loan: 50M DAI
2. Dump DAI в Uniswap V2 пулі DAI/ETH (spot price DAI падає)
3. Виклик протоколу, який читає Uniswap V2 spot price для оцінки collateral
   → Collateral у DAI тепер «дешевше», можна отримати знижку на ліквідацію
   або оцінити борг у DAI як менший
4. Прибуток → повернути flash loan

Інший тип—governance flash loan:

1. Flash loan governance токенів
2. Моментальне створення пропозала + голосування з величезною вагою
3. Виконання пропозала (drain treasury)
4. Повернення flash loan

(Саме так був атакований Beanstalk—зловмисник однією governance голосом прийняв пропозал про переведення treasury собі.)

Захист 1: Price Oracle—TWAP замість Spot

Це найпоширеніший та найкритичніший захист.

Чому Spot Price вразливий

Uniswap V2/V3 spot price = поточне співвідношення резервів. Великий swap у пулі миттєво змінює spot price. В одній транзакції можна зсунути ціну на 50–80% у пулі з помірною ліквідністю.

TWAP (Time-Weighted Average Price)

TWAP—середнє арифметичне ціни за період. Uniswap V2/V3 зберігає cumulative price accumulators, з яких можна обчислити TWAP за довільний період.

contract TWAPOracle {
    IUniswapV3Pool public pool;
    uint32 public constant TWAP_PERIOD = 30 minutes;
    
    function getTWAP() external view returns (uint256 price) {
        uint32[] memory secondsAgos = new uint32[](2);
        secondsAgos[0] = TWAP_PERIOD; // 30 хвилин назад
        secondsAgos[1] = 0;           // зараз
        
        (int56[] memory tickCumulatives,) = pool.observe(secondsAgos);
        
        int56 tickCumulativesDelta = tickCumulatives[1] - tickCumulatives[0];
        int24 arithmeticMeanTick = int24(tickCumulativesDelta / int56(uint56(TWAP_PERIOD)));
        
        // Конвертуємо tick у price
        price = TickMath.getSqrtRatioAtTick(arithmeticMeanTick);
        // ... конвертація sqrtPrice → людиночитаєма
    }
}

Вибір періоду TWAP—критичний параметр. Занадто короткий (1–5 хвилин)—зловмисник з достатнім капіталом може утримувати маніпульовану ціну кілька блоків. Занадто довгий (4–8 годин)—TWAP сильно відстає від ринку в волатильні періоди, викликаючи неправильні ліквідації.

Практика: 30 хвилин—розумний default для більшості DeFi протоколів. Для високовол ватильних активів—1–2 години.

Chainlink як основний oracle

Chainlink price feed—агрегована ціна від множества незалежних вузлів з heartbeat оновленням. Маніпуляція вимагає компрометації більшості oracle nodes—економічно недоцільно.

contract PriceConsumer {
    AggregatorV3Interface public priceFeed;
    uint256 public constant HEARTBEAT = 3600; // 1 година
    uint256 public constant MAX_STALENESS = HEARTBEAT * 2; // 2 години—максимум
    
    function getPrice() external view returns (uint256) {
        (
            uint80 roundId,
            int256 answer,
            ,
            uint256 updatedAt,
            uint80 answeredInRound
        ) = priceFeed.latestRoundData();
        
        // Перевірка staleness: дані не старші за MAX_STALENESS
        require(block.timestamp - updatedAt <= MAX_STALENESS, "Stale price");
        
        // Перевірка правильності раунду
        require(answeredInRound >= roundId, "Stale round");
        
        // Перевірка позитивності ціни
        require(answer > 0, "Invalid price");
        
        return uint256(answer);
    }
}

Загальна рекомендація: використовувати Chainlink як primary oracle, Uniswap TWAP як sanity check. Якщо два джерела розходяться більше ніж на X%—приостановити операції.

Захист 2: Snapshot Voting Power

Governance flash loan атаки використовують той факт, що voting power = поточний баланс токенів. ERC-20Votes вирішує це через checkpoint систему.

// Voting power фіксується на блоці snapshot (до початку голосування)
uint256 votePower = token.getPastVotes(voter, proposalSnapshot);

// Flash loan ПІСЛЯ snapshot не дає voting power
// Flash loan ДО snapshot вимагає утримування borrowed токенів через voting delay

Voting delay—мінімальний період між створенням пропозала та початком голосування. Якщо voting delay = 2 дні, зловмисник повинен утримувати borrowed токени 2 дні—економічно невигідно (fee + opportunity cost).

// OpenZeppelin Governor
constructor(...) GovernorSettings(
    2 days,  // votingDelay—захист від flash loan governance attacks
    5 days,  // votingPeriod
    threshold
) {}

Beanstalk був атакований саме тому, що не використовував voting delay: пропозал можна було створити та виконати в одній транзакції.

Захист 3: Reentrancy Guard та Same-Block Checks

Деякі flash loan атаки експлойтують reentrancy або same-block маніпуляцію стану.

Same-Block Checks

contract Vault {
    mapping(address => uint256) private _depositBlock;
    
    function deposit(uint256 amount) external {
        _depositBlock[msg.sender] = block.number;
        // ...
    }
    
    function withdraw(uint256 amount) external {
        // Не можна deposit та withdraw в одному блоці
        require(
            _depositBlock[msg.sender] < block.number,
            "Flash loan protection: same block"
        );
        // ...
    }
}

Це блокує паттерн: flash_loan → deposit → виклик функції яка читає баланс vault → withdraw → repay_loan.

Недостаток: legitimate користувачі також не можуть deposit+withdraw в одному блоці. Для більшості протоколів це прийнятно.

Nonreentrant + View функції

nonReentrant захищає state-changing функції від reentrancy. Але view функції не захищені—їх можна викликати з середини іншої транзакції.

Якщо view функція використовується зовнішнім протоколом для отримання ціни або TVL—маніпуляція стану через reentrancy змінює те, що бачить ця view функція.

// ВРАЗЛИВО: стан може бути маніпульований через reentrancy
function getSharePrice() external view returns (uint256) {
    return totalAssets() * 1e18 / totalSupply();
}

// totalAssets() читає баланс контракту—який може бути тимчасово надутий
function totalAssets() public view returns (uint256) {
    return IERC20(asset).balanceOf(address(this));
}

Рішення: зберігати cached значення total assets, оновлене тільки в protected функціях.

Захист 4: Circuit Breakers та Rate Limiting

Максимальний обсяг за транзакцію

uint256 public constant MAX_SINGLE_DEPOSIT = 1_000_000e6; // $1M max

function deposit(uint256 amount) external {
    require(amount <= MAX_SINGLE_DEPOSIT, "Exceeds single tx limit");
    // ...
}

Flash loan атаки зазвичай оперують сотнями мільйонів. Обмеження однієї транзакції зменшує максимальну шкоду від будь-якої атаки.

Pause механізм з автотриггером

contract ProtectedProtocol is Pausable {
    uint256 public lastTVL;
    uint256 public constant TVL_DROP_THRESHOLD = 20; // 20% за транзакцію
    
    modifier checkTVLAnomaly() {
        uint256 tvlBefore = totalValueLocked();
        _;
        uint256 tvlAfter = totalValueLocked();
        
        if (tvlBefore > 0) {
            uint256 dropPercent = ((tvlBefore - tvlAfter) * 100) / tvlBefore;
            if (dropPercent > TVL_DROP_THRESHOLD) {
                _pause();
                emit EmergencyPause(tvlBefore, tvlAfter, dropPercent);
            }
        }
    }
}

Circuit breaker: якщо за одну транзакцію TVL падає більше ніж на N%—протокол автоматично паузує. Це не запобігає атаці, але обмежує її масштаб.

Time-weighted Balances

Замість поточного баланса використовуйте time-weighted average balance для критичних розрахунків:

// ERC-20Votes checkpoint підхід застосований до ліквідності
function getTimeWeightedLiquidity(address provider, uint256 lookback) 
    external view returns (uint256) 
{
    // Усереднена ліквідність за lookback період
    // Маніпуляція в одній транзакції мінімально впливає на average
}

On-chain мониторинг

Система захисту неповна без мониторингу. Forta Network—децентралізована detection мережа з ботами, які мониторять on-chain активність.

// Forta бот: детекція потенційної flash loan атаки
async function handleTransaction(txEvent) {
    const findings = [];
    
    // Перевіряємо наявність flash loan calldata у транзакції
    const flashLoanCalls = txEvent.filterFunction([
        'flashLoan(address,address,uint256,bytes)',
        'flash(address,address,uint256,uint256,bytes)'
    ]);
    
    if (flashLoanCalls.length > 0) {
        // Перевіряємо значні зміни стану нашого протоколу
        const protocolEvents = txEvent.filterLog(PROTOCOL_EVENTS, PROTOCOL_ADDRESS);
        
        if (protocolEvents.length > 0) {
            findings.push(Finding.fromObject({
                name: "Flash loan + protocol interaction",
                description: `Flash loan detected in same tx as protocol events`,
                alertId: "FLASH-LOAN-INTERACTION",
                severity: FindingSeverity.Medium,
                type: FindingType.Suspicious
            }));
        }
    }
    
    return findings;
}

Forta алерти можна відправляти в PagerDuty / Telegram через webhook, давши команді 1–2 хвилини на відповідь до розповсюдження атаки.

Комплексна архітектура захисту

Ніщо з заходів окремо недостатньо. Ефективна система захисту—це шари:

Рівень Механізм Захищає від
Oracle Chainlink primary + TWAP sanity Price manipulation
Governance Voting delay (2+ дні) + ERC-20Votes Flash loan governance
State Same-block check на withdraw Deposit-exploit-withdraw
Flow Max per-tx лімити Damage limitation
Circuit breaker Auto-pause при TVL anomaly Early stop на атаку
Monitoring Forta bots Detection та alerting

Розробка повної системи захисту: аудит існуючих oracle залежностей та governance механізмів—1 тиж, розробка protective контрактів—2–3 тиж, інтеграція мониторингу—1 тиж, тести атак у fork environment—2 тиж.

Вартість залежить від складності протоколу та кількості oracle integration точок.