AlexGo Audit ::: Launchpad, Vault et Reserve Pool


CoinFabrik a été chargé d'auditer les contrats du projet AlexGo.

Portée

Les contrats audités proviennent du référentiel git alex-v1. L'audit est basé sur le commit. Les correctifs ont été ajoutés au commit.

Les contrats audités sont :

● Clarity/contracts/alex-vault.clar  : contrat qui stocke les jetons système et autorise les prêts flash.

● Clarity/contracts/pool/alex-launchpad.clar  : tableau de bord du jeton IDO.

● Clarity/contracts/pool/alex-reserve-pool.clar  : contrat pour le jalonnement de jetons.

La portée de la vérification est limitée à ces dossiers. Aucun autre fichier de ce référentiel n'a été audité. Ses dépendances sont supposées fonctionner conformément à leur documentation. De plus, aucun test n'a été examiné pour cet audit.

Analyses

Sans s'y limiter, le processus d'audit comprenait les analyses suivantes :

● Erreurs arithmétiques

● Conditions de course

● Attaques de réentrance

● Utilisation abusive des horodatages de bloc

● Attaques par déni de service

● Utilisation excessive de gaz

● Qualificateurs de fonction manquants ou mal utilisés

● Interactions de code et de contrat inutilement complexes

● Gestion des erreurs médiocre ou inexistante

● Validation insuffisante des paramètres d'entrée

● Manipulation incorrecte des signatures cryptographiques

● Centralisation et évolutivité

Résumé des conclusions

deux problèmes moyens et un problème mineur. Aussi, deux

des améliorations ont été proposées.

Le problème de gravité critique et les deux problèmes moyens ont été reconnus. Deux problèmes mineurs de gravité ont été corrigés. Une amélioration a été mise en place.

Problèmes de sécurité

Rôles privilégiés

Alex-vault.clar

Propriétaire

Au début, le propriétaire est l'adresse du déployeur. Ensuite, le propriétaire peut définir une adresse en tant que nouveau propriétaire. En outre, ce rôle peut définir un nouveau taux de frais de prêt flash et ajouter de nouveaux contrats approuvés, des utilisateurs de prêt flash et des jetons de prêt flash. Enfin, le propriétaire peut transférer des jetons fongibles et semi-fongibles stockés dans le coffre-fort.

Contrats approuvés

Les contrats approuvés sont des adresses qui peuvent exécuter les fonctions de transfert pour déplacer les jetons fongibles et semi-fongibles du contrat de coffre-fort. Cet ensemble d'adresses est initialisé, y compris alex-reserve-pool, collatéral-rebalancing-pool, fixed-weight-pool, liquidity-bootstrapping-pool, yield-token-pool et yield-collateral-rebalancing-pool.

Utilisateurs approuvés du prêt Flash

Les utilisateurs de prêt Flash sont des adresses autorisées à être utilisées lorsque flash-loan() est appelé. Ce contrat doit implémenter le trait spécifique pour que le contrat de coffre appelle la fonction execute().

Alex-launchpad.clar

Propriétaire

Au début, le propriétaire est l'adresse du déployeur. Ensuite, le propriétaire peut définir une adresse en tant que nouveau propriétaire. En outre, ce rôle peut créer de nouveaux pools de tickets de jeton.

Fournisseur de liquidité

Il s'agit d'une adresse définie par le propriétaire pour chaque pool créé. Cette adresse est la seule autorisée à fournir des jetons au pool. Aussi, cette adresse reçoit le montant des stacks payés pour valider le ticket gagnant.

Alex-reserve-pool.clar

Propriétaire

Au début, le propriétaire est l'adresse du déployeur. Ensuite, le propriétaire peut définir une adresse en tant que nouveau propriétaire. En outre, ce rôle peut ajouter de nouveaux contrats approuvés et des jetons approuvés, définir un nouveau délai d'activation, un seuil d'activation, une nouvelle valeur pour le cycle de réduction de moitié et le montant de la base de pièces d'un jeton et une nouvelle durée de cycle de récompense. Enfin, le propriétaire peut augmenter et diminuer le solde d'un jeton.

Contrats approuvés

Les contrats approuvés sont des adresses qui peuvent augmenter et diminuer le solde d'un jeton. Initialement, les contrats inclus dans cet ensemble sont :

pool de rééquilibrage des garanties, pool de pondération fixe, pool de jetons de rendement, pool de rééquilibrage des garanties de rendement et le pool de réserve lui-même.

Problèmes de sécurité détectés

Classification de gravité

Les risques de sécurité sont classés comme suit :

●Critique. Ils compromettent la

système au sérieux. Ils doivent être corrigés immédiatement.

●Moyen  : Ce sont des problèmes potentiellement exploitables.

réussissent à les exploiter ou si leur impact n'est pas clair, ils peuvent représenter un

risque de sécurité dans un proche avenir.

●Mineur : Ces problèmes représentent des problèmes relativement petits ou difficiles à exploiter, mais qui peuvent être exploités en combinaison avec d'autres problèmes. Ces types de problèmes ne bloquent pas les déploiements dans les environnements de production. Ils doivent être pris en compte et fixés quand c'est possible

Statut des problèmes

Un problème détecté par cet audit peut avoir quatre statuts distincts  :

●Non résolu  : le problème n'a pas été résolu.

● Reconnu  : le problème reste dans le code, mais il résulte d'une décision intentionnelle.

●Résolu  : Mise en œuvre ajustée du programme pour éliminer le risque.

Atténué  : actions mises en œuvre pour minimiser l'impact ou la probabilité du risque.

Problèmes de gravité critique

CR-01 Loteries déloyales par un faible caractère aléatoire

Emplacement:

●clarity/contracts/pool/alex-launchpad.clar

Les utilisateurs peuvent valider leurs tickets lors du processus d'inscription, délimité par les variables registration-start et registration-end. Un compteur est augmenté pour chaque ticket validé, et chaque utilisateur dispose d'une plage de positions liées au moment où il a rejoint la loterie et au nombre de tickets validés. Lorsque l'inscription se termine et que le nombre minimum de participants est atteint, les utilisateurs peuvent appeler réclamation() une fois pour chaque ticket validé.

Cette fonction détermine si le ticket est gagnant sur la base d'un nombre pseudo-aléatoire modulo le compteur de tickets. Si la valeur résultante est dans la plage de positions des tickets validés par l'utilisateur, alors c'est un ticket gagnant.

Cependant, le premier nombre pseudo-aléatoire est généré en fonction de la graine vrf du bloc de début d'enregistrement lors du premier appel à claim(). Pour les appels suivants, la fonction calcule un nouveau pseudo-aléatoire basé sur le dernier aléatoire.

Par conséquent, puisque le contrat est public et le processus transparent, n'importe qui peut calculer la séquence de valeurs à générer.

Recommandation

Enfin, la spéculation dans l'ordonnance de revendication peut être résolue en calculant le

nombre pseudo-aléatoire avec la graine VRF mentionnée et une valeur unique pour chaque ticket (par exemple, la position du ticket). Ensuite, en utilisant deux valeurs constantes, l'ordre de réclamation n'aura pas d'impact car le nombre aléatoire est déjà déterminé.

Statut

Reconnu. claim() utilise désormais registration-end au lieu de

registration-start pour la graine VRF. La spéculation a été réduite, mais elle utilise toujours une graine qui peut être connue si register() est appelé à la fin de l'enregistrement. L'utilisation du bloc à côté de registration-end peut résoudre le problème.

Les nouveaux changements ont également rendu toute la séquence aléatoire imprévisible. Cependant, le prochain hasard peut encore être prédit et l'utilisateur peut vérifier si ce hasard est bénéfique et attendre le prochain hasard si ce n'est pas le cas. Afin d'éviter la spéculation dans l'ordre de réclamation, le nombre doit être généré soit avec une entrée inconnue pour l'utilisateur, soit avec des valeurs constantes. La première solution rend le prochain aléatoire imprévisible pour l'utilisateur, tandis que la seconde le rend constant.

Problèmes de gravité moyenne

ME-01 Authentification non sécurisée via tx-sender

Emplacement:

●clarity/contracts/alex-vault.clar,

●clarity/contracts/pool/alex-launchpad.clar,

●clarity/contracts/pool/alex-reserve-pool.clar

La variable globale tx-sender renvoie l'expéditeur d'origine de la transaction en cours, ou si as-contract a été appelé pour modifier le contexte d'envoi, elle renvoie ce principal de contrat. L'utilisation de cette variable pour l'authentification n'est pas sécurisée. Les acteurs du système pourraient être la cible de phishing. Ceci est analogue à ce qui arrive à tx.origin et msg.sender dans Solidity. Là, la convention est d'utiliser msg.sender, qui fonctionne comme le contract-caller.

Par exemple, le propriétaire du coffre-fort peut être amené à appeler un contrat malveillant qui exécute le coffre-fort.set-contract-owner() contre sa volonté.

Recommandation

Préférez contract-caller à tx-sender pour l'authentification. contrat-appelant

renvoie l'appelant du contexte de contrat courant.

Statut

Reconnu. Un nouveau développement permettrait de résoudre ce problème.

ME-02 Probabilité de gagner indépendante à la loterie

Emplacement:

●clarity/contracts/pool/alex-launchpad.clar

Comme décrit dans CR-01, chaque exécution de claim() génère un nouveau nombre aléatoire. Par conséquent, bien qu'il y ait des jetons à transférer, la probabilité de gagner est indépendante et le nombre de gagnants est inconnu. Afin de le résoudre, la fonction vérifie si tous les tickets fournis ont été gagnés avant d'exécuter le reste de la fonction. Lorsque tous les billets gagnants sont déterminés, la liste est terminée et les nouvelles réclamations ne sont pas acceptées. Ce mécanisme peut entraîner deux problèmes.

Premièrement, certains jetons peuvent ne pas être réclamés s'il n'y a pas assez de billets gagnants. De plus, il n'y a aucune utilisation donnée à ces jetons restants.

Deuxièmement, il génère une condition de concurrence entre les utilisateurs pour réclamer avant que la liste ne soit terminée. Dans le cas contraire, un utilisateur ne pourra pas réclamer

même quand il a des billets.

Recommandation

Une solution serait de ne générer que n nombres aléatoires, où n est le nombre de tickets gagnants. Ensuite, claim() vérifierait si l'un des nombres aléatoires se trouvait dans la plage de tickets de l'utilisateur. Cependant, en raison des limites de Clarity, cette solution ne peut pas être mise en œuvre.

Statut

Reconnu.

Problèmes de gravité mineurs

MI-01 Sous-dépassement arithmétique Calcul de la récompense de jalonnement

Emplacement:

●clarity/contracts/pool/alex-reserve-pool.clar  :[379]

Dans get-entitled-staking-reward(), les récompenses sont calculées avec le quotient entre le montant misé par l'utilisateur et le montant total misé, multiplié par le montant coinbase du jeton.

Le résultat du quotient peut avoir une plus grande imprécision que le résultat obtenu par

en multipliant d'abord, puis en le divisant par le total jalonné.

Recommandation :

Pour un résultat plus précis, obtenez le produit entre le montant coinbase et le montant misé par l'utilisateur, et divisez-le par le montant total misé :

Statut

Résolu.

Le pool terminé MI-02 peut être créé

Emplacement:

●clarity/contracts/pool/alex-launchpad.clar

La fonction de création de pool (create-pool()) ne valide pas les numéros de bloc fournis pour les variables de début d'enregistrement et de fin d'enregistrement. Par conséquent, un pool peut être créé sans temps d'enregistrement.

Recommandation

Le début d'enregistrement d'entrée doit être vérifié pour être égal ou supérieur au numéro de bloc actuel.

Statut

Résolu.

Améliorations

Ces éléments ne représentent pas un risque pour la sécurité.

suggérer de mettre en œuvre.

Tableau

Des détails

Emplacement:

●clarity/contracts/pool/alex-launchpad.clar

Statut

Pas mis en œuvre. L'équipe de développement s'est engagée à ajouter la documentation.

FR-02 Calcul inutile pour vérifier si la liste est activée

Emplacement:

●clarity/contracts/pool/alex-launchpad.clar

Le mappage de liste contient une variable nommée enabled qui est initialement définie sur false lors de la création du pool, puis augmentée pour chaque nouveau registre. La fonction register() met à jour la valeur à true si le nombre de tickets validés (total-subscribed) a atteint le seuil d'activation.

Il n'y a pas d'autre fonction qui met à jour la valeur totale souscrite ni la valeur activée. Cependant, la fonction getter is-listing-activated() recalcule la comparaison entre les deux variables au lieu de lire à partir de la variable activée.

Recommandation :

Lire à partir de la variable activée au lieu d'effectuer à nouveau la comparaison.

Statut

Mis en œuvre.

Journal des modifications

●2022-01-07 – Rapport initial basé sur l'engagement

●2022-01-11 - Rapport de réaudit basé sur les correctifs dans le commit

●2022-01-13 – L'état du CR-01 est passé à " acquitté ".

ce rapport d'audit n'est pas une garantie de sécurité. De plus, il ne fournit pas de garantie d'irréprochabilité du code de contrat intelligent.

  • Audit AlexGoIntroduction CoinFabrik a été chargé d'auditer les contrats du projet AlexGo.