Astuces de développement de contrats : expériences apprises du code d'Uniswap
Récemment, en rédigeant un tutoriel sur le développement d'échanges décentralisés, j'ai consulté l'implémentation de Uniswap V3 et j'ai appris de nombreux points intéressants. En tant que novice tentant pour la première fois de développer des contrats Defi, ces astuces devraient être très utiles pour d'autres débutants souhaitant apprendre le développement de contrats.
Adresse de déploiement de contrat prévisible
Les adresses des contrats déployés semblent généralement aléatoires et difficiles à prédire. Cependant, dans certains cas, nous devons déduire l'adresse du contrat à partir des informations de la paire de transactions, par exemple pour déterminer les droits de transaction ou obtenir l'adresse de la piscine.
Uniswap utilise la méthode CREATE2 pour créer des contrats, en ajoutant un paramètre salt pour rendre l'adresse prévisible. La nouvelle logique de génération d'adresse est : hash("0xFF", adresse du créateur, salt, initcode). Cette méthode rend l'adresse du contrat prévisible, ce qui est très pratique.
Utiliser habilement les fonctions de rappel
Dans Solidity, les contrats peuvent s'appeler mutuellement. Dans certains cas, A appelle la méthode de B, et B rappelle A dans la méthode appelée, ce modèle est très utile.
Les transactions de swap d'Uniswap utilisent un mécanisme de rappel. La méthode swap de UniswapV3Pool rappellera swapCallback en passant le nombre réel de tokens nécessaires. L'appelant doit transférer les tokens dans le rappel, garantissant l'exécution complète et la sécurité de la méthode swap, sans avoir besoin d'enregistrements de variables compliqués.
Utiliser des exceptions pour transmettre des informations, réaliser une estimation de transaction avec try catch
Dans le contrat Quoter d'Uniswap, la méthode swap de UniswapV3Pool est entourée d'un try catch. Cela permet de simuler un swap pour estimer les tokens nécessaires à la transaction, mais l'estimation ne procédera pas à un échange réel de tokens, donc une erreur sera générée.
Uniswap lance des erreurs spéciales dans la fonction de rappel, puis capture cette erreur et extrait les informations nécessaires. Cette méthode semble être une ruse, mais elle est très pratique, car elle ne nécessite pas de modifier spécifiquement la méthode d'échange pour estimer la demande, ce qui rend la logique plus simple.
Résoudre les problèmes de précision avec de grands nombres
Le code Uniswap implique de nombreux calculs, tels que le calcul du nombre de tokens échangés en fonction du prix actuel et de la liquidité. Pour éviter la perte de précision lors des opérations de division, le processus de calcul utilise souvent l'opération "<< FixedPoint96.RESOLUTION", c'est-à-dire un décalage à gauche de 96 bits, ce qui équivaut à multiplier par 2^96.
Déplacez à gauche puis divisez, ce qui garantit la précision dans le cadre d'échanges normaux sans débordement. Bien qu'il y ait toujours une légère perte de précision en théorie, elle est désormais acceptable.
Calcul des bénéfices avec la méthode Share
Uniswap doit enregistrer les revenus de frais pour le fournisseur de liquidité LP(. Il est évident qu'il n'est pas possible d'enregistrer les frais pour chaque LP à chaque transaction, cela consommerait beaucoup de Gas.
La solution consiste à enregistrer feeGrowthInside0LastX128 et feeGrowthInside1LastX128 dans la structure Position, représentant les frais que chaque unité de liquidité doit recevoir lors du dernier retrait de frais pour chaque position.
Il suffit d'enregistrer les frais de transaction totaux et les frais de transaction alloués par unité de liquidité. Lors du retrait des LP, les frais récupérables peuvent être calculés en fonction de la liquidité détenue. C'est similaire à la détention d'actions, lors du retrait des bénéfices, il suffit de connaître le bénéfice historique par action et les bénéfices de la dernière extraction.
![Série pour débutants Web3 : Astuces de développement de contrats que j'ai apprises du code Uniswap])https://img-cdn.gateio.im/webp-social/moments-45e66af69435e6d4412ae506e77ab893.webp(
Toutes les informations ne doivent pas être obtenues sur la chaîne
Le stockage sur la chaîne est relativement coûteux, toutes les informations ne doivent pas être enregistrées sur la chaîne ou récupérées à partir de celle-ci. Par exemple, de nombreuses interfaces appelées par le front-end d'Uniswap sont des interfaces Web2 traditionnelles.
La liste des pools de trading, les informations, etc. peuvent être stockées dans une base de données ordinaire, certaines devant être synchronisées périodiquement depuis la chaîne, mais il n'est pas nécessaire d'appeler en temps réel la chaîne ou l'interface RPC du nœud pour obtenir des données.
De nombreux fournisseurs RPC de blockchain offrent également des interfaces avancées, permettant d'obtenir certaines données plus rapidement et à moindre coût. Ces interfaces utilisent généralement le cache pour améliorer les performances et l'efficacité.
Bien sûr, les transactions clés se déroulent toujours sur la chaîne.
Apprendre à diviser les contrats et à utiliser les contrats standards existants
Un projet peut contenir plusieurs contrats effectivement déployés. Même si un seul contrat est déployé, le code peut être divisé en plusieurs contrats à maintenir par héritage.
Le contrat NonfungiblePositionManager de Uniswap hérite de plusieurs contrats. Le contrat ERC721Permit utilise directement l'implémentation ERC721 d'OpenZeppelin, ce qui facilite la gestion des positions avec des NFT et améliore l'efficacité du développement.
Résumé
Développer vous-même une version simplifiée d'une bourse décentralisée vous permettra de mieux comprendre la mise en œuvre d'Uniswap et d'apprendre davantage de points de connaissance dans des projets réels. Bien que l'apprentissage théorique soit important, l'expérience pratique est encore plus précieuse. J'espère que ces petites astuces pourront vous aider dans votre parcours de développement de contrats.
![Série pour débutants Web3 : les petites astuces de développement de contrats que j'ai apprises du code Uniswap])https://img-cdn.gateio.im/webp-social/moments-f95ddc9d89809cf11dbe65b9bafda157.webp(
Cette page peut inclure du contenu de tiers fourni à des fins d'information uniquement. Gate ne garantit ni l'exactitude ni la validité de ces contenus, n’endosse pas les opinions exprimées, et ne fournit aucun conseil financier ou professionnel à travers ces informations. Voir la section Avertissement pour plus de détails.
19 J'aime
Récompense
19
7
Partager
Commentaire
0/400
GasWaster
· 07-16 11:49
Tout le monde qui étudie les contrats doit regarder
Voir l'originalRépondre0
MissedAirdropAgain
· 07-16 07:39
Il est trop tard pour apprendre le contrat...
Voir l'originalRépondre0
YieldWhisperer
· 07-14 20:20
j'ai vu ce même schéma sur dyydx en 2020... rien de nouveau à vrai dire
Voir l'originalRépondre0
MEVictim
· 07-14 20:18
Est-ce que ces connaissances sont vraiment utiles ?
Analyse du code Uniswap : 7 astuces de développement de smart contracts
Astuces de développement de contrats : expériences apprises du code d'Uniswap
Récemment, en rédigeant un tutoriel sur le développement d'échanges décentralisés, j'ai consulté l'implémentation de Uniswap V3 et j'ai appris de nombreux points intéressants. En tant que novice tentant pour la première fois de développer des contrats Defi, ces astuces devraient être très utiles pour d'autres débutants souhaitant apprendre le développement de contrats.
Adresse de déploiement de contrat prévisible
Les adresses des contrats déployés semblent généralement aléatoires et difficiles à prédire. Cependant, dans certains cas, nous devons déduire l'adresse du contrat à partir des informations de la paire de transactions, par exemple pour déterminer les droits de transaction ou obtenir l'adresse de la piscine.
Uniswap utilise la méthode CREATE2 pour créer des contrats, en ajoutant un paramètre salt pour rendre l'adresse prévisible. La nouvelle logique de génération d'adresse est : hash("0xFF", adresse du créateur, salt, initcode). Cette méthode rend l'adresse du contrat prévisible, ce qui est très pratique.
Utiliser habilement les fonctions de rappel
Dans Solidity, les contrats peuvent s'appeler mutuellement. Dans certains cas, A appelle la méthode de B, et B rappelle A dans la méthode appelée, ce modèle est très utile.
Les transactions de swap d'Uniswap utilisent un mécanisme de rappel. La méthode swap de UniswapV3Pool rappellera swapCallback en passant le nombre réel de tokens nécessaires. L'appelant doit transférer les tokens dans le rappel, garantissant l'exécution complète et la sécurité de la méthode swap, sans avoir besoin d'enregistrements de variables compliqués.
Utiliser des exceptions pour transmettre des informations, réaliser une estimation de transaction avec try catch
Dans le contrat Quoter d'Uniswap, la méthode swap de UniswapV3Pool est entourée d'un try catch. Cela permet de simuler un swap pour estimer les tokens nécessaires à la transaction, mais l'estimation ne procédera pas à un échange réel de tokens, donc une erreur sera générée.
Uniswap lance des erreurs spéciales dans la fonction de rappel, puis capture cette erreur et extrait les informations nécessaires. Cette méthode semble être une ruse, mais elle est très pratique, car elle ne nécessite pas de modifier spécifiquement la méthode d'échange pour estimer la demande, ce qui rend la logique plus simple.
Résoudre les problèmes de précision avec de grands nombres
Le code Uniswap implique de nombreux calculs, tels que le calcul du nombre de tokens échangés en fonction du prix actuel et de la liquidité. Pour éviter la perte de précision lors des opérations de division, le processus de calcul utilise souvent l'opération "<< FixedPoint96.RESOLUTION", c'est-à-dire un décalage à gauche de 96 bits, ce qui équivaut à multiplier par 2^96.
Déplacez à gauche puis divisez, ce qui garantit la précision dans le cadre d'échanges normaux sans débordement. Bien qu'il y ait toujours une légère perte de précision en théorie, elle est désormais acceptable.
Calcul des bénéfices avec la méthode Share
Uniswap doit enregistrer les revenus de frais pour le fournisseur de liquidité LP(. Il est évident qu'il n'est pas possible d'enregistrer les frais pour chaque LP à chaque transaction, cela consommerait beaucoup de Gas.
La solution consiste à enregistrer feeGrowthInside0LastX128 et feeGrowthInside1LastX128 dans la structure Position, représentant les frais que chaque unité de liquidité doit recevoir lors du dernier retrait de frais pour chaque position.
Il suffit d'enregistrer les frais de transaction totaux et les frais de transaction alloués par unité de liquidité. Lors du retrait des LP, les frais récupérables peuvent être calculés en fonction de la liquidité détenue. C'est similaire à la détention d'actions, lors du retrait des bénéfices, il suffit de connaître le bénéfice historique par action et les bénéfices de la dernière extraction.
![Série pour débutants Web3 : Astuces de développement de contrats que j'ai apprises du code Uniswap])https://img-cdn.gateio.im/webp-social/moments-45e66af69435e6d4412ae506e77ab893.webp(
Toutes les informations ne doivent pas être obtenues sur la chaîne
Le stockage sur la chaîne est relativement coûteux, toutes les informations ne doivent pas être enregistrées sur la chaîne ou récupérées à partir de celle-ci. Par exemple, de nombreuses interfaces appelées par le front-end d'Uniswap sont des interfaces Web2 traditionnelles.
La liste des pools de trading, les informations, etc. peuvent être stockées dans une base de données ordinaire, certaines devant être synchronisées périodiquement depuis la chaîne, mais il n'est pas nécessaire d'appeler en temps réel la chaîne ou l'interface RPC du nœud pour obtenir des données.
De nombreux fournisseurs RPC de blockchain offrent également des interfaces avancées, permettant d'obtenir certaines données plus rapidement et à moindre coût. Ces interfaces utilisent généralement le cache pour améliorer les performances et l'efficacité.
Bien sûr, les transactions clés se déroulent toujours sur la chaîne.
Apprendre à diviser les contrats et à utiliser les contrats standards existants
Un projet peut contenir plusieurs contrats effectivement déployés. Même si un seul contrat est déployé, le code peut être divisé en plusieurs contrats à maintenir par héritage.
Le contrat NonfungiblePositionManager de Uniswap hérite de plusieurs contrats. Le contrat ERC721Permit utilise directement l'implémentation ERC721 d'OpenZeppelin, ce qui facilite la gestion des positions avec des NFT et améliore l'efficacité du développement.
Résumé
Développer vous-même une version simplifiée d'une bourse décentralisée vous permettra de mieux comprendre la mise en œuvre d'Uniswap et d'apprendre davantage de points de connaissance dans des projets réels. Bien que l'apprentissage théorique soit important, l'expérience pratique est encore plus précieuse. J'espère que ces petites astuces pourront vous aider dans votre parcours de développement de contrats.
![Série pour débutants Web3 : les petites astuces de développement de contrats que j'ai apprises du code Uniswap])https://img-cdn.gateio.im/webp-social/moments-f95ddc9d89809cf11dbe65b9bafda157.webp(