Kako odrediti adresu pametnog ugovora prije implementacije: korištenje CREATE2 za razmjenu kriptovaluta

Tema blockchaina nikada ne prestaje biti izvor ne samo svih vrsta hypea, već i ideja koje su vrlo vrijedne sa tehnološke tačke gledišta. Stoga nije zaobišao ni stanovnike sunčanog grada. Ljudi pažljivo promatraju, proučavaju, pokušavaju prenijeti svoju stručnost u tradicionalnoj informacijskoj sigurnosti na blockchain sisteme. Za sada je to na licu mjesta: jedan od razvoja Rostelecom-Solar-a može provjeriti sigurnost softvera zasnovanog na blockchain-u. I usput se javljaju neka razmišljanja o rješavanju primijenjenih problema blockchain zajednice. Jedan od ovih životnih hakova - kako odrediti adresu pametnog ugovora prije implementacije pomoću CREATE2 - danas želim podijeliti s vama ispod reza.

Kako odrediti adresu pametnog ugovora prije implementacije: korištenje CREATE2 za razmjenu kriptovaluta
CREATE2 opcode je dodat u Constantinopol hard fork 28. februara ove godine. Kako je navedeno u EIP-u, ovaj opkod je uveden prvenstveno za državne kanale. Međutim, koristili smo ga da riješimo drugačiji problem.

Postoje korisnici sa stanjem na berzi. Svakom korisniku moramo dati Ethereum adresu na koju svako može slati tokene i na taj način dopuniti svoj račun. Nazovimo ove adrese "novčanici". Kada tokeni stignu u novčanike, moramo ih poslati u jedan novčanik (hotwallet).

U sljedećim odjeljcima analiziram opcije za rješavanje ovog problema bez CREATE2 i govorim vam zašto smo ih napustili. Ako vas zanima samo konačni rezultat, možete ga pronaći u odjeljku “Konačno rješenje”.

Ethereum adrese

Najjednostavnije rješenje je generiranje novih Ethereum adresa za nove korisnike. Ove adrese će biti novčanici. Za prijenos tokena iz novčanika u hotwallet, trebate potpisati transakciju pozivanjem funkcije transfer() sa privatnim ključem novčanika iz backenda.

Ovaj pristup ima sljedeće prednosti:

  • to je jednostavno
  • cijena prijenosa tokena iz novčanika u hotwallet jednaka je cijeni poziva funkcije transfer()

Međutim, odlučili smo se protiv ovog pristupa jer ima jedan veliki nedostatak: morate negdje pohraniti privatne ključeve. Ne samo da se mogu izgubiti, već morate pažljivo upravljati pristupom ovim ključevima. Ako je barem jedan od njih ugrožen, tokeni određenog korisnika neće doći do vrućeg novčanika.

Kako odrediti adresu pametnog ugovora prije implementacije: korištenje CREATE2 za razmjenu kriptovaluta

Napravite poseban pametni ugovor za svakog korisnika

Uvođenje zasebnog pametnog ugovora za svakog korisnika omogućava vam da izbjegnete pohranjivanje privatnih ključeva za novčanike na serveru. Burza će pozvati ovaj pametni ugovor za prijenos tokena na hotwallet.

Odustali smo i od ovog rješenja, jer korisniku ne može biti prikazana njegova adresa novčanika bez implementacije pametnog ugovora (to je zapravo moguće, ali na prilično složen način s drugim nedostacima o kojima ovdje nećemo govoriti). Na berzi korisnik može kreirati onoliko računa koliko mu je potrebno, a svaki od njih treba svoj novčanik. To znači da trebamo potrošiti novac na implementaciju ugovora, a da nismo ni sigurni da će korisnik koristiti ovaj račun.

Opcode CREATE2

Kako bismo riješili problem prethodne metode, odlučili smo koristiti CREATE2 opcode. CREATE2 vam omogućava da unaprijed odredite adresu na kojoj će pametni ugovor biti raspoređen. Adresa se izračunava pomoću sljedeće formule:

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


gdje:

  • adresa — adresa pametnog ugovora koji će zvati CREATE2
  • sol - slučajna vrijednost
  • init_code — bajt kod pametnog ugovora za implementaciju

Ovo osigurava da adresa koju dajemo korisniku zapravo sadrži željeni bajt kod. Štaviše, ovaj pametni ugovor se može primijeniti kad god nam zatreba. Na primjer, kada korisnik odluči da koristi svoj novčanik po prvi put.
Kako odrediti adresu pametnog ugovora prije implementacije: korištenje CREATE2 za razmjenu kriptovaluta
Štaviše, možete izračunati adresu pametnog ugovora svaki put umjesto da je pohranjujete jer:

  • adresa u formuli je konstantna, pošto je ovo adresa naše fabrike novčanika
  • sol — hash user_id
  • init_code je konstantan jer koristimo isti novčanik

Više poboljšanja

Prethodno rješenje još uvijek ima jedan nedostatak: morate platiti za implementaciju pametnog ugovora. Međutim, možete ga se riješiti. Da biste to učinili, možete pozvati funkciju transfer(), i onda samouništenje() u konstruktoru novčanika. A onda će gas za implementaciju pametnog ugovora biti vraćen.

Suprotno uvriježenom mišljenju, pametni ugovor možete implementirati na istu adresu više puta pomoću CREATE2 opcode-a. To je zato što CREATE2 provjerava da je nonce ciljne adrese nula (dodijeljena mu je vrijednost "1" na početku konstruktora). U ovom slučaju, funkcija samouništenje() resetuje nonce adrese svaki put. Dakle, ako ponovo pozovete CREATE2 sa istim argumentima, provjera nonce će proći.

Imajte na umu da je ovo rješenje slično opciji Ethereum adrese, ali bez potrebe za pohranjivanjem privatnih ključeva. Cijena prijenosa novca iz novčanika u hotwallet je približno jednaka cijeni pozivanja funkcije transfer(), budući da ne plaćamo implementaciju pametnog ugovora.

Konačna odluka

Kako odrediti adresu pametnog ugovora prije implementacije: korištenje CREATE2 za razmjenu kriptovaluta

Originalno pripremio:

  • funkcija dobivanja soli user_id
  • pametni ugovor koji će pozvati CREATE2 opcode s odgovarajućom soli (tj. tvornica novčanika)
  • bajt kod novčanika koji odgovara ugovoru sa sljedećim konstruktorom:

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


Za svakog novog korisnika prikazujemo njegovu/njenu adresu novčanika izračunavanjem

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


Kada korisnik prenese tokene na odgovarajuću adresu novčanika, naš backend vidi Transfer događaj s parametrom _to, jednako adresi novčanika. U ovom trenutku, već je moguće povećati saldo korisnika na berzi prije raspoređivanja novčanika.

Kada adresa novčanika akumulira dovoljan broj tokena, možemo ih sve odjednom prenijeti na hotwallet. Da bi to učinio, backend poziva funkciju tvornice pametnih ugovora, koja izvodi sljedeće radnje:

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


Tako se poziva konstruktor pametnog ugovora novčanika, koji prenosi sve svoje tokene na hotwallet adresu i zatim se samouništava.

Cijeli kod možete pronaći ovdje. Imajte na umu da ovo nije naš proizvodni kod, jer smo odlučili da optimiziramo bajt kod novčanika i zapisali ga u kodovima operacija.

Autor Pavel Kondratenkov, stručnjak za Ethereum

izvor: www.habr.com

Dodajte komentar