La naissance d'Ethereum a établi un nouveau modèle informatique basé sur le principe d'immuabilité, dans lequel le code source, une fois déployé sur la blockchain, existe pour toujours et ne peut être modifié. Cependant, dans la réalité du développement logiciel, cette immuabilité crée un obstacle majeur à la correction de bugs, aux mises à jour de fonctionnalités et à l’optimisation du système. Pour résoudre le conflit entre l’immuabilité de la blockchain et le besoin de flexibilité logicielle, le modèle Proxy Contract a été développé comme solution standard. Ce rapport, compilé par l'équipe de Tan Phat Digital, analyse en profondeur la nature des contrats de proxy, les mécanismes techniques sous-jacents, les normes populaires et surtout les risques de sécurité sophistiqués qui font que les utilisateurs finaux sont facilement trompés dans des scénarios réels.
1. Concepts de base et séparation de l'état et de la logique
Les contrats intelligents traditionnels sur Ethereum sont une entité monolithique, où le code d'exécution (logique) et l'espace de stockage (stockage) sont liés à une seule adresse. Proxy Contract brise cette structure en séparant le système en deux composants indépendants mais en interaction étroite : le contrat Proxy (qui contient l'état) et le contrat Logic (qui contient le code exécutable).
Ce modèle permet de conserver une adresse fixe pour les utilisateurs et les applications frontales, tandis que la logique métier sous-jacente peut être remplacée en changeant l'adresse pointant vers le contrat logique dans la mémoire du proxy. Cela crée une « illusion de variabilité » sur une infrastructure intrinsèquement immuable.
1.1 Rôle des composants dans l'architecture proxy
Dans cette architecture, le contrat proxy sert de point de contact unique. Tous les actifs, les soldes Ether et les variables d'état importantes telles que la propriété et les soldes des utilisateurs sont stockés en permanence à l'adresse du proxy. En revanche, un contrat logique (également appelé contrat de mise en œuvre) contient uniquement des instructions sur la façon de traiter les données.
Les principaux composants comprennent :
Contrat de proxy : stockage des données, solde des jetons, adresse de mise en œuvre et droits administratifs. Possède des propriétés d'adresse immuables, mais peut modifier les données internes.
Logique (implémentation) : contient le code source des fonctions métier (par exemple : transfert, menthe, échange). Remplaçable par de nouvelles versions.
ProxyAdmin : le contrat administratif ou le portefeuille a le droit d'effectuer des mises à niveau, aidant à contrôler la capacité de modifier l'ensemble du système.
Cette séparation apporte de grands avantages dans la maintenance du système. Si une vulnérabilité de sécurité est découverte dans la logique métier, le développeur déploie simplement un nouveau contrat de logique fixe et met à jour l'adresse dans le proxy, au lieu de devoir demander à des milliers d'utilisateurs de déplacer les actifs vers une toute nouvelle adresse.
Voir aussi : Qu'est-ce que le contrat intelligent ?
2. Mécanisme DELEGATECALL : le moteur de la mise à niveau
La base technique qui permet au Proxy Contract de fonctionner est l'opcode delegatecall, introduit dans l'EIP-7 du réseau Ethereum. Il s'agit d'un appel spécial qui permet à un contrat de récupérer du code exécutable à partir d'une autre adresse mais de l'exécuter dans son propre "contexte".
2.1 Préserver le contexte dans l'exécution de l'EVM
Lorsque le contrat proxy effectue un appel délégué au contrat logique, les variables d'environnement de la transaction sont conservées intactes. Cela signifie que dans le contrat Logic, les valeurs suivantes ne changeront pas par rapport à l'appel direct du proxy :
msg.sender: toujours l'adresse de l'utilisateur d'origine, pas l'adresse du proxy.msg.value: la quantité d'éther incluse dans la transaction est conservée comme ressource.stockage: toutes les lectures (SLOAD) et les écritures (SSTORE) agissent directement sur l'espace de stockage du proxy, pas sur le contrat logique.
La différence entre les appels réguliers (CALL) et DELEGATECALL est extrêmement importante pour la sécurité et la fonctionnalité. capacités du système. Dans une commande CALL, le contrat cible fonctionne sur sa propre mémoire et considère msg.sender comme le contrat appelant. Dans DELEGATECALL, le contrat cible agit comme une bibliothèque logique chargée dans le serveur proxy.
2.2 Analyser le flux d'exécution via la fonction de repli
Étant donné que le contrat proxy ne définit généralement pas de fonctions métier pour éviter les conflits, il utilise la fonction fallback pour recevoir tout appel inconnu. Lorsqu'un utilisateur appelle la fonction transfer(address,uint256) sur le proxy, puisque le proxy ne dispose pas de cette fonction, la machine virtuelle Ethereum (EVM) déclenchera la fonction fallback. Ici, un morceau de code assembleur de bas niveau sera exécuté pour autoriser l'appel.
Le processus technique est le suivant :
Utilisez
calldatacopypour copier toutes les données d'entrée de la transaction en mémoire.Obtenez l'adresse du contrat logique actuel à partir d'un emplacement de stockage spécifié.
Exécutez la commande
delegatecallavec tout le gaz disponible, transmet les données copiées.Une fois l'exécution du contrat logique terminée, le résultat est renvoyé et les données de sortie sont recopiées à l'aide de
returndatacopy.Le proxy renvoie le résultat à l'utilisateur d'origine, complétant ainsi le cycle de délégation de manière transparente.
3. Architecture de mémoire et normes EIP-1967
L'un des plus grands défis du modèle Proxy est la gestion des collisions de mémoire (Storage Collision). Étant donné que le proxy et l'implémentation partagent le même espace de stockage du proxy, s'ils tentent tous les deux d'utiliser le même « emplacement » de mémoire à des fins différentes, un désastre se produira.
3.1 Risque de collision de mémoire
Dans Solidity, les variables d'état sont disposées dans des emplacements de 32 octets dans l'ordre de déclaration. Supposons que Proxy déclare la variable address _implementation dans l'emplacement 0 pour stocker l'adresse logique. Si le contrat logique déclare la variable uint256 _balance également dans l'emplacement 0, alors chaque fois que la fonction logique met à jour la balance, elle écrasera accidentellement sa propre adresse dans le proxy. Cela conduit à la reprise du contrat par un attaquant s'il peut manipuler la valeur écrite dans cet emplacement.
3.2 Stockage non structuré et solution EIP-1967
Pour éviter les collisions, la norme EIP-1967 a été établie, qui définit des emplacements de stockage spéciaux pour les variables administratives du proxy en hachant les chaînes d'identification :

La soustraction de 1 après le hachage garantit que cet emplacement ne peut pas être créé par un hachage normal de tableaux dynamiques ou de mappages dans Solidity, minimisant ainsi la probabilité de collisions soudainement abandonnées à presque zéro.
En savoir plus : Qu'est-ce que l'audit de contrat intelligent ?
4. Modèles de proxy populaires et analyse des compromis
4.1 Modèle de proxy transparent (TPP)
Ce modèle vise à résoudre le problème de « collision d'identifiants de fonction ». Le mécanisme de TPP est basé sur la décentralisation de l'appelant : si l'appelant est un Admin, le Proxy n'appelle que ses propres fonctions administratives ; si l'appelant n'est pas un administrateur, le proxy transmet toujours l'appel à l'implémentation.
4.2 Norme de proxy évolutive universelle (UUPS) - EIP-1822
UUPS surpasse TPP en déplaçant la logique de mise à niveau du proxy vers le contrat d'implémentation lui-même. Le proxy est désormais extrêmement rationalisé, ce qui permet d'économiser du gaz car il n'est pas nécessaire de vérifier l'administrateur du proxy. Cependant, si vous effectuez une mise à niveau vers une nouvelle version dépourvue de la logique de mise à niveau, le contrat sera verrouillé pour toujours.
4.3 Beacon Proxy
Conçu pour les projets qui doivent déployer une série de contrats identiques. Les proxys pointent vers un contrat intermédiaire appelé « Beacon » qui contient l'adresse de mise en œuvre commune. Lors de la mise à jour de Beacon, tous les proxys dépendants seront mis à niveau simultanément.
4.4 Diamond Standard (EIP-2535)
Diamond Standard permet à un contrat de proxy de se connecter à de nombreux contrats de mise en œuvre différents (facettes). Cela répond à la limite de taille de contrat de 24 Ko en divisant la logique et en permettant à chaque partie d'être mise à niveau indépendamment.
5. Risques de sécurité et mécanismes de tromperie des utilisateurs
Selon les observations de Tan Phat Digital, les utilisateurs sont souvent trompés par un faux sentiment de sécurité lorsqu'ils voient une adresse de contrat inchangée ou un code source vérifié sur les explorateurs de blocs.
5.1 Risques d'administration et de centralisation
Le plus grand risque est le contrôle absolu de l'administrateur. Si la clé d'administrateur est compromise, un attaquant peut effectuer une « mise à niveau Flash » du code source malveillant pour retirer les fonds, puis revenir à l'ancienne version pour effacer les traces.
5.2 Erreur d'initialisation (vulnérabilité du proxy non initialisé)
Étant donné que le proxy ne peut pas utiliser le constructeur, le développeur utilise la fonction initialize. Si l'Admin oublie d'appeler cette fonction ou ne la protège pas, un attaquant peut l'appeler lui-même pour s'emparer des droits d'Admin. Le piratage du portefeuille Parity de 2017 qui a gelé plus de 500 000 ETH est un exemple historique douloureux de ce bug.
5.3 Conflits de mémoire et crashs d'Audius
Le piratage du protocole Audius de 2022 illustre une erreur d'emplacement mémoire :
Avant la mise à niveau : l'emplacement 0 stocke la création de l'état initial (
initialized = true). Le contrat fonctionne normalement.Après la mise à niveau : le développeur ajoute la variable
proxyAdminau proxy, chevauchant accidentellement l'emplacement 0.Exploit : la valeur de l'adresse de l'administrateur fait mal comprendre au système qu'il n'a pas été initialisé. Le pirate informatique appelle à nouveau la fonction
initialiseret en prend possession.Dommages : le pirate informatique transfère 6 millions de jetons USD hors du fonds communautaire.
5.4 Techniques de dissimulation et de déguisement
Les fraudeurs nomment souvent des fonctions dangereuses comme safeWithdraw() mais sont en réalité une fonction qui draine les fonds. Ils peuvent également vérifier uniquement le code source du proxy (qui est très court et inoffensif) tout en masquant le code source de l'implémentation contenant des « portes dérobées » malveillantes.
6. Analyse des cas typiques de Proxy Rug Pull (2024 - 2025)
6.1 Cas LIBRA et évolution du Rug Pull
Le projet LIBRA 2025 a utilisé la tactique « Fragmented Rug Pull » pour éviter la détection. Au lieu d'un retrait important, le fraudeur utilise un proxy pour distribuer les retraits vers une série de portefeuilles satellites, effectuant des milliers de petites transactions en dessous du seuil d'avertissement du système de surveillance. Ils ont ensuite mis à niveau le proxy vers un contrat contenant une commande selfdestruct pour effacer les preuves.
6.2 Kinto Finance et vulnérabilités du proxy de bas niveau
En juillet 2025, Kinto Finance a été attaquée via un bug dans le mécanisme d'administration du proxy. L'attaquant s'est emparé des droits de mise à niveau et a rapidement créé 110 000 jetons non autorisés supplémentaires, retirant 1,55 million USD des pools de liquidités.
7. Processus de test et de vérification pour les utilisateurs
Pour protéger les actifs, Tan Phat Digital recommande aux utilisateurs de suivre les étapes suivantes :
Vérifiez la fonctionnalité de vérification du proxy : vérifiez si Etherscan affiche un onglet « Lire en tant que proxy ».
Surveillez l'historique des mises à niveau : si un contrat est mis à niveau trop souvent sans préavis, c'est un signal d'alarme. dangereux.
Vérifiez les droits d'administrateur : l'adresse d'administrateur doit être un portefeuille multi-signature (Multisig) ou avoir un mécanisme Timelock pour retarder les modifications importantes.
Utilisez des outils d'assistance : exploitez des plates-formes telles que GoPlus Security ou TokenSniffer pour rechercher des signes de Honeypot ou des droits inhabituels des jetons Mint.
8. Stratégie de défense pour les développeurs
Les développeurs doivent utiliser les bibliothèques standard OpenZeppelin et toujours appliquer la technique "Storage Gap" (créer un tableau vide uint256 private __gap;) pour économiser de l'espace mémoire. Toute modification apportée à l'implémentation doit être testée pour vérifier la compatibilité de la disposition de la mémoire via des outils automatisés tels que le plug-in Hardhat Upgrades avant le déploiement.
9. Foire aux questions (FAQ)
Pourquoi utiliser un contrat proxy au lieu de déployer un nouveau contrat ? L'utilisation d'un proxy permet de conserver une adresse contractuelle unique et fixe pour les utilisateurs et les applications intégrées, évitant ainsi une migration coûteuse des données (migration) et obligeant les utilisateurs à se déplacer vers une nouvelle adresse à chaque fois qu'il y a une mise à jour ou une correction de bug.
Quelle est la principale différence entre les commandes CALL et DELEGATECALL ? Dans la commande
CALL, le contrat cible s'exécute sur sa propre mémoire. En revanche,DELEGATECALLcharge le code du contrat cible mais s'exécute dans le "contexte" du contrat appelant, ce qui signifie qu'il utilise la mémoire, l'équilibre et préserve lemsg.senderdu contrat appelant.Pourquoi Transparent Proxy consomme-t-il plus de gaz que UUPS ? Transparent Proxy nécessite de vérifier si l'appelant est un administrateur ou non à chaque transaction pour décider de la direction de l'appel (vers l'administrateur ou vers la logique). UUPS élimine cette vérification au niveau du proxy car la logique de mise à niveau se trouve directement dans le contrat de mise en œuvre.
Comment identifier un projet à l'aide d'un proxy ? Sur Etherscan, les utilisateurs peuvent trouver le bouton « Est-ce un proxy ? » ou les onglets « Lire en tant que proxy »/« Écrire en tant que proxy ». Si tel est le cas, il s'agit bien d'un contrat d'autorisation.
Qu'est-ce que Storage Gap ? Il s'agit d'une technique consistant à placer des tableaux vides (par exemple
uint256 private __gap;) dans le contrat de base pour réserver de l'espace de stockage pour de nouvelles variables à l'avenir, empêchant ainsi la bousculade des emplacements mémoire des contrats existants.Quel est le risque de ne pas initialiser le Proxy ? Si la fonction
initializen'est pas appelée immédiatement après le déploiement, un attaquant peut appeler lui-même cette fonction pour devenir propriétaire du contrat et en prendre le contrôle total.Pourquoi les proxys ne peuvent-ils pas utiliser de constructeurs ? Parce que le code du
constructorne s'exécute qu'une seule fois à l'adresse du contrat Logic lors de son déploiement, alors que l'état réel de l'utilisateur est à l'adresse du proxy.Qu'est-ce que le conflit de sélecteur de fonction ? Il s'agit du phénomène de deux fonctions ayant des noms différents mais ayant le même identifiant de 4 octets. Les pirates peuvent en profiter pour inciter les utilisateurs à appeler une fonction métier, mais en réalité activer une fonction d'administration dangereuse.
Comment garantir la sécurité de la mise à niveau du proxy ? Le projet doit utiliser un portefeuille multi-signature (Multisig) combiné à un mécanisme Timelock (délai d'exécution) afin que la communauté ait le temps de tester le nouveau code source avant qu'il n'entre en vigueur.
Les mises à niveau du proxy peuvent-elles être désactivées ? Oui. Les développeurs peuvent effectuer une mise à niveau vers une implémentation qui ne contient pas de logique de mise à niveau ou utiliser une renonciation de l'administrateur pour faire du proxy un contrat permanent et immuable.
En quoi un proxy Beacon est-il différent d'un proxy classique ? Au lieu que chaque proxy stocke une adresse logique, ils pointent vers un contrat intermédiaire (Beacon). La mise à jour de Beacon mettra simultanément à niveau des milliers de proxys dépendants en une seule transaction.
Quel est le rôle du contrat ProxyAdmin ? Dans le modèle de proxy transparent d'OpenZeppelin,
ProxyAdminest un contrat intermédiaire qui prend possession du proxy, aidant à administrer les mises à niveau de manière sécurisée et séparément des interactions utilisateur régulières.Comment détecter les portes dérobées dans les proxys ? Les utilisateurs doivent vérifier si le code source de l'implémentation a été vérifié et utiliser des outils comme Slither pour rechercher des fonctions avec les autorisations
onlyOwnerqui peuvent retirer des fonds ou bloquer des transactions.Qu'est-ce que Flash Upgrade Attack ? Il s'agit d'une technique d'attaque lorsque les pirates mettent à niveau Proxy vers un code malveillant, volent de l'argent, puis reviennent immédiatement à l'ancienne version en une seule transaction pour effacer les traces sur la chaîne.
Comment initialiser un proxy de la manière la plus sûre ? Les développeurs doivent utiliser le processus d'initialisation atomique, ce qui signifie que le déploiement du proxy et l'appel de la fonction
initializeont lieu dans la même transaction pour éviter d'être « harcelés » par des pirates informatiques.
Le contrat de proxy est une solution technique inévitable pour le développement de l'écosystème Blockchain. Toutefois, cette flexibilité comporte également des risques si elle n’est pas gérée de manière transparente. Tan Phat Digital estime que la transparence dans la gouvernance et la prudence des utilisateurs constituent la véritable « immuabilité » que la communauté doit viser dans le monde volatile du Web3.
Partager








