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.
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ë.
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ë.
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
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
Autori Pavel Kondratenkov, specialist i Ethereum
Burimi: www.habr.com