Si të përcaktoni adresën e një kontrate inteligjente përpara vendosjes: duke përdorur CREATE2 për një shkëmbim kripto

Tema e blockchain nuk pushon kurrë së qeni një burim jo vetëm i të gjitha llojeve të reklamave, por edhe ideve që janë shumë të vlefshme nga pikëpamja teknologjike. Prandaj, nuk i ka anashkaluar banorët e qytetit me diell. Njerëzit po shikojnë nga afër, studiojnë, përpiqen të transferojnë ekspertizën e tyre në sigurinë tradicionale të informacionit në sistemet blockchain. Deri më tani, është në vend: një nga zhvillimet e Rostelecom-Solar mund të kontrollojë sigurinë e softuerit të bazuar në blockchain. Dhe gjatë rrugës, lindin disa mendime për zgjidhjen e problemeve të aplikuara të komunitetit të blockchain. Një nga këto mashtrime të jetës - si të përcaktohet adresa e një kontrate inteligjente përpara vendosjes duke përdorur CREATE2 - sot dua të ndaj me ju nën prerje.

Si të përcaktoni adresën e një kontrate inteligjente përpara vendosjes: duke përdorur CREATE2 për një shkëmbim kripto
Opcode CREATE2 u shtua në hard fork-in e Kostandinopojës më 28 shkurt të këtij viti. Siç thuhet në EIP, ky kod optik u prezantua kryesisht për kanalet shtetërore. Megjithatë, ne e përdorëm atë për të zgjidhur një problem tjetër.

Ka përdorues me bilanc në bursë. Ne duhet t'i sigurojmë çdo përdoruesi një adresë Ethereum në të cilën çdokush mund të dërgojë argumente, duke rimbushur kështu llogarinë e tij. Le t'i quajmë këto adresa "portofol". Kur argumentet mbërrijnë në portofol, ne duhet t'i dërgojmë ato në një portofol të vetëm (hotwallet).

Në seksionet e mëposhtme, unë analizoj opsionet për zgjidhjen e këtij problemi pa CREATE2 dhe ju them pse i braktisëm ato. Nëse jeni të interesuar vetëm për rezultatin përfundimtar, mund ta gjeni në seksionin "Zgjidhja përfundimtare".

Adresat e Ethereum

Zgjidhja më e thjeshtë është krijimi i adresave të reja Ethereum për përdoruesit e rinj. Këto adresa do të jenë kuletat. Për të transferuar argumentet nga një portofol në portofolin e nxehtë, duhet të nënshkruani transaksionin duke thirrur funksionin transferimi () me çelësin privat të portofolit nga pjesa e pasme.

Kjo qasje ka përparësitë e mëposhtme:

  • është e drejtë
  • kostoja e transferimit të argumenteve nga një portofol në portofolin e nxehtë është e barabartë me koston e një thirrjeje funksioni transferimi ()

Megjithatë, ne vendosëm kundër kësaj qasjeje, sepse ajo ka një pengesë të madhe: ju duhet të ruani çelësat privatë diku. Jo vetëm që mund të humbasin, por gjithashtu duhet të menaxhoni me kujdes aksesin në këta çelësa. Nëse të paktën njëri prej tyre është i rrezikuar, atëherë argumentet e një përdoruesi të caktuar nuk do të arrijnë në portofolin e nxehtë.

Si të përcaktoni adresën e një kontrate inteligjente përpara vendosjes: duke përdorur CREATE2 për një shkëmbim kripto

Krijo një kontratë të veçantë inteligjente për çdo përdorues

Vendosja e një kontrate të veçantë inteligjente për çdo përdorues ju lejon të shmangni ruajtjen e çelësave privatë për kuletat në server. Shkëmbimi do ta thërrasë këtë kontratë inteligjente për të transferuar argumentet në portofolin e nxehtë.

Ne gjithashtu e braktisëm këtë zgjidhje, pasi përdoruesit nuk mund t'i tregohet adresa e portofolit të tij pa vendosur një kontratë inteligjente (kjo është në të vërtetë e mundur, por në një mënyrë mjaft komplekse me disavantazhe të tjera që nuk do t'i diskutojmë këtu). Në shkëmbim, një përdorues mund të krijojë aq llogari sa i nevojiten, dhe secili ka nevojë për portofolin e vet. Kjo do të thotë që ne duhet të shpenzojmë para për vendosjen e një kontrate pa qenë as të sigurt që përdoruesi do ta përdorë këtë llogari.

Opcode CREATE2

Për të zgjidhur problemin e metodës së mëparshme, vendosëm të përdorim kodin CREATE2. CREATE2 ju lejon të paracaktoni adresën ku do të vendoset kontrata inteligjente. Adresa llogaritet duke përdorur formulën e mëposhtme:

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


, ku:

  • adresë — adresa e kontratës inteligjente që do të thërrasë CREATE2
  • kripë - vlera e rastësishme
  • kodi_init — bytekodi i kontratës inteligjente për vendosje

Kjo siguron që adresa që ne i ofrojmë përdoruesit të përmbajë në të vërtetë bajtkodin e dëshiruar. Për më tepër, kjo kontratë inteligjente mund të vendoset sa herë që na nevojitet. Për shembull, kur një përdorues vendos të përdorë portofolin e tij për herë të parë.
Si të përcaktoni adresën e një kontrate inteligjente përpara vendosjes: duke përdorur CREATE2 për një shkëmbim kripto
Për më tepër, ju mund të llogarisni adresën e kontratës inteligjente çdo herë në vend që ta ruani atë sepse:

  • adresë në formulë është konstante, pasi kjo është adresa e fabrikës sonë të portofolit
  • kripë — hash user_id
  • kodi_init është konstante pasi përdorim të njëjtin portofol

Më shumë përmirësime

Zgjidhja e mëparshme ka ende një pengesë: duhet të paguani për të vendosur kontratën inteligjente. Megjithatë, ju mund të shpëtoni prej tij. Për ta bërë këtë, mund të telefononi funksionin transferimi (), dhe pastaj vetëshkatërrohen () në konstruktorin e portofolit. Dhe pastaj gazi për vendosjen e kontratës inteligjente do të kthehet.

Në kundërshtim me besimin popullor, ju mund të vendosni një kontratë inteligjente në të njëjtën adresë disa herë me kodin optik CREATE2. Kjo është për shkak se CREATE2 kontrollon që nonce e adresës së synuar është zero (i është caktuar vlera "1" në fillim të konstruktorit). Në këtë rast, funksioni vetëshkatërrohen () rivendos adresat nonce çdo herë. Pra, nëse thërrisni përsëri CREATE2 me të njëjtat argumente, kontrolli nonce do të kalojë.

Ju lutemi vini re se kjo zgjidhje është e ngjashme me opsionin e adresës Ethereum, por pa pasur nevojë të ruani çelësat privatë. Kostoja e transferimit të parave nga një portofol në portofolin e nxehtë është afërsisht e barabartë me koston e thirrjes së një funksioni transferimi (), pasi ne nuk paguajmë për vendosjen e kontratës inteligjente.

Vendimi përfundimtar

Si të përcaktoni adresën e një kontrate inteligjente përpara vendosjes: duke përdorur CREATE2 për një shkëmbim kripto

Përgatitur fillimisht nga:

  • funksion për të marrë kripën nga user_id
  • një kontratë inteligjente që do të thërrasë kodin optik CREATE2 me kripën e duhur (p.sh. fabrika e portofolit)
  • bytekodi i portofolit që korrespondon me kontratën me konstruktorin e mëposhtëm:

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


Për çdo përdorues të ri ne tregojmë adresën e portofolit të tij/saj me llogaritje

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


Kur një përdorues transferon argumentet në adresën përkatëse të portofolit, backend-i ynë sheh një ngjarje Transferimi me parametrin _ te, e barabartë me adresën e portofolit. Në këtë pikë, tashmë është e mundur të rritet balanca e përdoruesit në shkëmbim përpara se të vendosësh portofolin.

Kur një adresë portofoli grumbullon një numër të mjaftueshëm argumentesh, ne mund t'i transferojmë të gjitha menjëherë në hotwallet. Për ta bërë këtë, backend thërret funksionin e fabrikës së kontratës inteligjente, e cila kryen veprimet e mëposhtme:

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


Kështu, thirret konstruktori i kontratës inteligjente të portofolit, i cili transferon të gjitha shenjat e tij në adresën e hotwallet-it dhe më pas vetëshkatërrohet.

Kodi i plotë mund të gjendet këtu. Ju lutemi vini re se ky nuk është kodi ynë i prodhimit, pasi vendosëm të optimizonim bajtkodin e portofolit dhe e shkruam atë në kode optike.

Autori Pavel Kondratenkov, specialist i Ethereum

Burimi: www.habr.com

Shto një koment