Hvordan bestemme adressen til en smart kontrakt før distribusjon: bruk CREATE2 for en kryptoutveksling

Temaet blokkjede slutter aldri å være en kilde til ikke bare all slags hype, men også ideer som er svært verdifulle fra et teknologisk synspunkt. Derfor gikk den ikke utenom innbyggerne i den solfylte byen. Folk ser nøye etter, studerer, prøver å overføre sin ekspertise innen tradisjonell informasjonssikkerhet til blokkjedesystemer. Så langt er det spot on: en av Rostelecom-Solars utviklinger kan sjekke sikkerheten til blockchain-basert programvare. Og underveis dukker det opp noen tanker om å løse anvendte problemer i blockchain-fellesskapet. En av disse life hacks - hvordan bestemme adressen til en smart kontrakt før distribusjon ved hjelp av CREATE2 - i dag vil jeg dele med deg under snittet.

Hvordan bestemme adressen til en smart kontrakt før distribusjon: bruk CREATE2 for en kryptoutveksling
CREATE2-opkoden ble lagt til i Konstantinopel-hardgaffelen 28. februar i år. Som det fremgår av EIP, ble denne opkoden introdusert primært for statlige kanaler. Vi brukte den imidlertid til å løse et annet problem.

Det er brukere med saldo på børsen. Vi må gi hver bruker en Ethereum-adresse som alle kan sende tokens til, og dermed fylle opp kontoen deres. La oss kalle disse adressene "lommebøker". Når tokens kommer i lommebøker, må vi sende dem til én enkelt lommebok (hotwallet).

I de følgende delene analyserer jeg alternativer for å løse dette problemet uten CREATE2 og forteller deg hvorfor vi forlot dem. Hvis du bare er interessert i det endelige resultatet, kan du finne det i delen "Endelig løsning".

Ethereum-adresser

Den enkleste løsningen er å generere nye Ethereum-adresser for nye brukere. Disse adressene vil være lommebøker. For å overføre tokens fra en lommebok til hotwallet, må du signere transaksjonen ved å ringe funksjonen overføre() med den private nøkkelen til lommeboken fra backend.

Denne tilnærmingen har følgende fordeler:

  • det er enkelt
  • kostnaden for å overføre tokens fra en lommebok til hotwallet er lik kostnaden for et funksjonsanrop overføre()

Vi bestemte oss imidlertid for denne tilnærmingen fordi den har en stor ulempe: du må lagre de private nøklene et sted. Ikke bare kan de gå tapt, men du må også nøye administrere tilgangen til disse nøklene. Hvis minst en av dem er kompromittert, vil ikke tokenene til en bestemt bruker nå den varme lommeboken.

Hvordan bestemme adressen til en smart kontrakt før distribusjon: bruk CREATE2 for en kryptoutveksling

Opprett en egen smartkontrakt for hver bruker

Ved å distribuere en egen smart kontrakt for hver bruker kan du unngå å lagre private nøkler for lommebøker på serveren. Børsen vil kalle denne smarte kontrakten for å overføre tokens til hotwallet.

Vi forlot også denne løsningen, siden brukeren ikke kan vises lommebokadressen sin uten å implementere en smart kontrakt (dette er faktisk mulig, men på en ganske kompleks måte med andre ulemper som vi ikke vil diskutere her). På børsen kan en bruker opprette så mange kontoer han trenger, og hver enkelt trenger sin egen lommebok. Dette betyr at vi må bruke penger på å distribuere en kontrakt uten engang å være sikre på at brukeren vil bruke denne kontoen.

Opcode CREATE2

For å fikse problemet med den forrige metoden, bestemte vi oss for å bruke CREATE2-opkoden. CREATE2 lar deg forhåndsbestemme adressen der smartkontrakten skal distribueres. Adressen beregnes ved hjelp av følgende formel:

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


, hvor:

  • adresse — adressen til den smarte kontrakten som vil kalle CREATE2
  • salt - tilfeldig verdi
  • init_code — smart kontraktbytekode for distribusjon

Dette sikrer at adressen vi oppgir til brukeren faktisk inneholder den ønskede bytekoden. Dessuten kan denne smarte kontrakten distribueres når vi trenger det. For eksempel når en bruker bestemmer seg for å bruke lommeboken for første gang.
Hvordan bestemme adressen til en smart kontrakt før distribusjon: bruk CREATE2 for en kryptoutveksling
Dessuten kan du beregne smartkontraktsadressen hver gang i stedet for å lagre den fordi:

  • adresse i formelen er konstant, siden dette er adressen til vår lommebokfabrikk
  • salt — user_id hash
  • init_code er konstant siden vi bruker samme lommebok

Flere forbedringer

Den forrige løsningen har fortsatt én ulempe: du må betale for å distribuere den smarte kontrakten. Du kan imidlertid bli kvitt det. For å gjøre dette kan du kalle opp funksjonen overføre(), og så selvdestruksjon() i lommebokkonstruktøren. Og da vil gassen for utplassering av smartkontrakten bli returnert.

I motsetning til hva mange tror, ​​kan du distribuere en smart kontrakt til samme adresse flere ganger med CREATE2-opkoden. Dette er fordi CREATE2 sjekker at nonce av måladressen er null (den er tildelt verdien "1" i begynnelsen av konstruktøren). I dette tilfellet, funksjonen selvdestruksjon() tilbakestiller nonce-adresser hver gang. Så hvis du kaller CREATE2 igjen med de samme argumentene, vil nonce-kontrollen passere.

Vær oppmerksom på at denne løsningen ligner på Ethereum-adressealternativet, men uten behov for å lagre private nøkler. Kostnaden for å overføre penger fra en lommebok til en hotwallet er omtrent lik kostnaden for å ringe en funksjon overføre(), siden vi ikke betaler for smart kontraktsimplementering.

Siste avgjørelse

Hvordan bestemme adressen til en smart kontrakt før distribusjon: bruk CREATE2 for en kryptoutveksling

Opprinnelig utarbeidet av:

  • funksjon for å få salt ved user_id
  • en smart kontrakt som kaller CREATE2-opkoden med riktig salt (dvs. lommebokfabrikken)
  • lommebokbytekode som tilsvarer 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 bruker viser vi hans/hennes lommebokadresse ved beregning

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


Når en bruker overfører tokens til den tilsvarende lommebokadressen, ser vår backend en overføringshendelse med parameteren _til, lik lommebokadressen. På dette tidspunktet er det allerede mulig å øke brukerens saldo på børsen før du distribuerer lommeboken.

Når en lommebokadresse akkumulerer et tilstrekkelig antall tokens, kan vi overføre dem alle samtidig til hotwallet. For å gjøre dette kaller backend funksjonen smart kontrakt fabrikk, som utfører følgende handlinger:

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


Dermed kalles wallet smart contract constructor, som overfører alle sine tokens til hotwallet-adressen og deretter selvdestruerer.

Du finner hele koden her. Vær oppmerksom på at dette ikke er produksjonskoden vår, siden vi bestemte oss for å optimalisere lommebokbytekoden og skrev den i opkoder.

Forfatter Pavel Kondratenkov, Ethereum-spesialist

Kilde: www.habr.com

Legg til en kommentar