TOP
Utilisation de CREATE2 d'Ethereum - par Alice Henshaw
ACT, Blockchain, blockchain-development, capture-the-ether, ethereeum-development, Ethereum, ethereum-create2, ethereum-developers, software-development

“Utilisation de CREATE2 d'Ethereum – par Alice Henshaw”


Pour voir le contrat qui utilise CREATE2, passez à l'étape 2.

Le nouvel opcode

CREATE2

a été ajouté à la machine virtuelle Ethereum il y a près d'un an – fin février 2019. Cet opcode a introduit une deuxième méthode de calcul de l'adresse d'un nouveau contrat intelligent (auparavant uniquement

CREATE

était disponible). En utilisant

CREATE2

est certainement plus complexe que l'original

CREATE

. Vous ne pouvez plus simplement écrire

new Token()

dans Solidity, et doit à la place recourir à l'écriture en code assembleur.

pourtant

CREATE2

possède une propriété importante qui la rend préférable dans certaines situations: elle ne dépend pas de l'état actuel de l'adresse de déploiement. Cela signifie que vous pouvez être sûr que l'adresse du contrat calculée aujourd'hui serait la même que l'adresse calculée dans un an. Ceci est important car vous pouvez interagir avec l'adresse et l'envoyer ETH avant que le contrat intelligent ne lui soit déployé.

Donc, avec quelques parcours pratiques disponibles en ligne, j'ai décidé de créer ce blog explicatif simple pour expliquer:

  1. Comment
    CREATE

    et

    CREATE2

    chaque œuvre

  2. Comment utiliser
    CREATE2

    dans votre contrat intelligent, et

  3. Comment je l'ai utilisé pour résoudre l'un des Capturez l'éther défis

L'opcode CREATE.

Il s'agit de l'opcode utilisé par défaut pour déployer les contrats. L'adresse du contrat résultant est calculée en hachant:

  1. L'adresse de déploiement
  2. Le nombre de contrats qui ont déjà été déployés à partir de cette adresse – connu sous le nom de
    nonce
keccak256(rlp.encode(deployingAddress, nonce))(12:)

L'opcode CREATE2.

Cet opcode a été introduit sur Ethereum en février 2019 et est donc encore relativement nouveau. Il s'agit essentiellement d'une autre façon de déployer un contrat intelligent, mais avec une manière différente de calculer la nouvelle adresse du contrat. Il utilise:

  1. L'adresse de déploiement
  2. Le hachage du bytecode en cours de déploiement
  3. Un «sel» aléatoire (chaîne de 32 octets), fourni par le créateur.
keccak256(0xff ++ deployingAddr ++ salt ++ keccak256(bytecode))(12:)

Le défi

  1. A un
    name()

    fonction qui renvoie

    bytes32("smarx")
  2. A la chaîne
    badc0de

    quelque part dans son adresse.

Le premier est facile à mettre en œuvre. La seconde est où le défi entre en jeu, et pour le compléter, nous devons utiliser la connaissance de la façon dont Ethereum calcule les adresses des contrats – que nous venons de parcourir!

Résolvez-le avec CREATE?

Pour réussir ce défi en utilisant le

CREATE

opcode dont nous aurions besoin pour générer de nombreuses clés privées. Pour chacun d'eux, nous calculerions l'adresse Ethereum correspondante, utiliser un nonce de

0

pour calculer l'adresse du contrat résultant.

Le résoudre avec CREATE2?

En utilisant une seule adresse Ethereum, nous pouvons simplement parcourir différentes valeurs de sel jusqu'à ce que nous trouvions celle qui fonctionne. Cela semble être une bonne option pour générer potentiellement des centaines de milliers de clés privées.

Considérant que Capture l'éther a été créé en 2018,

CREATE2

n'était certainement pas la solution prévue pour le problème – mais je pense que cela semble être la meilleure option.

La solution

Utiliser

CREATE2

pour trouver une adresse contenant

badc0de

nous avons besoin:

  1. Le bytecode du contrat à déployer
  2. L'adresse de déploiement du contrat (un contrat qui utilise
    CREATE2

    )

  3. Notre sel – que nous calculerons.

Étape 1: le bytecode du contrat à déployer

La première étape consiste à obtenir le bytecode du contrat que nous voulons déployer à une adresse contenant badc0de. Le contrat à passer le défi est simple et peut être défini comme suit:
pragma solidity ^0.5.12;
contract BadCodeSmarx is IName {
   function callAuthenticate(address _challenge) public {
      FuzzyIdentityChallenge(_challenge).authenticate(); 
   }
   function name() external view returns (bytes32) {
      return bytes32("smarx");
   }
}
Courir rapidement

truffle

 compile

, le bytecode peut alors être trouvé à l'intérieur

/build/BadCodeSmarx.json

:

"bytecode": "0x608060405234801561001057600080fd5b506101468061002..."
Ou le même résultat peut être obtenu en utilisant Remix au lieu de la truffe.

Étape 2: un contrat qui utilise CREATE2

Maintenant, nous pouvons définir un contrat simple qui est fourni un sel, et utilise

CREATE2

pour déployer ce bytecode:

contract Deployer {
  bytes contractBytecode = hex"608060405234801561001057600080fd5b5061015d806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c806306fdde031461003b5780637872ab4914610059575b600080fd5b61004361009d565b6040518082815260200191505060405180910390f35b61009b6004803603602081101561006f57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506100c5565b005b60007f736d617278000000000000000000000000000000000000000000000000000000905090565b8073ffffffffffffffffffffffffffffffffffffffff1663380c7a676040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561010d57600080fd5b505af1158015610121573d6000803e3d6000fd5b505050505056fea265627a7a72315820fb2fc7a07f0eebf799c680bb1526641d2d905c19393adf340a04e48c9b527de964736f6c634300050c0032";
 
  function deploy(bytes32 salt) public {
    bytes memory bytecode = contractBytecode;
    address addr;
      
    assembly {
      addr := create2(0, add(bytecode, 0x20), mload(bytecode), salt)
    }
  }
}

Dans l'assemblage Solidity, create2 () prend 4 paramètres:

  • 1: Le montant de wei à envoyer au nouveau contrat comme
    msg.value

    . C'est 0 pour cet exemple.

  • 2–3: l'emplacement du bytecode en mémoire
  • 4: Le sel – que nous calculerons à l'étape 3. Nous le laissons comme paramètre afin qu'il puisse nous être fourni après l'avoir calculé.

Il renvoie également l'adresse du contrat créé – que vous devez saisir dans une variable que vous souhaitiez ou non l'utiliser.

Alors maintenant, ce contrat est prêt à démarrer. Je l'ai déployé sur Ropsten testnet à: 0xca4dfd86a86c48c5d9c228bedbeb7f218a29c94b. Maintenant que nous connaissons l'adresse qui déploiera notre

BadCodeSmarx

contrat, et nous avons le bytecode, tout ce que nous devons faire est de calculer un sel qui se traduira par une adresse contenant

badc0de

.

Étape 3: Calcul du sel

Pour trouver un sel qui se traduira par une adresse contenant

badc0de

, nous avons besoin d'un script simple pour parcourir chaque sel un par un et calculer l'adresse qu'il obtiendrait.

Afin de m'assurer que le script calculait correctement l'adresse résultante, j'ai déployé un contrat utilisant salt

0x00...001

. J'ai ensuite utilisé cette adresse de contrat pour m'assurer que mon script formatait et hachait correctement les paramètres – et produisait donc la même adresse que

CREATE2

fait onchain.

Pour rappel – la formule de création d'adresse est la suivante, où

(12:)

signifie que les 12 premiers octets sont supprimés pour trouver l'adresse.

keccak256(0xff ++ deployingAddr ++ salt ++ keccak256(bytecode))(12:)
Voici le script que j'ai utilisé. J'ai utilisé le package ethereumjs-util pour effectuer des hachages keccak256 – vous pouvez le trouver sur Github.
const eth = require('ethereumjs-util')

// 0xff ++ deployingAddress is fixed:
var string1 = '0xffca4dfd86a86c48c5d9c228bedbeb7f218a29c94b'

// Hash of the bytecode is fixed. Calculated with eth.keccak256():
var string2 = '4670da3f633e838c2746ca61c370ba3dbd257b86b28b78449f4185480e2aba51'

// In each loop, i is the value of the salt we are checking
for (var i = 0; i < 72057594037927936; i++) {
   // 1. Convert i to hex, and it pad to 32 bytes:
   var saltToBytes = i.toString(16).padStart(64, '0')

   // 2. Concatenate this between the other 2 strings
   var concatString = string1.concat(saltToBytes).concat(string2)
   
   // 3. Hash the resulting string
   var hashed = eth.bufferToHex(eth.keccak256(concatString))

   // 4. Remove leading 0x and 12 bytes
   // 5. Check if the result contains badc0de
   if (hashed.substr(26).includes('badc0de')) {
      console.log(saltToBytes)
      break
   }
}

En exécutant ce script, moins de 30 secondes plus tard, mon sel résultant a sauté:

0x00000000000000000000000000000000000000000000000000000000005b2bfe
Ensuite, tout ce que j'avais à faire était d'exécuter

Deployer.deploy(0x00...005b2bfe)

. Voici un exemple de

BadCodeSmarx

a été déployé à:

0xa905a3922a4ebfbc7d257cecdb1df04a3badc0de

Les références:

  1. EIP1014 – Skinny CREATE2
  2. Capturez l'éther – Identité floue
  3. Truffe
  4. ethereumjs-util



https://hackernoon.com/using-ethereums-create2-nw2137q7?source=rss

« Nous piétinerons éternellement aux frontières de l’Inconnu, cherchant à comprendre ce qui restera toujours incompréhensible. Et c’est précisément cela qui fait de nous des hommes. », Isaac Asimov
Faire un Don Bitcoin :
1Jn3fBqyXoBDFA2jR3azquTqSasRuKH7VT

«

»