以太坊虛擬機

靜態呼叫

STATICCALL 是一種帶著承諾的訊息呼叫:它所喚起的程式碼不准更改任何東西。它的行為像普通的 CALL——傳遞資料、執行目標的程式碼、回傳成功旗標與資料——但 EVM 會對整個子執行(包含它再發出的任何呼叫)強制施加一個唯讀沙盒。它是 EVM 在硬體層級給出的保證:「這只是一個提問,不是一道指令」。

STATICCALL 由 EIP-214(Byzantium,2017)引入,做法是在新的執行框架上設一個「static」模式旗標。只要該旗標被設上,任何會改動狀態的操作碼都會立即回滾該呼叫:SSTORE(儲存寫入)、LOG0–LOG4(發出事件)、CREATE 與 CREATE2(部署合約)、SELFDESTRUCT,以及任何試圖轉發非零 ETH 的 CALL。純運算、SLOAD 讀取、巢狀的 STATICCALL 則都沒問題。這個旗標會向下傳播,因此合約無法藉由呼叫第三份合約來逃脫這項限制。

這正是 Solidity 用來強制 view 與 pure 函式(當它們透過外部呼叫被觸及時)的手段。當你經由介面呼叫另一份合約的 view 函式時,編譯器會發出一個 STATICCALL,給你一個編譯期與執行期兼具的保證:查詢價格、餘額或某個設定值,不可能對鏈上狀態造成意外的副作用。

這份唯讀保證讓 STATICCALL 不只是 view 的工具,更是有用的安全利器。在 STATICCALL 下呼叫不受信任的程式碼,意味著它無法重入把你掏空、也無法悄悄翻動某個旗標,這正是預言機讀取與某些跨合約查詢偏好它的原因之一。代價是僵硬:一個需要記錄事件或更新計數器的函式,根本無法透過 STATICCALL 喚起——整個子呼叫一試圖動手就回滾。

view 函式在交易內被呼叫時並非沒有成本——STATICCALL 仍會為運算與讀取消耗 gas;「免費」只形容那些從不進入記憶池的鏈下 eth_call 查詢。