Comment éviter d’utiliser tx.origin quand on en a vraiment besoin?

Aydin.

Comment éviter d’utiliser tx.origin quand on en a vraiment besoin?


Il a été recommandé d’ éviter d’utiliser tx.origin.

Cependant, il y a des cas où c’est vraiment nécessaire, comme le cas suivant.


Supposons que nous ayons deux contrats intelligents: Sc1 et Sc2, tous deux créés par le même propriétaire . Il déploie d’abord Sc1 qui maintient un équilibre de jetons. Ensuite, le propriétaire crée un autre contrat intelligent Sc2, le déploie et permet aux utilisateurs d’interagir avec Sc2 et de transférer certains de leurs jetons de Sc1 à Sc2 (supposez donc que certains utilisateurs ont des jetons dans Sc1). Mais seuls les propriétaires de jetons devraient pouvoir le faire, personne d’autre (pas même le propriétaire des contrats).

Comme vous pouvez le voir ci-dessous, je dois utiliser tx.origin. Je suis conscient que si le propriétaire des contrats crée un autre contrat non valide et que l’utilisateur (les propriétaires de jetons) l’appelle, il pourra décrémenter leur token_bsalance dans Sc1. Ci-dessous le code du cas ci-dessus (l’attaque est exclue).

  contract Sc1{ mapping (address => uint) token_balance; mapping (address => bool) valid_caller_contracts;// keeps track //of those contract that can call this contract address owner; function Sc1(){ owner = msg.sender; } // only owner must be able to register. function register_valid_contract() external { require(tx.origin==owner); valid_caller_contracts[msg.sender] = true; } function decrement_token(uint val) external{ require(token_balance[tx.origin] >= val); token_balance[tx.origin] -=val; } } contract Sc2{ mapping (address => uint) token_balance2; address owner; function SC2(){ owner = msg.sender; } function register() external{ Sc1 c1=Sc1(0x22);//Let's assum the address of Sc1 after it's //deployed is 0x22 c1.register_valid_contract(); } // only those who have tokens in Sc1 must be able to tranfer //tokens to Sc2. function fetch_tokens(uint val) external{ Sc1 c1=Sc1(0x22);//Let's assum the address of Sc1 after it's //deployed is 0x22 c1.decrement_token(val); token_balance2[msg.sender] += val; } } 

Question : Dans le cas ci-dessus, pouvons-nous éviter d’utiliser tx.origin?

Réponses


 Ismael

Un problème sérieux pour un contrat dépendant de tx.origin est que votre contrat ne fonctionnera pas correctement avec les portefeuilles multisig (ou tout autre contrat intelligent).

Une solution au problème avec register_valid_contract consiste à passer l’adresse du contrat en paramètre et le propriétaire doit appeler la fonction comme étape supplémentaire.

 function register_valid_contract(address sc2) external { require(msg.sender == owner); valid_caller_contracts[sc2] = true; } 

Une autre approche est que SC1 utilise des patrons d’usine pour créer SC2 et il les enregistrera immédiatement à la création.


Pour decrement_token, vous pouvez passer msg.sender en paramètre, mais vous devez vous assurer que l’expéditeur est un contrat valide.

 function decrement_token(address from, uint val) external{ require(valid_caller_contracts[msg.sender]); require(token_balance[from] >= val); token_balance[from] -=val; } 

Dans cet exemple, si vous définissez la relation d’approbation entre SC1 et SC2, par exemple si SC1 crée SC2, alors SC1 peut vérifier que l’adresse de l’expéditeur est SC2 et faire confiance aux paramètres seront corrects.

Aydin.

Merci beaucoup pour la réponse. Je voulais juste mentionner que dans votre solution proposée (même si elle est correcte) les parties doivent interagir directement avec SC1, alors que je me demandais si cela pouvait se faire via SC2. Merci encore!

Ismael

Le problème est que vous devez appeler SC1 depuis SC2, et SC1 ne sait rien de SC2 (il peut s’agir d’un attaquant). Une solution est que le propriétaire envoie une signature avec le message, SC1 peut récupérer les adresses avec ECRECOVER et le valider auprès du propriétaire. Une autre solution est d’avoir un troisième contrat pour créer à la fois SC1 et SC2 et les enregistrer mutuellement à la création.

Aydin.

Merci pour votre commentaire. Concernant la première solution (si vous vouliez dire que l’expéditeur envoie un message et sa signature à SC2, alors SC1 et SC2 vérifient la signature), ne pensez-vous pas qu’il y aura une attaque de relecture? Parce que le message et la signature de l’expéditeur peuvent être copiés et envoyés à partir d’un autre contrat vers SC1.Dans ce cas, SC1 le valide toujours.

Ismael

Vous pouvez inclure plus d’informations dans la signature, l’adresse de SC2, un horodatage, afin que SC1 puisse vérifier que SC2 est l’appelant et que la date de signature est proche de la transaction.

 

‘tx.origin’?, #à, #en, Besoin, comment, d’utiliser, éviter, On, quand, vraiment

 

yahoo

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *