Balancer et les Automated Market Makers à moyenne constante – Les AMM décodés
Balancer est un AMM (automated market maker ou teneur de marché automatisé) versatile et flexible, déployé sur Ethereum. Il utilise le modèle de la moyenne constante : Balancer fournit l’équivalent des fonds indiciels pondérés de la finance traditionnelle.
Introduction
Un fond indiciel typique est construit autour d’un portfolio diversifié, réparti sur plusieurs actifs. Ce portfolio réplique un indice d’actifs financiers, comme le CAC40, le NASDAQ ou le SP500. En acquérant des parts du fonds, les investisseurs sont exposés de façon passive à tous les produits financiers ou valeurs mobilières de l’indice. Lorsque leur allocation change, les gérants du fonds sont responsables du rééquilibrage des actifs. Le fonds correspond alors à nouveau à l’indice, et ses gestionnaires récoltent des frais.
Les fonds indiciels sont populaires, car ils présentent moins de risques qu’un portfolio géré de façon active par l’investisseur. C’est dû à leur nature diversifiée, et aux frais de gestion peu élevés.
Avec les AMM de la finance décentralisée, les fonds indiciels pondérés deviennent des réserves de liquidité – liquidity pools. Puisque le modèle est décentralisé, il n’y a pas de gestionnaires de fonds. Ce sont les traders qui sont incités économiquement à rééquilibrer les portfolios, à travers les opportunités d’arbitrage.
Le protocole Balancer utilise la fonction à moyenne constante pour rééquilibrer les actifs au sein de ses pools. C’est fait lors de chaque échange (trade). Cette fonction permet aussi aux utilisateurs de créer des pools de liquidité contenant plus de deux actifs (jusqu’à 8).
Toutes ces opérations de rééquilibrage sont des opportunités financières pour les traders comme pour les fournisseurs de liquidité. Les frais d’échange (trading fees) sont payés aux fournisseurs de liquidité, qui reçoivent également des jetons BAL. Ce jeton de gouvernance natif du protocole leur est versé chaque semaine comme récompense, au prorata des fonds verrouillés. Les BAL permettent à leur détenteurs d’approuver ou de décliner les propositions de mise à jour du protocole, et même de modifier ses paramètres.
Aperçu théorique du protocole Balancer
Nous allons faire un peu de mathématiques pour comprendre la fonction à moyenne constante et son implémentation.
Fonction de valeur
Grâce à la fonction à moyenne constante, le protocole Balancer maintient (pour chaque trade) les valeurs de chaque actif en réserve en proportions constantes. Il y a entre 2 et 8 actifs dans un pool. La fonction de valeur à moyenne constante définit donc une surface, basée sur le poids et et le solde de chaque réserve de jetons.
Où :
- t est le nombre de jetons de chaque type composant le pool ;
- Bt est le solde (balance) de chaque jeton dans le pool ;
- Wt est le poids normalisé du jeton, e telle façon que la somme de tous les poids normalisés soit égale à 1.
Le protocole Balancer utilise cette surface comme invariant. Cela permet donc d’avoir des pools à jetons multiples – cette fonction de valeur est une extension de la fonction à produit constant.
Détermination du prix
Prix du marché (spot price)
Pour chaque paire de jetons dans un pool Balancer, le prix spot est défini par le ratio des soldes des réserves de chaque jeton, normalisés par son poids.
Où :
- Bi est le solde de la réserve du jeton i, le jeton qui est vendu par le trader. Ce jeton va donc dans la réserve (input) ;
- Bo est le solde de la réserve de jetons o, le jeton acheté par le trader, qui quitte donc la réserve (output) ;
- Wi est le poids du jeton i ;
- Wo est le poids du jeton o.
Ce modèle détermine ainsi le prix de chaque jeton d’un pool Balancer, et nous pouvons déjà en déduire quelques simples observations :
- Si les poids des jetons en réserve sont constants, leur prix est uniquement déterminé par le changement des soldes de leurs réserves respectives ;
- Ces soldes seront affectés par les échanges ayant lieu sur le marché, si le propriétaire du pool n’ajoute ou n’enlève pas de fonds ;
- Le prix d’un jeton de sortie va croître, tandis que le prix du jeton correspondant en entrée va décroître, puisque la surface V reste constante.
Comme pour les autres protocoles d’AMM, les arbitrageurs jouent un rôle lorsque le prix d’un jeton, déterminé par l’AMM, diverge de son prix sur d’autres plateformes d’échange.
Prix effectif
Le prix effectif est égal au prix spot lorsque les volumes d’échanges tendent vers zéro, et dévie du prix spot lorsque les volumes augmentent :
Où :
- Ao est la quantité de jetons achetés par le trader ;
- Ai est la quantité de jetons vendus par le trader.
Formules de trading
Les formules de trading suivantes sont calculées en gardant à l’esprit que la surface V est invariante. Sa valeur reste donc la même après un trade. En pratique, la valeur de V augmente, à cause des frais qui sont prélevés lors des échanges.
Out-given-in
On considère un trade de jetons i pour des jetons o. Tous les soldes des autres réserves de jetons restent les mêmes.
- Ai est la quantité de jetons i vendus par le trader ;
- Ao est la quantité de jetons o achetés par le trader.
Ao est calculé grâce à l’équivalence de la fonction de valeur avant et après le trade :
On obtient ainsi :
In-given-out
On calcule quelle quantité du jeton d’entrée i est nécessaire pour recevoir la quantité désirée de jeton de sortie o. La quantité Ai est fonction de la quantité Ao.
Nous obtenons donc :
In-given-price
Cette formule donne la quantité Ai de jetons i nécessaire pour changer son prix du prix spot SPio vers le prix spécifié SP’io. Cette formule est utile pour les arbitrageurs. Le prix spot désiré sera généralement le prix du marché sur d’autres exchanges. Les arbitrageurs génèrent donc du profit tant que le prix spot d’un jeton sur l’AMM diverge de son prix sur les marchés externes.
Le profit maximal est atteint lorsque le trade d’arbitrage aligne le prix spot du jeton sur l’AMM exactement avec son prix sur les marchés externes. C’est donc ce qui permet à Balancer de suivre les prix des marchés externes : on parle d’on-chain price sensor.
La quantité de jetons Ai de jetons i qu’un utilisateur doit échanger contre les jetons o afin que le prix spot de l’AMM change de SPio à SP’io est alors :
Formules d’apport de liquidité
N’importe quel utilisateur de Balancer peut déposer et retirer des actifs dans les réserves. Afin de garder la trace des actifs des fournisseurs de liquidité, le protocole crée des jetons LP (liquidity provider tokens ou pool tokens).
La quantité de jetons LP est proportionnelle à la fonction de valeur du pool. Ainsi, lorsqu’un fournisseur de liquidité dépose des actifs dans le pool, et accroît la fonction de valeur de 10%, la quantité de pool tokens augmente également de 10%
Il y a deux types d’opérations qui permettent aux fournisseurs de liquidité d’ajouter ou de retirer des jetons d’un pool : dépôt/retrait d’actifs pondérés (weighted asset deposit/withdrawal) ou dépôt/retrait d’actif unique (single asset deposit/withrawal).
Weighted asset
Ce type de dépôt doit respecter la distribution de chacun des actifs du pool. Ainsi, si un dépôt représente 10% du total des jetons en réserve :
- La fonction de valeur augmente de 10% ;
- Les pool tokens sont créés (minted) puis transférés au fournisseur de liquidité, et représentent donc 10% de la quantité totale de jetons LP.
On calcule la quantité de jetons Dk (pour chaque jeton k) à déposer dans le pool pour créer Pminted jetons LP, étant donné la quantité totale Psupply de jetons LP, et les soldes Bk de chaque jeton k en réserve avant le dépôt :
De la même façon, on calcule la quantité Ak de chaque jeton k retournée au fournisseur de liquidité lorsque qu’il retire Predeemed jetons LP, étant donné la quantité totale Psupply de jetons LP, et les soldes Bk de chaque jeton k en réserve avant le retrait :
Dépôt d’actif unique
Un fournisseur de liquidité peut souhaiter déposer dans un pool, mais sans être capable de fournir chaque actif dans les proportions. On parle alors de single asset deposit. Le protocole permet aux fournisseurs de liquidité d’obtenir des jetons LP même s’ils ne possèdent qu’un seul des actifs présents dans le pool.
Un dépôt d’actif unique est équivalent à :
- Déposer tous les actifs du pool proportionnellement à leur répartition ;
- Vendre l’actif A pour obtenir en retour tous les autres jetons déposés.
Le déposant va donc seulement dépenser l’actif A. La quantité de chaque autre jeton déposé dans le pool sera rendue à travers les trades.
On utilise la fonction de valeur pour obtenir la quantité de jetons LP envoyée au fournisseur de liquidité lors d’un dépôt d’actif unique :
Soit Pissued la quantité de jetons LP correspondant au dépôt. La quantité totale de jetons LP avant le dépôt est Psupply. La quantité totale de jetons LP va augmenter proportionnellement avec la fonction de valeur :
Où :
- V est la fonction de valeur avant le dépôt ;
- V’ est la fonction de valeur après le dépôt.
Soient :
- Bk le solde de l’actif k avant le dépôt ;
- B’k le solde de l’actif k après le dépôt.
Nous avons ainsi :
Soit t le jeton déposé. Comme les soldes de chacune des autres réserves de jetons ne change pas, nous avons donc :
Soit At la quantité de jeton t déposée. Le nouveau solde de la réserve de jetons t est donc :
Par substitution, la quantité de nouveaux jetons LP émise est donc :
Retrait d’actif unique
Dans le cas d’un retrait d’actif unique, on calcule la quantité Predeemed de jetons t qui sera envoyée au fournisseur de liquidité, pour une quantité At de jetons LP, et un solde Bt de jetons t avant le retrait :
Sans frais de trading, un fournisseur de liquidité effectuant un dépôt d’actif unique pour une quantité At de jetons t obtiendra la même quantité At de jetons, après avoir retiré la quantité correspondante Pissued de jetons LP.
Un dépôt (ou un retrait) d’actif unique dans un pool est l’équivalent d’échanger (1 – Wt) jetons pour tous les autres actifs du pool. Puisque le pool contient déjà la quantité Wt de jetons t, le protocole ne prélève pas de frais lors de cet échange.
Les réserves de liquidité de Balancer
Les liquidity pools de Balancer sont des smart contracts flexibles, qui définissent les règles de l’échange de jetons entre ses utilisateurs. La contribution principale du protocole Balancer est de permettre à ses utilisateurs de définir n’importe quel type de composition et de paramètres pour les liquidity pools. Il est possible de personnaliser entièrement les pools; il y en a donc différents types.
Réserves pondérées – weighted pools
Vue d’ensemble
Grace à la fonction de valeur, les weighted pools sont hautement configurables. Il peuvent ainsi inclure jusqu’à 8 jetons différents, même s’ils n’ont aucune corrélation de prix.
Au sein des weighted pools, chaque jeton peut donc être échangé contre les autres. Ainsi, le nombre de paires de trading augmente significativement avec le nombre de jetons disponibles.
Fonctionnalités
Les weighted pools offrent également aux fournisseurs de liquidité plus de flexibilité en termes d’exposition à un actif particulier. Cela a donc des conséquences sur les pertes impermanentes. Plus le poids d’un jeton est important dans un pool, et plus la perte impermanente sera élevée en cas de changement de prix.
Les utilisateurs peuvent alors affiner la composition d’un pool en fonction de leur stratégie. Un actif aura plus de poids si l’on suppose que son prix va augmenter; tandis qu’un pool 50/50 implique implicitement que la valeur des deux jetons restera proportionnelle sur le long terme.
Cependant, lorsqu’on augmente le poids d’un actif relativement aux autres, la réduction des pertes impermanentes entraîne plus de slippage.
Réserves stables – stable pools
Les stable pools sont dédiés aux actifs qui s’échangent généralement à parité. Il s’agit par exemple des stablecoins, ou des jetons synthétiques. Ces pools utilisent un modèle appelé Stable Maths, qui provient du protocole Curve. Stable Maths réduit ainsi le slippage, et améliore l’efficacité du capital.
Stable Maths
Ce modèle d’AMM combine les fonctions à somme constante et à produit constant pour former un nouvel invariant. Cet invariant permet d’échanger des actifs qui ont le même prix (ou sont liés au même actif).
L’invariant est déterminé en résolvant l’équation suivante pour D :
Où :
- n est le nombre de jetons ;
- xi le solde de chaque jeton i ;
- A le cœfficient d’amplification.
Pour plus d’informations sur la méthode employée pour calculer D, nous pouvons jeter un œil au dépôt GitHub de Balancer. Cette fonction peut ainsi être utilisée pour calculer l’invariant.
Voici à quoi ressemble la fonction de prix avec A tendant vers l’infini :
Caractéristiques
Le modèle permet aux utilisateurs d’effectuer des échanges à haut volume sans impact significatif sur le prix des jetons. Le spread est ainsi plus étroit qu’en utilisant une simple fonction à somme constante.
Puisque le protocole est le même pour les stable pools et pour les autres pools de jetons, les arbitrageurs qui échangent un jeton lié à 2 stablecoins différents peuvent échanger un stablecoin pour l’autre, en combinant les échanges en un trade unique (batch swap).
Les pools MetaStable de Balancer
Les MetaStable Pools sont l’extension des Stable Pools dédiée aux jetons ayant un taux d’échange connu. Le protocole utilise Stable Maths et le combine avec les taux d’échange. Ces pools sont efficace quand il s’agit d’échanger des jetons non-liés, mais dont les prix sont hautement corrélés.
Cela inclut, par exemple, les jetons avec des dérivés, comme le WETH et le wstETH.
Les pools d’amorçage de liquidité
Les Liquidity Bootstrapping Pools permettent à leur propriétaire de définir de quelle façon le poids des différents jetons va changer au cours du temps (dynamic weight). Le propriétaire du pool a tous les droits. Il peut ainsi définir les valeurs de départ, et peut aussi mettre les échanges en pause. La distribution des actifs dépend donc du temps et peut changer comme on le souhaite. Par exemple, elle peut passer de 1%/99% à 99%/1%.
Ces LBS présentent plusieurs avantages :
- Fair market (marché équitable) : les LBP qui se lancent avec des prix élevés découragent les whales et les bots de drainer la liquidité du pool dès son ouverture. Utiliser les LBP pour les premiers stades du lancement d’un jeton aide à assurer sa large diffusion.
- Faible capital requis : l’équipe de développement d’un jeton peut utiliser un LBP pour amorcer sa liquidité. Elle peut le faire avec moins de fonds qu’en créant un pool 50/50. Par exemple, une équipe lançant un pool TOKEN/DAI va bénéficier de la réduction de la quantité de DAI requise, disons 10 ou 20% plutôt que 50%. Les fonds économisés peuvent alors être utilisés ailleurs. De pus, la volatilité lors de la découverte du prix sera réduite. Enfin, l’équipe aura accès à plus de DAI à la fin de l’opération.
Les Liquidity Bootstrapping Pools sont adaptés aux ventes de jetons « équitables » en permettant aux petit investisseurs de rentrer.
Les Managed Pools de Balancer
Les Managed Pools tirent avantage de la nature flexible du protocole Balancer. Ils permettent ainsi de créer des pools personnalisés, comportant jusqu’à 50 jetons différents. Les gestionnaires de fonds peuvent utiliser le mécanisme de pondération des actifs, et composer des stratégies complexes. Par exemple, on peut définir un indice dédié à un ensemble de jetons particulier.
Les Managed Pools ont aussi des fonctionnalités classiques, telles que la possibilité de mettre en place des frais de gestion, ou des listes blanches pour les fournisseurs de liquidité.
Les Boosted Pools
Les Boosted Pools combinent les Stable Pools à des protocoles externes, comme Aave, et confèrent aux fournisseurs de liquidité et aux swappers une efficacité optimale. Les traders bénéficient des liquidités de Balancer pour leurs échanges de stablecoins, tandis que les fournisseurs de liquidité génèrent des intérêts supplémentaires.
Cela améliore l’efficacité du capital, car les fournisseurs de liquidité peuvent prêter leur jetons « inactifs » sur un protocole externe. Ils recevront les intérêts correspondants en plus de leur part des frais de trading.
De plus, chaque jeton d’un Boosted Pool peut être échangé avec les autres, et avec les pools tokens imbriqués (comme les aTokens d’Aave). Cela accroît leur liquidité.
Les Boosted Pools combinent les Linear Pools et les Phantom Pool Tokens pour optimiser la consommation de gas lors des processus de mint et de burn des jetons LP :
- Les Linear Pools utilisent le modèle Linear Maths pour faciliter les échanges entre deux jetons ayant un taux d’échange connu. Les frais peuvent être positifs ou négatifs, pour inciter les arbitrageurs à maintenir le ratio souhaité ;
- Phantom Boosted Pool Tokens (Phantom BPT) est une fonctionnalité utile qui permet de réduire les frais de gas lors de la création et de la destruction des jetons LP. Tous les jetons LP sont émis lors de la création du pool, et sont conservés par le pool lui-même. Au lieu d’appeler les fonctions
join
etexit
, les fournisseurs de liquidité utilisent les Batch Swaps pour trade vers un jeton LP (join
) ou depuis un jeton LP (exit
).
Les Boosted Pools augmentent la profondeur de la liquidité des stablecoins et des jetons des linear pools. En effet, ils relient ces jetons et leurs versions dérivées au sein du même pool. De même, ils augmentent les intérêts générés par les fournisseurs de liquidité.
Balancer et ses pools personnalisés – Custom Pools
Balancer est un protocole sans permission. Ainsi, n’importe quel utilisateur peut créer son propre AMM. Il peut se focaliser sur la création de fonctions de prix personnalisées, dédiées à des stratégies de trading spécifiques. Lorsqu’un Custom Pool est intégré au protocole, il peut accéder à la liquidité déjà existante sur Balancer. Les gestionnaires de pool peuvent définir des conditions d’entrée de sortie.
Les frais sur Balancer
Il y a différents types de frais sur Balancer, qui incitent économiquement les utilisateurs à participer à la croissance du protocole.
Les frais de swap
Ce sont les frais que les utilisateurs paient pour échanger des jetons avec un pool. Ils s’appliquent donc à chaque swap. Ils récompensent les fournisseurs de liquidité pour leur travail, et vont directement dans le pool, augmentant ainsi son solde. De ce fait, les fournisseurs de liquidité reçoivent automatiquement leur part des frais.
Quantitéfrais = Quantitéjetond’entrée * swapFee
Frais statiques et frais dynamiques
Le créateur d’un pool définit des frais et un propriétaire. Si le propriétaire est une adresse non-contrôlée (l’adresse zéro), alors les frais de swap seront fixes. Si les propriétaire est une adresse contrôlée, alors cette adresse peut changer les frais à n’importe quel moment (frais dynamiques). Le créateur du pool a deux options :
- Définir les frais manuellement via l’adresse propriétaire ;
- Déléguer la gestion des frais à un contrôleur, par exemple via un protocole de gouvernance.
Frais de swap du protocole Balancer
Ces frais sont déduis des frais de swap des différents pools. Ils sont ajoutés à la réserve de la DAO. Actuellement de 50%, ils peuvent être modifiés à travers les mécanismes du protocole de gouvernance. Ils sont définis dans le contrat Protocol Fees Collector de Balancer :
https://etherscan.io/address/0xce88686553686DA562CE7Cea497CE749DA109f9F#readContract
On peut connaître les frais courants avec getSwapFeePercentage().
Les oracles de Balancer
Certains types de pools de Balancer, comme les WeightedPool2Tokens ou les MetaStablePools se comportent comme des oracles. Ils sont utilisés de deux façons :
- Obtenir le prix instantané d’un jeton ;
- Obtenir le Time Weighted Average Price (TWAP) d’un jeton : son prix moyen sur une période de temps donnée.
Les contrats de l’implémentations de l’oracles peuvent être trouvés ici :
Prix instantané
Les requêtes pour obtenir le prix à l’instant t sont peu coûteuse en gas. Elles sont utilisées par les applications où une éventuelle manipulation du prix n’a pas d’impact :
- getLatest
- getPastAccumulators
Time weighted average price
La requête getTimeWeightedAverage donne le prix moyen d’un jeton sur une période allant de 2 minutes à 34 heures. Un accumulateur collecte les données du prix pour chaque échantillon :
Cet accumulateur est inspiré par les oracles TWAP d’Uniswap et ne nécessite aucune maintenance. Pour comprendre comment il fonctionne, étudions tout d’abord l’index en tête de l’accumulateur. Ces 10 bits correspondent à 1024 « photos » de l’accumulateur, couverts par un tampon circulaire :
Ensuite, l’accumulateur présente un champ d’horodatage (timestamp) de 32 bits correspondant à la dernière mise à jour de l’accumulateur.
Le champ priceAcc de 214 bits stocke l’accumulateur courant pour la paire de prix. Il est factorisé en deux nombres : 182 bits pour le prix, et un multiplicateur (priceMultiplier). Cela signifie donc que priceAcc = price * priceMultiplier. La raison en est que le prix accumulé n’est utile que lorsque deux horodatages sont pris en considération pour calculer le TWAP; cependant, avoir le prix instantané peut être utile pour certains cas d’usage.
Le Smart Order Router de Balancer
Le Smart Order Router est le système qui permet aux traders de Balancer d’obtenir les meilleurs prix en fonction des jetons d’entrée et de sortie. Le chemin pour l’échange peut utiliser un ou plusieurs pools (sauts multiples).
Le Smart Order Router permet à la liquidité de s’étendre aux différents pools de Balancer – qui peuvent reposer sur des mathématiques différentes. N’importe quel custom pool qui intègre le SOR peut ainsi utiliser toutes les liquidités de Balancer. Le créateur du pool personnalisé doit définir des fonctions spotPriceAfterSwap différentielles de premier et deuxième ordre (différentielles numériquement ou analytiquement).
Mécanisme
Le SOR prend en compte le prix du gas lors du calcul du meilleur itinéraire pour un échange. Dans un modèle idéal où les coûts du gas sont nuls, le routeur utilisera chaque pool, y compris les jetons échangés, pour maintenir des prix égaux dans tous les pools. Étant donné que chaque swap entraîne des coûts de gas, le routeur ajoutera plusieurs pools uniquement si les frais sont optimisés pour la limite de gas définie.
Le mécanisme trouve le chemin à travers un ensemble de pools ayant le rendement le plus élevé (après inclusion des coûts du gas). Cela permet des opportunités d’arbitrage entre les pools Balancer qui ne font pas partie du sous-ensemble.
Avec ce modèle, le routeur cherche des chemins ne présentant aucun opportunité d’arbitrage. Chacun des chemins doit mener au même prix spot une fois que l’échange est effectué. De cette façon, ce mécanisme assure que le trader obtiendra les meilleurs frais à partir de l’ensemble des pools sélectionnés par le routeur.
Balancer : plus qu’un simple AMM !
En conclusion, on peut dire que Balancer est plus qu’un simple AMM dédié aux échanges décentralisés. Ce protocole DeFi avancé a de nombreux cas d’utilisation, et peut être défini comme :
- Un gestionnaire de portefeuille automatisé ;
- Un fournisseur de liquidité ;
- Et un capteur de prix, un oracle on-chain.
Balancer aligne les intérêts économiques de ses utilisateurs, fournissant une liquidité suffisante aux traders souhaitant effectuer des swaps efficaces pour plusieurs paires de jetons à un coût optimal, tout en récompensant les fournisseurs de liquidité avec des rendements maximisés.
La différence avec un gestionnaire de fonds traditionnel réside dans la manière dont les frais sont utilisés. Grâce à ce protocole, les pools rééquilibrent automatiquement les réserves de jetons, grâce aux traders, d’où son nom.
Bibliographie
- Article introductif de Dmitriy Berenzon sur les AMM à fonction constante
- Balancer Is A New Type Of AMM – Alchemy
- Le livre blanc de Balancer
- La documentation complète de Balancer
- A Theroy of Automated Market Makers in DeFi – Massimo Bartoletti, James Hsin-Yu Chiang et Alberto Lluch-Lafuente
- Optimal Fees for Geometric Mean Market Makers – Alex Evans, Guillermo Angeris, Tarun Chitra