Tendencias del momento
#
Bonk Eco continues to show strength amid $USELESS rally
#
Pump.fun to raise $1B token sale, traders speculating on airdrop
#
Boop.Fun leading the way with a new launchpad on Solana.
Bienvenido de nuevo a Spotlight de Vulnerabilidades de Sherlock, donde destacamos una vulnerabilidad impactante descubierta durante una auditoría de Sherlock.
Esta semana, examinamos un cálculo incorrecto del nivel de colateral encontrado en el concurso de @plaza_finance por @0xadrii, @KupiaSecurity, @f,
@farman1094_, y @0xnovaman33.

Resumen de la vulnerabilidad:
En getRedeemAmount(...), el contrato calcula el nivel de colateral para las redenciones de BOND utilizando el estado post-transacción:
// código actual (vulnerable)
collateralLevel =
((tvl - (depositAmount * BOND_TARGET_PRICE)) * PRECISION)
/ ((bondSupply - depositAmount) * BOND_TARGET_PRICE);
Debido a que la fijación de precios de redención utiliza este collateralLevel estimado para decidir si pagar el precio máximo ($100), un atacante puede comprar BOND a tasas de creación mixtas (a veces con descuento) hasta que el nivel de colateral (actual) baje ≤ 1.2, y luego canjear todo BOND al límite de $100—calculando con un depositAmount elaborado que empuje el nivel de colateral estimado de nuevo por encima de 1.2. Esto permite al atacante extraer ETH (diferencial "sin riesgo") hasta que el nivel de colateral actual del fondo alcance el umbral.
Pasos del ataque:
1) Fase de configuración
Ejemplo de parámetros del pool:
- poolReserve = 120 ETH, bondSupply = 3000, levSupply = 200, precio de ETH = $3075
Reglas de precios:
Crear (comprar) BOND:
- Si collateralLevel ≤ 1.2: creationRate = tvl * 0.8 / bondSupply
- De lo contrario: creationRate = $100
Redimir (vender) BOND:
- Si estimated collateralLevel ≤ 1.2: redeemRate = tvl * 0.8 / bondSupply
- De lo contrario: redeemRate = $100
2) Fase A – Comprar BOND a tasas mixtas/descontadas
- Comprar BOND mientras se monitorea el nivel de colateral (actual) = tvl / (bondSupply * 100).
- La primera compra ocurre mientras el nivel de colateral > 1.2 → acuñar cerca de $100 por BOND.
- Compras posteriores empujan el nivel de colateral actual por debajo de 1.2 → acuñar a una tasa de creación descontada (por ejemplo, ~$94.07 en), acumulando un gran saldo de BOND de forma económica.
3) Fase B – Canjear todos los BOND al precio máximo
- Llamar a redeem(BOND, depositAmount = attackerBondBalance, ...)
- El contrato calcula el nivel de colateral estimado utilizando el estado posterior al canje (bondSupply - depositAmount) y (tvl - depositAmount * 100) y (en el ejemplo) obtiene un valor > 1.2
- Debido a que ese valor estimado excede el umbral, redeemRate se establece en el máximo de $100, permitiendo al atacante retirar todos los BOND acumulados a $100
4) Realización de beneficios
- La diferencia entre las compras con descuento y las ventas de $100 genera un beneficio neto en ETH.
- En los números del PoC: gastar 60 ETH en dos compras devuelve ~61.89 ETH al canjear → ~1.89 ETH de beneficio.
- El atacante puede iterar hasta que el nivel de colateral del pool caiga a ~1.2, extrayendo aproximadamente: USD extraíbles ≈ ethPrice × poolReserve − 120 × bondSupply
¿Cuál es el impacto?
Extracción directa de fondos / fuga de valor: El atacante acuña a tarifas descontadas y canjea a $100, drenando ETH del fondo.
Sin límites hasta el umbral: Puede continuar hasta que el nivel actual de colateral del fondo se reduzca a ≈ 1.2.
Inconsistencia de precios sistémica: Crea arbitraje que los usuarios honestos pagan a través de peores reservas/resultados del fondo.
La causa raíz:
Uso del estado post-comercio para la fijación de precios de redenciones
El código calcula collateralLevel como si la redención ya hubiera ocurrido:
// usa (tvl - depositAmount*100) y (bondSupply - depositAmount)
collateralLevel =
((tvl - (depositAmount * BOND_TARGET_PRICE)) * PRECISION)
/ ((bondSupply - depositAmount) * BOND_TARGET_PRICE);
1. Esto permite a un atacante elegir depositAmount de tal manera que el nivel estimado cruce el umbral (> 1.2), desbloqueando el $100 redeemRate, incluso cuando el estado actual del pool no lo justificaría.
2. Umbral de control en una métrica manipulada
La decisión del límite de $100 depende de este nivel de colateral estimado manipulable en lugar del nivel actual (pre-comercio), lo que permite manipular el precio.
La Mitigación:
Calcular el precio de redención a partir del estado actual del pool, no de los saldos estimados post-redención. La solución sugerida por el proyecto es correcta:
- collateralLevel = ((tvl - (depositAmount * BOND_TARGET_PRICE)) * PRECISION)
- / ((bondSupply - depositAmount) * BOND_TARGET_PRICE);
+ collateralLevel = (tvl * PRECISION) / (bondSupply * BOND_TARGET_PRICE);
Endurecimiento adicional (recomendado):
1. Monotonía de precios: Asegúrate de que el precio de canje no aumente a medida que aumenta el depositAmount (sin "vender más, obtener un mejor precio por unidad").
2. Precios basados en invariantes: Deriva la creación/canje de un solo invariante para que la simetría de compra/venta prevenga el arbitraje unilateral.
3. Comprobaciones de deslizamiento: Requiere tasas mínimas/máximas proporcionadas por el usuario tanto para crear como para canjear.
4. Límite y control: Límites de canje por transacción y por bloque para limitar el daño si se acercan a los umbrales.
5. Consistencia a través de rutas: Alinea las rutas de creación y canje para usar la misma definición de nivel de colateral (solo estado actual).
Estamos orgullosos de haber ayudado a asegurar @plaza_finance a través de este descubrimiento.
Cuando realmente necesita ser seguro, Sherlock es la elección correcta.
3,27K
Parte superior
Clasificación
Favoritos

