Sådan bestemmes adressen på en smart kontrakt før implementering: Brug CREATE2 til en kryptoudveksling

Emnet om blockchain ophører ikke med at være en kilde til ikke kun alle former for hype, men også meget værdifulde ideer fra et teknologisk synspunkt. Derfor gik hun ikke uden om indbyggerne i den solrige by. Folk kigger godt efter, studerer, forsøger at flytte deres ekspertise i den traditionelle infobase til blockchain-systemer. Indtil videre, pointwise: en af ​​udviklingerne af Rostelecom-Solar er i stand til at kontrollere sikkerheden af ​​software baseret på blockchain. Og undervejs opstår der nogle tanker om at løse anvendte problemer i blockchain-fællesskabet. Et af disse life hacks - hvordan man bestemmer adressen på en smart kontrakt før implementering ved hjælp af CREATE2 - i dag vil jeg dele med dig under klippet.

Sådan bestemmes adressen på en smart kontrakt før implementering: Brug CREATE2 til en kryptoudveksling
CREATE2-opkoden blev tilføjet i Konstantinopels hårde gaffel den 28. februar i år. Som anført i EIP blev denne opcode primært indført for statslige kanaler. Vi brugte det dog til at løse et andet problem.

Der er brugere med saldi på børsen. Vi skal give hver bruger en Ethereum-adresse, som alle kan sende tokens til, og derved genopfylde deres konto. Lad os kalde disse adresser "punge". Når tokens ankommer i tegnebøger, skal vi sende dem til en enkelt tegnebog (hotwallet).

I de følgende afsnit analyserer jeg muligheder for at løse dette problem uden CREATE2 og forklarer, hvorfor vi opgav dem. Hvis du kun er interesseret i det endelige resultat, kan du finde det i afsnittet Endelig løsning.

Ethereum adresser

Den enkleste løsning er at generere nye ethereum-adresser til nye brugere. Disse adresser vil være tegnebøgerne. For at overføre tokens fra tegnebogen til hotwallet, skal du underskrive transaktionen ved at kalde funktionen overførsel() med pungens private nøgle fra backend.

Denne tilgang har følgende fordele:

  • det er simpelt
  • omkostningerne ved at overføre tokens fra wallet til hotwallet er lig med omkostningerne ved at kalde funktionen overførsel()

Vi opgav dog denne tilgang, fordi den har en væsentlig ulempe: du skal gemme private nøgler et sted. Og det er ikke kun, at de kan gå tabt, men også, at du skal omhyggeligt administrere adgangen til disse nøgler. Hvis mindst en af ​​dem er kompromitteret, vil en bestemt brugers tokens ikke nå den varme pung.

Sådan bestemmes adressen på en smart kontrakt før implementering: Brug CREATE2 til en kryptoudveksling

Opret en separat smart kontrakt for hver bruger

Ved at implementere en separat smart kontrakt for hver bruger kan du ikke gemme private nøgler fra tegnebøger på serveren. Børsen vil kalde denne smarte kontrakt for at overføre tokens til hotwallet.

Vi har også opgivet denne løsning, da brugeren ikke kan få vist sin tegnebogsadresse uden at implementere en smart kontrakt (dette er faktisk muligt, men på en ret kompliceret måde med andre ulemper, som vi ikke vil diskutere her). På børsen kan brugeren oprette lige så mange konti, han har brug for, og alle har brug for deres egen pung. Det betyder, at vi skal bruge penge på at implementere en kontrakt uden selv at være sikre på, at brugeren vil bruge denne konto.

Opcode CREATE2

For at løse problemet med den tidligere metode besluttede vi at bruge CREATE2-opkoden. CREATE2 giver dig mulighed for at forudbestemme adressen, hvor den smarte kontrakt vil blive implementeret. Adressen beregnes ved hjælp af følgende formel:

keccak256 (0xff ++ address ++ salt ++ keccak256 (init_code)) [12:]


, Hvor:

  • adresse — adressen på den smarte kontrakt, der kalder CREATE2
  • salt - tilfældig værdi
  • init_code - smart kontrakt bytekode til implementering

Dette sikrer, at den adresse, vi giver brugeren, faktisk vil indeholde den ønskede bytekode. Denne smarte kontrakt kan også implementeres, når vi har brug for det. For eksempel når en bruger beslutter sig for at bruge sin tegnebog for første gang.
Sådan bestemmes adressen på en smart kontrakt før implementering: Brug CREATE2 til en kryptoudveksling
Desuden kan du beregne den smarte kontraktadresse hver gang i stedet for at gemme den, fordi:

  • adresse i formlen er konstant, da det er adressen på vores tegnebogsfabrik
  • salt - user_id hash
  • init_code er permanent, da vi bruger den samme pung

Flere forbedringer

Den tidligere løsning har stadig én ulempe: du skal betale for smart kontraktimplementering. Du kan dog slippe af med det. Til dette kan du kalde funktionen overførsel()og derefter selvdestruere() i tegnebogskonstruktøren. Og så vil gassen til at implementere den smarte kontrakt blive returneret.

I modsætning til hvad mange tror, ​​kan du implementere en smart kontrakt til den samme adresse flere gange med CREATE2-opkoden. Dette skyldes, at CREATE2 kontrollerer, at måladressens nonce er nul (den er tildelt værdien "1" i begyndelsen af ​​konstruktøren). Samtidig er funktionen selvdestruere() nulstiller nonce-adressen hver gang. Hvis du kalder CREATE2 igen med de samme argumenter, vil nonce-kontrollen bestå.

Bemærk venligst, at denne løsning ligner ethereum-adresseløsningen, men uden behov for at gemme private nøgler. Omkostningerne ved at overføre penge fra en tegnebog til en hotwallet er omtrent lig med omkostningerne ved at ringe til en funktion overførsel(), da vi ikke betaler for implementeringen af ​​den smarte kontrakt.

Endelige beslutning

Sådan bestemmes adressen på en smart kontrakt før implementering: Brug CREATE2 til en kryptoudveksling

Oprindeligt forberedt:

  • funktion at få salt ved user_id
  • smart kontrakt, der kalder CREATE2-opkoden med det passende salt (dvs. tegnebogsfabrikken)
  • tegnebogsbytekode svarende til kontrakten med følgende konstruktør:

constructor () {
    address hotWallet = 0x…;
    address token = 0x…;
    token.transfer (hotWallet, token.balanceOf (address (this)));
    selfdestruct (address (0));
}


For hver ny bruger viser vi hans/hendes tegnebogsadresse ved at beregne

keccak256 (0xff ++ address ++ salt ++ keccak256 (init_code)) [12:]


Når brugeren overfører tokens til den tilsvarende wallet-adresse, ser vores backend overførselshændelsen med parameteren _tillig med tegnebogens adresse. På dette tidspunkt er det allerede muligt at øge brugerens saldo på børsen, før tegnebogen implementeres.

Når der akkumuleres nok tokens i wallet-adressen, kan vi overføre dem alle på én gang til hotwallet. For at gøre dette kalder backend den smarte kontraktfabriksfunktion, som udfører følgende handlinger:

function deployWallet (соль uint256) {
    bytes memory walletBytecode =…;
    // invoke CREATE2 with wallet bytecode and salt
}


Således kaldes wallet smart contract constructor, som overfører alle sine tokens til hotwallet-adressen og derefter selvdestruerer.

Den komplette kode kan findes her. Bemærk venligst, at dette ikke er vores produktionskode, da vi besluttede at optimere wallet-bytekoden og skrive den i opcodes.

Forfatter Pavel Kondratenkov, Ethereum-specialist

Kilde: www.habr.com

Tilføj en kommentar