﻿---
title: "預言機小數位不相符"
description: "小數位不相符會對預言機答案、代幣數量、封裝匯率或協定數值採用錯誤單位縮放，造成借貸、鑄造、贖回與清算的數量級錯誤。"
image: "https://wiki.fcontext.com/og.png"
---

> Documentation Index
> Fetch the complete documentation index at: https://wiki.fcontext.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 預言機小數位不相符

> 僅供教育參考，不構成投資建議；投資可能產生損失。

<a id="answer"></a>

## 直接答案

合約以錯誤的單位指數、價格方向或內部尺度解讀原始整數時，就會發生預言機小數位不相符。資料源小數位、代幣小數位、報價代幣小數位、封裝或份額兌換率尺度，以及協定的 WAD 或 RAY 慣例彼此獨立。前端顯示正確，不代表使用端合約執行相同運算。

對基礎代幣原始數量 `A_raw`，其小數位為 `d_t`；正數資料源答案 `P_raw` 以小數位 `d_p` 表示「每個基礎代幣值多少報價代幣」。若報價代幣小數位為 `d_q`，其原始數量為 `V_raw = round(A_raw * P_raw * 10^d_q / 10^(d_t + d_p))`。此公式僅適用所述報價方向，且須先驗證資料源、單位、型別及捨入規則。轉接器已正規化的數值不得再次縮放。

ERC-20 的 `decimals()` 是可選的顯示中繼資料，不保證統一為 18 位。資料源的 `decimals()` 描述該資料源回應，而非代幣或協定尺度。檢查型運算可藉由回復阻止溢位，但無法發現量綱錯誤的公式；中間乘積溢位時，還可能使原本可表示的結果變成拒絕服務。

<a id="mechanism"></a>

## 運作方式

1. 鎖定鏈、區塊、使用端、轉接器、資料源代理與聚合器、代幣或金庫、編譯器與數學函式庫版本，以及升級狀態。
2. 清點每個整數的型別與單位：原始代幣數量、代幣小數位、有符號資料源答案、資料源小數位、基礎與報價方向、封裝或份額匯率、協定內部尺度及輸出代幣小數位。
3. 轉換前驗證來源：地址與方向正確、答案為正、時間戳與狀態有效、年齡與範圍可接受、備援語意明確，並在適用時檢查 L2 排序器寬限規則。
4. 從輸入原始單位推導至輸出原始單位的單一量綱公式。放大與縮小時明確分支，限制每個十次方指數，每一項只正規化一次。
5. 使用經證明的全精度乘除法或有界約分策略。避免先除後乘截斷、受檢中間值溢位、unchecked 回繞，以及不安全的有符號或窄化轉換。
6. 為每項經濟操作規定向下、向上或最接近捨入。擔保品、債務、借款、鑄造、贖回、費用、清算及金庫份額轉換可能需要不同的保守方向。
7. 對極端數量、小數位組合、倒數、複合資料源、零值、負值、過時答案、升級及微量值執行黃金向量與性質測試；以獨立高精度模型核對鏈上結果，並限制受影響曝險。

正規化是量綱分析，不是格式化。`BTC/USD` 與 `USD/BTC` 需要倒數公式；更改標籤不會反轉價格。複合資料源要求每一項的尺度與時間戳。Solidity 整數除法向零截斷，因此代數上等價的重排可能產生不同鏈上結果。全精度 `mulDiv` 解決中間位元寬度問題，但呼叫端仍須提供正確的分子、分母、單位、邊界與捨入方向。

<a id="example"></a>

## 計算範例

- **八位與十八位小數。** BTC/USD 資料源回傳 `6,000,000,000,000`，且 `d_p = 8`，所以價格為 `60,000 USD/BTC`。把原始答案視為 18 位小數會得到 `0.000006 USD/BTC`，低估 `10^10` 倍，而非 `10^9`。將價格縮放至 WAD 得到 `6,000,000,000,000 * 10^(18 - 8) = 60,000,000,000,000,000,000,000`。
- **數量、價格與輸出單位。** `A_raw = 2,500,000` 代表 `2.5` 個代幣，其小數位為 `d_t = 6`；`P_raw = 200,000,000` 代表 `2` 個報價代幣，其小數位為 `d_p = 8`。對 18 位內部報價數值，`2,500,000 * 200,000,000 * 10^18 / 10^(6 + 8) = 5,000,000,000,000,000,000`，即 `5 quote tokens`。省略代幣分母會高估 `10^6` 倍。
- **倒數與截斷。** WAD 尺度的 ETH/USD 為 `2,000 * 10^18`。同尺度的 USD/ETH 為 `floor(10^36 / (2,000 * 10^18)) = 500,000,000,000,000`，即 `0.0005 ETH/USD`。另有 `A_raw = 999,999`、`d_t = 6`、價格 `2 * 10^18` 時，全精度乘除得到 `1,999,998,000,000,000,000`；若先將數量除以 `10^6`，結果為 `0`，全部價值遺失。
- **中間溢位與捨入。** 設 `x = 2^200`、`y = 2^100`、分母為 `2^100`。精確結果是 `2^200`，可放入 `uint256`，但 `x * y = 2^300` 無法放入。檢查型乘法回復，unchecked 乘法回繞；全精度 `mulDiv` 回傳 `2^200`。整數 `5 / 2` 向下為 `2`，向上規則回傳 `3`，因此捨入屬於經濟不變量。

<a id="risks"></a>

## 風險

- 鏈、資料源、代理、轉接器、代幣、金庫或使用端地址錯誤。
- 基礎與報價方向反轉而未做倒數轉換。
- 假定代幣為 18 位，或可選中繼資料無法取得或錯誤。
- 假定資料源為 8 位，而未讀取並鎖定。
- 混淆報價代幣小數位與協定 WAD、RAY、市場或會計尺度。
- 遺漏封裝、份額、指數或兌換率小數位。
- 轉接器已正規化後重複套用縮放因子。
- 遺漏必要縮放因子或分母。
- 未檢查正值便將有符號答案轉成無符號。
- 接受零值、過時、不完整、封頂或無效資料源結果。
- 小數指數或十次方計算下溢、溢位或超出邊界。
- 最終商可表示，但中間乘積溢位。
- unchecked 運算、位移或明確窄化靜默回繞或截斷。
- 先除後乘破壞精度或使微量值歸零。
- 經濟操作採用錯誤的向下、向上或最接近捨入。
- 重複轉換累積精度損失或系統性價值流失。
- 以不同單位比較價格、上限、比率、百分比、基點、WAD 與 RAY。
- 資料源、代幣、代理、轉接器或金庫升級使快取的小數位假設失效。
- 前端、錢包、RPC 或索引器格式化掩蓋不同的鏈上運算。
- 錯誤估值放大借貸、鑄造、贖回、清算、上限、壞帳或不公平份額發行。

<a id="misconceptions"></a>

## 常見誤解

- **「每個 ERC-20 代幣都使用 18 位小數。」** ERC-20 中繼資料方法是可選的，已部署資產採用不同數值與行為。
- **「每個美元價格資料源都使用 8 位小數。」** 資料源精度是具體部署的介面屬性，必須讀取並納入版本管理。
- **「原始整數很大就證明遭操縱。」** 若不知道單位、方向、小數位、時間戳與使用尺度，原始數量沒有意義。
- **「Solidity 0.8 會保證縮放正確。」** 檢查型溢位可回復，但不會修正錯誤單位、截斷、型別轉換或捨入政策。
- **「先乘後除或增加小數位總會提高精度。」** 這可能溢位、重複縮放或保留錯誤單位；全精度運算仍需要正確公式。

<a id="related"></a>

## 相關主題

- [代幣小數位驗證](/zh-tw/crypto/token-decimals-verification/)
- [預言機](/zh-tw/crypto/oracle/)
- [預言機攻擊](/zh-tw/crypto/oracle-attack/)

<a id="sources"></a>

## 資料來源

- [Data Feeds API Reference](https://docs.chain.link/data-feeds/api-reference) - Chainlink Documentation（存取日期：2026-08-13）
- [Chainlink Data Feeds](https://docs.chain.link/data-feeds) - Chainlink Documentation（存取日期：2026-08-13）
- [ERC-20: Token Standard](https://eips.ethereum.org/EIPS/eip-20) - Ethereum Improvement Proposals（存取日期：2026-08-13）
- [Types](https://docs.soliditylang.org/en/latest/types.html) - Solidity Documentation（存取日期：2026-08-13）
- [Expressions and Control Structures](https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic) - Solidity Documentation（存取日期：2026-08-13）
- [Utils](https://docs.openzeppelin.com/contracts/5.x/api/utils) - OpenZeppelin Contracts Documentation（存取日期：2026-08-13）
- [Oracles](https://aave.com/docs/aave-v3/smart-contracts/oracles) - Aave Protocol Documentation（存取日期：2026-08-13）
- [Compound v2 Price Feed](https://docs.compound.finance/v2/prices/) - Compound Documentation（存取日期：2026-08-13）

Source: https://wiki.fcontext.com/zh-tw/crypto/oracle-decimal-mismatch/index.mdx
