Saltar al contenido

Desajustes de decimales en oráculos

Un desajuste de decimales aplica una escala de unidades incorrecta a la respuesta de un oráculo, el importe de un token, la tasa de un wrapper o un valor del protocolo, lo que causa errores de varios órdenes de magnitud en préstamos, acuñaciones, reembolsos y liquidaciones.

Actualizado

Solo con fines educativos; no constituye asesoramiento de inversión. Invertir puede ocasionar pérdidas.

Respuesta directa

Un desajuste de decimales de un oráculo se produce cuando un contrato interpreta un entero bruto con un exponente de unidad, una dirección del precio o una escala interna incorrectos. Los decimales del feed, del token y del token cotizado, las escalas del tipo de cambio de un wrapper o de participaciones y las convenciones WAD o RAY del protocolo son independientes. Que una interfaz muestre un valor correcto no demuestra que el contrato consumidor aplique la misma aritmética.

Para un importe del token base A_raw con d_t decimales y una respuesta positiva del feed P_raw que cotiza un token base en tokens cotizados con d_p decimales, un importe bruto del token cotizado con d_q decimales es V_raw = round(A_raw * P_raw * 10^d_q / 10^(d_t + d_p)). La fórmula solo es válida para la dirección de cotización indicada y tras validar feed, unidades, tipos y regla de redondeo. Un adaptador que ya normalizó un valor no debe volver a escalarlo.

En ERC-20, decimals() son metadatos de visualización opcionales, no una garantía universal de 18 decimales. Los decimals() de un feed describen su respuesta, no la escala del token ni la del protocolo. La aritmética comprobada puede detener un desbordamiento mediante revert, pero no detecta una fórmula dimensionalmente errónea y puede convertir un resultado representable en una denegación de servicio si desborda un producto intermedio.

Cómo funciona

  1. Fije cadena, bloque, consumidor, adaptador, proxy y agregador del feed, token o vault, versiones del compilador y de la biblioteca matemática y estado de actualización.
  2. Inventaríe cada entero con su tipo y unidad: importe bruto del token, decimales del token, respuesta con signo del feed, decimales del feed, orientación base/cotizada, tasa del wrapper o participación, escala interna del protocolo y decimales del token de salida.
  3. Valide la fuente antes de convertir: dirección y sentido correctos, respuesta positiva, timestamp y estado, antigüedad e intervalo aceptables, semántica del fallback y reglas de gracia del secuenciador L2 cuando proceda.
  4. Derive una única fórmula dimensional desde las unidades brutas de entrada hasta las de salida. Separe explícitamente el aumento y la reducción de escala, acote cada exponente de potencia de diez y normalice cada componente exactamente una vez.
  5. Use una multiplicación-división de precisión completa demostrada o una cancelación acotada. Evite el truncamiento por dividir antes de multiplicar, el desbordamiento intermedio comprobado, el wraparound no comprobado y las conversiones con signo o estrechas inseguras.
  6. Especifique redondeo hacia abajo, arriba o al más próximo para cada acción económica. Garantía, deuda, préstamo, acuñación, reembolso, comisiones, liquidación y conversiones de participaciones pueden requerir sentidos conservadores distintos.
  7. Pruebe vectores conocidos y propiedades con importes extremos, combinaciones de decimales, recíprocos, feeds compuestos, respuestas cero, negativas y obsoletas, actualizaciones y dust; concilie los resultados onchain con un modelo independiente de alta precisión y limite la exposición afectada.

La normalización es análisis dimensional, no formato. BTC/USD y USD/BTC requieren fórmulas recíprocas; cambiar una etiqueta no invierte el precio. Los feeds compuestos exigen la escala y el timestamp de cada componente. La división entera de Solidity trunca hacia cero, por lo que reordenamientos algebraicamente equivalentes pueden producir resultados onchain distintos. Un mulDiv de precisión completa resuelve el ancho intermedio, pero quien lo invoca aún debe proporcionar numerador, denominador, unidades, límites y sentido de redondeo correctos.

Ejemplos resueltos

  • Ocho frente a dieciocho decimales. Un feed BTC/USD devuelve 6,000,000,000,000 con d_p = 8, por lo que el precio es 60,000 USD/BTC. Interpretar la respuesta bruta con 18 decimales da 0.000006 USD/BTC, una infravaloración por 10^10, no por 10^9. Escalar el precio a WAD da 6,000,000,000,000 * 10^(18 - 8) = 60,000,000,000,000,000,000,000.
  • Unidades de importe, precio y salida. A_raw = 2,500,000 representa 2.5 tokens con d_t = 6; P_raw = 200,000,000 representa 2 tokens cotizados con d_p = 8. Para un valor cotizado interno de 18 decimales, 2,500,000 * 200,000,000 * 10^18 / 10^(6 + 8) = 5,000,000,000,000,000,000, o 5 quote tokens. Omitir el denominador del token sobrevalora la posición por 10^6.
  • Recíproco y truncamiento. ETH/USD a escala WAD es 2,000 * 10^18. USD/ETH a la misma escala es floor(10^36 / (2,000 * 10^18)) = 500,000,000,000,000, o 0.0005 ETH/USD. Por separado, con A_raw = 999,999, d_t = 6 y precio 2 * 10^18, la multiplicación-división completa da 1,999,998,000,000,000,000; dividir primero el importe por 10^6 da 0 y pierde todo el valor.
  • Desbordamiento intermedio y redondeo. Sean x = 2^200, y = 2^100 y el denominador 2^100. El resultado exacto es 2^200, que cabe en uint256, pero x * y = 2^300 no. La multiplicación comprobada revierte y la no comprobada hace wrap; un mulDiv de precisión completa devuelve 2^200. La división entera 5 / 2 redondea hacia abajo a 2, mientras que una regla de techo devuelve 3, de modo que el redondeo forma parte del invariante económico.

Riesgos

  • Cadena, feed, proxy, adaptador, token, vault o consumidor incorrectos.
  • Orientación base/cotizada invertida sin conversión recíproca.
  • Se supone que el token tiene 18 decimales o sus metadatos opcionales no están disponibles o son erróneos.
  • Se supone que el feed tiene 8 decimales en vez de leerlos y fijarlos.
  • Se confunden los decimales del token cotizado con la escala WAD, RAY, de mercado o contable del protocolo.
  • Se omiten los decimales del wrapper, participación, índice o tasa de cambio.
  • Se aplica dos veces un factor después de que el adaptador ya haya normalizado el valor.
  • Se omite un factor de escala o denominador necesario.
  • Una respuesta con signo se convierte a unsigned antes de verificar que sea positiva.
  • Se acepta una respuesta cero, obsoleta, incompleta, limitada o inválida.
  • Un exponente decimal o potencia de diez sufre underflow, overflow o excede los límites.
  • Un producto intermedio desborda aunque el cociente final quepa.
  • Aritmética unchecked, desplazamientos de bits o estrechamientos explícitos hacen wrap o truncan silenciosamente.
  • Dividir antes de multiplicar destruye precisión o convierte dust en cero.
  • El redondeo hacia abajo, arriba o al más próximo es incorrecto para la acción económica.
  • Conversiones repetidas acumulan pérdida de precisión o fuga sistemática de valor.
  • Precios, límites, ratios, porcentajes, puntos básicos, WAD y RAY se comparan en unidades distintas.
  • Actualizaciones de feed, token, proxy, adaptador o vault invalidan supuestos de decimales almacenados.
  • El formato de interfaz, wallet, RPC o indexador oculta un cálculo onchain diferente.
  • La valoración errónea amplifica préstamos, acuñaciones, reembolsos, liquidaciones, límites, deuda incobrable o emisión injusta de participaciones.

Errores frecuentes

  • «Todos los tokens ERC-20 usan 18 decimales». El método de metadatos ERC-20 es opcional y los activos desplegados emplean valores y comportamientos distintos.
  • «Todos los feeds de precios en USD usan 8 decimales». La precisión es una propiedad de interfaz del despliegue exacto y debe leerse y versionarse.
  • «Un entero bruto grande demuestra manipulación». Su magnitud carece de significado sin unidades, dirección, decimales, timestamp y escala del consumidor.
  • «Solidity 0.8 hace correcto el escalado». El overflow comprobado puede revertir, pero no corrige unidades, truncamiento, conversiones ni política de redondeo.
  • «Multiplicar antes de dividir o añadir decimales siempre mejora la precisión». Puede desbordar, duplicar la escala o conservar una unidad incorrecta; incluso la aritmética de precisión completa exige una fórmula correcta.

Temas relacionados

Fuentes

Navegación

Buscar en la wiki...