昨天拆解 Aave、Compound 借貸協議時,健康因子與清算門檻反覆出現一個關鍵變數:抵押品「現在值多少錢」。健康因子 = 抵押品價值 × 清算門檻 ÷ 借款總值——分子那個「抵押品價值」不是合約自己算得出來的,它是一個外部價格。ETH 現在一顆多少美元?這件事發生在鏈外的中心化交易所、店頭市場、成千上萬筆成交裡,而以太坊虛擬機(EVM)是一個封閉的確定性沙盒,它讀不到自己以外的任何真實世界資料。那個價格從哪來、可不可信、能不能被人動手腳,就是「預言機問題」(the oracle problem)。今天我們把這座橋徹底看清楚:它是整個 DeFi 樂高裡最不起眼、卻最致命的一塊。

📖 學

預言機難題:區塊鏈為什麼天生「瞎眼」

區塊鏈的核心價值來自「確定性」與「可驗證」:同一筆交易,全球每個節點各自重跑一遍,必須算出一模一樣的結果,共識才成立。這個嚴苛要求帶來一個副作用——智能合約不能主動去外面抓資料。假設合約裡寫了「呼叫某個 API 拿 ETH 價格」,不同節點在不同毫秒呼叫,拿到的價格會不一樣,某些節點的網路請求還可能失敗,於是各節點算出的狀態就分岔了,共識當場破裂。

所以 EVM 是刻意設計成封閉、確定性的沙盒:它只認得鏈上已經存在的資料。它知道每個地址有多少 ETH、某個合約的儲存槽裡存了什麼,但它不知道今天美元兌台幣多少、台積電股價、世足賽比數、外面的天氣。這就是預言機難題:區塊鏈的安全性正是建立在「與外界隔絕」之上,可是絕大多數有用的應用(借貸、衍生品、保險、預測市場)偏偏都需要真實世界的資料。預言機(oracle)就是那個被授權「把鏈外資料搬進鏈內」的機制。名字借自古希臘神諭——凡人無法直接與神溝通,得透過神諭這個中介。

要特別澄清:預言機不是「資料的來源」,它是「資料的搬運工與驗證層」。價格本身還是誕生在鏈外的市場,預言機負責把它取來、驗證、上鏈,讓合約能安全地使用。

中心化預言機 vs 去中心化預言機

最直覺的做法是架一台伺服器:自己去交易所抓 ETH 價格,簽名後寫進鏈上合約。這叫中心化預言機。它快、便宜、實作簡單,但它把整條信任鏈收斂到「單一一方」身上——這正是區塊鏈最想消滅的東西。

單點的風險是全方位的:那台伺服器可能被駭客入侵、竄改價格;營運方自己可能作惡(明明 ETH 值 3000 美元,故意報 300 美元,觸發大規模清算牟利);伺服器可能單純當機,讓依賴它的所有協議一起停擺。想像一下:一個號稱「去信任」的百億美元借貸協議,清算大權竟然掌握在一台隨時可能被關掉或被買通的伺服器手上。這叫「單點故障」(single point of failure)。你把智能合約寫得再滴水不漏,只要餵價的那一方壞了,整個系統照樣崩。

去中心化預言機(decentralized oracle)的解法,是把「取資料」這件事本身也去中心化:找一大群彼此獨立、互不信任的節點,各自從各自的來源取得資料,再用某種聚合機制(通常是取中位數)彙整成一個大家都同意的結果才上鏈。單一節點作惡或當機,會被其他多數節點的報價稀釋、蓋過。信任於是從「相信某一方」變成「相信多數節點不會同時串謀」,這跟區塊鏈本身的安全假設同構。

Chainlink 是目前市佔最高的去中心化預言機網路。它的核心組織單位叫 DON(Decentralized Oracle Network,去中心化預言機網路):一群獨立運行的 Chainlink 節點,各由不同的專業節點營運商(node operator)經營,分散在不同地理位置、用不同的基礎設施。

以一條 ETH/USD 價格為例,運作流程大致是:

  1. 取數:DON 裡的每個節點,各自向多個高品質資料商(data aggregator)取得 ETH 的市場價格。這些資料商本身又聚合了眾多中心化與去中心化交易所的成交,所以每個節點拿到的已經是一個「市場均價」,而非單一交易所的可能被操縱的價。
  2. 鏈下聚合與簽名:節點之間透過 OCR(Off-Chain Reporting,鏈下報告)協定通訊,先在鏈下就價格達成共識、取中位數,然後把這個聚合結果打包成「一份帶有多個節點數位簽章」的報告。
  3. 上鏈:由其中一個節點把這份聚合報告送上鏈,鏈上的聚合合約(aggregator contract)會驗證裡面確實有足夠數量的合法節點簽名,通過後才更新價格。

關鍵在於 OCR 這個設計:早期做法是每個節點各自發一筆交易上鏈報價,n 個節點就是 n 筆交易,gas 成本高得嚇人;OCR 讓聚合在鏈下完成,最後只需一筆交易帶著所有簽名上鏈,成本大幅下降,也讓更多節點參與變得可行。節點營運商需要質押 LINK 代幣、建立長期聲譽,報錯價會被罰沒質押、砸掉招牌接不到案子——經濟誘因與加密簽章雙管齊下,撐起這個網路的可信度。

Price Feed / Data Feed 怎麼運作

對上層開發者來說,用 Chainlink 價格其實很簡單。Chainlink 在每條鏈上維護一組 Data Feed(資料饋送,價格類的又稱 Price Feed),每一條 feed 對應一個聚合合約,永遠存著「最近一次更新的價格」。你的合約只要呼叫這個聚合合約的 latestRoundData() 介面(透過標準的 AggregatorV3Interface),就能讀到當前價格、以及這筆價格是第幾輪、何時更新的。

價格什麼時候會更新?Chainlink 採兩個觸發條件,滿足其一就更新:

  • 偏差門檻(deviation threshold):當市場價相對鏈上最新價的偏移超過某個百分比(例如 0.5%),就觸發一次更新。市場劇烈波動時更新得勤,平靜時就少更新、省 gas。
  • 心跳(heartbeat):即使價格沒動,只要超過某個時間上限(例如 1 小時)沒更新,也強制更新一次,確保資料不會過期成一灘死水。

這裡藏著一個開發者必知的陷阱:latestRoundData() 回傳的價格帶有 updatedAt 時間戳,正確的用法一定要檢查這個時間戳夠不夠新。如果某條 feed 因故停止更新,你讀到的可能是幾小時前的舊價——拿舊價去清算,跟拿錯價一樣危險。

上面描述的 Chainlink 傳統 Data Feed 是「推送模式」(push):由預言機網路主動、定期把價格寫上鏈,價格「已經在鏈上等著」,你的合約隨時讀隨時有。優點是使用者呼叫合約時零額外步驟、體驗單純;代價是持續往鏈上寫入要付 gas,也不可能把每一毫秒的價格變化都推上去,天生有一定延遲與更新頻率上限。

另一個流派是「拉取模式」(pull),以 Pyth Network 為代表。它平時把高頻價格(可到次秒級)維持在鏈下的一個網路裡,不主動上鏈;誰需要用價格,就在自己那筆交易裡「順手把最新的簽名價格報告帶上鏈」,一次性驗證後使用。好處是可以做到極低延遲、極高更新頻率(適合高頻衍生品、永續合約),而且上鏈成本轉嫁給真正使用它的那筆交易,沒人用就不燒 gas。代價是使用者(或前端)必須多做一步「去鏈下取報告再附帶上鏈」的動作,整合較複雜。

沒有絕對的優劣:借貸協議的清算對「幾秒延遲」通常可接受,push 的簡單穩定更划算;而高槓桿永續交易所對延遲極度敏感,pull 的低延遲才撐得住。理解這個 push/pull 光譜,就能看懂為什麼不同協議選了不同的預言機。

預言機操縱攻擊:呼應昨天的清算風險

回到昨天的主軸。借貸協議的清算完全依賴預言機報價——只要能讓某個抵押品的「鏈上價格」瞬間失真,就能觸發不該發生的清算,或反過來借出被高估的資產。這就是預言機操縱攻擊(oracle manipulation),而它跟昨天講的閃電貸是天作之合的犯罪搭檔。

最經典的錯誤示範,是協議直接拿「某個 AMM 池的即時現貨價」當預言機。AMM 的價格由池內兩種資產的比例決定,而池子的流動性若不夠深,攻擊者就能用閃電貸借出巨額資金,在同一個原子交易內:先砸大錢把某資產在池裡的價格瞬間拉高或砸低 → 讓依賴這個池價的借貸協議誤判抵押品價值 → 借出/清算牟利 → 反向平倉、還掉閃電貸。整套動作在一個區塊內完成,價格閃現又復原,肉眼幾乎抓不到,協議金庫卻已經被掏空。2022 年 Mango Markets 被以類似手法操縱定價、盜走約 1.17 億美元,就是血淋淋的案例。

防禦的核心思路有二。其一是別用單一 AMM 池的即時價,改用 Chainlink 這種聚合了眾多交易所、單一池子動不了大局的去中心化預言機。其二是TWAP(Time-Weighted Average Price,時間加權平均價格):不取某一瞬間的價,而取一段時間內的平均價。攻擊者要操縱 TWAP,就得在「連續好幾個區塊」持續維持被扭曲的價格,這意味著要長時間承受套利者的反向套利與巨大資金風險,成本與難度呈指數級上升。閃電貸只能操縱「單一區塊」的瞬時價,對「跨區塊的時間平均」幾乎無能為力——TWAP 正是掐住了這個要害。這也呼應昨天提到的:Uniswap V3 內建 TWAP 預言機,就是為了提供難以在單區塊操縱的價格來源。

不只價格:VRF 可驗證隨機與 CCIP 跨鏈

預言機的職責遠不只搬價格。區塊鏈的確定性還帶來另一個難題:鏈上生不出真正的隨機數。合約若用區塊雜湊、時間戳這類「鏈上變數」當亂數種子,出塊的礦工/驗證者能預先看到甚至操控這些值,對於 NFT 抽卡、鏈遊掉寶、公平抽獎這類場景,等於留了一道可被莊家操控的後門。

Chainlink VRF(Verifiable Random Function,可驗證隨機函數)解決這件事:它在鏈下用一把私鑰生成隨機數,同時附上一份加密證明;鏈上合約用對應的公鑰驗證這份證明,確認這個隨機數確實是照規則生成、事前無法預測、事後無法竄改的。既隨機又可驗證,任何人(包括產生者自己)都無法作弊。

另一條產品線 CCIP(Cross-Chain Interoperability Protocol,跨鏈互通協定)則把預言機網路的「多節點驗證」能力用在跨鏈上:讓不同區塊鏈之間安全地傳遞代幣與訊息。跨鏈橋一向是駭客金庫(歷史上多起數億美元級失竊都出在橋),CCIP 引入獨立的「風險管理網路」(Risk Management Network)在旁邊監看、對異常喊停,試圖把橋的安全性拉到與底層預言機同級。從價格、隨機數到跨鏈,可以看出「去中心化預言機網路」本質上是一套通用的鏈下↔鏈上可信中介層,價格只是它最出名的第一個應用。

破除迷思:「去信任」其實是把信任外包了

一個廣為流傳的說法是:「智能合約是 trustless(去信任)的,所以完全不需要信任任何人。」這句話只對了一半,而漏掉的那一半正是本文的重點。

合約的執行確實是去信任的——程式碼公開、邏輯確定、全網驗證,沒人能偷改它的執行結果。但合約吃進去的資料一點都不去信任。當你的借貸協議相信 Chainlink 報的 ETH 價格,你就是把信任從「相信某個中心化機構」轉移到「相信這個去中心化預言機網路的多數節點不會同時作惡、資料商不會集體餵錯」。信任沒有消失,它被外包、被分散、被重新定價了。去中心化預言機做的事,是把信任攤薄到讓「攻破它」的成本高到不划算,而不是讓信任歸零。

這帶出資訊工程的老話——garbage in, garbage out(垃圾進,垃圾出)。你的合約邏輯再嚴謹、審計再徹底、被形式化驗證證明過沒有漏洞,只要餵進來的價格是錯的,它就會一絲不苟、忠實無比地執行一個錯誤的決定,把使用者的抵押品精準地清算光。上層合約的安全,永遠不會高於它所依賴的預言機的安全。這就是為什麼在 DeFi 的攻擊史裡,預言機這一環反覆成為最貴的破口。

🧠 記

  • 預言機難題:區塊鏈為維持確定性共識而刻意與外界隔絕,讀不到任何鏈外資料;預言機是被授權「把鏈外資料搬進鏈內」的驗證與搬運層,不是資料的原始來源。
  • 中心化預言機 = 單點故障:單一伺服器會被駭、會作惡、會當機;去中心化預言機用一群互不信任的獨立節點聚合(常取中位數),把信任從「某一方」換成「多數節點不串謀」。
  • Chainlink DON 三步驟:多節點各自向多家資料商取數 → 透過 OCR 在鏈下聚合並多方簽名 → 一筆交易帶著所有簽名上鏈由聚合合約驗證;節點需質押 LINK 並靠聲譽自律。
  • Data/Price Feed 靠「偏差門檻」與「心跳」兩條件更新;讀價務必檢查 updatedAt 時間戳,舊價與錯價一樣致命。
  • push vs pull:Chainlink 傳統 feed 主動推價上鏈(簡單穩定、有延遲);Pyth 走拉取模式(低延遲高頻、用時才附價上鏈、整合較複雜),依應用對延遲的敏感度取捨。
  • 預言機操縱 + 閃電貸:直接用單一 AMM 池即時價最危險,可被閃電貸在單區塊內拉盤觸發錯誤清算(如 Mango Markets)。用聚合預言機 + TWAP 防禦——TWAP 迫使攻擊者跨多區塊維持扭曲價,成本暴增。
  • VRF 提供可驗證隨機(附加密證明)、CCIP 做跨鏈互通,顯示 DON 是通用的鏈下↔鏈上可信中介層。
  • 迷思破除:合約執行去信任,但輸入資料不是;「去信任」實為把信任外包並分散給預言機。garbage in, garbage out——上層再安全,餵錯價一樣崩。

✍️ 實踐

挑一個你熟悉的 DeFi 協議(例如昨天的 Aave 或 Compound),去它的官方文件或治理論壇找出一個問題的答案:「它的清算價格從哪個預言機來?」你會發現絕大多數主流協議都明列 Chainlink 為主要餵價來源,有些還會設計「備援預言機」與「熔斷機制」(價格偏離過大或 feed 停止更新時暫停清算)。試著把這件事串起來想:昨天你計算過的健康因子公式,分子的抵押品價值就是這條 feed 餵進去的;若這條 feed 被操縱或過期,你精心設定的清算門檻就形同虛設。

進階一點:去 Etherscan 之類的區塊瀏覽器,找到某條 Chainlink ETH/USD 聚合合約,觀察它的更新交易——看看多久更新一次、每次價格偏移多少才觸發、updatedAt 時間戳的節奏。把「一個抽象的預言機」變成「一個你親眼看過它心跳的具體合約」,你對 DeFi 風險的直覺會完全不同:你不再只看協議本身安不安全,而會下意識追問「它信任誰餵價、那個來源可不可信」。

🔗 延伸學習

  • Oracles | ethereum.org — 以太坊官方對預言機的中立總覽:輸入/輸出/運算型預言機、中心化 vs 去中心化的信任模型、即時讀取/發布訂閱/請求回應三種架構,並列出 Chainlink、Pyth、API3 等方案。
  • Chainlink Data Feeds | Chainlink Documentation — Chainlink 官方文件,說明 Data/Price Feed 如何由眾多獨立節點聚合、AggregatorV3Interface 怎麼讀價、偏差門檻與心跳的更新機制。
  • Chainlink CCIP | Chainlink Documentation — CCIP 跨鏈互通協定的官方概念與架構文件,含風險管理網路的設計。
  • Blockchain oracle - Wikipedia — 維基百科對區塊鏈預言機的定義、類型分類,以及中心化預言機的中間人攻擊/共識預言機分散信任的討論。

💬 問 AI

把預言機從「一個名詞」變成「一套可以被你追問到底的信任假設」。複製下面的 prompt 丟給你的 AI 助理,讓它帶你走一遍攻防推演:

我正在學區塊鏈的預言機(oracle)。請用繁體中文台灣用語,分四步帶我深入:

1. 先用一個「智能合約想根據 ETH 價格自動清算借貸部位」的具體例子,解釋為什麼 EVM 天生讀不到鏈外價格(預言機難題),以及為什麼不能讓合約自己去呼叫 API。

2. 對比中心化預言機與 Chainlink 這類去中心化預言機網路(DON):後者如何用多節點取數、OCR 鏈下聚合取中位數、多方簽名上鏈,把「信任某一方」換成「多數節點不串謀」?並解釋 push(Chainlink 傳統 feed)與 pull(Pyth)兩種模式的取捨。

3. 扮演攻擊者:假設某借貸協議直接用單一 Uniswap 池的即時價當預言機,請一步步演示我如何用閃電貸在單一原子交易內操縱價格、觸發錯誤清算牟利。然後扮演防禦方,解釋為什麼「聚合預言機 + TWAP」能擋住這種攻擊,而 TWAP 具體是如何把攻擊成本推高的。

4. 最後幫我用「garbage in, garbage out」和「去信任其實是把信任外包」兩個角度,總結:為什麼一個通過完整審計、程式碼零漏洞的合約,仍可能因為預言機被攻破而損失全部資金?

每一步都用具體數字舉例,不要只給抽象定義。