Только в образовательных целях; не является инвестиционным советом или инвестиционной рекомендацией. Инвестиции могут привести к убыткам.
Краткий ответ
Несоответствие десятичных разрядов оракула возникает, когда контракт интерпретирует исходное целое число с неверным показателем масштаба, направлением цены или внутренней шкалой. Разряды фида, токена и токена котировки, масштабы курса обертки или доли и принятые в протоколе форматы 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() фида описывает ответ этого фида, а не шкалу токена или протокола. Проверяемая арифметика может предотвратить переполнение откатом, но не обнаруживает формулу с неверной размерностью и способна вызвать отказ в обслуживании, если промежуточное произведение переполнится при представимом конечном результате.
Как это работает
- Зафиксируйте сеть, блок, потребителя, адаптер, прокси и агрегатор фида, токен или хранилище, версии компилятора и математической библиотеки, а также состояние обновления.
- Инвентаризируйте каждое целое число с типом и единицей: исходное количество токена, разряды токена, знаковый ответ фида, разряды фида, направление базового и котируемого активов, курс обертки или доли, внутренний масштаб протокола и разряды выходного токена.
- До преобразования проверьте источник: правильные адрес и направление, положительный ответ, время и статус, допустимые возраст и диапазон, семантику резервного источника и льготные правила секвенсора L2, если применимо.
- Выведите одну размерностную формулу от исходных единиц входа до исходных единиц выхода. Явно разделяйте повышение и понижение масштаба, ограничивайте каждый показатель степени десяти и нормализуйте каждое звено ровно один раз.
- Используйте доказанную операцию умножения-деления полной точности или ограниченную стратегию сокращения. Избегайте потери точности от деления до умножения, проверяемого переполнения промежуточного значения, непроверяемого зацикливания и небезопасных преобразований знака либо разрядности.
- Определите округление вниз, вверх или к ближайшему для каждого экономического действия. Обеспечение, долг, заимствование, выпуск, погашение, комиссии, ликвидация и конвертация долей хранилища могут требовать разных консервативных направлений.
- Проверяйте эталонные векторы и свойства на предельных количествах, сочетаниях разрядов, обратных и составных фидах, нулевых, отрицательных и устаревших ответах, обновлениях и пыли; сверяйте результаты в сети с независимой моделью высокой точности и ограничивайте затронутую экспозицию.
Нормализация — это анализ размерностей, а не форматирование. Для BTC/USD и USD/BTC нужны взаимно обратные формулы; замена подписи не обращает цену. Составные фиды требуют масштаба и времени каждого звена. Целочисленное деление Solidity усекает к нулю, поэтому алгебраически равносильные перестановки могут давать разные результаты в сети. Полноточный mulDiv решает проблему разрядности промежуточного результата, но вызывающая сторона все равно должна передать правильные числитель, знаменатель, единицы, границы и направление округления.
Примеры расчета
- Восемь разрядов против восемнадцати. Фид 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раз. - Обратная цена и усечение. ETH/USD в масштабе WAD равен
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не помещается. Проверяемое умножение откатывается, непроверяемое зацикливается, а полноточныйmulDivвозвращает2^200. Целочисленное5 / 2округляется вниз до2, тогда как округление вверх дает3, поэтому правило округления входит в экономический инвариант.
Риски
- Неверная сеть, фид, прокси, адаптер, токен, хранилище или адрес потребителя.
- Направление базового и котируемого активов обращено без преобразования к обратной цене.
- Разряды токена считаются равными 18 либо необязательные метаданные отсутствуют или ошибочны.
- Разряды фида считаются равными 8 вместо чтения и фиксации.
- Разряды токена котировки смешиваются со шкалой WAD, RAY, рынка или учета протокола.
- Разряды обертки, доли, индекса или обменного курса пропущены.
- Коэффициент масштаба применяется дважды после нормализации значения адаптером.
- Необходимый коэффициент масштаба или знаменатель пропущен.
- Знаковый ответ преобразуется в беззнаковый до проверки положительности.
- Принимается нулевой, устаревший, незавершенный, ограниченный или недействительный ответ фида.
- Показатель десятичной степени или расчет степени десяти уходит ниже нуля, переполняется или превышает границы.
- Промежуточное произведение переполняется, хотя итоговый частный результат поместился бы.
- Непроверяемая арифметика, битовые сдвиги или явное сужение незаметно зацикливают либо усекают значение.
- Деление до умножения уничтожает точность или превращает пыль в ноль.
- Округление вниз, вверх или к ближайшему неверно для экономического действия.
- Повторные преобразования накапливают потерю точности или систематическую утечку стоимости.
- Цены, лимиты, коэффициенты, проценты, базисные пункты, WAD и RAY сравниваются в разных единицах.
- Обновления фида, токена, прокси, адаптера или хранилища делают закэшированные предположения о разрядах недействительными.
- Форматирование интерфейса, кошелька, RPC или индексатора скрывает иной расчет в сети.
- Ошибочная оценка усиливает заимствование, выпуск, погашение, ликвидацию, лимиты, безнадежный долг или несправедливый выпуск долей.
Распространенные заблуждения
- «Каждый токен ERC-20 использует 18 разрядов». Метод метаданных ERC-20 необязателен, а развернутые активы используют разные значения и поведение.
- «Каждый долларовый ценовой фид использует 8 разрядов». Точность фида — свойство интерфейса конкретного развертывания, которое нужно читать и версионировать.
- «Большое исходное целое число доказывает манипуляцию». Исходная величина лишена смысла без единиц, направления, разрядов, времени и масштаба потребителя.
- «Solidity 0.8 делает масштабирование правильным». Проверка переполнения может откатить транзакцию, но не исправляет неверные единицы, усечение, преобразование типов или политику округления.
- «Умножение до деления или добавление разрядов всегда повышает точность». Это может вызвать переполнение, двойное масштабирование или сохранить неверную единицу; полноточной арифметике также нужна правильная формула.
Связанные темы
Источники
- Data Feeds API Reference - Chainlink Documentation (дата обращения: 2026-08-13)
- Chainlink Data Feeds - Chainlink Documentation (дата обращения: 2026-08-13)
- ERC-20: Token Standard - Ethereum Improvement Proposals (дата обращения: 2026-08-13)
- Types - Solidity Documentation (дата обращения: 2026-08-13)
- Expressions and Control Structures - Solidity Documentation (дата обращения: 2026-08-13)
- Utils - OpenZeppelin Contracts Documentation (дата обращения: 2026-08-13)
- Oracles - Aave Protocol Documentation (дата обращения: 2026-08-13)
- Compound v2 Price Feed - Compound Documentation (дата обращения: 2026-08-13)