El 16 de abril de 2023, Hundred Finance, un fork de Compound V2, fue atacado, lo que provocó una pérdida de aproximadamente 7,4 millones de dólares. El ataque involucró dos problemas principales:
- Un problema de pérdida de precisión (un problema de redondeo incorrecto);
- Mercados vacíos, que permitieron al hacker manipular el exchangeRate.
Compound V2, el protocolo de préstamos más bifurcado según DeFiLlama, cuenta con más de 100 forks. Auditado por OpenZeppelin y probado en batalla, sus contratos se consideran seguros. Sin embargo, el ataque a Hundred Finance destacó cómo la pérdida de precisión, especialmente en baja liquidez, puede afectar de manera crítica la seguridad de los protocolos DeFi, desencadenando una ola de exploits similares en forks notables como Midas y Radiant.
Para una comprensión más profunda, se recomienda consultar el análisis completo. A continuación, ofrecemos una introducción concisa a este incidente, destacándolo como uno de los diez principales incidentes de seguridad de 2023.
Antecedentes
Descripción general de Hundred Finance
Hundred Finance es un fork de Compound v2 que opera en múltiples mainnets, utilizando oráculos de Chainlink. A diferencia de las prácticas de préstamo en finanzas tradicionales, los protocolos de préstamos DeFi como Compound y Aave no permiten los préstamos con sobrecolateralización. En pocas palabras, si depositas $100 en valor de Token A, solo puedes pedir prestado activos por menos de $100. Según los coeficientes de control de riesgo de la mayoría de los protocolos, esta proporción generalmente oscila entre el 50% y el 80%.
Para los protocolos de préstamos, los métodos de ataque comunes incluyen la manipulación de precios y la reentrada. Curiosamente, Hundred Finance había experimentado previamente un ataque de reentrada en marzo de 2022, pero este incidente creó un nuevo vector de ataque.
hToken
Los protocolos de préstamos que bifurcan de Compound y Aave crean un token contable correspondiente para cada token subyacente (colateral). Para Hundred Finance:
- USDC corresponde a hUSDC
- WBTC corresponde a hWBTC
La tasa de cambio entre el token subyacente y el hToken se denomina exchangeRate.
- Al depositar activos, los usuarios deben llamar al
mint()del hToken. - Al retirar activos, el usuario debe llamar al
redeem()del hToken.
exchangeRate
La siguiente es la fórmula para calcular el exchangeRate:

Donde:
getCash(): La cantidad de saldo del token subyacente que posee este contrato hToken. Este es un parámetro clave que puede ser manipulado. Por favor, recuerde esto.totalBorrows(): La cantidad de token subyacente actualmente prestado por el mercado, y la cantidad sobre la cual se acumula interés para los proveedores del mercado.totalReserves(): Las reservas son una entrada contable en cada contrato hToken que representa una porción del interés histórico reservado como efectivo que puede retirarse o transferirse a través de la gobernanza del protocolo.totalSupply(): El número de tokens actualmente en circulación en este mercado hToken.
Nota: El exchangeRate entre un hToken y el activo subyacente, por ejemplo (dai vs hDai o eth vs hEth), comienza en 0.020 y aumenta a una tasa igual a la tasa de interés compuesta del mercado.
Liquidación
Para prevenir deudas incobrables, los protocolos de préstamos permiten a cualquier usuario liquidar la deuda de otro usuario. Usemos el siguiente ejemplo para ilustrarlo:
- Alice deposita BTC por valor de $100 y pide prestado ETH por valor de $70.
- Si el precio del ETH sube o el precio del BTC baja, los activos de Alice pueden alcanzar el umbral de liquidación.
- Bob puede usar una cierta cantidad de ETH para liquidar el BTC de Alice, llevando la deuda de Alice a un nivel saludable para garantizar la seguridad de los fondos del protocolo (el protocolo recompensa a los usuarios que inician la liquidación).
La liquidación no es el foco de este ataque, pero estuvo involucrada en el ataque. Aquí, solo necesitamos saber que cualquier usuario puede liquidar la deuda de otro usuario con un tipo de Token, lo que reducirá el hToken correspondiente.
La Vulnerabilidad
Problema de Pérdida de Precisión
El hacker hace que cuando el colateral se retira a través de redeem(), el cálculo de la cantidad de hToken a deducir resulta en 1.99999992 (muy cercano a 2 pero menor que 2). Al convertir a un entero en truncate(), el uso del redondeo hacia abajo lleva a un resultado final de 1.

exchangeRate
El cálculo del exchangeRate, como se introdujo anteriormente, involucra getCash(), que se refiere a la cantidad de saldo subyacente que posee el contrato hToken. Al transferir directamente tokens subyacentes al contrato (sin mint, solo transfiriendo), el hacker puede manipular el exchangeRate.
Sin embargo, es importante señalar que este problema de exchangeRate por sí solo no compromete la seguridad del protocolo; los hackers no pueden obtener ganancias de él de forma aislada. En el contexto de este ataque, fue explotado principalmente para amplificar las ganancias del hacker, permitiéndoles agotar rápidamente el pool. De lo contrario, el ataque pasa de ser un golpe único y decisivo a una serie de pequeñas puñaladas, que requieren numerosas iteraciones para tener un impacto significativo.
En resumen, la pérdida de precisión es el problema clave en este ataque.
El Proceso del Ataque
Aquí está la transacción del ataque, y ahora usaremos Phalcon Explorer para analizar esta compleja transacción.
Transacción: 0x6e9ebcdebbabda04fa9f2e3bc21ea8b2e4fb4bf4f4670cb8483e2f0b2604f451
-
Tomar prestados 500 WBTC de Aave V3 a través de un Flashloan.
-
Redimirtodos los hWBTC adquiridos previamente, restablecer eltotalSupplyde hWBTC a 0.
El objetivo anterior es preparar fondos de reserva usando un flashloan y restablecer hWBTC como un nuevo mercado.
-
Crearel segundo contrato de ataque (en adelante denominado Contrato de Ataque 2) y transferir todos los WBTC (500.30063816 WBTC) al Contrato de Ataque 2.
-
Mint()hWBTC usando 4 WBTC para producir 200 hWBTC. -
Redeem()199.99999998 hWBTC, dejando el total de hWBTC en 0.00000002 (2 wei hWBTC). -
Transferir todos los WBTC (500.30063816 WBTC) a hWBTC. Nota, las transferencias directas no incrementan hWBTC; puede verse como donar WBTC al pool. El propósito principal de este paso es manipular el
exchangeRatemencionado anteriormente. En este punto, eltotalSupplyde hWBTC permanece en 2 wei hWBTC, pero ahora hay 500.30064194 WBTC, lo que hace que elexchangeRatesea cientos de veces el original.

-
Tomar prestados 1021 Ether del mercado hETH.
-
Redeem()50030063815 WBTC, donde, tras el cálculo, deberían deducirse 1.9999992 hBTC, pero debido a la pérdida de precisión, solo se deduce 1 hBTC, creando una pérdida de precisión significativa (casi el 50%).
En este punto, el hacker tiene 500 WBTC + 1021 Ether, habiendo obtenido con éxito una ganancia de 1021 Ether. -
El atacante
liquidate()los hWBTC restantes, restableciendo sutotalSupplya 0, en preparación para continuar los ataques en otros mercados. Dado que casi todos los WBTC dentro de hWBTC han sido retirados, el hacker lo logra con solo 0.000002 Ether.
-
Continuar atacando otros mercados, agotando todo el protocolo.
-
Reembolsar el Flashloan a Aave.
Recomendaciones de Seguridad
Mitigaciones para Protocolos de Préstamos
Este problema es prevalente, particularmente para los forks de Compound y Aave. Un enfoque proactivo implica, al lanzar nuevos mercados, acuñar algunos tokens contables para garantizar que el totalSupply nunca llegue a 0.
Mitigaciones para el Problema de Pérdida de Precisión
Para eludir mejor la serie de problemas debidos a la pérdida de precisión, establecer un valor mínimo es un método efectivo en la práctica. Esta estrategia ayuda a evitar el impacto significativo causado por la pérdida de precisión cuando se trabaja con valores muy pequeños.
Leer otros artículos de esta serie:
- Introducción: Los Diez Principales Incidentes de Seguridad "Increíbles" de 2023
- #1: Cosechando Bots MEV Explotando Vulnerabilidades en Flashbots Relay
- #2: Incidente de Euler Finance: El Mayor Hackeo de 2023
- #3: Incidente de KyberSwap: Explotación Magistral de Errores de Redondeo con Cálculos Extremadamente Sutiles
- #4: Incidente de Curve: Error del Compilador Produce Bytecode Defectuoso a partir de Código Fuente Inocente
- #5: Platypus Finance: Sobreviviendo Tres Ataques con un Golpe de Suerte
- #7: Incidente de ParaSpace: Una Carrera Contra el Tiempo para Frustrar el Ataque Más Crítico de la Industria hasta el Momento
- #8: Incidente de SushiSwap: Un Torpé Intento de Rescate Conduce a una Serie de Ataques Imitadores
- #9: MEV Bot 0xd61492: De Depredador a Presa en un Exploit Ingenioso
- #10: Incidente de ThirdWeb: La Incompatibilidad Entre Módulos de Confianza Expone una Vulnerabilidad



