Status transakcji na sukces, a transfer tokenów się nie udał

2026-09-03

Status transakcji na sukces, a transfer tokenów się nie udał

Portfel pisze, że potwierdzone. Na stronie eksploratora widnieje zielony znacznik. A tokenów na koncie nie ma. Nic się nie zablokowało i nic nie wymaga ponownego wysłania: pole stanu odpowiedziało na węższe pytanie niż to, które zadajesz. Poniżej jest to, co to pole poświadcza, co pomija i gdzie zapisana jest odpowiedź, której naprawdę szukasz.

Status transakcji na sukces, a transfer tokenów się nie udał: co poświadcza stan potwierdzenia i gdzie naprawdę zapisany jest ruch tokenów

Co status sukcesu naprawdę poświadcza

EIP-658 umieścił w potwierdzeniu transakcji kod stanu i zdefiniował jego dwie wartości jedną linijką: 0 oznacza niepowodzenie wywołane dowolną operacją, która może cofnąć transakcję lub wywołanie na najwyższym poziomie, a 1 oznacza powodzenie. Eksplorator bloków zamienia tę jedynkę w znacznik.

Liczy się zakres tej definicji. Kod opisuje wywołanie na najwyższym poziomie. Mówi, że najbardziej zewnętrzna część wykonania zakończyła się bez cofnięcia, i nie mówi nic ponadto: ani że zmieniło się konkretne saldo tokena, ani że przesunęła się kwota, o którą ci chodziło, ani że wywołany kontrakt zrobił to, o co go prosiłeś. Potwierdzenie ze stanem 0 to właśnie to, co eksplorator oznacza jako reverted. Potwierdzenie ze stanem 1 wyklucza ten przypadek i na tym poprzestaje.

Każdy przypadek poniżej mieszka w tej szczelinie. Łańcuch zapisał w całości to, co się wydarzyło. A jednowyrazowe streszczenie na górze strony odpowiadało na inne pytanie.

Pytanie, które zadajesz Gdzie zapisana jest odpowiedź
Czy trafiła do bloku Numer bloku w potwierdzeniu
Czy zewnętrzne wywołanie uniknęło cofnięcia Kod stanu w potwierdzeniu
Czy zmieniło się saldo tego tokena Zdarzenia transferu w dziennikach
Czy moja operacja użytkownika wykonała swoją pracę Flaga powodzenia w jej własnym zdarzeniu

Dlaczego transfer tokenów może się nie udać bez cofnięcia

Standard tokena ERC-20 deklaruje transfer jako funkcję zwracającą wartość logiczną i o konsekwencji mówi stanowczo: wywołujący musi obsłużyć false z returns bool success, a wywołujący nie może zakładać, że false nigdy nie zostanie zwrócone. Niepowodzeniu wolno przyjść jako wartość zwracana, a nie jako cofnięcie.

Gdy token zgłasza niepowodzenie w ten sposób, wynik zależy od kontraktu, który go wywołał. Wywołujący, który sprawdza wartość logiczną, może cofnąć się na false i potwierdzenie wraca ze stanem 0. Wywołujący, który tę wartość odrzuca, idzie dalej, najbardziej zewnętrzne wywołanie kończy się, potwierdzenie mówi o powodzeniu, a saldo ani drgnęło.

Wartości zwracane różnią się jeszcze w drugi sposób. Biblioteka SafeERC20 od OpenZeppelin opisuje samą siebie jako nakładki na operacje ERC-20, które zgłaszają wyjątek przy niepowodzeniu, gdy kontrakt tokena zwraca false, i dodaje, że tokeny niezwracające żadnej wartości również są obsługiwane, a wywołania bez cofnięcia uznaje się za udane. Biblioteka napisana po to, by ujednolicić te wartości zwracane, jest bezpośrednim dowodem na to, że nie są one jednolite.

Niepowodzenia, które kontrakt celowo połyka

Kontrakt może wywołać inny kontrakt i z góry postanowić, że nie polegnie razem z nim. Konstrukcja try i catch w Solidity oraz niskopoziomowe wywołanie, które oddaje flagę powodzenia zamiast przekazywać cofnięcie wyżej, istnieją właśnie po to, by wykonanie mogło biec dalej po wewnętrznym niepowodzeniu. Routery, batchery i przekaźniki korzystają z tego celowo: jedna noga pakietu nie przechodzi, pozostałe nogi się rozliczają, a transakcja jako całość kończy się powodzeniem.

Od strony potwierdzenia jest to nie do odróżnienia od poprzedniego przypadku. Wewnętrzne wywołanie nie przeszło, zewnętrzne wywołanie wchłonęło to niepowodzenie, a pole stanu zapisało wynik zewnętrzny. Wewnętrzne niepowodzenie nadal jest w łańcuchu, ale siedzi w śladzie wykonania i w tym, czego w dziennikach nie ma, a nie w polu stanu.

Zbyt niski limit wydatkowania to jedna z dróg do tego kształtu. Kontrakt, który zabiera twoje tokeny przez transferFrom, wydaje w granicach limitu ustawionego przez ciebie zatwierdzeniem tokenów. Gdy limit jest mniejszy od pobieranej kwoty, wewnętrzne wywołanie nie przechodzi, a o tym, czy razem z nim upada cała transakcja, decyduje wywołujący, a nie token.

Gdy dociera mniej, niż zostało wysłane

W trzecim przypadku nie ma żadnego niepowodzenia, a arytmetyka i tak nie wychodzi. Kontrakt tokena może potrącać coś wewnątrz własnej funkcji transfer, zapisując odbiorcy mniej, niż oddał nadawca. Wyślij 5 000 jednostek tokena, który bierze 3% od każdego transferu, a dotrze 4 850. Potwierdzenie mówi o powodzeniu, zdarzenie transferu istnieje, a liczba w środku nie jest liczbą, którą wpisano.

Tokeny z rebase dają pokrewną rozbieżność z przeciwnej strony. Ich salda są przepisywane przez kontrakt, a nie przenoszone transferem, więc saldo może się zmienić bez żadnego zdarzenia transferu za sobą. Uzgadnianie tego, co pokazuje portfel, z kwotami w historii transakcji dla takiego tokena się nie zepnie, a żaden z dwóch odczytów nie jest błędny.

Co znaczy komunikat o nieudanej transakcji z paymasterem

Przy abstrakcji konta to, co wysyłasz, nie jest transakcją. ERC-4337 definiuje obiekt UserOperation z własnym mempoolem oraz bundlera, który pakuje takie obiekty w jedną zwykłą transakcję do kontraktu EntryPoint. Paymaster to kontrakt, który zgadza się zapłacić za transakcję zamiast nadawcy. Komunikat o błędzie wymieniający paymaster obejmuje dwie sytuacje, które nie mają ze sobą nic wspólnego poza słowem niepowodzenie.

Pierwsza to odrzucenie podczas walidacji. ERC-4337 wymaga, by w razie niepowodzenia dowolnego wywołania validateUserOp handleOps pominął wykonanie co najmniej tej operacji użytkownika, i wymaga od bundlerów odrzucania nieprawidłowych operacji ze swojego mempoola zamiast umieszczania ich w łańcuchu. Paymaster, który odmawia sponsorowania wywołania, ma zbyt mały depozyt albo nie przechodzi własnej walidacji, kieruje operację w tę gałąź. Nic nie zostało włączone, nic nie zostało pobrane i nie ma hasha do sprawdzenia, bo niepowodzenie zdarzyło się, zanim łańcuch zobaczył operację.

Druga dzieje się po włączeniu i to ona daje zielony znacznik. Po przejściu walidacji specyfikacja stwierdza, że wykonanie nastąpi i nastąpi tylko raz, a także gwarantuje zapłatę opłaty. EntryPoint emituje następnie dla każdej operacji użytkownika zdarzenie z flagą powodzenia, opisaną jako true, jeśli transakcja nadawcy się powiodła, i false, jeśli została cofnięta, obok faktycznej kwoty zapłaconej przez konto lub paymaster. Transakcja pakietowa kończy się powodzeniem, paymaster zostaje obciążony, a flaga twojej operacji ma wartość false. Wszystkie trzy zdania są prawdziwe naraz.

Gdzie nastąpiło niepowodzenie Trafiło do bloku Kto zapłacił Co można sprawdzić
Walidacja, przed włączeniem Nie Nikt Błąd od bundlera lub portfela i żadnego zapisu w łańcuchu
Wykonanie, po włączeniu Tak Konto albo paymaster Udana transakcja, której zdarzenie operacji użytkownika ma flagę powodzenia false

Gdzie patrzeć zamiast na pole stanu

Ruchy tokenów zapisywane są jako zdarzenia w dziennikach. Widok transferów tokenów w eksploratorze to przedstawienie tych zdarzeń, więc jeśli twojego adresu nie ma w żadnym z nich, token się nie ruszył, cokolwiek mówi stan. Sprawdza się dzienniki; stan jest streszczeniem.

Trzy pytania wykonują całą pracę. Czy zdarzenie transferu z twoim adresem w ogóle istnieje, czy ta sekcja strony jest pusta? Jeśli istnieje, czy jego kwota jest kwotą, która została wysłana? I czy kontrakt, który je emituje, to ten kontrakt tokena, o który chodziło, w tej sieci, o którą chodziło.

Czwarta możliwość przeżywa wszystkie trzy sprawdzenia: transfer wydarzył się dokładnie tak, jak polecono, a szuka się go w złym miejscu. Drugi adres wyprowadzony z tej samej frazy odzyskiwania, ten sam adres w innej sieci oraz token, którego portfel nie pokaże, dopóki jego kontraktu nie doda się ręcznie, każdy daje pusty ekran obok całkiem sprawnego potwierdzenia.

Podsumowanie

Stan potwierdzenia to zdanie o najbardziej zewnętrznym wywołaniu i o niczym więcej. Powodzenie znaczy, że transakcja się nie cofnęła. Nigdy nie znaczyło, że token się przesunął, że przesunęła się właściwa kwota ani że kontrakt zrobił z nią to, czego chciano. Te fakty mieszkają w dziennikach zdarzeń, a przy ERC-4337 we fladze powodzenia trzymanej osobno od stanu transakcji, która ją niesie.

Gdy transfer ginie za zielonym znacznikiem, schodź warstwami po kolei: zdarzenie transferu, potem jego kwota, potem kontrakt tokena i sieć. Aby dalej poznawać podstawy, śledź kolejne materiały Bitbase Academy.

Powiązane artykuły

Inne artykuły Bitbase na ten temat:

- Jak bezpiecznie zmienić endpoint RPC

- Maksymalna opłata za transakcję przekroczona: co oznacza to ostrzeżenie portfela

- Przekroczony limit zapytań RPC i co z tym zrobić

- Czym jest kod QR w krypto?

- Globalna płynność, M2 i bitcoin: przewodnik po pomiarze

Zastrzeżenie: ten artykuł to treść edukacyjna Bitbase Academy, wyłącznie w celach informacyjnych. Nie stanowi porady inwestycyjnej, handlowej, podatkowej ani finansowej. Kryptoaktywa są zmienne — samodzielnie oceń ryzyko. Napisano w wrześniu 2026 r.; sprawdzaj aktualne oficjalne informacje.

Źródła

[1] Ethereum Improvement Proposals, EIP-20: Token Standard (funkcja transfer i jej booleanowska wartość zwracana) eips.ethereum.org

[2] Ethereum Improvement Proposals, EIP-658: Embedding transaction status code in receipts (pole stanu w potwierdzeniu transakcji) eips.ethereum.org

[3] Ethereum Improvement Proposals, ERC-4337: Account Abstraction Using Alt Mempool (walidacja, bundlery i paymastery) eips.ethereum.org

[4] eth-infinitism, account-abstraction, contracts/interfaces/IEntryPoint.sol, tag v0.7.0 (deklaracja UserOperationEvent) raw.githubusercontent.com

[5] OpenZeppelin, openzeppelin-contracts, contracts/token/ERC20/utils/SafeERC20.sol, tag v5.1.0 (komentarz dokumentacyjny biblioteki) raw.githubusercontent.com