Définition
delegatecall : définition
delegatecall est une instruction de l'EVM qui permet à un smart contract d'exécuter le code d'un autre contrat dans son propre contexte : le stockage, le solde et l'expéditeur d'origine (msg.sender) restent ceux du contrat appelant.
Thème : Ethereum et smart contracts
Lors d'un appel classique (CALL), le contrat cible s'exécute avec son propre stockage, et l'appelant devient le msg.sender. Avec delegatecall, le code du contrat cible est emprunté mais exécuté comme s'il appartenait à l'appelant : les lectures et écritures portent sur le stockage de l'appelant, msg.sender et msg.value restent ceux de l'appel d'origine, et aucun ETH n'est transféré vers le contrat cible. Cela revient à charger une bibliothèque de code à la volée, qui agit sur les données de celui qui l'appelle.
Cette instruction est la base des contrats proxy évolutifs. Le proxy conserve les données et l'adresse publique, et transmet chaque appel par delegatecall à un contrat de logique ; pour mettre à jour le protocole, il suffit de pointer vers une nouvelle logique. Les clones minimaux de l'EIP-1167 et le modèle Diamond de l'EIP-2535 l'utilisent aussi. La difficulté tient à la disposition du stockage : les variables sont repérées par leur position, appelée slot, et si la logique et le proxy n'utilisent pas exactement la même organisation, les données sont écrasées ou mal interprétées. Des standards comme l'EIP-1967 réservent des slots dédiés pour éviter ces collisions.
Un exemple concret
Imaginons un portefeuille intelligent dont la logique est partagée dans un contrat bibliothèque. Lorsque Zoé appelle la fonction de transfert de son portefeuille, celui-ci fait un delegatecall vers la bibliothèque. Le code s'exécute, mais ce sont bien le solde et le stockage du portefeuille de Zoé qui sont modifiés, et non ceux de la bibliothèque, qui ne détient rien.
Les risques à connaître
Un delegatecall vers une adresse non fiable donne à ce code un contrôle total sur le stockage et les fonds du contrat appelant. Les collisions de stockage entre proxy et logique ont causé de nombreux bugs. Les incidents du portefeuille multisig Parity en 2017, un vol puis un gel massif de fonds, impliquaient un contrat bibliothèque utilisé via delegatecall.
Questions fréquentes sur delegatecall
Quelle est la différence entre call et delegatecall ?
Avec call, le contrat cible s'exécute avec son propre stockage et voit l'appelant comme expéditeur. Avec delegatecall, le code cible s'exécute dans le stockage de l'appelant et conserve l'expéditeur et la valeur de l'appel d'origine.
Pourquoi delegatecall est-il considéré comme dangereux ?
Parce qu'il donne au code appelé un accès complet au stockage du contrat appelant. Une adresse cible mal contrôlée ou une incompatibilité de stockage peut permettre de prendre le contrôle du contrat ou de corrompre ses données.