錢包顯示已確認。瀏覽器頁面上是一個綠色剔號。而代幣並不在賬戶裡。沒有任何東西卡住,也不需要重發:狀態欄位回答的問題比你正在問的那個更窄。本文講清楚這個欄位證明了甚麼、漏掉了甚麼,以及你真正要找的答案記錄在哪裡。
成功狀態到底證明了甚麼
EIP-658 在交易收據裡放進一個狀態碼,並用一句話定義了它的兩個取值:0 代表失敗,源於任何可能導致該交易或頂層調用回退的操作;1 代表成功。區塊瀏覽器把這個 1 渲染成一個剔號。
這條定義管到哪裡,才是關鍵。狀態碼描述的是頂層調用。它報告最外層那段執行沒有回退,除此之外甚麼都不報告:不報告某個代幣餘額變了,不報告你想轉的那筆數額動了,也不報告你調用的合約做了你要求它做的事。狀態為 0 的收據就是瀏覽器標記為 reverted 的那種。狀態為 1 的收據排除了這一種,然後就到此為止。
下面每一種情形都住在這道縫隙裡。鏈把發生的事完整記了下來。而頁面頂部那個一個詞的摘要,回答的是另一個問題。
| 你在問的問題 | 答案記錄在哪裡 |
|---|---|
| 它進區塊了嗎 | 收據上的區塊號 |
| 最外層調用避開回退了嗎 | 收據狀態碼 |
| 這個代幣餘額變了嗎 | 日誌裡的轉賬事件 |
| 我的用戶操作辦成事了嗎 | 它自己那條事件上的成功標誌 |
代幣轉賬為甚麼可以不回退地失敗
ERC-20 代幣標準把 transfer 聲明為一個返回布林值的函數,而標準本身對後果說得很硬:調用方必須處理 returns bool success 返回的 false,調用方不得假定 false 永遠不會被返回。失敗是允許以返回值的形式抵達的,不必以回退的形式。
當一個代幣用這種方式報告失敗時,結果取決於調用它的那個合約。檢查這個布林值的調用方可以在 false 上回退,收據回來時狀態是 0。丟掉這個布林值的調用方繼續往下走,最外層調用完成,收據說成功,而餘額從來沒有動過。
返回值還有第二重差異。OpenZeppelin 的 SafeERC20 庫這樣描述自己:它是包在 ERC-20 操作外面、在代幣合約返回 false 時拋出的封裝器;並補充說完全不返回值的代幣同樣受支援,不回退的調用被視為成功。一個專門為歸一這些返回值而寫的庫,本身就是這些返回值並不統一的直接證據。
合約有意吞掉的失敗
一個合約可以調用另一個合約,並事先決定不跟著它一起失敗。Solidity 的 try 與 catch 結構,以及那種把成功標誌交回來、而不把回退往上傳的低層調用,存在的意義就是讓執行能越過內層失敗繼續走下去。路由器、批處理器和中繼器有意用這一點:一批裡的某一條腿失敗了,其餘的腿照樣結清,而這筆交易整體上是成功的。
從收據上看,這與上一種情形無法區分。內層調用失敗了,外層調用把這個失敗吸收掉了,狀態欄位記錄的是外層結果。內層失敗仍然在鏈上,但它待在執行追蹤裡、待在日誌裡沒有的那些東西裡,而不在狀態欄位裡。
授權額度不足是通往這個形態的一條路。用 transferFrom 搬走你代幣的合約,花的是你用代幣授權設下的那個額度。當額度小於被拉走的數額時,內層調用失敗,而整筆交易是否跟著失敗,由調用方決定,不由代幣決定。
到賬的數額小於發出的數額
第三種情形裡根本沒有失敗,而算術照樣對不上。代幣合約可以在它自己的 transfer 函數裡扣掉一部分,記給接收方的比發送方交出去的少。發出 5,000 單位一個每次轉賬收 3% 的代幣,到賬的是 4,850。收據說成功,轉賬事件也在,而事件裡的那個數不是當初輸進去的那個數。
變基代幣從相反的方向產生一種相關的錯位。它們的餘額是被合約改寫的,不是被一次轉賬搬走的,所以餘額可以在背後沒有任何轉賬事件的情況下發生變化。拿錢包顯示去和交易歷史裡的數額對賬,對這類代幣是對不上的,而兩邊的讀數都沒有錯。
paymaster 交易失敗這句提示是甚麼意思
在賬戶抽象之下,你提交的並不是一筆交易。ERC-4337 定義了一個 UserOperation 對象,它有自己的記憶池,還有一個 bundler 把這些對象打包進一筆發往 EntryPoint 合約的普通交易。paymaster 是一個同意替發送方支付這筆交易的合約。一句點了 paymaster 名字的失敗提示,覆蓋的是兩種情形,它們之間除了失敗這個詞以外沒有共同點。
第一種是驗證階段的拒收。ERC-4337 要求:如果任何 validateUserOp 調用失敗,handleOps 必須至少跳過那一個用戶操作的執行;它還要求 bundler 把無效的操作從自己的記憶池裡拒掉,而不是把它們放上鏈。一個不肯贊助這次調用、押金餘額太少、或者自己驗證不過的 paymaster,會把這個操作推進這一支。甚麼都沒有被納入,甚麼都沒有被扣費,也沒有雜湊可查,因為失敗發生在鏈看見這個操作之前。
第二種發生在納入之後,而它正是那個會產生剔號的情形。規範說,一旦驗證通過,執行就會發生且只發生一次,並且手續費的支付也得到保證。隨後 EntryPoint 會為每個用戶操作發出一條事件,事件裡帶著一個成功標誌,其文檔寫明:發送方交易成功為 true,回退為 false;旁邊還有由賬戶或 paymaster 實際支付的金額。這筆打包交易成功了,paymaster 被扣了費,而你那個操作上的標誌是 false。三件事同時成立。
| 失敗發生在哪 | 是否進了區塊 | 誰付的錢 | 有甚麼可查 |
|---|---|---|---|
| 驗證階段,納入之前 | 否 | 無人 | 來自 bundler 或錢包的一條報錯,鏈上沒有記錄 |
| 執行階段,納入之後 | 是 | 賬戶或 paymaster | 一筆成功的交易,而它的用戶操作事件帶著一個為 false 的成功標誌 |
不看狀態欄位,該看哪裡
代幣的移動記錄在日誌的事件裡。瀏覽器的代幣轉賬視圖就是這些事件的一種呈現,所以如果你的地址沒有出現在其中任何一條裡,那個代幣就沒有動過,不管狀態怎麼說。日誌才是核對的對象,狀態只是摘要。
三個問題就能把事情辦完。有沒有一條牽涉到你地址的轉賬事件,還是這一欄是空的?如果有,它的數額是不是發出去的那個數額?發出這條事件的合約,是不是你要的那個代幣合約,在不在你要的那條網絡上。
還有第四種可能能挺過上面三關:轉賬完全按指令發生了,只是找錯了地方。同一句助記詞派生出的另一個地址、另一條網絡上的同一個地址、以及一個不手動添加合約就不顯示的代幣,都會在一張完好的收據旁邊給你一塊空屏。
小結
收據狀態是關於最外層調用的一句陳述,僅此而已。成功的意思是這筆交易沒有回退。它從來不意味著某個代幣動了、動的是對的數額,或者合約用它做了你想要的事。這些事實住在事件日誌裡,而在 ERC-4337 之下,住在一個與承載它的那筆交易的狀態相分離的成功標誌裡。
當一筆轉賬消失在綠色剔號背後時,按層次逐級往下查:先看有沒有轉賬事件,再看它的數額,最後看代幣合約與網絡。想繼續打基礎,請關注 Bitbase 學院的更多內容。
相關閱讀
幣貝上與本主題相關的其他文章:
風險披露:本文為 Bitbase(幣貝)學院的科普內容,僅供教育與資訊參考,不構成任何投資、交易、稅務或財務建議。加密資產波動劇烈,請自行評估風險。本文撰寫於 2026 年 9 月,請以官方最新資訊為準。
參考資料
[1] Ethereum Improvement Proposals,EIP-20: Token Standard(transfer 函數及其布林返回值) eips.ethereum.org
[2] Ethereum Improvement Proposals,EIP-658: Embedding transaction status code in receipts(交易收據裡的狀態欄位) eips.ethereum.org
[3] Ethereum Improvement Proposals,ERC-4337: Account Abstraction Using Alt Mempool(驗證、bundler 與 paymaster) eips.ethereum.org
[4] eth-infinitism,account-abstraction,contracts/interfaces/IEntryPoint.sol,標籤 v0.7.0(UserOperationEvent 的聲明) raw.githubusercontent.com
[5] OpenZeppelin,openzeppelin-contracts,contracts/token/ERC20/utils/SafeERC20.sol,標籤 v5.1.0(庫的文檔註釋) raw.githubusercontent.com






