Ochrona przed MEV z Jito DontFront

Ochrona przed MEV z Jito DontFront

Maximal Extractable Value (MEV) to wartość, którą można pozyskać poprzez przekształcanie kolejności, włączanie lub wykluczanie transakcji w bloku. MEV nie jest charakterystyczne tylko dla jednego łańcucha – to fundamentalna właściwość każdego blockchainu, w którym producenci bloków kontrolują kolejność transakcji. Niektóre formy MEV, takie jak arbitraż, pomagają utrzymać efektywność rynku poprzez korygowanie rozbieżności cenowych między DEX-ami. Inne, jak ataki kanapkowe, wyciągają wartość bezpośrednio od użytkowników. Dla deweloperów tworzących aplikacje DeFi może to oznaczać gorszą realizację transakcji i utratę zysków.

Ten przewodnik skupia się na atakach kanapkowych – powszechnej formie szkodliwego MEV – oraz na tym, jak je ograniczać przy użyciu funkcji dontfront od Jito.

Zalecane materiały wstępne: Jito Bundles

MEV na Solanie

Architektura Solany już teraz zmniejsza powierzchnię ataku MEV w porównaniu z łańcuchami posiadającymi publiczne pule pamięci (mempool). Transakcje są przesyłane bezpośrednio do nadchodzącego lidera bloku, zamiast oczekiwać w współdzielonym mempoolu, a nieprzetworzone transakcje wygasają po około 150 blokach (~1 minuta). Znacząco zawęża to okno czasowe, w którym searcher może obserwować oczekujące transakcje i reagować na nie.

Niemniej jednak ekstrakcja MEV nadal ma miejsce. Searcherzy z zoptymalizowaną infrastrukturą i bezpośrednimi połączeniami z validator-ami mogą obserwować przepływ transakcji i na niego reagować. Większość aktywności MEV na Solanie to atomowy arbitraż: boty korygujące różnice cenowe między DEX-ami w ramach jednej transakcji. Ten rodzaj MEV jest generalnie korzystny, ponieważ poprawia spójność cen na rynkach.

Szkodliwy rodzaj MEV – ataki kanapkowe – to coś, przed czym deweloperzy powinni aktywnie się chronić.

Czym jest atak kanapkowy?

Atak kanapkowy ma miejsce, gdy searcher wykrywa Twój oczekujący swap i wykorzystuje kolejność transakcji:

  1. Front-run: searcher kupuje token przed Twoją transakcją, podbijając cenę w górę
  2. Twoja transakcja jest realizowana po gorszej cenie niż oczekiwano
  3. Back-run: searcher sprzedaje token po Twojej transakcji, zagarniając różnicę

Na Solanie może to odbywać się za pośrednictwem Jito bundles. Searcher przesyła bundle transakcji w postaci: [frontrun_tx, your_tx, backrun_tx], a silnik bloków wykonuje je atomowo po kolei. Ofiara otrzymuje gorszą cenę realizacji, podczas gdy searcher czerpie zysk ze spreadu.

Jak działa DontFront

DontFront to funkcja silnika bloków Jito, która uniemożliwia searcherom umieszczanie transakcji przed Twoją w bundlu.

Mechanizm działania: dodaj dowolny prawidłowy klucz publiczny Solany zaczynający się od jitodontfront do dowolnej instrukcji w swojej transakcji. Silnik bloków rozpoznaje ten prefiks i egzekwuje regułę: każdy bundle zawierający Twoją transakcję musi umieścić ją pod indeksem 0.

Without dontfront: [frontrun_tx, your_tx, backrun_tx] ← sandwich possible
With dontfront: [your_tx, ...] ← your tx must be first

Krok po kroku

  1. Wybierz prawidłowy adres zaczynający się od jitodontfront (np. jitodontfront111111111111111111111111111111). Konto nie musi istnieć w łańcuchu; nigdy nie jest odczytywane ani zapisywane. Możesz sprawdzić, czy dany ciąg znaków jest prawidłowym adresem, używając funkcji assertIsAddress z pakietu @solana/kit lub wpisując adres w Solana Explorer, aby sprawdzić, czy zostanie rozwiązany. Tutaj znajdziesz przykład nieprawidłowego adresu.

  2. Dodaj go jako konto tylko do odczytu, bez podpisywania do dowolnej instrukcji w swojej transakcji. Oznacz je jako tylko do odczytu, aby uzyskać optymalną szybkość lądowania. Większość programów (w tym System Program) ignoruje dodatkowe konta poza tymi, których oczekuje.

  3. Prześlij za pośrednictwem silnika bloków Jito:

    • sendTransaction: https://mainnet.block-engine.jito.wtf/api/v1/transactions
    • sendBundle: https://mainnet.block-engine.jito.wtf/api/v1/bundles

    Dokumentacja: sendTransaction i sendBundle

  4. Silnik bloków wykrywa prefiks jitodontfront i egzekwuje reguły kolejności.

Co dzieje się w silniku bloków

Gdy silnik bloków wykryje transakcję zawierającą konto jitodontfront:

  • Przez sendTransaction: transakcja jest chroniona. Żaden bundle nie może umieścić innej transakcji przed nią
  • Przez sendBundle: transakcja musi pojawić się pod indeksem 0, w przeciwnym razie cały bundle zostaje odrzucony

Transakcje i bundle, które nie zawierają konta jitodontfront, nie są w żaden sposób dotknięte.

Reguły kolejności bundli

Poniższe reguły obowiązują, gdy transakcja jitodontfront pojawia się w bundlu.

Dozwolone wzorce

[tx_with_dontfront, tip]
[tx_with_dontfront, arbitrage, tip]
[tx_with_dontfront_signer1, tx_with_dontfront_signer1_and_signer2, tip]

Wiele transakcji DontFront w jednym bundlu

Wiele transakcji dontfront w jednym bundlu jest dozwolonych, gdy spełnione są oba poniższe warunki:

  1. Wszystkie transakcje dontfront są ciągłe na początku bundla
  2. Każda transakcja dontfront dzieli co najmniej jednego podpisującego z pierwszą transakcją 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)

Niedozwolone wzorce

❌ [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

Przykłady integracji

Po szybki przepis na kod zajrzyj do wpisu MEV Protection w cookbook.

TypeScript (@solana/kit)

Podstawowa idea to funkcja pomocnicza, która dołącza konto dontfront do dowolnej instrukcji:

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 }
]
};
}

Następnie prześlij podpisaną transakcję do silnika bloków Jito zamiast do standardowego węzła RPC. Zawsze używaj kodowania base64. Base58 jest wycofany w 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" }]
})
}
);

Najlepsze praktyki

DontFront to jedna warstwa ochrony. Solidna strategia ograniczania MEV łączy wiele podejść:

Ochrona na poziomie transakcji

  • Ustaw ścisłe tolerancje poślizgu (slippage). Najbardziej skuteczną obroną przed atakami kanapkowymi jest ograniczenie akceptowalnego poślizgu przy swapach. Mniejsze okno poślizgu zmniejsza margines zysku dostępny dla atakujących, czyniąc Twoją transakcję mniej atrakcyjną dla ataku kanapkowego.

  • Ustaw odpowiednie napiwki i opłaty priorytetowe. W czasie przeciążenia sieci wyższe napiwki i opłaty priorytetowe zwiększają prawdopodobieństwo szybkiego lądowania Twojej transakcji/bundla, skracając okno czasowe dla searcherów. Więcej informacji na temat ustawiania odpowiednich napiwków znajdziesz w dokumentacji Jito dotyczącej Tip Amounts.

  • Optymalizuj użycie jednostek obliczeniowych (compute units). Każdy blok dysponuje ograniczoną liczbą jednostek obliczeniowych (a konta mają ograniczoną liczbę jednostek obliczeniowych dostępnych na blok). Aby zmaksymalizować prawdopodobieństwo włączenia Twojej transakcji/bundla do bloku, powinieneś zoptymalizować wykorzystanie jednostek obliczeniowych. Szczegóły znajdziesz w przewodniku How to Optimize Compute Usage on Solana.

Specyficzne dla DontFront

  1. Oznacz konto dontfront jako tylko do odczytu. Oznaczenie jako zapisywalne również działa, ale tryb tylko do odczytu optymalizuje szybkość lądowania.

  2. Używaj unikalnego pubkey dontfront dla każdej aplikacji. Działa każdy pubkey zaczynający się od jitodontfront. Używanie unikalnego wariantu (np. jitodontfront111111111111111111111111111123) pozwala rozróżniać użycie według aplikacji podczas przeglądania danych w łańcuchu.

  3. DontFront obsługuje Address Lookup Tables. Konto dontfront może być dołączone poprzez ALT. Nie używaj jednak ALT dla kont napiwkowych.

Ograniczenia

  • Tylko silnik bloków. DontFront jest egzekwowany przez silnik bloków Jito. Transakcje przesyłane bezpośrednio do validator-ów (z pominięciem Jito) nie są chronione.

  • Brak gwarancji. Z dokumentacji Jito: "Ta funkcja może pomóc w ograniczeniu ataków kanapkowych, ale nie jest to gwarantowane i nie stanowi rozwiązania dla wszystkich wariantów kolejności transakcji, w tym kolejności realizowanej przez osoby trzecie."

  • Tylko Mainnet/Testnet. Jest to funkcja silnika bloków Jito. Nie działa na devnecie ani na localhoście.

Odnośniki

Is this page helpful?