7 janvier 2022
Introduction
UMA est une plate-forme qui permet aux utilisateurs de conclure des contrats financiers à confiance minimisée sur la blockchain Ethereum. Nous avons préalablement audité l'oracle décentralisé, un modèle de contrat financier particulier, quelques demandes d'extraction ad hoc, le modèle multipartite perpétuel, diverses demandes d'extraction incrémentielles sur un engagement plus long ainsi que le pont assuré.
Dans cet audit, nous avons examiné un nouveau contrat de proposition de gouvernance, un mécanisme pour étendre l'écosystème UMA sur plusieurs chaînes, un mécanisme pour distribuer des récompenses aux détenteurs de jetons ERC721 conformément à une spécification hors chaîne et une mise à jour du pont assuré pour soutenir WETH sur la chaîne Optimisme.
Le commit audité est 0c4cea3c3d5e48da6f8984b8ba3afdfea4ce47cc
et le périmètre comprend les contrats suivants :
oracle/implementation/Proposer.sol
cross-chain-oracle/*
(hors contrats test et Polygon)financial-templates/optimistic-rewarder/*
(hors contrats de test)
Nous avons également examiné les modifications apportées aux fichiers de solidité dans Demande de tirage 3611.
Tous les codes externes et les dépendances de contrat ont été supposés fonctionner comme documenté.
Présentation du système
Le courant Governance
Le contrat permet à la Fondation Risk Labs de proposer de nouvelles actions de gouvernance pouvant être ratifiées par les détenteurs de jetons UMA. Le nouveau Proposer
Le contrat est destiné à jouer le rôle de proposant, permettant à quiconque de faire de nouvelles propositions tant qu'il fournit un lien qui sera sacrifié si la proposition échoue. Il n'y a pas d'incitation spécifique à faire des propositions. L'intention est de s'assurer que seules les actions qui sont très susceptibles d'être acceptées seront proposées.
Le nouveau mécanisme inter-chaînes permet de transmettre la proposition de gouvernance du réseau principal Ethereum aux chaînes Optimism et Arbitrum. De cette manière, le mécanisme de gouvernance UMA sur la couche 1 peut être utilisé pour régir les contrats UMA sur les chaînes de couche 2 prises en charge. Le mécanisme permet également de transmettre les demandes de prix et les résolutions entre les couches, de sorte que les oracles optimistes sur les chaînes de couche 2 peuvent être sécurisés par le mécanisme de vérification des données du réseau principal de la même manière que l'Oracle optimiste de couche 1 est sécurisé par le DVM.
Il convient de noter que ces messages sont envoyés à l'aide de la mécanique de pont native, ce qui signifie qu'ils sont limités par les caractéristiques des chaînes de couche 2 concernées. En particulier, les messages de la couche 2 à la couche 1 pourraient prendre une semaine ou plus pour transiter par le pont. De plus, le mécanisme de gouvernance UMA prend en charge les propositions qui incluent plusieurs transactions ordonnées, mais cela limite simplement l'ordre dans lequel elles peuvent être ajoutées au pont. Il est possible que certaines de ces transactions soient exécutées dans un ordre différent, ou pas du tout, sur la couche 2.
Le contrat Optimistic Rewarder crée simplement des jetons ERC721 pour quiconque en fait la demande. Il permet également à quiconque d'associer des données arbitraires à n'importe quel jeton et de déposer divers jetons ERC20 à distribuer en récompense. L'interprétation des données arbitraires et la distribution attendue des récompenses entre les détenteurs de jetons sont déterminées à l'aide d'une procédure hors chaîne non spécifiée. N'importe qui peut prétendre qu'un jeton ERC721 spécifique est dû à un ensemble de récompenses s'il est prêt à déposer une caution. Le mécanisme standard d'Optimistic Oracle est utilisé pour permettre à quelqu'un d'autre de contester la réclamation, qui sera résolue par le DVM. Les réclamations qui ne sont pas contestées à temps sont supposées être valides et le contrat distribue les récompenses en conséquence. La seule restriction (pour simplifier la comptabilité) est que le jeton obligataire oracle ne peut pas être utilisé comme jeton de récompense.
Enfin, PR3611 modifie le mécanisme de pont assuré pour éviter d'envoyer WETH via le pont de jetons Optimism, qui n'est pas pris en charge. Au lieu de cela, tout L2 WETH déposé dans la boîte de dépôt Optimism est déballé en L2 ETH avant de transiter par le pont. Sur la couche 1, l'ETH est converti en WETH avant d'être transmis au pool de ponts WETH.
Gravité critique
[C01] Impossible de contester une récompense non valide
Lors de la contestation d'une demande de récompense, le OptimisticRewardBase
contrat d'abord déclenche une proposition sur le SkinnyOptimisticOracle
et alors conteste cette proposition. Cependant, la proposition définit le délai d'expiration en décalage par rapport à l'heure actuelle (du litige), tandis que le litige précise l'expiration comme un décalage par rapport au moment de la demande de récompense d'origine. Dans la plupart des cas, cet écart empêchera l'oracle d'identifier la proposition à contester, ce qui signifie que les litiges valides ne seront pas traités et que les demandes de récompense non valides seront acceptées.
Envisagez de mettre à jour l'appel de contestation pour spécifier correctement la proposition à contester.
Mettre à jour: Fixé à partir du commit 9e15557
in PR3690.
[C02] Résoudre les propositions à plusieurs reprises
Les resolveProposal
fonction de la Proposer
contrat valide simplement que l'oracle a résolu, mais ne vérifie pas si le lien a été distribué. Cela signifie que la même proposition peut être résolue plusieurs fois, ce qui entraîne des paiements de cautionnement en double. Envisagez de signaler ou de supprimer des propositions existantes lorsqu'elles sont résolues.
Mettre à jour: Fixé à partir du commit b152718
in PR3689.
Haute gravité
Aucun.
Gravité moyenne
[M01] Paramètres d'événement incorrects
Les OptimisticRewarderBase
contrat définit un Requested
un événement qui est émis par le requestRedemption
fonctionner lorsqu'un rachat est demandé. Cet événement est défini pour émettre le date d'expiration du rachat comme dernier paramètre. Cependant, lorsque l'événement est émis, son dernier paramètre est incorrectement défini sur heure actuelle.
De même, le Redeemed
un événement lit l'heure d'expiration après la suppression de l'enregistrement, il sera donc incorrectement défini sur zéro.
Étant donné que cet événement peut être utilisé pour déclencher des calculs hors chaîne, envisagez de mettre à jour la valeur émise de manière appropriée.
Mettre à jour: Fixé à partir du commit f04eef9
in PR3694.
Faible gravité
[L01] Absence d'émission d'événement après contestation d'un rachat
Les OptimisticRewarderBase
contrat définit un Disputed
un événement qui est destiné à être déclenché si un rachat est contesté. Cependant, cet événement n'est pas émis à l'intérieur ou à l'extérieur de la OptimisticRewarderBase
contrat.
Envisagez d'émettre l'événement après que des modifications sensibles ont eu lieu dans le dispute
fonction, pour faciliter le suivi et informer les clients hors chaîne suite à l'activité des contrats.
Mettre à jour: Fixé à partir du commit c275e92
in PR3695.
[L02] Garde de réentrance incohérente
Les Optimism_ParentMessenger
ainsi que Arbitrum_ParentMessenger
les contrats appliquent de manière incohérente nonReentrant
modificateur. Envisagez de l'inclure dans toutes les fonctions publiques.
Mettre à jour: Fixé à partir du commit 6275c39
in PR3677.
[L03] Commentaires trompeurs
Voici quelques commentaires trompeurs que nous avons identifiés lors de notre examen :
ChildMessengerConsumerInterface.sol
:- Ligne 5 dit « messager parent » au lieu de « messager enfant »
GovernorSpoke.sol
:- Lignes 49 à 51 liens vers un
Gnosis
fichier même si le commentaire indique que l'extrait a été copié à partir deGovernor.sol
. De plus, l'extrait n'est pas identique à celui deGovernor.sol
- Lignes 49 à 51 liens vers un
Mettre à jour: Fixé à partir du commit cc350f9
in PR3678.
[L04] Timbre de données auxiliaires manquant
Lors d'une demande de prix sur OracleSpoke
contrat, les données annexes fournies est estampillé avec l'identifiant de la chaîne enfant. Cependant, le hasPrice
ainsi que getPrice
fonctions ne tamponnent pas les données annexes lors de l'identification de la demande de prix. Cela oblige les contrats d'appel à appliquer eux-mêmes le tampon, ce qui entraîne une incohérence entre les mécanismes de demande de prix et de récupération des prix. Envisagez d'apposer le tampon dans le hasPrice
ainsi que getPrice
fonctions.
Mettre à jour: Fixé à partir du commit fdb845d
in PR3668.
[L05] Paramètre NatSpec manquant
De nombreuses fonctions dans le OptimisticRewarderBase
contrat il manque le @return
paramètre dans leurs commentaires de spécification naturelle. Pensez à l'inclure par souci d'exhaustivité.
Mettre à jour: Fixé à partir du commit 8920f38
in PR3679.
[L06] Indemnité résiduelle
Pour invoquer l'Oracle Optimiste, le OptimisticRewarderBase
contrat lui accorde une indemnité symbolique, afin qu'il puisse retirer les paiements de la caution. Si la proposition échoue, l'échange de récompense est annulé mais l'allocation n'est pas réinitialisée. Par conséquent, l'Oracle Optimiste conservera une allocation résiduelle inutile jusqu'au prochain déclenchement d'un litige. Envisagez de révoquer l'allocation si la proposition échoue.
Mettre à jour: Fixé à partir du commit c2d444b
in PR3698.
[L07] Adresse de remboursement invalide
L'adresse de remboursement L2 du Arbitrum_ParentMessenger
est initialisé au propriétaire du contrat, qui devrait être le gouverneur L1. De même, le setRefundL2Address
a un commentaire indiquant qu'il doit être défini pour le gouverneur. Cependant, lors de la transmission de messages sur le pont, cette valeur est défini comme utilisateur L2, qui est l'adresse sur Arbitrum qui reçoit les fonds excédentaires une fois le ticket résolu. Étant donné que l'adresse du gouverneur L1 ne sera pas accessible sur Arbitrum, tous les fonds envoyés à cette adresse seront perdus.
Envisagez de le définir sur une adresse L2 valide.
Mettre à jour: Fixé à partir du commit b3f2dd1
in PR3687.
[L08] Mécanisme pour changer les enfants messagers
Les GovernorSpoke
ainsi que OracleSpoke
contract each initialise le messager enfant dans le constructeur, sans mécanisme pour le mettre à jour. Cela signifie que lorsque le messager enfant est changé, les deux contrats à rayons deviennent obsolètes.
Étant donné que le contrat de rayons est probablement plus stable que les messagers, envisagez d'inclure un mécanisme pour mettre à jour le messager sur les rayons.
Mettre à jour: Fixé à partir du commit 7c9e061
in PR3688.
Remarques et informations supplémentaires
[N01] Changer le jeton d'obligation
Les Proposer
le contrat comprend un mécanisme pour que le propriétaire modifie la taille du cautionnement de proposition. Demandez-vous s'ils devraient également pouvoir changer le jeton d'obligation. Notez que cela nécessiterait un mécanisme pour identifier la devise correcte des obligations lorsque les propositions existantes sont résolues.
Mettre à jour: Pas une solution. Déclaration de l'UMA pour ce problème :
N01 recommande d'autoriser le contrat proposant à remplacer le jeton d'obligation par autre chose que UMA. Nous n'avons aucune intention de prendre en charge un jeton autre que $UMA pour cette fonction et avons donc choisi de ne pas apporter de modifications à ce problème. De plus, un seul jeton par contrat garde cette logique aussi simple que possible. Enfin, si un changement était nécessaire (dans le cas d'une migration de jeton, par exemple), nous pourrions simplement déployer un nouveau contrat de proposant avec l'autre jeton et initier une proposition de migration du système pour utiliser celui-ci.
[N02] Interface incomplète
Les ChildMessengerInterface
ne précise pas un processMessageFromCrossChainParent
fonction, même si elle est supposée exister par les messagers parents. Pensez à l'inclure par souci d'exhaustivité.
Mettre à jour: Non fixé. Déclaration de l'UMA pour ce problème :
Nous avons intentionnellement choisi de laisser cette interface incohérente car son implémentation dans ChildMessengerInterface rompt la compatibilité avec Polygon_ChildMessenger car la méthode de Polygon pour traiter les messages d'autres chaînes nécessite une logique quelque peu personnalisée dans laquelle une méthode interne est appelée _processMessageFromRoot.
[N03] Interface incorrecte
Les GovernorSpoke
contrat incorrect utilise l' ChildMessengerConsumerInterface
type pour décrire sa messenger
variable. Pensez à utiliser le ChildMessengerInterface
à la place.
Mettre à jour: Fixé à partir du commit f31a527
in PR3680.
[N04] Tirez les jetons vers le magasin
Dans un audit précédent nous nous sommes interrogés sur le but de Store
contrat payOracleFeesErc20
fonction (dans le numéro L19). L'équipe UMA a choisi de conserver la fonction standardiser l'interface pour d'éventuelles modifications futures. Étant donné que l'objectif de la fonction n'est pas entièrement spécifié, il n'est pas clair si elle doit être déclenchée lorsque le Proposer
contrat confisque une caution. Il devrait probablement être utilisé lorsque le OracleHub
paie une demande de prix. Déterminez si la fonction doit être utilisée dans l'un ou l'autre scénario.
Mettre à jour: Reconnu. Déclaration de l'UMA pour ce problème :
N04 recommande d'utiliser la méthode payOracleFeeErc20 du Store pour payer les frais dans les contrats Proposer et OracleHub afin d'être cohérent avec l'utilisation du Store. Nous avons choisi de ne pas utiliser cette fonction car cela impliquerait d'importer une interface supplémentaire (pour le magasin) et d'exiger la conversion du montant de la caution en un point fixe (ce qui nécessiterait également une importation supplémentaire. Pour garder le code simple et propre Nous avons choisi de ne pas le faire. Les commentaires d'OZ sur payOracleFeeErc20 lors de la phase d'audit 1 en avril 2020 ont confirmé que cette méthode n'est pas vraiment utile, ce qui rend ce type d'intégration plus difficile à raisonner.
[N05] TODO dans le code
Il y a des commentaires "TODO" dans la base de code qui doivent être suivis dans le backlog des problèmes du projet. Par example:
- Gamme 37 of
Arbitrum_ParentMessenger
contrat - Gamme 25 of
Optimism_ChildMessenger
contrat - Lignés 83 ainsi que 146 of
OracleHub
contrat.
Pendant le développement, avoir des commentaires "TODO" bien décrits facilitera le processus de suivi et de résolution de ceux-ci. Sans ces informations, ces commentaires pourraient avoir tendance à pourrir et des informations importantes pour la sécurité du système pourraient être oubliées au moment de leur mise en production.
Ces commentaires TODO doivent contenir une brève description de la tâche en attente et un lien vers le problème correspondant dans le référentiel du projet.
Envisagez de mettre à jour les commentaires TODO pour ajouter ces informations. Pour l'exhaustivité et la traçabilité, une signature et un horodatage peuvent être ajoutés. Par example:
// TODO: point this at an interface instead.
// https://github.com/UMAprotocol/protocol/issues/XXXX
// --mrice32 - 20211209
Mettre à jour: Fixé à partir du commit 5d57b5b
in PR3684.
[N06] Erreurs typographiques
La base de code contient les erreurs typographiques suivantes :
- Dans le
Admin_ChildMessenger
Contrat,impleenting
devrait êtreimplementing
- Dans le
OptimisticRewarderBase
Contrat,timestap
devrait êtretimestamp
. - Dans le
OptimisticRewarderBase
Contrat,liveness liveness
devrait êtreliveness
. - Dans le
GovernorSpoke
Contrat,only called
devrait êtreonly be called
. - Dans le
Optimism_ChildMessenger
Contrat:
Mettre à jour: Fixé à partir du commit 9b92b0b
in PR3681.
[N07] Importations non utilisées
Pour améliorer la lisibilité du code, envisagez de supprimer les importations inutilisées suivantes :
Mettre à jour: Fixé à partir du commit 40b7221
in PR3682.
[N08] Ordre des transactions L2
Les Governor
Assure les transactions au sein d'une proposition sont exécutées dans l'ordre. Cependant, lorsque ces transactions impliquent des transactions inter-chaînes, cela garantit simplement qu'elles arrivent au contrat de pont L1 dans le bon ordre. Dans le cas Arbitrum, ils peuvent être réorganisés avant d'être finalisés sur L2. Par conséquent, les propositions de gouvernance devraient être élaborées pour permettre la possibilité de réorganiser les transactions L2.
Mettre à jour: Fixé à partir du commit 0fb2e7b
in PR3703L’ GovernorHub
peut maintenant relayer un tableau de transactions L2.
Conclusion
Deux problèmes critiques ont été trouvés dans la base de code. Un problème de gravité moyenne et plusieurs vulnérabilités mineures ont été trouvés, et des recommandations de correctifs ont été suggérées.
- &
- 2020
- 7
- 9
- Qui sommes-nous
- Comptabilité
- à travers
- actes
- Ad
- Supplémentaire
- propos
- Tous
- Permettre
- Avril
- audit
- va
- blockchain
- Box
- PONT
- cas
- Change
- enfant
- prétentions
- code
- commentaires
- contient
- contrat
- contrats
- pourriez
- Cross-Chain
- Devise
- Courant
- données
- Décentralisé
- Développement
- différent
- Contestation
- distribué
- risque numérique
- émission
- permettant
- ERC20
- ETH
- Ethereum
- Blockhaus d'Ethereum
- événement
- exemple
- attendu
- étendre
- Frais
- la traduction de documents financiers
- Prénom
- trouvé
- Fondation
- fonction
- fonds
- avenir
- gouvernance
- Gouverneur
- ayant
- titulaires
- HTTPS
- identifier
- important
- Y compris
- d'information
- l'intégration
- Interfaces
- vous aider à faire face aux problèmes qui vous perturbent
- IT
- Labs
- limité
- LINK
- Location
- Fabrication
- moyenne
- Messager
- (en fait, presque toutes)
- compenser
- oracle
- de commander
- Autre
- propriétaire
- Paiements
- phase
- plateforme
- Polygone
- pool
- prix
- processus
- Vidéo
- Projet
- proposition
- proposer
- fournir
- public
- record
- dépôt
- Avis
- Programme de fidélité
- Analyse
- sécurité
- set
- mise
- étapes
- Taille
- So
- solidité
- Quelqu'un
- quelque chose
- Déclaration
- Boutique
- Support
- Appareils
- Les soutiens
- combustion propre
- tester
- fiable
- jeton
- Tokens
- Traçabilité
- Tracking
- transaction
- Transactions
- transit
- Mises à jour
- utilisateurs
- Plus-value
- Vérification
- vulnérabilités
- semaine
- WHO
- dans les
- sans
- Activités principales
- vaut
- zéro