Exploration des mécanismes fondamentaux d'UniswapV4

AvancéDec 24, 2023
Cet article interprète trois caractéristiques innovantes d'UniswapV4 - Flash Accounting, Singleton Contract et Hooks Architecture - du point de vue du code et de la mise en œuvre.
Exploration des mécanismes fondamentaux d'UniswapV4

Introduction :

Depuis l'annonce d'UniswapV4, cette plate-forme d'échange a subi une transformation importante, passant d'une simple plate-forme d'échange à un fournisseur de services d'infrastructure. En particulier, la fonction "Hooks" de la V4 a fait l'objet d'une grande attention. Après des recherches approfondies, j'ai compilé quelques contenus pour aider chacun à mieux comprendre cette transformation et sa mise en œuvre.

L'innovation d'UniswapV4 ne consiste pas seulement à améliorer la technologie AMM, mais aussi à élargir l'écosystème. Plus précisément, cette innovation comprend les caractéristiques clés suivantes :

  • Comptabilité Flash
  • Contrat Singleton
  • Hooks Architecture

Dans les sections suivantes, j'expliquerai en détail l'importance de ces caractéristiques et leurs principes de mise en œuvre.

source: https://twitter.com/jermywkh/status/1670779830621851650

Comptabilité Flash

Comptabilité en partie double

UniswapV4 adopte une méthode d'enregistrement similaire à la comptabilité à double entrée pour suivre les changements de solde des jetons correspondant à chaque opération. Cette méthode de comptabilité en partie double nécessite l'enregistrement simultané de chaque transaction dans plusieurs comptes et l'assurance que le solde des actifs entre ces comptes reste équilibré. Par exemple, supposons qu'un utilisateur échange 100 TokenA contre 50 TokenB du pool. L'enregistrement dans le grand livre serait le suivant :

  • UTILISATEUR : le jeton A a diminué de 100 unités (-100), tandis que le jeton B a augmenté de 50 unités (+50).
  • POOL : le TokenA a augmenté de 100 unités (+100), tandis que le TokenB a diminué de 50 unités (-50).

Token Delta et opérations connexes

Dans UniswapV4, cette méthode d'enregistrement est principalement utilisée pour les opérations importantes, et une variable de stockage nommée lockState.currencyDelta[currency] est utilisé dans le code pour enregistrer le montant des changements de solde des jetons. Si la valeur de ce delta est positive, elle représente l'augmentation attendue du nombre de jetons dans le pool, tandis qu'une valeur négative représente la diminution attendue du nombre de jetons. Par ailleurs, si la valeur est positive, elle indique le manque de jetons dans le pool (le montant attendu à recevoir), tandis qu'une valeur négative indique l'excès de jetons dans le pool (le montant attendu à retirer par les utilisateurs). La liste suivante montre les effets de diverses opérations sur le Token Delta :

  • modifyPosition : Représente l'opération d'ajout/suppression de liquidité. Pour la liquidité Add, TokenDelta est mis à jour en utilisant l'addition (représentant la quantité attendue de TokenA à ajouter au pool). En cas de retrait de liquidité, le TokenDelta est mis à jour par soustraction (représentant le montant attendu de TokenB à retirer du pool).
  • swap : Représente l'opération Swap. Si l'on prend l'exemple de l'échange du jetonA contre le jetonB, le jetonADelta est mis à jour par addition, tandis que le jetonBDelta est mis à jour par soustraction.
  • régler : Accompagne le transfert des jetons vers le pool. Le pool calcule l'augmentation de la quantité de jetons avant et après et met à jour TokenDelta par soustraction. Si le pool reçoit la quantité de jetons attendue, la soustraction annulera le TokenDelta.
  • prendre : Accompagne le retrait de jetons de la réserve. TokenDelta est mis à jour par addition, indiquant que les jetons ont été retirés du pool.
  • ment : Le comportement de la mise à jour de TokenDelta est similaire à celui de "take", mais au lieu de retirer des jetons du pool, des jetons ERC1155 sont émis comme preuve de retrait, tandis que les jetons restent dans le pool. Par la suite, les utilisateurs peuvent récupérer les jetons du pool en brûlant les jetons ERC1155. L'objectif de cette approche peut être double : 1. économiser les coûts de gaz pour les transferts de jetons ERC20 (appel de contrat + une écriture de stockage en moins), et utiliser la combustion de jetons ERC1155 à l'avenir pour mettre à jour TokenDelta pour les transactions. 2. Préserver la liquidité dans le pool afin de maintenir un pool de liquidité profond pour améliorer l'expérience d'échange des utilisateurs.
  • donate : Cette opération déclare le don de jetons au pool, mais en réalité, les jetons doivent encore être transférés au pool à l'aide de "settle". Par conséquent, le TokenDelta est mis à jour par addition dans ce cas.

Parmi ces opérations, seules les opérations "settle" et "take" impliquent le transfert effectif de jetons, tandis que les autres opérations sont uniquement responsables de la mise à jour de la valeur TokenDelta.

Exemple de delta de jetons

Nous utiliserons ici un exemple simple pour illustrer comment mettre à jour TokenDelta. Supposons que nous échangions aujourd'hui 100 TokenA contre 50 TokenB :

  1. Avant le début de la transaction, le TokenADelta et le TokenBDelta sont tous deux à 0.
  2. échanger : Calculez la quantité de TokenA que le Pool doit recevoir et la quantité de TokenB que l'utilisateur recevra. À ce stade, TokenADelta = 100, TokenBDelta = -50.
  3. réglez : Envoyez 100 TokenA au Pool et mettez à jour TokenADelta = 100 - 100 = 0.
  4. prendre : Transférez 50 TokenB du Pool vers le compte de l'utilisateur et mettez à jour TokenBDelta = -50 + 50 = 0.
  5. Une fois la transaction terminée, le TokenADelta et le TokenBDelta sont tous deux à 0.

Lorsque l'opération d'échange est terminée, le TokenADelta et le TokenBDelta sont remis à 0, ce qui signifie que l'opération a été complètement équilibrée, garantissant ainsi la cohérence des soldes des comptes.

EIP-1153 : Opcodes de stockage transitoire

Il a été mentionné précédemment qu'UniswapV4 utilise des variables de stockage pour enregistrer le TokenDelta. Toutefois, dans le cadre du contrat, la lecture et l'écriture dans les variables de stockage sont assez coûteuses. Ceci nous amène à un autre EIP introduit par Uniswap : EIP1153 - Transient Storage Opcodes.

UniswapV4 prévoit d'utiliser les opcodes TSTORE et TLOAD fournis par l' EIP1153 pour mettre à jour le TokenDelta. Les variables de stockage qui adoptent des opcodes de stockage transitoire seront éliminées à la fin de la transaction (comme les variables de mémoire), ce qui réduira les frais de gaz.

Il a été confirmé que l'EIP1153 sera inclus dans la prochaine mise à jour de Cancun, et UniswapV4 a également déclaré qu'il sera mis en service après la mise à jour de Cancun, comme indiqué ici.

source : https://etherworld.co/2022/12/13/transient-storage-for-beginners/

Comptabilité Flash - Verrouillage

UniswapV4 introduit un mécanisme de verrouillage, ce qui signifie qu'avant d'effectuer une opération sur le pool, vous devez d'abord appeler PoolManager.lock() pour acquérir un verrou. Lors de l'exécution de lock(), il vérifie si la valeur TokenDelta est égale à 0, sinon il revient en arrière. Une fois que PoolManager.lock() a été acquis avec succès, il appelle la fonction lockAcquired() de msg.sender. Dans la fonction lockAcquired(), les opérations liées au pool, telles que swap et modifyPosition, sont effectuées.

Le processus est illustré ci-dessous. Lorsqu'un utilisateur doit effectuer une opération d'échange de jetons, il doit appeler un contrat intelligent avec la fonction lockAcquired() (appelée contrat de rappel). Le contrat de rappel appelle d'abord PoolManager.lock(), puis le PoolManager appelle la fonction lockAcquired() du contrat de rappel. La fonction lockAcquired() définit la logique relative aux opérations de pool, telles que l'échange, le règlement et la prise. Enfin, lorsque le lock() est sur le point de se terminer, le PoolManager vérifie si le TokenDelta associé à cette opération a été remis à 0, ce qui permet de s'assurer que l'équilibre des actifs dans le Pool reste intact.

Contrat Singleton

Le contrat Singleton signifie qu'UniswapV4 a abandonné l'ancien modèle Factory-Pool. Chaque pool n'est plus un contrat intelligent indépendant, mais tous les pools partagent un contrat unique. Cette conception, associée au mécanisme de comptabilité flash, ne nécessite que la mise à jour des variables de stockage nécessaires, ce qui réduit encore la complexité et le coût des opérations.

Dans l'exemple ci-dessous, en utilisant UniswapV3, l'échange d'ETH contre DAI nécessiterait au moins quatre transferts de tokens (opérations d'écriture de stockage). Cela inclut de multiples changements enregistrés pour les jetons USDC, USDT et DAI. Toutefois, grâce aux améliorations apportées par UniswapV4 et au mécanisme de comptabilité Flash, un seul transfert de jeton est nécessaire (déplacement du DAI du pool vers l'utilisateur), ce qui réduit considérablement le nombre d'opérations et les coûts.

source: https://twitter.com/Uniswap/status/1671208668304486404

Hooks Architecture

Dans la dernière mise à jour d'UniswapV4, la caractéristique la plus notable est l'architecture Hooks. Cette mise à jour apporte une grande flexibilité en termes de disponibilité des pools. Les crochets sont des actions supplémentaires qui sont déclenchées par le contrat de crochets lors de l'exécution d'opérations spécifiques sur le pool. Ces actions sont classées en trois catégories : initialiser (créer un pool), modifier la position (ajouter/supprimer des liquidités), échanger et donner. Chaque catégorie comporte des actions préalables à l'exécution et des actions postérieures à l'exécution.

  • avantInitialisation / aprèsInitialisation
  • avantModifierPosition / aprèsModifierPosition
  • beforeSwap / afterSwap
  • avant le don / après le don

Cette conception permet aux utilisateurs d'exécuter une logique personnalisée avant et après des opérations spécifiques, ce qui rend le système plus flexible et élargit la fonctionnalité d'UniswapV4.

source : https://github.com/Uniswap/v4-core/blob/main/whitepaper-v4-draft.pdf

Exemple de crochet - Crochet d'ordre à cours limité

Ensuite, nous utiliserons un exemple d'ordre à cours limité pour expliquer le processus de fonctionnement des Hooks dans UniswapV4. Avant de commencer, expliquons brièvement le principe de la mise en œuvre des ordres à cours limité dans UniswapV4.

Mécanisme d'ordre limite de l'UniswapV4

L'implémentation UniswapV4 de l'ordre à cours limité fonctionne en ajoutant de la liquidité à une fourchette de prix spécifique et en exécutant ensuite l'opération de suppression de liquidité si la liquidité dans cette fourchette est échangée.

Par exemple, disons que nous ajoutons de la liquidité dans la fourchette de prix 1900-2000 pour l'ETH, et que le prix de l'ETH passe de 1800 à 2100. À ce stade, toutes les liquidités d'ETH que nous avons précédemment ajoutées dans la fourchette de prix 1900-2000 ont été échangées contre des USDC (en supposant que le pool ETH-USDC soit constitué). En supprimant la liquidité à ce moment-là, nous pouvons obtenir un effet similaire à l'exécution d'un ordre de marché ETH dans la fourchette de prix actuelle de 1900-2000.

Ordre à cours limité Contrat de crochet

Cet exemple est tiré de GitHub de UniswapV4. Dans cet exemple, le contrat Limit Order Hook fournit deux crochets, à savoir afterInitialize et afterSwap. Le hook afterInitialize est utilisé pour enregistrer la fourchette de prix (tick) lors de la création d'un pool, afin de déterminer quels ordres limités ont été appariés après que quelqu'un ait échangé.

Passer un ordre

Lorsque l'utilisateur doit passer un ordre, le contrat Hook exécute l'opération d'ajout de liquidité sur la base de la fourchette de prix et de la quantité spécifiées par l'utilisateur. Dans le contrat Hook pour les ordres limités, vous pouvez voir la fonction place(). La logique principale consiste à appeler la fonction lockAcquiredPlace() après avoir acquis le verrou pour exécuter l'opération d'ajout de liquidité, ce qui équivaut à passer un ordre à cours limité.

source : https://github.com/Uniswap/v4-periphery/blob/main/contracts/hooks/examples/LimitOrder.sol#L246

crochet afterSwap

Une fois que l'utilisateur a complété un jeton d'échange au sein de ce pool, ce dernier invoque la fonction afterSwap( ) du contrat de crochet. La logique principale d'afterSwap est de supprimer la liquidité des ordres précédemment placés qui ont été exécutés entre la fourchette de prix précédente et la fourchette de prix actuelle. Ce comportement équivaut à l'exécution de l'ordre.

source : https://github.com/Uniswap/v4-periphery/blob/main/contracts/hooks/examples/LimitOrder.sol#L192

Flux d'ordres limités

Voici un organigramme illustrant le processus d'exécution d'un ordre à cours limité :

  1. Le donneur d'ordre envoie l'ordre au contrat de crochet.
  2. Le contrat de crochet exécute les opérations d'ajout de liquidité sur la base des informations relatives à l'ordre.
  3. Les utilisateurs réguliers effectuent des opérations d'échange de jetons dans le pool.
  4. Une fois l'opération d'échange de jetons terminée, le pool appelle la fonction afterSwap() du contrat de crochet.
  5. Le contrat Hook exécute des opérations de retrait de liquidité pour les ordres limités remplis sur la base de la variation de la fourchette de prix des jetons échangés.

Vous trouverez ci-dessus l'ensemble du processus de mise en œuvre de l'ordre limité à l'aide du mécanisme de crochet.

Crochet : Autres caractéristiques

Hooks a soulevé plusieurs points intéressants qui méritent d'être partagés.

Crochets Bit d'adresse de contrat

La décision d'effectuer des opérations spécifiques avant/après est déterminée par l'octet le plus à gauche de l'adresse du contrat de crochet. 1 octet est égal à 8 bits, ce qui correspond à 8 actions supplémentaires. Le pool vérifiera si le bit de cette action est à 1 pour déterminer s'il faut invoquer la fonction de crochet correspondante du contrat Hook. Cela signifie également que l'adresse du contrat d'accroche doit être conçue de manière spécifique et ne peut pas être choisie arbitrairement comme contrat d'accroche. Cette conception vise principalement à réduire la consommation de gaz et à transférer les coûts vers le déploiement de contrats afin d'obtenir des opérations plus efficaces. (PS : Dans la pratique, différents sels CREATE2 peuvent être utilisés pour calculer par force brute les adresses de contrat qui remplissent les conditions).

Redevance dynamique

Outre la possibilité d'effectuer des opérations supplémentaires avant et après chaque action, les crochets permettent également de mettre en œuvre des frais dynamiques. Lors de la création d'un pool, vous pouvez spécifier si les frais dynamiques doivent être activés. Si les frais dynamiques sont activés, la fonction getFee() du contrat Hook est appelée lors de l'échange de jetons. Le contrat de crochet peut déterminer le montant des frais à facturer en fonction de l'état actuel de la piscine. Cette conception permet un calcul flexible des frais en fonction des circonstances réelles, ce qui accroît la flexibilité du système.

Création d'une piscine

Chaque pool doit déterminer le contrat de crochet lors de sa création, et il ne peut pas être modifié par la suite (bien que différents pools puissent partager le même contrat de crochet). Cela s'explique principalement par le fait que les crochets sont considérés comme faisant partie de la clé de pool et que le PoolManager utilise la clé de pool pour identifier le pool sur lequel il doit opérer. Même si les actifs sont identiques, si le contrat de crochet est différent, il sera considéré comme un pool différent. Cette conception garantit que l'état et les opérations des différents pools peuvent être gérés de manière indépendante, ce qui assure la cohérence des pools. Cependant, cela augmente également la complexité du routage à mesure que le nombre de pools augmente (UniswapX est peut-être conçu pour résoudre ce problème).

TL;DR

  • La comptabilité flash est utilisée pour suivre les changements de quantité de chaque jeton afin de s'assurer que tous les changements sont remis à zéro après la réalisation d'une transaction. Pour économiser les frais de gaz, Flash Accounting utilise une méthode de stockage spéciale fournie par EIP1153.
  • La conception du contrat Singleton permet de réduire la consommation de gaz en évitant les mises à jour de plusieurs variables de stockage.
  • L'architecture des crochets fournit des opérations supplémentaires, divisées en étapes de pré-exécution et de post-exécution. Cela permet une plus grande flexibilité dans le fonctionnement de chaque groupe, mais rend également l'acheminement des groupes plus complexe.

UniswapV4 met clairement l'accent sur l'expansion de l'ensemble de l'écosystème Uniswap, en le transformant en infrastructure pour permettre à davantage de services d'être construits sur la base des Pools Uniswap. Cela permet d'améliorer la compétitivité d'Uniswap et de réduire le risque lié aux services alternatifs. Toutefois, il reste à voir s'il obtiendra le succès escompté. La combinaison de la comptabilité flash et de l'EIP1153 en est un exemple. Nous pensons que d'autres services adopteront ces fonctionnalités à l'avenir, ce qui donnera lieu à divers scénarios d'application. Il s'agit du concept de base d'UniswapV4, et nous espérons qu'il vous permettra de mieux comprendre le fonctionnement d'UniswapV4. Si l'article contient des erreurs, n'hésitez pas à les signaler. Les discussions et les commentaires sont également les bienvenus.

Enfin, nous tenons à remercier Anton Cheng et Ping Chen pour leur relecture de l'article et leurs précieux commentaires !

Clause de non-responsabilité:

  1. Cet article est repris de[medium]. Tous les droits d'auteur appartiennent à l'auteur original[林瑋宸 Albert Lin]. Si vous avez des objections à cette réimpression, veuillez contacter l'équipe de Gate Learn(gatelearn@gate.io),qui s'en chargera rapidement.
  2. Clause de non-responsabilité : Les points de vue et les opinions exprimés dans cet article sont uniquement ceux de l'auteur et ne constituent pas un conseil en investissement.
  3. Les traductions de l'article dans d'autres langues sont effectuées par l'équipe de Gate Learn. Sauf mention contraire, il est interdit de copier, distribuer ou plagier les articles traduits.
* 投資有風險,入市須謹慎。本文不作為Gate.io提供的投資理財建議或其他任何類型的建議。
* 在未提及Gate.io的情況下,複製、傳播或抄襲本文將違反《版權法》,Gate.io有權追究其法律責任。
即刻開始交易
註冊並交易即可獲得
$100
和價值
$5500
理財體驗金獎勵!
立即註冊