Rapport d'audit de contrat intelligent pour Dusa

Résumé de gestion

Dusa a contacté Sayfer pour effectuer un audit de sécurité sur ses contrats intelligents. 

Ce rapport documente les recherches effectuées par Sayfer ciblant les ressources sélectionnées définies dans le cadre de la recherche. En particulier, ce rapport présente l'examen de la posture de sécurité des contrats intelligents de Dusa.

Au cours de la période de recherche de 4 semaines, nous avons découvert 17 vulnérabilités dans le contrat.

Dans l’ensemble, Dusa est un protocole bien construit. Le fait qu’il soit dérivé et traduit de TraderJoe en fait un protocole très solide avec une architecture assez courante, mais considérée comme optimale. Cependant, nous avons quelques recommandations qui, selon nous, pourraient améliorer la qualité et la sécurité du protocole. Ces recommandations sont détaillées dans la section « Revue de l'architecture ».

En conclusion, plusieurs correctifs devraient être mis en œuvre suite au rapport, mais la posture de sécurité du système est compétente.

Après examen par l'équipe Sayfer, nous certifions que tous les problèmes de sécurité mentionnés dans ce rapport ont été résolus ou reconnus par l'équipe Dusa.

Méthodologie des risques

Chez Sayfer, nous nous engageons à fournir à nos clients des audits de contrats intelligents de la plus haute qualité. C'est pourquoi nous avons mis en œuvre un modèle complet d'évaluation des risques pour évaluer la gravité de nos constatations et fournir à nos clients les meilleures recommandations possibles pour les atténuer.

Notre modèle d’évaluation des risques repose sur deux facteurs clés : IMPACT ainsi que PROBABILITÉ. L'impact fait référence au préjudice potentiel qui pourrait résulter d'un problème, tel qu'une perte financière, une atteinte à la réputation ou un système non opérationnel. La probabilité fait référence à la probabilité qu'un problème se produise, en tenant compte de facteurs tels que la complexité du contrat et le nombre d'attaquants potentiels.

En combinant ces deux facteurs, nous pouvons créer une compréhension globale du risque posé par un problème particulier et fournir à nos clients une évaluation claire et exploitable de la gravité du problème. Cette approche nous permet de prioriser nos recommandations et de garantir que nos clients reçoivent les meilleurs conseils possibles sur la façon de protéger leurs contrats intelligents.

Le risque est défini comme suit :

Vulnérabilités par risque

Haute – Menace directe sur les processus métier clés.
Moyenne – Menace indirecte sur les processus métier clés ou menace partielle sur les processus métier.
Faible – Aucune menace directe n'existe. La vulnérabilité peut être exploitée à l'aide d'autres vulnérabilités.
D'information – Cette constatation n'indique pas de vulnérabilité, mais énonce un commentaire qui signale des défauts de conception et une mise en œuvre incorrecte qui pourraient causer un problème à long terme.

Gravité
# de problèmes
Haute
2
Moyenne
1
Faible
8
D'information
6
Critical
0

Approche

Introduction

Dusa a contacté Sayfer pour effectuer un audit de sécurité sur ses contrats intelligents.

Ce rapport documente les recherches effectuées par Sayfer ciblant les ressources sélectionnées définies dans le cadre de la recherche. En particulier, ce rapport affiche l'examen de la posture de sécurité pour les contrats susmentionnés.

Aperçu de la portée

En collaboration avec l'équipe du client, nous avons défini le contrat suivant comme la portée du projet.

Contract Sha-256
Usine.ts b86a4c350c37a0d8c62495bde0be2b0dca2c8a9f343149238548690df5104cee
main.ts d0073078a6ef26a402bcfb368e94dfb9dddc3f2a629eabc842e2b62d62772b6a
Paire.ts 186f3bd5fab92cb4e98ea5daef31f44d1889f28e683663d056ff6649685ce36c
Citation.ts b51c762d8ebe50c6b966c9b52a33819a674fb7cf056062ebe34d8f425d879aad
Routeur.ts 038e32c21432ad173cf8f3b77a586f222a99a8d0f8e033e40145643671ff87ee
WMAS.ts bcef456ec5e27527ae560e21b00fb9f4c8300016aae584da3aa1e869c7018832

Nos tests ont été réalisés entre janvier et février 2024.

Qu'il ne soit pas trop tard !

Commencez votre audit avec Sayfer

Validation de la portée

Nous avons commencé par nous assurer que le périmètre qui nous avait été défini par le client était techniquement logique. Décider quelle portée convient à un système donné fait partie de la discussion initiale.

Modèle de menace

Nous defiIl est évident que la plus grande menace actuelle pour le système est la capacité des utilisateurs malveillants à voler des fonds sur le contrat.

Qu'il ne soit pas trop tard !

Commencez votre audit avec Sayfer

Présentation du protocole

Présentation du protocole

Dusa est un protocole de finance décentralisée (DeFi) révolutionnaire, introduisant une expérience de teneur de marché automatisé (AMM) entièrement décentralisée et avancée. Construit sur la blockchain Massa, Dusa met l'accent sur des principes clés tels que la décentralisation complète, l'accessibilité pour tous les profils d'utilisateurs, l'interopérabilité avec les futures applications décentralisées (DApps) et un engagement fort en faveur de la sécurité et de la résistance à la censure. Sa feuille de route décrit une approche progressive, comprenant la recherche et le développement, les tests, les quêtes incitatives et le déploiement d'un échange décentralisé (DEX). Les caractéristiques uniques de Dusa incluent une liquidité concentrée, des frais variables, une liquidité autonome et des ordres de négociation complexes, tous conçus pour améliorer l'expérience utilisateur et maximiser le rendement. Avec une équipe dédiée, des investisseurs stratégiques et des conseillers, Dusa vise à être pionnier dans l'adoption de contrats intelligents autonomes et à étendre ses solutions décentralisées à d'autres écosystèmes.

Examen de l'architecture

Reconnaissant que Dusa est un dérivé d'une solution bien établie, TraderJoe, et s'aligne sur un modèle architectural reconnu, nous notons des recommandations supplémentaires limitées pour l'architecture actuelle. Cependant, notre évaluation de l’architecture du protocole Dusa a conduit à une vision globale, combinant des informations précieuses avec des recommandations réfléchies d’amélioration :

  • Du point de vue des meilleures pratiques, nous recommandons d'envisager la mise en œuvre d'un portefeuille multisig pour gérer les rôles privilégiés à l'avenir. Bien que nous reconnaissions la publication récente du code Massa multisig (https://github.com/massalabs/massa-standards/tree/feature/multisig-sc/smart-contracts/assembly/contracts/multisig), nous conseillons la prudence et considérons l’utilisation d’une clé privée standard également comme une option viable pour le moment.
  • Une autre recommandation judicieuse suggère d’adopter un modèle de liquidité unifié, en envisageant un Vault/PoolManager global au lieu de contrats individuels par pool. Ce changement stratégique, inspiré des récentes avancées des AMM comme Uniswap V4 et Balancer, promet des avantages significatifs. Il s’agit notamment de swaps multi-sauts rentables et d’une capacité de prêt flash améliorée, attribuées à un accès rationalisé à l’ensemble du pool de liquidités.

Évaluation de la sécurité

Tests spécifiques à Dusa

Comme Dusa se trouve dans une situation unique en tant que reflet de TraderJoe dans un langage de programmation différent, nous avons effectué plusieurs tests supplémentaires en plus de nos tests habituels pour nous assurer qu'il n'y a aucune pièce manquante. Voici une liste de tests réalisés spécifiquement pour le protocole Dusa :

Contrôles de sécurité

  • Vérifications de débordement/sous-débordement, notamment en raison du changement de base de code d'un langage avec des vérifications par défaut à un langage où des vérifications explicites sont requises.
  • Utilisation de bibliothèques sécurisées (checked_*).
  • Cohérence entre les contrats concernant les flux de fonds et les appels.
  • Visibilité des fonctions pour garantir que les fonctions appropriées sont exportées.
  • Mise en place du contrôle d'accès et protection des fonctions sensibles.
  • Swap protection pour sécuriser les interactions avec la liquidité contre le dérapage.

Authentification et autorisation

  • Audit de l'ensemble du processus d'authentification, des droits des propriétaires et du schéma d'autorisation des points d'entrée publics individuels.
  • Identification des vulnérabilités potentielles conduisant à des autorisations malveillantes pour les attaquants.

Mathématiques et gestion des variables

  • Problèmes liés aux calculs, notamment avec plusieurs types de variables, la conversion et la gestion des nombres à virgule flottante.
  • Erreurs décimales liées à l'aspect unique de MASSA ayant 9 décimales.
  • Gestion des capacités de débordement/sous-débordement.

Prêt Flash et gestion des liquidités

  • Examen des erreurs typiques liées aux prêts flash, notamment les erreurs de calcul et le blocage de fonds.
  • Problèmes liés à la création d'usines et de paires, tels que la création de pools dangereux et la gestion des liquidités.
  • Vérification des calculs de suppression de liquidité, en tenant compte des frais obtenus lors de l'apport de liquidité.

Fonctionnalité et mise en œuvre

  • Mise en œuvre de swaps par rapport aux autres DEX, en mettant l'accent sur la gestion des frais et les différences dans les types de jetons.
  • Possibilité d'attaques DoS lors de l'utilisation de types dangereux tels que des vecteurs ou des tableaux.
  • Vérification des problèmes de centralisation, tels que l'influence potentielle sur les prix, les transferts de jetons utilisateur et les changements de configuration.

Gestion des données contextuelles

  • Vérifiez la transmission des données contextuelles correctes aux fonctions pour éviter les vulnérabilités.

 

Tests génériques

Les cas de test suivants ont été la ligne directrice lors de l'audit du système. Cette liste de contrôle est une version modifiée de la SCSVS v1.2, avec une grammaire améliorée, de la clarté, de la concision et des critères supplémentaires. Lorsqu'il y a une lacune dans la numérotation, un critère initial a été supprimé. Les critères marqués d'un astérisque ont été ajoutés par nos soins.

Architecture, conception et modélisation des menaces

Architecture, conception et modélisation des menaces Nom du test
G1.2 Chaque modification de conception introduite est précédée d'une modélisation des menaces.
G1.3 La documentation définit clairement et précisément toutes les frontières de confiance dans le contrat (relations de confiance avec les autres contrats et flux de données importants).
G1.4 Le SCSVS, les exigences ou la politique de sécurité sont disponibles pour tous les développeurs et testeurs.
G1.5 Les événements pour les opérations (changement d'état/cruciales pour l'entreprise) sont définis.
G1.6 Le projet inclut un mécanisme qui peut stopper temporairement les fonctionnalités sensibles en cas d'attaque. Ce mécanisme ne doit pas bloquer l'accès des utilisateurs à leurs actifs (par exemple, les jetons).
G1.7 La quantité de crypto-monnaies non utilisées conservées sur le contrat est contrôlée et au niveau minimum acceptable afin de ne pas devenir une cible potentielle d'attaque.
G1.8 Si la fonction de secours peut être appelée par n'importe qui, elle est incluse dans le modèle de menace.
G1.9 La logique métier est cohérente. Des changements importants dans la logique doivent être appliqués dans tous les contrats.
G1.10 Des outils d'analyse de code automatique sont utilisés pour détecter les vulnérabilités.
G1.11 La dernière version majeure de Solidity est utilisée.
G1.12 Lors de l'utilisation d'une implémentation externe d'un contrat, la version la plus récente est utilisée.
G1.13 Lorsque les fonctions sont remplacées pour étendre les fonctionnalités, le mot-clé super est utilisé pour conserver les fonctionnalités précédentes.
G1.14 L'ordre d'héritage est soigneusement spécifié.
G1.15 Il existe un composant qui surveille l'activité du contrat à l'aide d'événements.
G1.16 Le modèle de menace inclut les transactions de baleines.
G1.17 La fuite d'une clé privée ne compromet pas la sécurité de l'ensemble du projet.

Les politiques et les procédures

Les politiques et les procédures Nom du test
G2.2 La sécurité du système fait l'objet d'une surveillance constante (par exemple, le niveau de financement attendu).
G2.3 Il existe une politique pour suivre les nouvelles vulnérabilités de sécurité et mettre à jour les bibliothèques vers la dernière version sécurisée.
G2.4 Le service de sécurité peut être contacté publiquement et que la procédure de traitement des bogues signalés (par exemple, une prime de bogue approfondie) est bien définie.
G2.5 Le processus d'ajout de nouveaux composants au système est bien défini.
G2.6 Le processus de modifications majeures du système implique la modélisation des menaces par une société externe.
G2.7 Le processus d'ajout et de mise à jour des composants du système comprend un audit de sécurité par une société externe.
G2.8 En cas de piratage, une procédure d'atténuation claire et bien connue est en place.
G2.9 La procédure en cas de piratage définit clairement quelles personnes doivent exécuter les actions requises.
G2.10 La procédure consiste à alerter d'autres projets sur le piratage via des canaux de confiance.
G2.11 Une procédure d'atténuation des fuites de clé privée est définie.

Évolutivité

Évolutivité Nom du test
G3.2 Avant la mise à jour, une émulation est faite dans un fork du réseau principal et tout fonctionne comme prévu sur la copie locale.
G3.3 Le processus de mise à niveau est exécuté par un contrat multisig où plus d'une personne doit approuver l'opération.
G3.4 Les timelocks sont utilisés pour les opérations importantes afin que les utilisateurs aient le temps d'observer les changements à venir (veuillez noter que la suppression des vulnérabilités potentielles dans ce cas peut être plus difficile).
G3.5 initialiser() ne peut être appelé qu'une seule fois.
G3.6 initialiser() ne peut être appelé que par un rôle autorisé via des modificateurs appropriés (par exemple initialiseur, seul propriétaire).
G3.7 Le processus de mise à jour est effectué en une seule transaction afin que personne ne puisse l'exécuter en amont.
G3.8 Les contrats évolutifs ont réservé un espace sur les créneaux horaires pour éviter l'écrasement.
G3.9 Le nombre d'emplacements réservés (en tant qu'écart) a été réduit de manière appropriée si de nouvelles variables ont été ajoutées.
G3.10 Il n'y a aucun changement dans l'ordre dans lequel les variables d'état du contrat sont déclarées, ni leurs types.
G3.11 Les nouvelles valeurs renvoyées par les fonctions sont les mêmes que dans les versions précédentes du contrat (par exemple propriétaire(), balanceOf(adresse)).
G3.12 L'implémentation est initialisée.
G3.13 L'implémentation ne peut pas être détruite.

 

Logique métier

Logique métier Nom du test
G4.2 La mise en œuvre de la logique du contrat et des paramètres du protocole correspond à la documentation.
G4.3 La logique métier procède dans un ordre d'étape séquentiel et il n'est pas possible de sauter des étapes ou de le faire dans un ordre différent de celui conçu.
G4.4 Le contrat a correctement appliqué les limites commerciales.
G4.5 La logique métier ne repose pas sur les valeurs récupérées à partir de contrats non approuvés (en particulier lorsqu'il y a plusieurs appels au même contrat dans un seul flux).
G4.6 La logique métier ne repose pas sur le solde du contrat (par exemple, solde == 0).
G4.7 Les opérations sensibles ne dépendent pas des données de bloc (par exemple, bloc de hachage, horodatage).
G4.8 Le contrat utilise des mécanismes qui atténuent les attaques de commande de transaction (front-running) (par exemple, les schémas de pré-engagement).
G4.9 Le contrat n'envoie pas de fonds automatiquement, mais permet aux utilisateurs de retirer des fonds dans des transactions distinctes à la place.

Contrôle d'accès

Contrôle d'accès Nom du test
G5.2 Le principe du moindre privilège est respecté. Les autres contrats ne devraient pouvoir accéder qu'aux fonctions et données pour lesquelles ils disposent d'une autorisation spécifique.
G5.3 Les nouveaux contrats ayant accès au contrat audité respectent le principe des droits minimaux par défaut. Les contrats doivent avoir un minimum ou aucune autorisation jusqu'à ce que l'accès aux nouvelles fonctionnalités soit explicitement accordé.
G5.4 Le créateur du contrat respecte le principe du moindre privilège et ses droits suivent strictement ceux décrits dans la documentation.
G5.5 Le contrat applique les règles de contrôle d'accès spécifiées dans un contrat de confiance, en particulier si le contrôle d'accès côté client dApp est présent et peut être contourné.
G5.6 Les appels à des contrats externes ne sont autorisés qu'en cas de nécessité.
G5.7 Le code modificateur est clair et simple. La logique ne doit pas contenir d'appels externes à des contrats non approuvés.
G5.8 Tous les attributs d'utilisateur et de données utilisés par les contrôles d'accès sont conservés dans des contrats de confiance et ne peuvent pas être manipulés par d'autres contrats, sauf autorisation spécifique.
G5.9 Les contrôles d'accès échouent en toute sécurité, y compris lorsqu'un retour se produit.
G5.10 Si l'entrée (paramètres de la fonction) est validée, l'approche de validation positive (liste blanche) est utilisée dans la mesure du possible.

Communication

Communication Nom du test
G6.2 Les bibliothèques qui ne font pas partie de l'application (mais dont le contrat intelligent dépend pour fonctionner) sont identifiées.
G6.3 L'appel délégué n'est pas utilisé avec les contrats non approuvés.
G6.4 Les contrats de tiers n'occultent pas les fonctions spéciales (par exemple, revenir).
G6.5 Le contrat ne vérifie pas si l'adresse est un contrat utilisant l'opcode extcodesize.
G6.6 Les attaques de réentrance sont atténuées en bloquant les appels récursifs provenant d'autres contrats et en suivant le modèle Check-Effects-Interactions. N'utilisez pas la fonction d'envoi sauf si c'est indispensable.
G6.7 Le résultat d'appels de fonction de bas niveau (par exemple envoyer, déléguer appeler, appeler) d'autres contrats est cochée.
G6.8 Le contrat repose sur les données fournies par le bon expéditeur et non sur la valeur tx.origin.

Arithmétique

Arithmétique Nom du test
G7.2 Les valeurs et les opérations mathématiques résistent aux débordements d'entiers. Utilisez la bibliothèque SafeMath pour les opérations arithmétiques avant Solidity 0.8.*.
G7.3 Les extraits de code non cochés de Solidity ≥ 0.8.* n'introduisent pas de sous/débordements entiers.
G7.4 Les valeurs extrêmes (par exemple, les valeurs maximales et minimales du type de variable) sont prises en compte et ne modifient pas le flux logique du contrat
G7.5 L'inégalité non stricte est utilisée pour l'égalité d'équilibre.
G7.6 Les ordres de grandeur corrects sont utilisés dans les calculs.
G7.7 Dans les calculs, la multiplication est effectuée avant la division pour plus de précision.
G7.8 Le contrat ne suppose pas une précision en virgule fixe et utilise un multiplicateur ou stocke à la fois le numérateur et le dénominateur.

Déni de service

Déni de service Nom du test
G8.2 Le contrat n'itère pas sur des boucles non liées.
G8.3 La fonctionnalité d'autodestruction n'est utilisée que si nécessaire. S'il est inclus dans le contrat, il doit être clairement décrit dans la documentation.
G8.4 La logique métier n'est pas bloquée si un acteur (par exemple contrat, compte, oracle) est absent.
G8.5 La logique métier ne décourage pas les utilisateurs d'utiliser des contrats (par exemple, le coût de la transaction est supérieur au profit).
G8.6 Les expressions de fonctions assert ou require ont une variante passante.
G8.7 Si la fonction de secours ne peut être appelée par personne, elle ne bloque pas les fonctionnalités du contrat.
G8.8 Il n'y a pas d'opérations coûteuses en boucle.
G8.9 Il n'y a pas d'appels à des contrats non approuvés dans une boucle.
G8.10 S'il existe une possibilité de suspendre l'exécution du contrat, il est également possible de le reprendre.
G8.11 Si des listes blanches et des listes noires sont utilisées, elles n'interfèrent pas avec le fonctionnement normal du système.
G8.12 Il n'y a pas de DoS causé par les débordements et les débordements.

Données de la chaîne de blocs

Données de la chaîne de blocs Nom du test
G9.2 Toutes les données enregistrées dans les contrats ne sont pas considérées comme sécurisées ou privées (même les variables privées).
G9.3 Aucune donnée confidentielle n'est stockée dans la blockchain (mots de passe, données personnelles, token etc.).
G9.4 Les contrats n'utilisent pas de littéraux de chaîne comme clés pour les mappages. Les constantes globales sont utilisées à la place pour empêcher l'attaque homoglyphe.
G9.5 Le contrat ne génère pas trivialement des nombres pseudo-aléatoires basés sur les informations de la blockchain (par exemple, l'ensemencement avec le numéro de bloc).

Utilisation du gaz et limites

Utilisation du gaz et limites Nom du test
G10.1 L'utilisation du gaz est anticipée, définie et a des limites claires qui ne peuvent pas être dépassées. La structure du code et les entrées malveillantes ne doivent pas provoquer d'épuisement des gaz.
G10.2 L'exécution et la fonctionnalité des fonctions ne dépendent pas des frais de gaz codés en dur (ils sont susceptibles de varier).

Clarté et lisibilité

Clarté et lisibilité Nom du test
G11.2 La logique est claire et modularisée en plusieurs contrats et fonctions simples.
G11.3 Chaque contrat comporte un court commentaire de 1 à 2 phrases qui explique son objectif et sa fonctionnalité.
G11.4 Des implémentations prêtes à l'emploi sont utilisées, cela est clairement indiqué dans les commentaires. Si ces implémentations ont été modifiées, les modifications sont notées tout au long du contrat.
G11.5 L'ordre d'héritage est pris en compte dans les contrats qui utilisent plusieurs fonctions d'héritage et de duplication.
G11.6 Dans la mesure du possible, les contrats utilisent du code testé existant (par exemple, des contrats de jeton ou des mécanismes tels que propriétaire) au lieu d'implémenter les leurs.
G11.7 Des modèles de dénomination cohérents sont suivis tout au long du projet.
G11.8 Les variables ont des noms distinctifs.
G11.9 Toutes les variables de stockage sont initialisées.
G11.10 Les fonctions avec le type de retour spécifié renvoient une valeur de ce type.
G11.11 Toutes les fonctions et variables sont utilisées.
G11.12 exigent est utilisé au lieu de revenir in if Déclarations.
G11.13 La affirmer La fonction est utilisée pour tester les erreurs internes et le exigent La fonction est utilisée pour garantir une condition valide dans les entrées des utilisateurs et des contrats externes.
G11.14 Le code d'assemblage n'est utilisé que si nécessaire.

Couverture de test

Couverture de test Nom du test
G12.2 Les récits d'abus détaillés dans le modèle de menace sont couverts par des tests unitaires
G12.3 Les fonctions sensibles dans les contrats vérifiés sont couvertes par des tests en phase de développement.
G12.4 La mise en œuvre des contrats vérifiés a été vérifiée pour les vulnérabilités de sécurité à l'aide d'analyses statiques et dynamiques.
G12.5 La spécification du contrat a été formellement vérifiée
G12.6 La spécification et les résultats de la vérification formelle sont inclus dans la documentation.

Finance décentralisée

Finance décentralisée Nom du test
G13.1 Le contrat du prêteur ne suppose pas que son solde (utilisé pour confirmer le remboursement du prêt) soit modifié uniquement avec ses propres fonctions.
G13.2 Les fonctions qui modifient le solde des prêteurs et/ou prêtent de la crypto-monnaie sont non réentrantes si le contrat intelligent permet d'emprunter la crypto-monnaie de la plateforme principale (par exemple Ethereum). Il bloque les attaques qui mettent à jour le solde de l'emprunteur lors de l'exécution du prêt flash.
G13.3 Les fonctions de prêt Flash ne peuvent appeler que des fonctions prédéfinies sur le contrat de réception. Si cela est possible, définissez un sous-ensemble de contrats de confiance à appeler. Habituellement, le contrat d'envoi (d'emprunt) est celui à rappeler.
G13.4 Si cela inclut des opérations potentiellement dangereuses (par exemple, renvoyer plus d'ETH/tokens qu'emprunté), la fonction du destinataire qui gère les ETH ou les tokens empruntés ne peut être appelée que par le pool et dans le cadre d'un processus initié par le propriétaire du contrat destinataire ou une autre source de confiance (par exemple multisig).
G13.5 Les calculs de la part du pool de liquidités sont effectués avec la plus grande précision possible (par exemple, si la contribution est calculée pour ETH, elle doit être effectuée avec une précision de 18 chiffres - pour Wei, pas Ether). Le dividende doit être multiplié par 10 à la puissance du nombre de chiffres décimaux (par exemple dividende * 10^18 / diviseur).
G13.6 Les récompenses ne peuvent pas être calculées et distribuées dans le même appel de fonction qui dépose des jetons (il doit également être défini comme non réentrant). Cela protège des fluctuations momentanées des actions.
G13.7 Les contrats de gouvernance sont protégés contre les attaques de prêts flash. Une technique d'atténuation possible consiste à exiger que le processus de dépôt de jetons de gouvernance et de proposition d'un changement soit exécuté dans différentes transactions incluses dans différents blocs.
G13.8 Lors de l'utilisation d'oracles en chaîne, les contrats peuvent suspendre les opérations en fonction du résultat des oracles (en cas d'oracle compromis).
G13.9 Les contrats externes (même ceux de confiance) qui sont autorisés à modifier les attributs d'un contrat de projet (par exemple, le prix du jeton) ont les limitations suivantes mises en œuvre : des seuils pour le changement (par exemple, pas plus/moins de 5 %) et une limite de mises à jour (par exemple une mise à jour par jour).
G13.10 Les attributs de contrat pouvant être mis à jour par les contrats externes (même ceux de confiance) sont surveillés (par exemple à l'aide d'événements) et une procédure de réponse aux incidents est mise en place (par exemple lors d'une attaque en cours).
G13.11 Les opérations mathématiques complexes qui consistent à la fois en opérations de multiplication et de division effectuent d'abord des multiplications, puis des divisions.
G13.12 Lors du calcul des prix d'échange (par exemple ETH à jeton ou vice versa), le numérateur et le dénominateur sont multipliés par les réserves (voir le getInputPrice fonction de l' UniswapExchange Contrat).

 

Commandez l'audit de Sayfer





    Ce site est protégé par reCAPTCHA et Google Données privées ainsi que Conditions d'utilisation s'appliquent.

    Constatations des audits

    [H] Risque de course avant lors de la création d'une nouvelle paire

    ID DIRE-01
    Statut Fixé
    Analyse Haute
    La Brochure Impact Dans certains cas, les utilisateurs peuvent perdre les fonds qu'ils ont déposés afin de financer la création de paires. Soit un leader malveillant peut créer une paire aux dépens d'un autre utilisateur, soit plusieurs utilisateurs peuvent tenter de créer une paire en même temps, avec succès ou échec au hasard.
    Localisation
    • Routeur.ts ; créerLBPair(StaticArray )
    • Usine.ts ; créerLBPair(StaticArray )

    Description

    Afin de créer une nouvelle paire, l'utilisateur doit appeler Routeur ::createLBPair(StaticArray ). Sous le capot, cette fonction appelle Usine : createLBPair (StaticArray ), qui à son tour appelle Massa transferCoins(Adresse, numéro).

    • Usine.ts:264 ; créerLBPair(StaticArray )

    transferCoins(_pair._origin, 200 * ONE_COIN);

    Selon le Documentation, cette fonction transfère simplement les pièces de l'adresse actuelle vers une adresse donnée. Cela signifie que ces fonds doivent être préalablement envoyés à Usine. D'autre part, les utilisateurs ont la possibilité d'appeler créer une paire depuis le routeur, qui est le point d’entrée par défaut pour d’autres opérations. Cependant, s'ils sont déposés dans le cadre d'une transaction distincte, il est possible que quelqu'un, intentionnellement ou non, appelle également créerLBPair(StaticArray ).

    Lorsqu'un bloc de transactions est finalisé, elles seront disposées dans un ordre inconnu. Ensuite, la première transaction incluse verra ces fonds transférés de Factory vers une nouvelle paire, tandis que le deuxième utilisateur (cette dernière transaction) verra sa transaction annulée en raison du manque de fonds disponibles.

    Atténuation

    Le financement de la création de paires doit effectivement avoir lieu dans la même transaction pour éviter les problèmes de réorganisation des transactions. 

    Par exemple, l'un des moyens d'y parvenir pourrait être un mécanisme vérifiant le solde de l'usine et le solde du pool à la fin d'une fonction et renvoyant le surplus, similaire à celui-ci. https://github.com/massalabs/coin-vester/blob/master/smart-contract/assembly/contracts/main.ts#L34

    Le mécanisme sera en place dans le créerLBPair fonction de Usine), dans le constructeur, menthe, brûler, collecter les frais, augmenterOracleLength, transfert sécuriséDe & safeBatchTransferFrom (de paire). Ce sont les fonctions capables de dépenser Massa pour le stockage car elles peuvent créer de nouvelles entrées dans le stockage (la modification du stockage ne coûte rien). Les fonctions interagissant avec ces fonctions doivent également disposer de ce mécanisme. 

    On peut les séparer en deux sortes différentes :

    • Fonctions interagissant avec celles-ci et qui n'interagissent pas avec WMAS (créerLBPair du routeur et de l'usine + ajouterLiquidité, supprimerLiquidité) transférera tous les Pièces transférées, enregistrez le solde du SC dans une constante, et après l'appel du SC, retransférez à l'appelant la différence entre le nouveau solde et le solde enregistré.
    • Fonctions interagissant avec celles-ci et qui interagissent avec WMAS (ajouterLiquiditéMAS, supprimerLiquiditéMAS) aura besoin d'un paramètre supplémentaire pour connaître le nombre de pièces à emballer, vous enverrez la différence entre Pièces transférées et ce numéro dans l'appel. Le reste du mécanisme de ces fonctions sera le même que celui juste avant.

     

    [H] Les fonds déposés pour la création de paires peuvent être perdus

    ID DIRE-02
    Statut Fixé
    Analyse Haute
    Impact sur les entreprises Les utilisateurs qui déposent des fonds sur le routeur pour créer une paire peuvent perdre leur argent sans voir de résultat. Nous avons évalué ce problème comme étant élevé (plutôt que critique) car il existe un flux de travail alternatif : appeler usine::createLBPair(StaticArray ) directement avec les fonds.
    Localisation
    • Routeur.ts ; créerLBPair(StaticArray )
    • Usine.ts:264 ; créerLBPair(StaticArray )

    Description

    Ce problème résulte de la façon dont la création de paires est conçue. Un utilisateur peut appeler Routeur ::createLBPair(StaticArray ) et comme une création de paire nécessite un dépôt, il peut joindre des fonds à l'appel de fonction, ce qui semble être une solution intuitive.

    Cependant, si l'utilisateur le fait, les fonds n'atteindront jamais la paire et seront perdus dans le contrat (bien qu'ils puissent être récupérés par le propriétaire). En effet, ils seront bloqués dans le contrat du routeur, tandis que la création de la paire a lieu dans le contrat d'usine, où transferCoins(), qui déduit les fonds de l'adresse actuelle (de l'usine), est utilisé à la place.

    • Usine.ts:264 ; créerLBPair(StaticArray )

    transferCoins(_pair._origin, 200 * ONE_COIN);

    Puisqu'il est implémenté dans l'usine, les fonds envoyés au routeur n'atteindront pas l'usine, qui n'aura pas non plus les fonds nécessaires pour créer une paire et revenir en arrière.

    Atténuation

    Une option consiste à mettre en œuvre la solution suggérée dans DIRE-01.
    Inversement, Usine.ts peut être appelé directement pour créer des paires et demander aux utilisateurs d'envoyer soit le montant exact requis avec l'appel de fonction, OU au moins le montant requis avec le remboursement de tout excédent de fonds envoyé.

     

    [M] Plusieurs paires du même type peuvent diluer la liquidité

    ID DIRE-03
    Statut Fixé
    Analyse Moyenne
    Impact sur les entreprises Si une application AMM permet de créer plusieurs pools avec les mêmes paramètres, la liquidité peut être diluée dans ces pools, au lieu d'être concentrée dans un seul. Cela pourrait avoir un impact négatif sur les utilisateurs et entraîner des transactions moins favorables pour les utilisateurs du protocole.

    De plus, la paire précédente ne sera plus utilisée pour le routage. Cela peut entraîner des liquidités ou une manipulation des prix.

    Localisation
    • Usine.ts ; créerLBPair(StaticArray )
    • Routeur.ts ; créerLBPair(StaticArray )

    Description

    Lors de la création d’une nouvelle paire, il n’est pas vérifié si exactement la même paire existe déjà. Cela peut disperser les liquidités des utilisateurs sur plusieurs pools équivalents. Les pools à faible liquidité sont plus sujets aux manipulations de prix et offrent des transactions moins favorables ; ils doivent donc être évités.

    Atténuation

    Vérifiez si une paire de certains paramètres existe déjà lors de la création de la paire, si c'est le cas, annulez.

     

    [L] La vérification exacte du solde après un prêt flash peut être utilisée de manière abusive

    ID DIRE-04
    Statut Fixé
    Analyse Faible
    Impact sur les entreprises Un destinataire de prêt flash peut effectuer des appels externes lors du rappel. Étant donné que le système exige que le solde après le prêt flash soit exactement le solde avant plus les frais, ces contrats externes pourraient transférer un très petit montant à la paire pendant l'exécution pour garantir que le prêt flash échouera (ce qui peut être rentable pour eux). dans certaines situations).
    Localisation
    • Paire.ts:280 ; flashLoan(StaticArray )

    Description

    Après un prêt flash, le système exige que le solde soit exactement le solde avant le prêt flash plus les frais.

    • flashLoan(StaticArray )

    assert(

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

      LBPair__FlashLoanInvalidBalance(),

    );

    En règle générale, il est nécessaire que le solde soit supérieur, car exiger une correspondance exacte est restrictif.

    Atténuation

    Vérifiez uniquement si le solde est supérieur au solde avant le prêt flash majoré des frais. C'est également la logique que TraderJoe utilise dans sa fonction de prêt flash.

     

    [L] Ignorer une paire LB n'émet pas d'événement

    ID DIRE-05
    Statut Fixé
    Analyse Faible
    La Brochure Impact Les indexeurs hors chaîne peuvent recevoir des informations incorrectes, conduisant à des calculs erronés.
    Localisation
    • Usine.ts ; setLBPairInformation(StaticArray )

    Description

    La fonction setLBPairIgnored(StaticArray ) peut être utilisé pour contrôler si une paire doit être ignorée pour le routage ou non. Tout changement de flag via cette fonction émet l'événement SET_LBPAIR_IGNORED. Cependant, il est également possible de changer le drapeau via setLBPairInformation(StaticArray ), qui n'émet pas d'événement.

    Atténuation

    Émettez toujours un événement lors du changement d'indicateur pour garantir que les systèmes hors chaîne savent quelles paires seront prises en compte pour le routage.

    [L] Recouvrement des frais incohérent

    ID DIRE-06
    Statut Reconnu
    Analyse Faible
    La Brochure Impact N'importe quel utilisateur peut déclencher la collecte des frais pour d'autres utilisateurs, alors que la collecte des frais de protocole ne peut être déclenchée que par le propriétaire.
    Localisation
    • Paire.ts; collecter des frais (StaticArray )
    • Paire.ts : 723-726 ; collectProtocolFees(StaticArray )

    Description

    N'importe qui peut appeler collecter des frais (StaticArray ) pour toute adresse de répartir les frais à cette adresse. Cela peut être indésirable pour certains utilisateurs qui souhaitent contrôler le moment où les frais leur sont distribués. 

    Ceci est en outre incompatible avec collectProtocolFees(StaticArray ), qui ne peut être appelé que par le destinataire.

    • collectProtocolFees(StaticArray )

    assert(

      Context.caller().equals(_feeRecipient),

      LBPair__OnlyFeeRecipient(_feeRecipient, Context.caller()),

    );

    Atténuation

    Pensez à changer la logique dans collecter des frais (StaticArray ) faire correspondre collectProtocolFees(StaticArray ), c'est-à-dire permettre uniquement au destinataire de percevoir ses frais.

    [L] Utilisation incohérente de SafeMath

    ID DIRE-07
    Statut Fixé
    Analyse Faible
    La Brochure Impact Les dépassements de capacité ou les dépassements inférieurs dans le code peuvent entraîner des retours inattendus et/ou des erreurs de calcul. 
    Localisation -

    Description

    Même si SafeMath est utilisé à de nombreux endroits, certaines fonctions qui utilisent des opérations arithmétiques restent non protégées, ce qui peut par conséquent conduire à des débordements ou des sous-débordements.

    Atténuation

    Bien qu'aucun endroit n'ait été identifié où une telle situation pourrait être probable, en raison de la grande taille de la base de code et de la multitude de calculs, nous recommandons d'implémenter SafeMath dans autant d'opérations que possible.

    [L] Énumération des actifs inefficace

    ID DIRE-08
    Statut Fixé
    Analyse Faible
    La Brochure Impact Certaines fonctions d'usine consommeront plus de gaz que nécessaire. Dans le pire des cas, si le propriétaire enregistre un très grand nombre d’actifs, cela pourrait conduire à un DoS. Mais c'est peu probable.
    Localisation
    • Usine.ts : 102-106 ; isQuoteAsset (Adresse)

    Description

    voici deux problèmes avec cette fonction : 

    1. La boucle ne se rompt pas après avoir trouvé un actif et parcourt inutilement le reste du tableau. Ainsi, chaque cas is le pire des cas.
    2. Un mappage serait ici plus efficace, car il nécessite une recherche temporelle constante.
    • isQuoteAsset (Adresse)

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

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

        isQuoteAsset = true;

      }

    }

    Atténuation

    Il y a deux solutions ici :

    1. Conservez l'algorithme de recherche linéaire actuel et ajoutez simplement une pause dans le if bloquer après réglage isQuoteAsset à vrai.
    2. Une meilleure solution serait de passer à un mappage. Lorsqu'un nouveau jeton est ajouté au système, quoteActifs[token] doit être défini sur true. Désormais, il est accessible en cas de besoin – plus besoin de le rechercher. Peut-être que toute la fonction peut simplement être remaniée.

    [L] Les frais maximum du prêt Flash ne sont pas définis après le déploiement

    ID DIRE-09
    Statut Fixé
    Analyse Faible
    La Brochure Impact Il est possible d'avoir des frais de prêt flash supérieurs à MAX_FEE.
    Localisation
    • Usine.ts:80 ; constructeur (StaticArray )

    Description

    Chaque fois que les frais du prêt flash sont définis à l'aide de setFlashLoanFee(), on valide qu'elle est inférieure à la valeur MAX_FEE. Toutefois, cette vérification n’est pas effectuée lors de l’initialisation du contrat et il est possible d’y fixer des frais de prêt flash arbitrairement élevés.

    Atténuation

    Validez les frais du prêt flash chez le constructeur.

    [L] Protection contre les glissements incomplète – Contrôle des délais manquants

    ID DIRE-10
    Statut Fixé
    Analyse Faible
    La Brochure Impact Il existe une probabilité accrue que les utilisateurs obtiennent des transactions moins favorables lorsqu'ils utilisent l'AMM.
    Localisation Routeur.ts

    • addLiquidity(bs : StaticArray )
    • addLiquidityMAS(bs : StaticArray )

    Description

    Le slippage est le résultat d'une volatilité des solutions de type AMM, et signifie simplement que le prix lors de la demande d'un changement de transaction/swap/liquidité est différent de celui lors de l'exécution de la transaction. Pour protéger les utilisateurs d'énormes dérapages, qui peuvent être naturels ou résulter d'attaques intentionnelles comme le Sandwiching, il existe deux types génériques de protections : le montant minimal, qui est présent, et le contrôle des délais, qui manque.

    Ces contrôles doivent être mis en œuvre pour tout swap, ajout ou retrait de liquidité, car tous sont sujets à des dérapages.

    Un contrôle de délai ne permet tout simplement pas d'inclure la transaction après un certain moment, qui peut par exemple être intentionnellement inclus plus tard par un constructeur de blocs malveillant pour tenter quand même d'exécuter la transaction à des conditions de prix moins favorables. Cependant, étant donné qu’un montant minimal de jetons est vérifié, l’impact de ce problème est limité.

    Atténuation

    Mettre en œuvre le  _assurer (date limite) de la même manière, il est déjà présent dans toutes les autres fonctions traitant de la liquidité.

    [L] Transfert de propriété en une étape

    ID DIRE-11
    Statut Fixé
    Analyse Faible
    La Brochure Impact Fournir une adresse incorrecte pourrait entraîner une perte irrévocable de la propriété du contrat.
    Localisation
    • Usine.ts ; transfert de propriété ([u8])

    Description

    In Usine.ts, le changement de propriétaire est réalisé par l'ancien propriétaire en appelant le transfert de propriété ([u8]) avec le nouveau propriétaire. La fonction modifie alors le PROPRIÉTAIRE état variable.

    • transfert de propriété ([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());

    }

    Atténuation

    Nous recommandons de mettre en œuvre un processus en deux étapes pour le transfert de propriété. Ceci est conforme aux bonnes pratiques largement reconnues et pourrait empêcher les transferts accidentels. Pour illustrer, nous utiliserons l'implémentation d'OpenZepplin.

    Un transfert de propriété en deux étapes nécessite d’abord que le propriétaire actuel initie le transfert.

    function transferOwnership(address newOwner) public virtual override onlyOwner {

     _pendingOwner = newOwner;

     emit OwnershipTransferStarted(owner(), newOwner);

    }

    Mais pour finaliser le processus, le nouveau propriétaire doit approuver le transfert.

    function acceptOwnership() public virtual {

     address sender = _msgSender();

     if (pendingOwner() != sender) {

         revert OwnableUnauthorizedAccount(sender);

     }

     _transferOwnership(sender);

    }

    Cela garantit que le nouveau propriétaire est la cible visée.

    [I] Émission d'événement insuffisante

    ID DIRE-12
    Statut Fixé
    Analyse D'information
    La Brochure Impact Diminution de la traçabilité et de la visibilité des changements historiques d’état clé affectant le protocole.
    Localisation Usine.ts

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

    Description

    Certains des changements d'état clés du protocole n'émettent pas d'événement associé.

    Remarque: transferOwnership (bs: StaticArray ) émet un événement, mais uniquement pour _setFeeRecipient.

    Atténuation

    Ajoutez une émission d’événement aux emplacements spécifiés.

    [I] Les getters et setters sont mélangés avec des fonctions externes

    ID DIRE-13
    Statut Fixé
    Analyse D'information
    La Brochure Impact Le mixage, les getters, les setters, les points d'entrée et les fonctions internes rendent le code moins lisible.
    Localisation
    • Usine.ts : 631, 639
    • Paire.ts : 1031, 1227

    Description

    Certains contrats ont des sections distinctes contenant des fonctions qui changent l'état (setters), le lisent (getters) ou font partie de l'arborescence des appels de fonction (interne).

    Mais dans certains contrats, cet ordre est perturbé – les fonctions sont mélangées. Parfois, les fonctions exportées (points d’entrée) sont également confondues avec les fonctions internes.

    Atténuation

    Nous recommandons que les sections du code soient correctement séparées, les points d'entrée séparés des fonctions internes et que la convention d'utilisation du signe _ avant les fonctions privées soit maintenue.

    [I] Manque de tests unitaires

    ID DIRE-14
    Statut Reconnu
    Analyse D'information
    La Brochure Impact Les scénarios de test et les tests unitaires aident les développeurs à détecter les bogues et les vulnérabilités qui autrement passeraient inaperçus lors d'une simple analyse statique. Les tests dynamiques sont inestimables pour garantir la qualité du produit fini.
    Localisation -

    Description

    Hormis une dizaine de tests pour un certain nombre de fonctionnalités de la bibliothèque, le code ne comportait pas de tests unitaires, fonctionnels ou d'intégration. Tous les défauts ne peuvent pas être détectés par une simple analyse statique, laissant le produit dans une position précaire.

    Atténuation

    Il est considéré comme une bonne pratique de garantir que la couverture du code pour les tests est aussi élevée que possible et que les scénarios de test incluent à la fois des chemins heureux et malheureux.

    [I] Code inutile

    ID DIRE-15
    Statut Fixé
    Analyse D'information
    La Brochure Impact Ce problème n'a aucun impact direct sur le code ou sur le protocole et a donc été classé à titre informatif.
    Localisation Routeur.ts : 770-772 ; _getAmountsIn(u64[], Adresse[], IERC20[], u256)

    Description

    La fonction _getAmountsIn() prend les étapes bin comme argument et effectue la vérification suivante :

    • _getAmountsIn(u64[], Adresse[], IERC20[], u256)

    if (_binStep == 0) {

      // means TraderJoe V1 swap

    } else {

      ...

    }

    Cependant, cela n’est pas nécessaire. Le système ne prend pas en charge les swaps de style V1 et le reste de la fonction ne prend pas en compte les étapes bin, car il reçoit les paires (correspondant aux étapes bin) comme argument supplémentaire.

    Atténuation

    Pensez à supprimer l'argument _pairBinSteps et la clause if inutile.

    [I] Importations inutilisées

    ID DIRE-16
    Statut Fixé
    Analyse D'information
    La Brochure Impact Ce problème n'a aucun impact direct sur le code ou sur le protocole et a donc été classé à titre informatif.
    Localisation
    • Paire.ts:35,
    • Routeur.ts : 4,
    • WMAS.ts:5,6,
    • interfaces/IPair.ts:5

    Description

    Les importations spécifiées semblent ne jamais être utilisées dans leurs contrats respectifs. Ils pourraient être supprimés.

    Atténuation

    Supprimez les importations inutilisées.

    [I] Utilisation des « nombres magiques »

    ID DIRE-17
    Statut Reconnu
    Analyse D'information
    La Brochure Impact Cela peut augmenter la difficulté d'analyser le code pour les lecteurs inconnus.
    Localisation
    • Paire.ts:113
    • Usine.ts : 264, 735

    Description

    À plusieurs endroits, le contrat utilise des valeurs numériques qui ne sont pas bien documentées, décrites ou commentées.

    Atténuation

    Ajoutez des commentaires expliquant le choix des constantes.

    Vous pouvez trouver plus d'informations à ce sujet sur notre Blog

    Le blog de Sayfer se concentre sur la recherche sur le web3, la sécurité et les vulnérabilités. Nous pensons que dans le secteur de la cybersécurité, il est crucial de se tenir au courant des dernières tendances et avancées. Actuellement, notre équipe de chercheurs expérimentés aime faire des recherches sur les technologies de pointe de la blockchain et du web3.
    Nous contacter

    Restez à l'écoute

    Téléphone
    Localisation
    Tel Aviv, Israël
    Messagers:
    N'hésitez pas à nous contacter, nous nous ferons un plaisir de vous répondre !





      Ce site est protégé par reCAPTCHA et Google Données privées ainsi que Conditions d'utilisation s'appliquent.
      Passer au contenu