Захист від MEV за допомогою Jito DontFront
Максимально вилучувана цінність (MEV) — це цінність, яку можна отримати шляхом зміни порядку, включення або виключення транзакцій у блоці. MEV не є унікальним явищем для жодного окремого блокчейну — це фундаментальна властивість будь-якого блокчейну, де виробники блоків контролюють порядок транзакцій. Деякі форми MEV, як-от арбітраж, сприяють ефективності ринків, усуваючи цінові розбіжності між DEX. Інші, зокрема сендвіч-атаки, безпосередньо вилучають цінність у користувачів. Для розробників DeFi-застосунків це може означати гірше виконання угод і втрату прибутку.
Цей посібник зосереджений на сендвіч-атаках — поширеній формі шкідливого MEV — та
способах їх пом'якшення за допомогою функції dontfront від Jito.
Рекомендоване попереднє читання: Jito Bundles
MEV на Solana
Архітектура Solana вже зменшує площу MEV порівняно з блокчейнами з публічними мемпулами. Транзакції пересилаються безпосередньо до майбутнього лідера блоку, а не очікують у спільному мемпулі, а необроблені транзакції закінчуються приблизно після 150 блоків (~1 хвилина). Це суттєво звужує вікно можливостей для пошукачів, які намагаються спостерігати за очікуваними транзакціями та реагувати на них.
Проте вилучення MEV все одно відбувається. Пошукачі з оптимізованою інфраструктурою та прямими підключеннями до validator можуть відстежувати потік транзакцій і реагувати на нього. Більша частина MEV-активності на Solana — це атомарний арбітраж: боти, що виправляють цінові відмінності між DEX в одній транзакції. Цей тип MEV загалом є корисним, оскільки покращує узгодженість цін між ринками.
Шкідливий різновид — сендвіч-атаки — це те, від чого розробники повинні активно захищатися.
Що таке сендвіч-атака?
Сендвіч-атака відбувається, коли пошукач виявляє вашу очікувану транзакцію обміну та експлуатує порядок транзакцій:
- Випередження (Front-run): пошукач купує токен до вашої угоди, підвищуючи ціну
- Ваша угода виконується за гіршою ціною, ніж очікувалося
- Зворотній запуск (Back-run): пошукач продає токен після вашої угоди, привласнюючи різницю
На Solana це може відбуватися через
Jito bundles. Пошукач
подає бандл транзакцій, наприклад:
[frontrun_tx, your_tx, backrun_tx], і рушій блоків виконує їх
атомарно в зазначеному порядку. Жертва отримує гіршу ціну виконання, тоді як
пошукач отримує прибуток зі спреду.
Як працює DontFront
DontFront — це функція рушія блоків Jito, яка запобігає розміщенню пошукачами своїх транзакцій перед вашими у бандлі.
Механізм: додайте будь-який валідний публічний ключ Solana, що починається з jitodontfront,
до будь-якої інструкції у вашій транзакції. Рушій блоків розпізнає цей префікс
та застосовує правило: будь-який бандл, що містить вашу транзакцію, повинен
розмістити її за індексом 0.
Without dontfront: [frontrun_tx, your_tx, backrun_tx] ← sandwich possibleWith dontfront: [your_tx, ...] ← your tx must be first
Покроково
-
Виберіть валідну адресу, що починається з
jitodontfront(наприклад,jitodontfront111111111111111111111111111111). Обліковий запис не повинен існувати в мережі — він ніколи не зчитується та не записується. Ви можете перевірити, чи є рядок валідною адресою, за допомогою функціїassertIsAddressз @solana/kit або ввівши адресу в Solana Explorer, щоб перевірити, чи вона розпізнається. Ось приклад невалідної адреси. -
Додайте її як обліковий запис лише для читання без підпису до будь-якої інструкції у вашій транзакції. Позначте як лише для читання для оптимальної швидкості потрапляння. Більшість програм (включно з System Program) ігнорують зайві облікові записи поза тими, що вони очікують.
-
Надішліть через рушій блоків Jito:
sendTransaction:https://mainnet.block-engine.jito.wtf/api/v1/transactionssendBundle:https://mainnet.block-engine.jito.wtf/api/v1/bundles
Документація: sendTransaction та sendBundle
-
Рушій блоків виявляє префікс
jitodontfrontта застосовує правила впорядкування.
Що відбувається на рівні рушія блоків
Коли рушій блоків виявляє транзакцію, що містить обліковий запис jitodontfront:
- Через
sendTransaction: транзакція захищена. Жоден бандл не може розмістити іншу транзакцію перед нею - Через
sendBundle: транзакція повинна знаходитися за індексом 0, інакше весь бандл відхиляється
Транзакції та бандли, що не містять облікового запису jitodontfront, не
зазнають жодних змін.
Правила впорядкування бандлів
Ці правила застосовуються, коли транзакція з jitodontfront з'являється у бандлі.
Дозволені шаблони
[tx_with_dontfront, tip][tx_with_dontfront, arbitrage, tip][tx_with_dontfront_signer1, tx_with_dontfront_signer1_and_signer2, tip]
Кілька транзакцій DontFront в одному бандлі
Кілька dontfront-транзакцій в одному бандлі дозволені за умови дотримання обох вимог:
- Всі dontfront-транзакції розташовані суміжно на початку бандлу
- Кожна dontfront-транзакція має хоча б одного підписанта спільного з першою dontfront-транзакцією
✅ [txA_df, txB_df, txC_df, arbitrage, tip](contiguous at front, overlapping signers)✅ [txA_df_signer1_signer2, txB_df_signer1_signer3, txC_df_signer2_signer4](each shares a signer with txA)
Заборонені шаблони
❌ [tip, tx_with_dontfront]→ dontfront tx is not at index 0❌ [txA_df_signer1, txB_df_signer2]→ no overlapping signer between txA and txB❌ [trade, tx_with_dontfront, arbitrage, tip]→ dontfront tx is not at the front
Приклади інтеграції
Для швидкого прикладу коду дивіться запис у кулінарній книзі MEV Protection.
TypeScript (@solana/kit)
Основна ідея — допоміжна функція, що додає dontfront-обліковий запис до будь-якої інструкції:
import {address,AccountRole,type Instruction,type Address} from "@solana/kit";const DONT_FRONT: Address = address("jitodontfront111111111111111111111111111111");function withDontFront(ix: Instruction): Instruction {return {...ix,accounts: [...(ix.accounts ?? []),{ address: DONT_FRONT, role: AccountRole.READONLY }]};}
Потім надішліть підписану транзакцію до рушія блоків Jito замість стандартного RPC-вузла. Завжди використовуйте кодування base64. Base58 є застарілим у API Jito.
const response = await fetch("https://mainnet.block-engine.jito.wtf/api/v1/transactions",{method: "POST",headers: { "Content-Type": "application/json" },body: JSON.stringify({jsonrpc: "2.0",id: 1,method: "sendTransaction",params: [base64Tx, { encoding: "base64" }]})});
Найкращі практики
DontFront — це один рівень захисту. Надійна стратегія пом'якшення MEV поєднує кілька підходів:
Захист на рівні транзакцій
-
Встановіть жорсткі допуски прослизання. Найефективніший захист від сендвіч-атак — це обмеження допустимого прослизання під час обмінів. Менше вікно прослизання зменшує маржу прибутку для зловмисників, роблячи вашу транзакцію менш привабливою для сендвіч-атаки.
-
Встановіть відповідні чайові та пріоритетні комісії. Під час перевантаження вищі чайові та пріоритетні комісії збільшують імовірність швидкого потрапляння вашої транзакції/бандлу, зменшуючи вікно можливостей для пошукачів. Дивіться документацію Jito щодо розмірів чайових для отримання докладнішої інформації про встановлення відповідних чайових.
-
Оптимізуйте використання обчислювальних одиниць. Кожен блок має обмежену кількість доступних обчислювальних одиниць (а облікові записи мають обмежену кількість обчислювальних одиниць на блок). Щоб максимізувати ймовірність включення вашої транзакції/бандлу в блок, слід оптимізувати використання обчислювальних одиниць. Дивіться посібник Як оптимізувати використання обчислювальних ресурсів на Solana для отримання деталей.
Специфічні рекомендації для DontFront
-
Позначте dontfront-обліковий запис як лише для читання. Позначення як записуваного також працює, але лише для читання оптимізує швидкість потрапляння.
-
Використовуйте унікальний dontfront pubkey для кожного застосунку. Будь-який pubkey, що починається з
jitodontfront, підходить. Використання унікального варіанту (наприклад,jitodontfront111111111111111111111111111123) дозволяє розрізняти використання за застосунком під час перевірки даних у мережі. -
DontFront підтримує таблиці пошуку адрес (ALT). Dontfront-обліковий запис може бути включений через ALT. Але не використовуйте ALT для облікових записів чайових.
Обмеження
-
Лише рушій блоків. DontFront застосовується рушієм блоків Jito. Транзакції, надіслані безпосередньо до validator (в обхід Jito), не захищені.
-
Без гарантій. З документації Jito: «Ця функція може допомогти зменшити сендвіч-атаки, але не гарантує цього і не є рішенням для всіх варіацій впорядкування транзакцій, включно з будь-яким впорядкуванням, що здійснюється третіми сторонами.»
-
Лише Mainnet/Testnet. Це функція рушія блоків Jito. Вона не працює в devnet або localhost.
Посилання
Is this page helpful?