Informe de auditoría de contratos inteligentes para Dusa

Resumen de gestión

Dusa se puso en contacto con Sayfer para realizar una auditoría de seguridad de sus contratos inteligentes. 

Este informe documenta la investigación realizada por Sayfer dirigida a los recursos seleccionados definidos bajo el alcance de la investigación. En particular, este informe muestra la revisión de la postura de seguridad de los contratos inteligentes de Dusa.

Durante el período de investigación de 4 semanas, descubrimos 17 vulnerabilidades en el contrato.

En general, Dusa es un protocolo bien construido. El hecho de que se derive y traduzca de TraderJoe lo convierte en un protocolo muy sólido con una arquitectura bastante común, pero considerada óptima. Sin embargo, tenemos algunas recomendaciones que creemos que podrían mejorar la calidad y seguridad del protocolo. Estas recomendaciones se detallan en la sección "Revisión de arquitectura".

En conclusión, se deben implementar varias correcciones después del informe, pero la postura de seguridad del sistema es competente.

Después de una revisión por parte del equipo de Sayfer, certificamos que todos los problemas de seguridad mencionados en este informe han sido abordados o reconocidos por el equipo de Dusa.

Metodología de Riesgo

En Sayfer, estamos comprometidos a ofrecer auditorías de contratos inteligentes de la más alta calidad a nuestros clientes. Es por eso que hemos implementado un modelo integral de evaluación de riesgos para evaluar la gravedad de nuestros hallazgos y brindar a nuestros clientes las mejores recomendaciones posibles para la mitigación.

Nuestro modelo de evaluación de riesgos se basa en dos factores clave: IMPACTO y PROBABILIDAD. El impacto se refiere al daño potencial que podría resultar de un problema, como pérdidas financieras, daños a la reputación o un sistema no operativo. La probabilidad se refiere a la probabilidad de que ocurra un problema, teniendo en cuenta factores como la complejidad del contrato y la cantidad de atacantes potenciales.

Al combinar estos dos factores, podemos crear una comprensión integral del riesgo que plantea un problema en particular y brindar a nuestros clientes una evaluación clara y procesable de la gravedad del problema. Este enfoque nos permite priorizar nuestras recomendaciones y garantizar que nuestros clientes reciban el mejor asesoramiento posible sobre cómo proteger sus contratos inteligentes.

El riesgo se define de la siguiente manera:

Vulnerabilidades por Riesgo

Alta – Amenaza directa a los procesos clave del negocio.
Medio – Amenaza indirecta a los procesos comerciales clave o amenaza parcial a los procesos comerciales.
Baja – No existe amenaza directa. La vulnerabilidad puede explotarse utilizando otras vulnerabilidades.
Informativo – Este hallazgo no indica vulnerabilidad, pero establece un comentario que notifica sobre fallas de diseño e implementación incorrecta que podría causar un problema a largo plazo.

Gravedad
# de problemas
Alta
2
Medio
1
Baja
8
Informativo
6
Critical
0

Enfoque

Introducción

Dusa se puso en contacto con Sayfer para realizar una auditoría de seguridad de sus contratos inteligentes.

Este informe documenta la investigación realizada por Sayfer dirigida a los recursos seleccionados definidos bajo el alcance de la investigación. En particular, este informe muestra la revisión de la postura de seguridad de los contratos antes mencionados.

Descripción general del alcance

Junto con el equipo del cliente definimos el siguiente contrato como alcance del proyecto.

Contrato Sha-256
Fábrica.ts b86a4c350c37a0d8c62495bde0be2b0dca2c8a9f343149238548690df5104cee
principal.ts d0073078a6ef26a402bcfb368e94dfb9dddc3f2a629eabc842e2b62d62772b6a
par.ts 186f3bd5fab92cb4e98ea5daef31f44d1889f28e683663d056ff6649685ce36c
Cotizador.ts b51c762d8ebe50c6b966c9b52a33819a674fb7cf056062ebe34d8f425d879aad
enrutador.ts 038e32c21432ad173cf8f3b77a586f222a99a8d0f8e033e40145643671ff87ee
WMAS.ts bcef456ec5e27527ae560e21b00fb9f4c8300016aae584da3aa1e869c7018832

Nuestras pruebas se realizaron entre enero y febrero de 2024.

¡No dejes que sea demasiado tarde!

Comienza tu auditoría con Sayfer

Validación del alcance

Comenzamos asegurándonos de que el alcance que nos definió el cliente fuera técnicamente lógico. Decidir qué alcance es el adecuado para un sistema determinado es parte de la discusión inicial.

Modelo de amenaza

Nosotros defiCabe señalar que la mayor amenaza actual para el sistema es la capacidad de los usuarios malintencionados de robar fondos del contrato.

¡No dejes que sea demasiado tarde!

Comienza tu auditoría con Sayfer

Descripción general del protocolo

Introducción al protocolo

Dusa es un protocolo innovador de finanzas descentralizadas (DeFi), que presenta una experiencia de creador de mercado automatizado (AMM) totalmente descentralizada y avanzada. Dusa, construida sobre la cadena de bloques Massa, enfatiza principios clave como la descentralización total, la accesibilidad para todos los perfiles de usuario, la interoperabilidad con futuras aplicaciones descentralizadas (DApps) y un fuerte compromiso con la seguridad y la resistencia a la censura. Su hoja de ruta describe un enfoque por fases, que incluye investigación y desarrollo, pruebas, misiones incentivadas y el despliegue de un intercambio descentralizado (DEX). Las características únicas de Dusa incluyen liquidez concentrada, tarifas variables, liquidez autónoma y órdenes comerciales complejas, todas diseñadas para mejorar la experiencia del usuario y maximizar el rendimiento. Con un equipo dedicado, inversores estratégicos y asesores, Dusa pretende ser pionero en la adopción de contratos inteligentes autónomos y extender sus soluciones descentralizadas a otros ecosistemas.

Revisión de arquitectura

Reconociendo que Dusa es un derivado de una solución bien establecida, TraderJoe, y se alinea con un patrón arquitectónico reconocido, observamos recomendaciones adicionales limitadas para la arquitectura actual. Sin embargo, nuestra evaluación de la arquitectura del protocolo Dusa ha dado lugar a una visión integral, que combina conocimientos valiosos con recomendaciones bien pensadas para mejorar:

  • Desde el punto de vista de las mejores prácticas, recomendamos considerar la implementación de una billetera multifirma para administrar roles privilegiados en el futuro. Si bien reconocemos el reciente lanzamiento del código multifirma de Massa (https://github.com/massalabs/massa-standards/tree/feature/multisig-sc/smart-contracts/assembly/contracts/multisig), aconsejamos prudencia y consideramos el uso de una clave privada estándar también como una opción viable por el momento.
  • Otra recomendación reveladora sugiere adoptar un modelo de liquidez unificado, imaginando un Vault/PoolManager global en lugar de contratos individuales por grupo. Este cambio estratégico, inspirado en avances recientes en AMM como Uniswap V4 y Balancer, promete ventajas significativas. Estos incluyen swaps rentables de múltiples saltos y una capacidad mejorada de préstamos flash, atribuidos al acceso simplificado a todo el fondo de liquidez.

Evaluación de seguridad

Pruebas específicas de Dusa

Como Dusa se encuentra en una situación única al ser un reflejo de TraderJoe en un lenguaje de programación diferente, realizamos múltiples pruebas adicionales además de las habituales para asegurarnos de que no falten piezas. Aquí hay una lista de pruebas realizadas específicamente para el protocolo Dusa:

Revisiones de seguridad

  • Comprobaciones de desbordamiento/infradesbordamiento, especialmente debido al cambio en el código base de un idioma con comprobaciones predeterminadas a uno donde se requieren comprobaciones explícitas.
  • Uso de bibliotecas seguras (marcado_*).
  • Consistencia entre contratos en cuanto al flujo de fondos y convocatorias.
  • Visibilidad de las funciones para garantizar que se exporten las funciones adecuadas.
  • Implementación de control de acceso y protección de funciones sensibles.
  • Protección swap para proteger las interacciones con liquidez contra deslizamientos.

Autenticacion y autorizacion

  • Auditoría de todo el proceso de autenticación, derechos de propietario y esquema de autorización de puntos de entrada públicos individuales.
  • Identificación de posibles vulnerabilidades que conduzcan a permisos maliciosos para los atacantes.

Matemáticas y manejo de variables

  • Problemas relacionados con el cálculo, especialmente con múltiples tipos de variables, conversión y gestión de números de punto flotante.
  • Errores decimales relacionados con el aspecto único de que MASSA tiene 9 decimales.
  • Manejo de capacidades de desbordamiento/desbordamiento insuficiente.

Gestión de liquidez y préstamos flash

  • Examen de errores típicos relacionados con préstamos flash, incluidos errores de cálculo y bloqueo de fondos.
  • Cuestiones relacionadas con la creación de fábricas y pares, como la creación de pools peligrosos y la gestión de liquidez.
  • Verificación de los cálculos de remoción de liquidez, considerando las comisiones obtenidas durante la provisión de liquidez.

Funcionalidad e implementación

  • Implementación de swaps en comparación con otros DEX, centrándose en la gestión de tarifas y las diferencias en los tipos de tokens.
  • Posibilidad de ataques DoS al operar en tipos inseguros como vectores o matrices.
  • Verificación de problemas de centralización, como posible influencia en los precios, transferencias de tokens de usuario y cambios de configuración.

Manejo de datos de contexto

  • Verifique que se pasen los datos de contexto correctos a las funciones para evitar vulnerabilidades.

 

Pruebas genéricas

Los siguientes casos de prueba fueron la pauta durante la auditoría del sistema. Esta lista de verificación es una versión modificada de la SCSVS v1.2, con gramática mejorada, claridad, concisión y criterios adicionales. Donde hay una brecha en la numeración, se eliminó un criterio original. Los criterios que están marcados con un asterisco fueron agregados por nosotros.

Arquitectura, Diseño y Modelado de Amenazas

Arquitectura, Diseño y Modelado de Amenazas Nombre de la prueba
G1.2 Cada cambio de diseño introducido está precedido por el modelado de amenazas.
G1.3 La documentación define de forma clara y precisa todos los límites de confianza en el contrato (relaciones de confianza con otros contratos y flujos de datos significativos).
G1.4 El SCSVS, los requisitos de seguridad o la política están disponibles para todos los desarrolladores y probadores.
G1.5 Se definen los eventos para las operaciones (cambio de estado/crucial para el negocio).
G1.6 El proyecto incluye un mecanismo que puede detener temporalmente funcionalidades sensibles en caso de un ataque. Este mecanismo no debe bloquear el acceso de los usuarios a sus activos (por ejemplo, tokens).
G1.7 La cantidad de criptomonedas no utilizadas mantenidas en el contrato está controlada y en el nivel mínimo aceptable para no convertirse en un objetivo potencial de un ataque.
G1.8 Si cualquier persona puede llamar a la función de reserva, se incluye en el modelo de amenazas.
G1.9 La lógica de negocios es consistente. Los cambios importantes en la lógica deben aplicarse en todos los contratos.
G1.10 Se emplean herramientas automáticas de análisis de código para detectar vulnerabilidades.
G1.11 Se utiliza la versión principal más reciente de Solidity.
G1.12 Cuando se utiliza una implementación externa de un contrato, se utiliza la versión más reciente.
G1.13 Cuando las funciones se anulan para ampliar la funcionalidad, la palabra clave super se utiliza para mantener la funcionalidad anterior.
G1.14 El orden de la herencia se especifica cuidadosamente.
G1.15 Hay un componente que monitorea la actividad del contrato usando eventos.
G1.16 El modelo de amenaza incluye transacciones de ballenas.
G1.17 La fuga de una clave privada no compromete la seguridad de todo el proyecto.

Pólizas y Procedimientos

Pólizas y Procedimientos Nombre de la prueba
G2.2 La seguridad del sistema está bajo control constante (por ejemplo, el nivel esperado de fondos).
G2.3 Existe una política para rastrear nuevas vulnerabilidades de seguridad y actualizar las bibliotecas a la última versión segura.
G2.4 Se puede contactar públicamente al departamento de seguridad y que el procedimiento para manejar los errores informados (p. ej., una recompensa completa por errores) esté bien definido.
G2.5 El proceso de agregar nuevos componentes al sistema está bien definido.
G2.6 El proceso de cambios importantes en el sistema implica el modelado de amenazas por parte de una empresa externa.
G2.7 El proceso de adición y actualización de componentes al sistema incluye una auditoría de seguridad por parte de una empresa externa.
G2.8 En caso de que se produzca un ataque, existe un procedimiento de mitigación claro y bien conocido.
G2.9 El procedimiento en caso de hackeo define claramente qué personas deben ejecutar las acciones requeridas.
G2.10 El procedimiento incluye alertar a otros proyectos sobre el hackeo a través de canales confiables.
G2.11 Se define un procedimiento de mitigación de fugas de clave privada.

Capacidad de actualización

Capacidad de actualización Nombre de la prueba
G3.2 Antes de actualizar, se realiza una emulación en una bifurcación de la red principal y todo funciona como se espera en la copia local.
G3.3 El proceso de actualización se ejecuta mediante un contrato multisig donde más de una persona debe aprobar la operación.
G3.4 Los bloqueos de tiempo se utilizan para operaciones importantes para que los usuarios tengan tiempo de observar los próximos cambios (tenga en cuenta que eliminar posibles vulnerabilidades en este caso puede ser más difícil).
G3.5 inicializar() solo se puede llamar una vez.
G3.6 inicializar() solo puede ser llamado por un rol autorizado a través de modificadores apropiados (por ejemplo, inicializador, solo propietario).
G3.7 El proceso de actualización se realiza en una sola transacción para que nadie pueda adelantarlo.
G3.8 Los contratos actualizables tienen espacios reservados en las ranuras para evitar la sobrescritura.
G3.9 El número de espacios reservados (como un espacio) se ha reducido adecuadamente si se han agregado nuevas variables.
G3.10 No hay cambios en el orden en que se declaran las variables de estado del contrato, ni en sus tipos.
G3.11 Los nuevos valores devueltos por las funciones son los mismos que en versiones anteriores del contrato (por ejemplo, propietario(), saldoDe(dirección)).
G3.12 Se inicializa la implementación.
G3.13 La implementación no puede ser destruida.

 

Lógica de negocios

Lógica de negocios Nombre de la prueba
G4.2 La implementación de la lógica del contrato y los parámetros del protocolo corresponde a la documentación.
G4.3 La lógica empresarial procede en un orden de pasos secuenciales y no es posible omitir pasos o hacerlo en un orden diferente al diseñado.
G4.4 El contrato ha aplicado correctamente los límites comerciales.
G4.5 La lógica empresarial no se basa en los valores recuperados de contratos que no son de confianza (especialmente cuando hay varias llamadas al mismo contrato en un solo flujo).
G4.6 La lógica comercial no se basa en el saldo del contrato (por ejemplo, saldo == 0).
G4.7 Las operaciones sensibles no dependen de los datos del bloque (p. ej., hash de bloque, marca de tiempo).
G4.8 El contrato utiliza mecanismos que mitigan los ataques de ordenación de transacciones (ejecución inicial) (por ejemplo, esquemas de compromiso previo).
G4.9 El contrato no envía fondos automáticamente, sino que permite a los usuarios retirar fondos en transacciones separadas.

Control de Acceso

Control de Acceso Nombre de la prueba
G5.2 Se mantiene el principio del menor privilegio. Otros contratos solo deberían poder acceder a funciones y datos para los que posean autorización específica.
G5.3 Los nuevos contratos con acceso al contrato auditado se adhieren al principio de derechos mínimos por defecto. Los contratos deben tener permisos mínimos o nulos hasta que se otorgue explícitamente el acceso a las nuevas funciones.
G5.4 El creador del contrato cumple con el principio del mínimo privilegio y sus derechos siguen estrictamente los señalados en la documentación.
G5.5 El contrato hace cumplir las reglas de control de acceso especificadas en un contrato de confianza, especialmente si el control de acceso del lado del cliente de la dApp está presente y podría omitirse.
G5.6 Las llamadas a contratos externos solo están permitidas si es necesario.
G5.7 El código modificador es claro y simple. La lógica no debe contener llamadas externas a contratos que no sean de confianza.
G5.8 Todos los atributos de usuario y datos utilizados por los controles de acceso se mantienen en contratos confiables y no pueden ser manipulados por otros contratos a menos que se autorice específicamente.
G5.9 Los controles de acceso fallan de forma segura, incluso cuando se produce una reversión.
G5.10 Si se valida la entrada (parámetros de la función), se utiliza el enfoque de validación positiva (lista blanca) siempre que sea posible.

Comunicación

Comunicación Nombre de la prueba
G6.2 Se identifican las bibliotecas que no forman parte de la aplicación (pero de las que depende el contrato inteligente para funcionar).
G6.3 La llamada de delegado no se usa con contratos que no son de confianza.
G6.4 Los contratos de terceros no ocultan funciones especiales (por ejemplo, reversión).
G6.5 El contrato no verifica si la dirección es un contrato usando código de operación de tamaño de código ext.
G6.6 Los ataques de reingreso se mitigan bloqueando las llamadas recursivas de otros contratos y siguiendo el patrón Verificar-Efectos-Interacciones. No utilice la función de envío a menos que sea imprescindible.
G6.7 El resultado de llamadas a funciones de bajo nivel (p. ej. enviar, delegar llamar, llamar) de otros contratos se comprueba.
G6.8 El contrato se basa en los datos proporcionados por el remitente correcto y no se basa en el valor de tx.origin.

Aritmética

Aritmética Nombre de la prueba
G7.2 Los valores y las operaciones matemáticas son resistentes a los desbordamientos de enteros. Use la biblioteca SafeMath para operaciones aritméticas antes de solidity 0.8.*.
G7.3 Los fragmentos de código no verificados de Solidity ≥ 0.8.* no introducen desbordamientos/desbordamientos de enteros.
G7.4 Los valores extremos (por ejemplo, valores máximos y mínimos del tipo variable) se consideran y no cambian el flujo lógico del contrato.
G7.5 La desigualdad no estricta se utiliza para la igualdad de equilibrio.
G7.6 En los cálculos se utilizan órdenes de magnitud correctos.
G7.7 En los cálculos, la multiplicación se realiza antes de la división para mayor precisión.
G7.8 El contrato no asume una precisión de punto fijo y utiliza un multiplicador o almacena tanto el numerador como el denominador.

Denegación de servicio

Denegación de servicio Nombre de la prueba
G8.2 El contrato no itera sobre bucles no vinculados.
G8.3 La funcionalidad de autodestrucción se usa solo si es necesario. Si está incluido en el contrato, debe estar claramente descrito en la documentación.
G8.4 La lógica empresarial no se bloquea si un actor (por ejemplo, contrato, cuenta, oráculo) está ausente.
G8.5 La lógica comercial no desincentiva a los usuarios a usar contratos (por ejemplo, el costo de la transacción es mayor que la ganancia).
G8.6 Las expresiones de funciones afirmar o requerir tienen una variante de paso.
G8.7 Si nadie puede llamar a la función de reserva, no está bloqueando las funcionalidades del contrato.
G8.8 No hay operaciones costosas en un bucle.
G8.9 No hay llamadas a contratos que no son de confianza en un bucle.
G8.10 Si existe la posibilidad de suspender la vigencia del contrato, también es posible reanudarla.
G8.11 Si se utilizan listas blancas y listas negras, no interfieren con el funcionamiento normal del sistema.
G8.12 No hay DoS causado por desbordamientos y subdesbordamientos.

Datos de la cadena de bloques

Datos de la cadena de bloques Nombre de la prueba
G9.2 Los datos guardados en los contratos no se consideran seguros ni privados (incluso las variables privadas).
G9.3 No se almacenan datos confidenciales en la cadena de bloques (contraseñas, datos personales, token, etc.).
G9.4 Los contratos no utilizan cadenas literales como claves para las asignaciones. En su lugar, se utilizan constantes globales para evitar el ataque de homoglifos.
G9.5 El contrato no genera trivialmente números pseudoaleatorios basados ​​en la información de la cadena de bloques (p. ej., inicialización con el número de bloque).

Uso de gas y limitaciones

Uso de gas y limitaciones Nombre de la prueba
G10.1 El uso de gas está previsto, definido y tiene limitaciones claras que no se pueden exceder. Tanto la estructura del código como la entrada maliciosa no deberían causar el agotamiento del gas.
G10.2 La ejecución de la función y la funcionalidad no dependen de las tarifas de gas codificadas (están obligadas a variar).

Claridad y legibilidad

Claridad y legibilidad Nombre de la prueba
G11.2 La lógica es clara y modularizada en múltiples contratos y funciones simples.
G11.3 Cada contrato tiene un breve comentario de 1-2 oraciones que explica su propósito y funcionalidad.
G11.4 Se utilizan implementaciones listas para usar, esto se aclara en el comentario. Si estas implementaciones han sido modificadas, las modificaciones se anotan a lo largo del contrato.
G11.5 El orden de herencia se tiene en cuenta en los contratos que utilizan múltiples funciones de herencia y sombra.
G11.6 Siempre que sea posible, los contratos utilizan código probado existente (por ejemplo, contratos de token o mecanismos como poseer) en lugar de implementar los suyos propios.
G11.7 Se siguen patrones de nomenclatura coherentes a lo largo del proyecto.
G11.8 Las variables tienen nombres distintivos.
G11.9 Todas las variables de almacenamiento se inicializan.
G11.10 Las funciones con un tipo de devolución especificado devuelven un valor de ese tipo.
G11.11 Se utilizan todas las funciones y variables.
G11.12 exigir se utiliza en lugar de revertir in if Declaraciones.
G11.13 El afirmar La función se utiliza para probar errores internos y la exigir La función se utiliza para garantizar una condición válida en la entrada de los usuarios y los contratos externos.
G11.14 El código ensamblador solo se usa si es necesario.

Cobertura de prueba

Cobertura de prueba Nombre de la prueba
G12.2 Las narrativas de abuso detalladas en el modelo de amenazas están cubiertas por pruebas unitarias
G12.3 Las funciones sensibles en los contratos verificados se cubren con pruebas en la fase de desarrollo.
G12.4 Se ha comprobado la implementación de contratos verificados en busca de vulnerabilidades de seguridad mediante análisis estáticos y dinámicos.
G12.5 La especificación del contrato se ha verificado formalmente
G12.6 La especificación y los resultados de la verificación formal se incluyen en la documentación.

Finanzas descentralizadas

Finanzas descentralizadas Nombre de la prueba
G13.1 El contrato del prestamista no asume que su saldo (utilizado para confirmar el pago del préstamo) se cambie solo con sus propias funciones.
G13.2 Las funciones que cambian el saldo de los prestamistas y/o prestan criptomonedas no son reingresantes si el contrato inteligente permite tomar prestada la criptomoneda de la plataforma principal (por ejemplo, Ethereum). Bloquea los ataques que actualizan el saldo del prestatario durante la ejecución del préstamo flash.
G13.3 Las funciones de préstamo flash solo pueden llamar a funciones predefinidas en el contrato de recepción. Si es posible, defina un subconjunto confiable de contratos para llamar. Por lo general, el contrato de envío (préstamo) es el que debe devolverse.
G13.4 Si incluye operaciones potencialmente peligrosas (p. ej., devolver más ETH/tokens de los prestados), la función del receptor que maneja ETH o tokens prestados puede ser llamada solo por el grupo y dentro de un proceso iniciado por el propietario del contrato receptor u otra fuente confiable (p. ej. multigrado).
G13.5 Los cálculos de la cuota del fondo de liquidez se realizan con la mayor precisión posible (por ejemplo, si la contribución se calcula para ETH, debe hacerse con una precisión de 18 dígitos, para Wei, no para Ether). El dividendo debe multiplicarse por 10 a la potencia del número de dígitos decimales (por ejemplo, dividendo * 10^18 / divisor).
G13.6 Las recompensas no se pueden calcular y distribuir dentro de la misma llamada de función que deposita tokens (también debe definirse como no reingreso). Esto protege de fluctuaciones momentáneas en las acciones.
G13.7 Los contratos de gobernanza están protegidos contra ataques de préstamos rápidos. Una posible técnica de mitigación es requerir que el proceso de depositar tokens de gobernanza y proponer un cambio se ejecute en diferentes transacciones incluidas en diferentes bloques.
G13.8 Cuando se utilizan oráculos en cadena, los contratos pueden pausar las operaciones en función del resultado de los oráculos (en caso de un oráculo comprometido).
G13.9 Los contratos externos (incluso los de confianza) que pueden cambiar los atributos de un contrato de proyecto (p. ej., el precio del token) tienen implementadas las siguientes limitaciones: umbrales para el cambio (p. ej., no más/menos del 5 %) y un límite de actualizaciones (p. ej., una actualización por día).
G13.10 Los atributos del contrato que pueden ser actualizados por los contratos externos (incluso los confiables) se monitorean (por ejemplo, usando eventos) y se implementa un procedimiento de respuesta a incidentes (por ejemplo, durante un ataque en curso).
G13.11 Las operaciones matemáticas complejas que consisten en operaciones de multiplicación y división primero realizan multiplicaciones y luego divisiones.
G13.12 Al calcular los precios de intercambio (por ejemplo, ETH a token o viceversa), el numerador y el denominador se multiplican por las reservas (ver el obtenerPrecioEntrada en función de la Intercambio Uniswap contrato).

 

Ordenar auditoría de Sayfer





    Este sitio está protegido por reCAPTCHA y Google Política de Privacidad y Términos de Servicio aplican.

    Resultados de la auditoría

    [H] Riesgo adelantado al crear un nuevo par

    ID DECIR-01
    Estado fijo
    Riesgo Alta
    Empresa Impacto En algunos casos, los usuarios pueden perder los fondos que depositaron para financiar la creación de pares. Un pionero malicioso puede crear un par a expensas de otro usuario, o varios usuarios pueden intentar crear un par al mismo tiempo, con éxito o sin éxito de forma aleatoria.
    Destino
    • Enrutador.ts; crearLBPair(StaticArray )
    • Fábrica.ts; crearLBPair(StaticArray )

    Descripción

    Para crear un nuevo par, el usuario debe llamar Enrutador::createLBPair(StaticArray ). Debajo del capó, esta función llama Fábrica::createLBPair(StaticArray ), que a su vez llama a Massa transferirCoins(Dirección, número).

    • Ts de fábrica: 264; crearLBPair(StaticArray )

    transferCoins(_pair._origin, 200 * ONE_COIN);

    Según la documentación, esta función simplemente transfiere monedas desde la dirección actual a una dirección determinada. Eso significa que estos fondos tienen que ser enviados previamente a Fábrica. Por otro lado, los usuarios tienen la posibilidad de llamar crear par desde el enrutador, que es el punto de entrada predeterminado para otras operaciones. Sin embargo, si se depositan en cualquier transacción separada, existe la posibilidad de que alguien, intencionalmente o no, también llame crearLBPair(StaticArray ).

    Cuando se finaliza un bloque con transacciones, se distribuirán en un orden desconocido. Luego, a la primera transacción incluida se le transferirán estos fondos desde Factory a un nuevo par, mientras que al segundo usuario (la última transacción) se le revertirá su transacción debido a la falta de fondos disponibles.

    Mitigación

    La financiación de la creación de pares debe realizarse realmente en la misma transacción para evitar problemas de reordenación de transacciones. 

    Por ejemplo, una de las formas de lograrlo podría ser un mecanismo que verifique el saldo de fábrica y el saldo del fondo común al final de una función y devuelva el excedente, similar a este https://github.com/massalabs/coin-vester/blob/master/smart-contract/assembly/contracts/main.ts#L34

    El mecanismo se implementará en el crearLBPair funcion de Fábrica), en el constructor, menta, quemar, cobrar tarifas, aumentarOracleLongitud, transferencia seguradesde & transferencia segura por lotes desde (de pareja). Estas son las funciones que Massa puede gastar en almacenamiento, ya que pueden crear nuevas entradas en el almacenamiento (modificar el almacenamiento no cuesta nada). Las funciones que interactúan con estas funciones también deben tener este mecanismo. 

    Se pueden dividir en dos tipos diferentes:

    • Funciones que interactúan con estos y que no interactúan con WMAS (crearLBPair desde el enrutador y la fábrica + agregar liquidez, eliminarLiquidez) transferirá todos los transferidoMonedas, guarde el saldo del SC de forma constante y, después de la llamada del SC, transfiera nuevamente a la persona que llama la diferencia entre el nuevo saldo y el saldo guardado.
    • Funciones que interactúan con estos y que interactúan con WMAS (agregarLiquidezMAS, eliminarLiquidezMAS) necesitará un parámetro más para saber la cantidad de monedas que deben envolverse, enviará la diferencia entre transferidoMonedas y este número en la llamada. El resto del mecanismo en estas funciones será el mismo que el anterior.

     

    [H] Se pueden perder los fondos depositados para la creación de pares

    ID DECIR-02
    Estado fijo
    Riesgo Alta
    Impacto en el negocio Los usuarios que depositan fondos en el enrutador para crear un par pueden perder su dinero sin ver ningún resultado. Calificamos este problema como alto (en lugar de crítico) porque existe un flujo de trabajo alternativo: llamar fábrica::createLBPair(StaticArray ) directamente con los fondos.
    Destino
    • Enrutador.ts; crearLBPair(StaticArray )
    • Ts de fábrica: 264; crearLBPair(StaticArray )

    Descripción

    Este problema es el resultado de cómo se diseña la creación de parejas. Un usuario puede llamar Enrutador::createLBPair(StaticArray ) y dado que la creación de un par requiere un depósito, puede adjuntar fondos a la llamada de función, lo que parece una solución intuitiva.

    Sin embargo, si el usuario lo hace, los fondos nunca llegarán al par y se perderán en el contrato (aunque pueden ser rescatados por el propietario). Esto se debe a que quedarán atrapados en el contrato del enrutador, mientras que la creación del par se lleva a cabo en el contrato de fábrica, donde en su lugar se utiliza transferCoins(), que deduce fondos de la dirección actual (la de la fábrica).

    • Ts de fábrica: 264; crearLBPair(StaticArray )

    transferCoins(_pair._origin, 200 * ONE_COIN);

    Dado que está implementado en la fábrica, los fondos enviados al enrutador no llegarán a la fábrica, que tampoco tendrá los fondos para crear un par y revertirlo.

    Mitigación

    Una opción es implementar la solución sugerida en DECIR-01.
    A la inversa, Fábrica.ts se puede llamar directamente para crear pares y requerir que los usuarios envíen la cantidad exacta requerida junto con la llamada a la función, O al menos la cantidad requerida con reembolsos de los fondos excedentes enviados.

     

    [M] Múltiples pares del mismo tipo pueden diluir la liquidez

    ID DECIR-03
    Estado fijo
    Riesgo Medio
    Impacto en el negocio Si una aplicación AMM permite crear múltiples grupos con los mismos parámetros, la liquidez puede diluirse entre estos grupos, en lugar de concentrarse en uno solo. Esto podría afectar negativamente a los usuarios y podría resultar en operaciones menos favorables disponibles para los usuarios del protocolo.

    Además, el par anterior ya no se utilizará para el enrutamiento. Esto puede resultar en liquidez o manipulación de precios.

    Destino
    • Fábrica.ts; crearLBPair(StaticArray )
    • Enrutador.ts; crearLBPair(StaticArray )

    Descripción

    Al crear un nuevo par, no se comprueba si ya existe exactamente el mismo par. Esto puede dispersar la liquidez de los usuarios entre múltiples grupos equivalentes. Los fondos comunes de baja liquidez son más propensos a manipulaciones de precios y ofrecen operaciones menos favorables y, por lo tanto, deben evitarse.

    Mitigación

    Compruebe si ya existe un par de ciertos parámetros al crear el par; de ser así, revierta.

     

    [L] Verificación exacta del saldo después de que se pueda abusar de un préstamo flash

    ID DECIR-04
    Estado fijo
    Riesgo Baja
    Impacto en el negocio Un receptor de préstamo rápido podría realizar llamadas externas en la devolución de llamada. Debido a que el sistema requiere que el saldo después del préstamo flash sea exactamente el saldo anterior más las tarifas, estos contratos externos podrían transferir una cantidad muy pequeña al par durante la ejecución para garantizar que el préstamo flash fracase (lo que puede ser rentable para ellos). en determinadas situaciones).
    Destino
    • Par.ts:280; préstamo flash (StaticArray )

    Descripción

    Después de un préstamo rápido, el sistema requiere que el saldo sea exactamente el saldo antes del préstamo rápido más las tarifas.

    • préstamo flash (StaticArray )

    assert(

      _balanceAfter == SafeMath256.add(_balanceBefore, _fees.total),

      LBPair__FlashLoanInvalidBalance(),

    );

    Normalmente, se requiere que el saldo sea mayor, ya que exigir una coincidencia exacta es restrictivo.

    Mitigación

    Solo verifique si el saldo es mayor que el saldo antes del préstamo rápido más las tarifas. Esta es también la lógica que utiliza TraderJoe dentro de su función de préstamos rápidos.

     

    [L] Ignorar un par LB no emite un evento

    ID DECIR-05
    Estado fijo
    Riesgo Baja
    Empresa Impacto Los indexadores fuera de la cadena pueden recibir información incorrecta, lo que genera cálculos incorrectos.
    Destino
    • Fábrica.ts; setLBPairInformation(StaticArray )

    Descripción

    La función setLBPairIgnored(StaticArray ) se puede utilizar para controlar si un par debe ignorarse o no para el enrutamiento. Cualquier cambio en la bandera a través de esta función emite el evento SET_LBPAIR_IGNORED. Sin embargo, también es posible cambiar la bandera a través de setLBPairInformation(StaticArray ), que no emite un evento.

    Mitigación

    Emita siempre un evento al cambiar la bandera para garantizar que los sistemas fuera de la cadena sepan qué pares se considerarán para el enrutamiento.

    [L] Cobro de tarifas inconsistente

    ID DECIR-06
    Estado Admitido
    Riesgo Baja
    Empresa Impacto Cualquier usuario puede activar el cobro de tarifas para otros usuarios, mientras que el cobro de tarifas de protocolo solo puede ser activado por el propietario.
    Destino
    • Par.ts; cobrar tarifas (StaticArray )
    • Par.ts:723-726; recopilarProtocolFees(StaticArray )

    Descripción

    Cualquiera puede llamar cobrar tarifas (StaticArray ) para cualquier dirección para distribuir las tarifas a esta dirección. Esto puede resultar indeseable para ciertos usuarios que desean controlar cuándo se les distribuyen las tarifas. 

    Esto además es inconsistente con recopilarProtocolFees(StaticArray ), que sólo puede ser llamado por el destinatario.

    • recopilarProtocolFees(StaticArray )

    assert(

      Context.caller().equals(_feeRecipient),

      LBPair__OnlyFeeRecipient(_feeRecipient, Context.caller()),

    );

    Mitigación

    Considere cambiar la lógica en cobrar tarifas (StaticArray ) para que coincida con recopilarProtocolFees(StaticArray ), es decir, permitir únicamente al destinatario cobrar sus tarifas.

    [L] Uso inconsistente de SafeMath

    ID DECIR-07
    Estado fijo
    Riesgo Baja
    Empresa Impacto Los desbordamientos o subdesbordamientos en el código pueden provocar reversiones inesperadas y/o errores de cálculo. 
    Destino -

    Descripción

    Aunque SafeMath se utiliza en muchos lugares, ciertas funciones que utilizan operaciones aritméticas quedan desprotegidas, lo que en consecuencia puede provocar desbordamientos o desbordamientos.

    Mitigación

    Aunque no se ha identificado ningún lugar donde tal situación pueda ser probable, debido al gran tamaño del código base y la multitud de cálculos, recomendamos implementar SafeMath en tantas operaciones como sea posible.

    [L] Enumeración de activos ineficiente

    ID DECIR-08
    Estado fijo
    Riesgo Baja
    Empresa Impacto Algunas funciones de fábrica consumirán más gas del necesario. En el peor de los casos, si el propietario registra una cantidad muy grande de activos, esto podría provocar una DoS. Pero esto es poco probable.
    Destino
    • Ts de fábrica: 102-106; isQuoteAsset(Dirección)

    Descripción

    Aquí hay dos problemas con esta función: 

    1. El bucle no se rompe después de encontrar un activo y se repite innecesariamente sobre el resto de la matriz. Así, cada caso is el peor caso.
    2. Un mapeo sería más eficiente aquí, ya que tiene una búsqueda de tiempo constante.
    • isQuoteAsset(Dirección)

    for (let i = 0; i < quoteAssets.length; i++) {

      if (quoteAssets[i].equals(_token)) {

        isQuoteAsset = true;

      }

    }

    Mitigación

    Hay dos soluciones aquí:

    1. Mantenga el algoritmo de búsqueda lineal actual y simplemente agregue una interrupción en el if bloquear después de configurar esQuoteAsset a la verdad
    2. Una mejor solución sería cambiar a un mapeo. Cuando se agrega un nuevo token al sistema, citaAssets[token] debe establecerse en verdadero. De ahora en adelante, se podrá acceder a él cuando sea necesario, sin necesidad de buscarlo. Quizás toda la función pueda simplemente refactorizarse.

    [L] La tarifa máxima de préstamo flash no se establece después de la implementación

    ID DECIR-09
    Estado fijo
    Riesgo Baja
    Empresa Impacto Es posible tener una tarifa de préstamo flash superior a la MAX_FEE.
    Destino
    • Ts de fábrica: 80; constructor(StaticArray )

    Descripción

    Siempre que la tarifa del préstamo rápido se establezca usando establecer tarifa de préstamo flash(), se valida que sea menor que el valor MAX_FEE. Sin embargo, esta verificación no se realiza cuando se inicializa el contrato y allí es posible establecer una tarifa de préstamo flash arbitrariamente alta.

    Mitigación

    Validar la tarifa del préstamo flash en el constructor.

    [L] Protección contra deslizamiento incompleta: falta de verificación de fecha límite

    ID DECIR-10
    Estado fijo
    Riesgo Baja
    Empresa Impacto Existe una mayor probabilidad de que los usuarios obtengan operaciones menos favorables al utilizar el AMM.
    Destino enrutador.ts

    • agregarLiquidez(bs: StaticArray )
    • agregarLiquidezMAS(bs: StaticArray )

    Descripción

    El deslizamiento es el resultado de la volatilidad en las soluciones de tipo AMM y simplemente significa que el precio al solicitar un cambio de operación/swap/liquidez es diferente que cuando se ejecuta la transacción. Para proteger a los usuarios de un enorme deslizamiento, que puede ser natural o resultado de ataques intencionales como Sandwiching, existen dos tipos genéricos de protección: cantidad mínima, que está presente, y verificación de fecha límite, que falta.

    Esos controles deben implementarse en cualquier swap, adición y eliminación de liquidez, ya que todos ellos están sujetos a deslizamientos.

    Una verificación de fecha límite simplemente no permite que la transacción se incluya después de un cierto momento, lo que, por ejemplo, puede ser incluido intencionalmente más tarde por un creador de bloques malicioso para intentar ejecutar la transacción en condiciones de precio menos favorables. Sin embargo, dado que se verifica una cantidad simbólica mínima, el impacto de este problema es limitado.

    Mitigación

    Implementar  _asegurar(fecha límite) de la misma manera ya está presente en todas las demás funciones relacionadas con la liquidez.

    [L] Transferencia de propiedad en un solo paso

    ID DECIR-11
    Estado fijo
    Riesgo Baja
    Empresa Impacto Proporcionar una dirección incorrecta podría provocar la pérdida irrevocable de la propiedad del contrato.
    Destino
    • Fábrica.ts; transferirPropiedad([u8])

    Descripción

    In Fábrica.ts, el cambio de propiedad se logra cuando el antiguo propietario llama al transferirPropiedad([u8]) con el nuevo dueño. La función luego cambia el PROPIETARIO variable de estado.

    • transferirPropiedad([u8])

    export function transferOwnership(bs: StaticArray<u8>): void {

      _onlyOwner();

      const _newOwner = new Address(new Args(bs).nextString().unwrap());

      _setFeeRecipient(_newOwner);

      Storage.set(OWNER, _newOwner.toString());

    }

    Mitigación

    Recomendamos implementar un proceso de dos pasos para la transferencia de propiedad. Esto está en consonancia con buenas prácticas ampliamente reconocidas y podría evitar transferencias accidentales. Para ilustrar, usaremos la implementación de OpenZepplin.

    Una transferencia de propiedad en dos pasos requiere primero que el propietario actual inicie la transferencia.

    function transferOwnership(address newOwner) public virtual override onlyOwner {

     _pendingOwner = newOwner;

     emit OwnershipTransferStarted(owner(), newOwner);

    }

    Pero para completar el proceso, el nuevo propietario debe aprobar la transferencia.

    function acceptOwnership() public virtual {

     address sender = _msgSender();

     if (pendingOwner() != sender) {

         revert OwnableUnauthorizedAccount(sender);

     }

     _transferOwnership(sender);

    }

    Esto garantiza que el nuevo propietario sea el objetivo previsto.

    [I] Emisión de eventos insuficiente

    ID DECIR-12
    Estado fijo
    Riesgo Informativo
    Empresa Impacto Disminución de la trazabilidad y visibilidad de los cambios históricos de estado clave que afectan el protocolo.
    Destino Fábrica.ts

    • setLBPairInformation(bs: StaticArray )
    • forceDecay(bs: StaticArray )
    • transferirPropiedad(bs: StaticArray )

    Descripción

    Algunos de los cambios de estado clave del protocolo no emiten un evento asociado.

    Nota: transferirPropiedad(bs: StaticArray ) emite un evento, pero sólo para _setFeeRecipient.

    Mitigación

    Agregue emisión de eventos en las ubicaciones especificadas.

    [I] Los captadores y definidores se mezclan con funciones externas

    ID DECIR-13
    Estado fijo
    Riesgo Informativo
    Empresa Impacto La mezcla, los captadores, definidores, puntos de entrada y funciones internas hacen que el código sea menos legible.
    Destino
    • Ts de fábrica: 631, 639
    • Par.ts:1031, 1227

    Descripción

    Ciertos contratos tienen secciones separadas que contienen funciones que cambian el estado (definidores), lo leen (captadores) o son parte del árbol de llamadas de funciones (interno).

    Sin embargo, en algunos contratos este orden se altera: las funciones se confunden. A veces, las funciones exportadas (puntos de entrada) también se mezclan con las internas.

    Mitigación

    Recomendamos que las secciones del código estén separadas adecuadamente, los puntos de entrada separados de las funciones internas y que se mantenga la convención de usar el signo _ antes de las funciones privadas.

    [I] Falta de pruebas unitarias

    ID DECIR-14
    Estado Admitido
    Riesgo Informativo
    Empresa Impacto Los escenarios de prueba y las pruebas unitarias ayudan a los desarrolladores a detectar errores y vulnerabilidades que de otro modo pasarían desapercibidos en un simple análisis estático. Las pruebas dinámicas son invaluables para garantizar la calidad del producto terminado.
    Destino -

    Descripción

    Aparte de una docena de pruebas para una serie de funcionalidades de la biblioteca, el código no tenía pruebas unitarias, funcionales o de integración. No todos los defectos pueden detectarse mediante un simple análisis estático, lo que deja al producto en una posición precaria.

    Mitigación

    Se considera una buena práctica garantizar que la cobertura del código para las pruebas sea lo más alta posible y que los escenarios de prueba incluyan rutas felices e infelices.

    [I] Código innecesario

    ID DECIR-15
    Estado fijo
    Riesgo Informativo
    Empresa Impacto Esta cuestión no tiene un impacto directo en el código ni en el protocolo y, por lo tanto, se calificó como informativa.
    Destino Enrutador.ts:770-772; _getAmountsIn(u64[], Dirección[], IERC20[], u256)

    Descripción

    La función _getMontosEn() toma los pasos del contenedor como argumento y realiza la siguiente verificación:

    • _getAmountsIn(u64[], Dirección[], IERC20[], u256)

    if (_binStep == 0) {

      // means TraderJoe V1 swap

    } else {

      ...

    }

    Sin embargo, esto es innecesario. El sistema no soporta swaps estilo V1 y el resto de la función no considera los pasos bin, ya que recibe los pares (correspondientes a los pasos bin) como argumento adicional.

    Mitigación

    Considere eliminar el argumento _pairBinSteps y la cláusula if innecesaria.

    [I] Importaciones no utilizadas

    ID DECIR-16
    Estado fijo
    Riesgo Informativo
    Empresa Impacto Esta cuestión no tiene un impacto directo en el código ni en el protocolo y, por lo tanto, se calificó como informativa.
    Destino
    • Par.ts:35,
    • Enrutador.ts:4,
    • WMAS.ts:5,6,
    • interfaces/IPair.ts:5

    Descripción

    Las importaciones especificadas nunca parecen utilizarse en sus respectivos contratos. Podrían eliminarse.

    Mitigación

    Elimine las importaciones no utilizadas.

    [I] Uso de 'Números Mágicos'

    ID DECIR-17
    Estado Admitido
    Riesgo Informativo
    Empresa Impacto Esto puede aumentar la dificultad de analizar el código para lectores desconocidos.
    Destino
    • Par.ts:113
    • Ts de fábrica: 264, 735

    Descripción

    En varios lugares, el contrato utiliza valores numéricos que no están bien documentados, descritos o comentados.

    Mitigación

    Agregue comentarios que expliquen la elección de constantes.

    Puedes encontrar más información al respecto en nuestro Blog

    El blog de Sayfer se centra en web3, seguridad e investigación de vulnerabilidades. Creemos que en la industria de la ciberseguridad es crucial mantenerse actualizado sobre las últimas tendencias y avances. En la actualidad, nuestro equipo de investigadores experimentados disfruta investigando tecnologías blockchain y web3 de vanguardia.
    Contáctenos

    Mantenerse en contacto

    Destino
    Tel Aviv, Israel
    Correo electrónico
    Mensajeros
    No dude en ponerse en contacto con nosotros, ¡estaremos encantados de responderle!





      Este sitio está protegido por reCAPTCHA y Google Política de Privacidad y Términos de Servicio aplican.
      Ir al contenido