Kaip nustatyti išmaniosios sutarties adresą prieš įdiegiant: naudojant CREATE2 kriptovaliutų mainams

Blockchain tema nenustoja būti ne tik įvairiausių ažiotažų, bet ir technologiniu požiūriu labai vertingų idėjų šaltiniu. Todėl neaplenkė ir saulėto miesto gyventojų. Žmonės atidžiai žiūri, studijuoja, bando perkelti savo žinias tradicinės informacijos saugumo srityje į blockchain sistemas. Kol kas tai puikiai tinka: vienas iš „Rostelecom-Solar“ patobulinimų gali patikrinti „blockchain“ programinės įrangos saugumą. O pakeliui kyla minčių sprendžiant taikomas blockchain bendruomenės problemas. Vienas iš šių gyvenimo įsilaužimų – kaip nustatyti išmaniosios sutarties adresą prieš diegiant naudojant CREATE2 – šiandien noriu pasidalinti su jumis.

Kaip nustatyti išmaniosios sutarties adresą prieš įdiegiant: naudojant CREATE2 kriptovaliutų mainams
Šių metų vasario 2 d. Konstantinopolio kietojoje šakėje buvo pridėtas CREATE28 opkodas. Kaip teigiama EIP, šis opkodas pirmiausia buvo įvestas valstybiniams kanalams. Tačiau mes jį panaudojome norėdami išspręsti kitą problemą.

Yra vartotojų, turinčių likučius biržoje. Kiekvienam vartotojui privalome suteikti Ethereum adresą, kuriuo kiekvienas galėtų siųsti žetonus ir taip papildyti savo paskyrą. Pavadinkime šiuos adresus „piniginėmis“. Kai žetonai patenka į pinigines, turime juos išsiųsti į vieną piniginę (hotwallet).

Tolesniuose skyriuose analizuoju šios problemos sprendimo būdus be CREATE2 ir pasakysiu, kodėl jų atsisakėme. Jei jus domina tik galutinis rezultatas, jį galite rasti skiltyje „Galutinis sprendimas“.

Ethereum adresai

Paprasčiausias sprendimas yra sukurti naujus Ethereum adresus naujiems vartotojams. Šie adresai bus piniginės. Norėdami perkelti žetonus iš piniginės į karštąją piniginę, turite pasirašyti operaciją paskambinę funkcijai perduoti () su privačiu piniginės raktu iš backend.

Šis metodas turi šiuos privalumus:

  • tai tiesiog
  • žetonų perkėlimo iš piniginės į karštąją piniginę kaina yra lygi funkcijos skambučio kainai perduoti ()

Tačiau nusprendėme atsisakyti šio požiūrio, nes jis turi vieną didelį trūkumą: reikia kažkur saugoti privačius raktus. Juos galima ne tik pamesti, bet ir atidžiai valdyti prieigą prie šių raktų. Jei bent vienas iš jų bus pažeistas, konkretaus vartotojo žetonai nepasieks karštosios piniginės.

Kaip nustatyti išmaniosios sutarties adresą prieš įdiegiant: naudojant CREATE2 kriptovaliutų mainams

Sukurkite atskirą išmaniąją sutartį kiekvienam vartotojui

Kiekvienam vartotojui įdiegus atskirą išmaniąją sutartį, serveryje nesaugosite privačių piniginių raktų. Birža iškvies šią išmaniąją sutartį, kad perkeltų žetonus į „hotwallet“.

Atsisakėme ir šio sprendimo, nes vartotojui negali būti parodytas piniginės adresas neįdiegus išmaniosios sutarties (tai iš tikrųjų įmanoma, tačiau gana sudėtingai su kitais trūkumais, kurių čia nekalbėsime). Biržoje vartotojas gali susikurti tiek paskyrų, kiek jam reikia, ir kiekvienai reikia savo piniginės. Tai reiškia, kad turime išleisti pinigus sutarčiai sudaryti net nebūdami tikri, kad vartotojas naudosis šia paskyra.

Opkodas CREATE2

Norėdami išspręsti ankstesnio metodo problemą, nusprendėme naudoti CREATE2 opkodą. CREATE2 leidžia iš anksto nustatyti adresą, kuriame bus įdiegta išmanioji sutartis. Adresas apskaičiuojamas pagal šią formulę:

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


kur:

  • adresas — išmaniosios sutarties, kuri skambins CREATE2, adresas
  • druska - atsitiktinė vertė
  • init_code — išmanusis sutarties baitų kodas diegimui

Taip užtikrinama, kad adresas, kurį pateikiame vartotojui, iš tikrųjų turi pageidaujamą baito kodą. Be to, ši sumanioji sutartis gali būti įdiegta, kai tik mums reikia. Pavyzdžiui, kai vartotojas nusprendžia pirmą kartą pasinaudoti savo pinigine.
Kaip nustatyti išmaniosios sutarties adresą prieš įdiegiant: naudojant CREATE2 kriptovaliutų mainams
Be to, išmaniosios sutarties adresą galite apskaičiuoti kiekvieną kartą, o ne jį saugoti, nes:

  • adresas formulėje yra pastovus, nes tai yra mūsų piniginės gamyklos adresas
  • druska - vartotojo_id maiša
  • init_code yra pastovus, nes naudojame tą pačią piniginę

Daugiau patobulinimų

Ankstesnis sprendimas vis dar turi vieną trūkumą: už išmaniosios sutarties įdiegimą reikia mokėti. Tačiau galite jo atsikratyti. Norėdami tai padaryti, galite iškviesti funkciją perduoti ()ir tada Susinaikinti() piniginės konstruktoriuje. Ir tada bus grąžintos dujos, skirtos išmaniajai kontraktai įdiegti.

Priešingai populiariems įsitikinimams, išmaniąją sutartį tuo pačiu adresu galite įdiegti kelis kartus naudodami CREATE2 operacinės sistemos kodą. Taip yra todėl, kad CREATE2 patikrina, ar tikslinio adreso nonce yra lygus nuliui (konstruktoriaus pradžioje jam priskiriama reikšmė „1“). Šiuo atveju funkcija Susinaikinti() kiekvieną kartą iš naujo nustato nonce adresus. Taigi, jei dar kartą iškviesite CREATE2 su tais pačiais argumentais, nonce patikrinimas bus atliktas.

Atkreipkite dėmesį, kad šis sprendimas yra panašus į Ethereum adreso parinktį, tačiau nereikia saugoti privačių raktų. Pinigų pervedimo iš piniginės į karštąją piniginę kaina yra maždaug lygi funkcijos iškvietimui perduoti (), nes nemokame už išmaniosios sutarties diegimą.

Paskutinis sprendimas

Kaip nustatyti išmaniosios sutarties adresą prieš įdiegiant: naudojant CREATE2 kriptovaliutų mainams

Iš pradžių parengė:

  • funkcija gauti druskos user_id
  • išmanioji sutartis, kuri iškvies CREATE2 operatyvinį kodą su atitinkama druska (t. y. piniginės gamykla)
  • piniginės baito kodas, atitinkantis sutartį su šiuo konstruktoriumi:

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


Kiekvienam naujam vartotojui apskaičiuojant parodome jo piniginės adresą

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


Kai vartotojas perkelia žetonus į atitinkamą piniginės adresą, mūsų užpakalinė programa mato Perdavimo įvykį su parametru , lygus piniginės adresui. Šiuo metu jau galima padidinti vartotojo likutį biržoje prieš įdiegiant piniginę.

Kai piniginės adresas sukaupia pakankamai žetonų, galime juos visus vienu metu perkelti į hotwallet. Norėdami tai padaryti, užpakalinė programa iškviečia išmaniųjų sutarčių gamyklos funkciją, kuri atlieka šiuos veiksmus:

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


Taigi iškviečiamas piniginės išmaniosios sutarties konstruktorius, kuris visus savo žetonus perkelia į hotwallet adresą ir tada sunaikina save.

Visą kodą galima rasti čia. Atkreipkite dėmesį, kad tai nėra mūsų gamybos kodas, nes nusprendėme optimizuoti piniginės baito kodą ir įrašėme jį opcodes.

Autorius Pavelas Kondratenkovas, Ethereum specialistas

Šaltinis: www.habr.com

Добавить комментарий