Reclamación doble de referidos en Level Finance
Level Finance en BNB Chain perdió 1,1 M$ porque LevelReferralControllerV2 pagaba recompensas sin marcar la época reclamada, permitiendo reclamaciones repetidas.
- Fecha
- Víctima
- Level Finance
- Cadena(s)
- Estado
- Fondos robados
El 1 de mayo de 2023, el protocolo de perpetuos en BNB Chain Level Finance perdió aproximadamente 1,1 millones de dólares (214.000 tokens LVL) mediante un bug de doble reclamación en su contrato LevelReferralControllerV2. La función de reclamación de recompensas de referidos pagaba antes de marcar la época como reclamada, dejando a un atacante reclamar las recompensas de la misma época repetidamente en un bucle.
Qué ocurrió
Level Finance corría un programa de referidos: los usuarios ganaban recompensas en tokens LVL basadas en volumen de trading referido, reclamables por época. La función claimMultiple en LevelReferralControllerV2 procesaba estas reclamaciones.
El bug era una violación de manual de checks-effects-interactions específica a la contabilidad de reclamaciones:
- La función de reclamación calculaba las recompensas debidas al usuario para una época.
- Transfería los tokens LVL al usuario.
- Luego actualizaba la contabilidad para marcar esa época como reclamada.
Como el paso "marcar como reclamada" ocurría después del pago, y como la función podía llamarse repetidamente dentro del mismo contexto de transacción antes de que el estado se asentara, el atacante podía reclamar las recompensas de la misma época muchas veces antes de que el contrato registrara alguna como reclamada.
El atacante bucleó la reclamación, extrayendo 214.000 LVL (~1,1 M$) contra el derecho legítimo de una sola época, luego volcó el LVL en liquidez.
Consecuencias
- Level Finance confirmó el exploit e identificó el orden defectuoso de la reclamación como la única causa raíz.
- El equipo pausó el contrato de referidos y desplegó una versión corregida con el estado de reclamación actualizado antes del pago.
- El token LVL sufrió un golpe de precio por el volcado; el protocolo continuó operando con el contrato parcheado.
Por qué importa
Level Finance es una instancia de pocos dólares pero pedagógicamente perfecta de la regla más antigua de la seguridad de contratos inteligentes: checks-effects-interactions: actualiza tu estado antes de hacer la llamada externa / pago, nunca después.
El DAO lo enseñó en 2016. Es la primera regla en cada guía de seguridad de Solidity. Y aun así sigue saliendo a producción: aquí en una función de reclamación de recompensas en vez de una función de retiro, que es exactamente por qué se coló: los desarrolladores interiorizan "aplica CEI a los retiros" pero no siempre reconocen que una reclamación de recompensa de referido es estructuralmente un retiro y necesita la misma disciplina.
El catálogo está lleno de este fallo de generalización: la clase de bug central es bien conocida, pero reaparece cada vez vistiendo ropa ligeramente distinta:
- Reentrada en depósitos (Grim), no solo en retiros.
- Comprobaciones de solvencia ausentes en funciones de emergencia (Platypus), no solo en funciones de ruta normal.
- CEI violado en reclamaciones de recompensas (Level Finance), no solo en transferencias de tokens.
La lección que Level Finance cristaliza: una clase de vulnerabilidad no está "manejada" porque las instancias obvias de ella estén manejadas. Cada función que mueve valor está sujeta a las mismas reglas, y los bugs se agrupan precisamente en las funciones que los desarrolladores no piensan como movedoras de valor: periferia, recompensas, migración, emergencia, reclamación. Esas son las funciones escritas más rápido y revisadas menos, y el catálogo muestra, una y otra vez, que son donde aparecerá la siguiente instancia de los bugs más antiguos.
Fuentes y evidencia on-chain
- [01]halborn.comhttps://www.halborn.com/blog/post/explained-the-level-finance-hack-may-2023
- [02]beincrypto.comhttps://beincrypto.com/decentralized-perpetual-market-level-finance-hacked-1-1m/
- [03]rekt.newshttps://rekt.news/level-finance-rekt