
Identifier les opportunités d'arbitrage dans la DeFi via le code
TechFlow SélectionTechFlow Sélection

Identifier les opportunités d'arbitrage dans la DeFi via le code
Cet article analysera certaines opportunités d'arbitrage potentielles au niveau du code des contrats de quelques bourses décentralisées ainsi que des agrégateurs.
Aperçu
La finance décentralisée (en anglais : Decentralized Finance, communément appelée DeFi) est une forme de finance construite sur la blockchain qui ne dépend pas d'institutions financières telles que courtiers, bourses ou banques pour fournir des instruments financiers. Elle repose plutôt sur des contrats intelligents déployés sur la blockchain pour mener à bien des activités financières. Le domaine DeFi recèle de nombreuses opportunités d'arbitrage, notamment le remboursement forcé (liquidation), l'arbitrage de prix entre marchés, etc. Cet article analyse certaines opportunités d'arbitrage potentielles au niveau du code des contrats de bourses décentralisées (DEX) et de leurs agrégateurs.
Analyse
Uniswap
Uniswap est une plateforme décentralisée de trading de cryptomonnaies utilisant un modèle de market-maker automatique (AMM). Il existe actuellement deux versions populaires, Uniswap V2 et Uniswap V3. Nous allons analyser séparément les opportunités d'arbitrage potentielles dans chacune d'elles.
Router Uniswap V2
Dans Uniswap V2, les utilisateurs interagissent généralement avec les contrats Pair et Factory via un contrat Router. En général, le Router sert uniquement de relais pour les jetons lors des transactions et ne conserve pas de jetons en dépôt. Toutefois, pour diverses raisons — comme des airdrops ou des erreurs de transfert — certains jetons peuvent se retrouver stockés dans le contrat Router. Comment extraire ces jetons ?
L’analyse du code du contrat Router 02 d’Uniswap V2 révèle la présence de la fonction removeLiquidityETHSupportingFeeOnTransferTokens :

Cette fonction permet de retirer la liquidité lorsque l’un des deux jetons est du WETH. Elle appelle internement la fonction removeLiquidity, en spécifiant comme adresse de destination address(this), c’est-à-dire que les deux jetons sont d’abord transférés vers le contrat Router, puis redistribués par celui-ci vers l’adresse finale. Bien que la quantité de WETH transférée corresponde exactement à celle retournée par removeLiquidity (donc non modifiable), la quantité de l’autre jeton transféré dépend du solde disponible dans le contrat Router, soit balanceOf(address(this)).
D’après cette observation, on peut établir le processus suivant pour réaliser un arbitrage :
-
Surveiller si le contrat Router 02 détient des jetons ERC-20 ;
-
Appeler
addLiquidityETHpour ajouter de la liquidité composée de ce jeton ERC-20 et de WETH ; -
Appeler
removeLiquidityETHSupportingFeeOnTransferTokenspour retirer la liquidité.
Limites :
-
Si ce jeton n’a jamais été associé au WETH auparavant, une petite partie de la liquidité (MINIMUM_LIQUIDITY) sera perdue lors de la première création du pool ;
-
Aucune méthode n’a été trouvée pour extraire les WETH ou ETH présents dans le contrat Router 02.
Pair Uniswap V2
Le contrat Pair d’Uniswap V2, également appelé pool de liquidité, contient deux jetons fournis par les fournisseurs de liquidité. Contrairement aux approches basées sur balanceOf(address(this)), ce contrat utilise des variables reserve pour suivre les soldes. Si un utilisateur transfère par erreur un jeton directement au contrat Pair, cela crée une différence entre le solde réel (balance) et la réserve enregistrée. Le contrat dispose toutefois d’une fonction nommée skim qui permet précisément de récupérer cette différence :

Comme indiqué, cette fonction transfère vers l’adresse to la différence entre le solde réel et la réserve pour chacun des deux jetons du pool.
Outre ces deux jetons, d’autres jetons ERC-20 peuvent également se retrouver dans le pool suite à des erreurs de transfert ou des airdrops. Comment extraire ces jetons supplémentaires ?
L’analyse du code du contrat Pair montre qu’il n’existe aucun moyen d’en extraire directement ces autres jetons, sauf dans un cas particulier : lorsque le pool contient ses propres jetons LP (jetons de liquidité).
Dans ce cas, il est possible d’appeler la fonction burn du contrat Pair afin de retirer la liquidité et récupérer les deux jetons sous-jacents :

SwapRouter Uniswap V3
Le contrat SwapRouter d’Uniswap V3 présente une situation similaire à celle du Router d’Uniswap V2 : il peut contenir des jetons ERC-20 ainsi que de l’ETH. Heureusement, SwapRouter propose plusieurs fonctions facilitant l’extraction de ces fonds.
Pour extraire des jetons ERC-20, on peut utiliser la fonction sweepToken :

Pour récupérer de l’ETH, la fonction refundETH est disponible :

On peut aussi directement appeler la fonction unwrapWETH9 pour convertir le WETH en ETH et le retirer :

Ce qui précède constitue l’analyse des opportunités d’arbitrage liées au contrat SwapRouter d’Uniswap V3.
L’analyse du code du contrat Pool d’Uniswap V3 révèle qu’il n’est pas possible d’extraire d’autres jetons stockés dans ce contrat, ni de tirer parti d’écart entre balance et reserve comme dans Uniswap V2 Pair.
SushiSwap
SushiSwap a initialement été un fork d’Uniswap, avant de devenir un écosystème indépendant offrant divers services et produits financiers.
Étant donné que SushiSwap suit une architecture similaire à Uniswap V2, les stratégies d’arbitrage décrites ci-dessus s’appliquent également à SushiSwap.
SushiXSwap
SushiXSwap est un protocole de swap multichaîne lancé par SushiSwap, basé sur LayerZero. Il supporte les réseaux Optimism, Arbitrum, Fantom, BNB Chain, Polygon et Avalanche, permettant aux utilisateurs d’effectuer des transactions inter-chaînes entre actifs supportés.
Comment extraire les jetons présents dans le contrat SushiXSwap ?
Les fonctionnalités principales de SushiXSwap sont centralisées dans la fonction cook, qui prend en charge une série d’opérations listées ci-dessous :

Parmi celles-ci figure l’opération ACTION_DST_WITHDRAW_TOKEN, dont l’implémentation est la suivante :

Elle commence par décoder les données passées à la fonction cook, puis vérifie si amount est égal à zéro. Si oui, la valeur de amount est remplacée par le solde du contrat en jeton ERC-20 ou en ETH. Enfin, la fonction _transferTokens transfère les jetons vers l’adresse cible :

Il suffit donc de construire correctement les paramètres actions et datas passés à cook : définir actions comme ACTION_DST_WITHDRAW_TOKEN, et inclure dans data le jeton souhaité, l’adresse destinataire et le montant, pour réussir à retirer des jetons du contrat SushiXSwap.
Sushi BentoBox
Sushi BentoBox est un composant clé de l’écosystème SushiSwap. Il s’agit d’un produit DeFi hautement flexible optimisé pour les taux d’intérêt. En résumé, c’est une plateforme de contrats intelligents permettant aux utilisateurs de déposer, emprunter et générer des intérêts. L’objectif principal de BentoBox est d’optimiser les rendements des utilisateurs dans l’univers DeFi.
Le contrat BentoBox sur Ethereum détient une grande quantité de jetons. Existe-t-il des opportunités d’arbitrage ici ?
Les utilisateurs peuvent déposer des fonds via la fonction deposit, dont l’implémentation est la suivante :

L’utilisateur fournit l’adresse du jeton, l’adresse d’envoi, l’adresse de réception, le montant et les parts. Après quelques vérifications, la fonction convertit amount ou share. Le point critique se situe aux lignes 195–198, où une vérification est effectuée : amount <= _tokenBalanceOf(token).sub(total.elastic).
Dans BentoBox, le solde total d’un jeton est enregistré via total.elastic, similaire à reserve dans Uniswap Pair. Dans certains cas, cela peut différer de _tokenBalanceOf(token). On peut exploiter cette particularité de la fonction deposit pour convertir cette différence en solde crédité dans le contrat.
En réglant token sur l’adresse du jeton concerné, amount sur la différence, from sur l’adresse du contrat BentoBox et to sur notre propre adresse, la ligne 207 n’effectuera aucun transfert physique (car l’adresse source est celle du contrat lui-même), mais ajustera simplement les valeurs total.elastic et _tokenBalanceOf(token), tout en créditant le montant correspondant à l’adresse to.
DODO
DODO est une plateforme de trading décentralisée utilisant un algorithme propriétaire de market-maker actif (PMM) pour fournir une liquidité efficace sur chaîne pour les actifs Web3. DODO fournit sa propre liquidité tout en agrégeant celle d’autres plateformes.
DODO dispose d’une série de contrats. Les utilisateurs interagissent principalement via le contrat DODO V2 Proxy 02 pour échanger des jetons. Comme le Router d’Uniswap, ce contrat peut accumuler des jetons par erreur ou suite à des airdrops. Comment les extraire ?
DODO V2 Proxy 02
Le contrat DODO V2 Proxy 02 contient la fonction externalSwap, utilisée pour échanger via des plateformes externes agrégées par DODO, comme 0x ou 1inch. Son implémentation est la suivante :

Les lignes 1719–1721 valident les paramètres entrants. La ligne 1724 vérifie si fromToken est ETH. Sinon, les jetons de l’appelant sont transférés vers le contrat, puis autorisés. L’analyse du contrat DODOAPPROVE montre qu’on peut contourner cette étape en fixant fromTokenAmount à zéro :

Ensuite, le contrat vérifie que le swapTarget fait partie d’une liste blanche. Or, swapTarget et calldataConcat sont contrôlés par l’utilisateur. On peut donc choisir l’adresse d’un contrat comme 0x ou 1inch, et configurer calldataConcat avec l’encodage d’une fonction view renvoyant true, satisfaisant ainsi la condition require suivante :

Ensuite, tous les jetons toToken présents dans le contrat sont transférés à l’appelant. Ce toToken peut être un jeton ERC-20 ou de l’ETH. Après le transfert, une vérification du montant minimal attendu est effectuée. En fixant minReturnAmount à une très faible valeur, cette condition est facilement satisfaite. Les deux derniers appels sont sans importance.

Grâce à cette méthode, il est possible d’extraire les jetons ERC-20 et l’ETH présents dans le contrat DODO V2 Proxy 02.
1inch
1inch est un agrégateur de bourses décentralisées (DEX) qui regroupe la liquidité de plusieurs DEX afin d’offrir aux utilisateurs le meilleur prix possible lors de l’échange de jetons. En consolidant la liquidité provenant de différentes sources, 1inch aide les utilisateurs à optimiser leurs transactions et à trouver les meilleurs prix disponibles. Ses contrats intelligents exécutent automatiquement des swaps entre différentes DEX, permettant aux utilisateurs d’obtenir facilement les meilleurs taux et les moindres glissements. 1inch propose également d'autres fonctionnalités comme le minage de liquidité et un jeton de gouvernance.
Le contrat principal de 1inch est AggregationRouter, dont les versions V4 et V5 sont largement utilisées. Ces contrats peuvent, pour diverses raisons, contenir des jetons. Il est possible d’extraire ces jetons en manipulant judicieusement les paramètres des fonctions.
AggregationRouterV5
Le contrat AggregationRouterV5 possède une fonction swap, dont l’implémentation est la suivante :

Après vérification du minReturnAmount dans la structure desc, les jetons source (srcToken) et destination (dstToken) sont extraits. Les lignes 986–997 peuvent être contournées en configurant correctement les champs flags et srcToken dans desc :

Puis la fonction _execute est appelée. Elle effectue un appel externe (call) et vérifie son statut. Comme executor est contrôlé par l’utilisateur, on peut utiliser l’adresse nulle (0x0) pour contourner cette vérification :

Ensuite, le solde du contrat en dstToken est récupéré. Les lignes 1007–1018 peuvent être contournées en ajustant flags et minReturnAmount dans desc :

Enfin, tout le solde en dstToken est transféré vers l’adresse dstReceiver, entièrement contrôlée par l’utilisateur :

Par ces étapes, il est possible de construire les paramètres de la fonction swap pour retirer tous les jetons présents dans le contrat AggregationRouterV5.
AggregationRouterV4
AggregationRouterV4 est très similaire à V5. Il contient également une fonction swap, dont l’implémentation est quasiment identique :

On constate que la logique est identique à celle de V5, à l’exception d’une optimisation mineure du call. Ainsi, la même méthode utilisée pour V5 permet d’extraire les jetons présents dans AggregationRouterV4.
Conclusion
Cet article a présenté brièvement plusieurs bourses décentralisées et agrégateurs, explorant les opportunités d’arbitrage potentielles. Une analyse au niveau du code des contrats a permis de comprendre les mécanismes sous-jacents. Toutefois, la réussite pratique dépend de nombreux facteurs tels que le coût en gaz (GAS) et la vitesse des nœuds.
Bienvenue dans la communauté officielle TechFlow
Groupe Telegram :https://t.me/TechFlowDaily
Compte Twitter officiel :https://x.com/TechFlowPost
Compte Twitter anglais :https://x.com/BlockFlow_News














