Hur man bestämmer adressen till ett smart kontrakt före implementering: Använd CREATE2 för ett kryptoutbyte

Ämnet blockchain upphör aldrig att vara en källa till inte bara alla typer av hype, utan också idéer som är mycket värdefulla ur teknisk synvinkel. Därför gick det inte förbi invånarna i den soliga staden. Människor tittar noga, studerar, försöker överföra sin expertis inom traditionell informationssäkerhet till blockkedjesystem. Hittills är det perfekt: en av Rostelecom-Solars utvecklingar kan kontrollera säkerheten för blockchain-baserad programvara. Och på vägen dyker det upp några tankar om att lösa tillämpade problem i blockchain-gemenskapen. Ett av dessa life hacks - hur man bestämmer adressen till ett smart kontrakt före implementering med CREATE2 - idag vill jag dela med dig under klippet.

Hur man bestämmer adressen till ett smart kontrakt före implementering: Använd CREATE2 för ett kryptoutbyte
CREATE2-opkoden lades till i Konstantinopel hårdgaffel den 28 februari i år. Som anges i EIP introducerades denna op-kod främst för statliga kanaler. Men vi använde det för att lösa ett annat problem.

Det finns användare med saldon på börsen. Vi måste förse varje användare med en Ethereum-adress till vilken vem som helst kan skicka tokens och därigenom fylla på sitt konto. Låt oss kalla dessa adresser för "plånböcker". När tokens kommer in i plånböcker måste vi skicka dem till en enda plånbok (hotwallet).

I följande avsnitt analyserar jag alternativen för att lösa detta problem utan CREATE2 och berättar varför vi övergav dem. Om du bara är intresserad av det slutliga resultatet kan du hitta det i avsnittet "Slutlig lösning".

Ethereum adresser

Den enklaste lösningen är att generera nya Ethereum-adresser för nya användare. Dessa adresser kommer att vara plånböckerna. För att överföra tokens från en plånbok till hotwallet måste du signera transaktionen genom att anropa funktionen överföra() med plånbokens privata nyckel från backend.

Detta tillvägagångssätt har följande fördelar:

  • det är enkelt
  • kostnaden för att överföra tokens från en plånbok till hotwallet är lika med kostnaden för ett funktionssamtal överföra()

Vi beslutade oss dock för detta tillvägagångssätt eftersom det har en stor nackdel: du måste lagra de privata nycklarna någonstans. De kan inte bara gå förlorade, utan du måste också noggrant hantera åtkomsten till dessa nycklar. Om åtminstone en av dem äventyras, kommer tokens för en viss användare inte att nå den heta plånboken.

Hur man bestämmer adressen till ett smart kontrakt före implementering: Använd CREATE2 för ett kryptoutbyte

Skapa ett separat smart kontrakt för varje användare

Genom att distribuera ett separat smart kontrakt för varje användare kan du undvika att lagra privata nycklar för plånböcker på servern. Exchange kommer att kalla detta smarta kontrakt för att överföra tokens till hotwallet.

Vi övergav också denna lösning, eftersom användaren inte kan visas sin plånboksadress utan att använda ett smart kontrakt (detta är faktiskt möjligt, men på ett ganska komplicerat sätt med andra nackdelar som vi inte kommer att diskutera här). På börsen kan en användare skapa så många konton han behöver, och var och en behöver sin egen plånbok. Det betyder att vi måste spendera pengar på att implementera ett kontrakt utan att ens vara säkra på att användaren kommer att använda detta konto.

Opcode CREATE2

För att åtgärda problemet med den tidigare metoden bestämde vi oss för att använda CREATE2 opcode. CREATE2 låter dig förbestämma adressen där det smarta kontraktet kommer att distribueras. Adressen beräknas med följande formel:

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


, Var:

  • adress — adressen till det smarta kontraktet som kommer att anropa CREATE2
  • salt - slumpmässigt värde
  • init_code — smart kontraktsbytekod för distribution

Detta säkerställer att adressen vi tillhandahåller användaren faktiskt innehåller den önskade bytekoden. Dessutom kan detta smarta kontrakt användas när vi behöver. Till exempel när en användare bestämmer sig för att använda sin plånbok för första gången.
Hur man bestämmer adressen till ett smart kontrakt före implementering: Använd CREATE2 för ett kryptoutbyte
Dessutom kan du beräkna den smarta kontraktsadressen varje gång istället för att lagra den eftersom:

  • adress i formeln är konstant, eftersom detta är adressen till vår plånboksfabrik
  • salt — user_id hash
  • init_code är konstant eftersom vi använder samma plånbok

Fler förbättringar

Den tidigare lösningen har fortfarande en nackdel: du måste betala för att implementera det smarta kontraktet. Du kan dock bli av med det. För att göra detta kan du anropa funktionen överföra()och då självförstörelse() i plånbokskonstruktören. Och sedan kommer gasen för att implementera det smarta kontraktet att returneras.

Tvärtemot vad många tror kan du distribuera ett smart kontrakt till samma adress flera gånger med CREATE2-opkoden. Detta beror på att CREATE2 kontrollerar att nonce av måladressen är noll (den tilldelas värdet "1" i början av konstruktorn). I det här fallet funktionen självförstörelse() återställer nonce-adresser varje gång. Så om du anropar CREATE2 igen med samma argument kommer nonce-kontrollen att passera.

Observera att denna lösning liknar Ethereum-adressalternativet, men utan att behöva lagra privata nycklar. Kostnaden för att överföra pengar från en plånbok till hotwallet är ungefär lika med kostnaden för att ringa en funktion överföra(), eftersom vi inte betalar för smart kontraktsinstallation.

Slutgiltigt beslut

Hur man bestämmer adressen till ett smart kontrakt före implementering: Använd CREATE2 för ett kryptoutbyte

Ursprungligen beredd av:

  • funktion för att få salt genom USER_ID
  • ett smart kontrakt som kommer att anropa CREATE2-opkoden med lämpligt salt (d.v.s. plånboksfabriken)
  • plånboksbytekod som motsvarar kontraktet med följande konstruktör:

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


För varje ny användare visar vi hans/hennes plånboksadress genom beräkning

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


När en användare överför tokens till motsvarande plånboksadress, ser vår backend en Transfer-händelse med parametern _till, lika med plånboksadressen. Vid denna tidpunkt är det redan möjligt att öka användarens saldo på börsen innan plånboken distribueras.

När en plånboksadress samlar på sig ett tillräckligt antal tokens kan vi överföra dem alla på en gång till hotwallet. För att göra detta anropar backend den smarta kontraktsfabriksfunktionen, som utför följande åtgärder:

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


Således kallas den smarta kontraktskonstruktören för plånboken, som överför alla sina tokens till hotwallet-adressen och sedan självdestruerar.

Hela koden finns här. Observera att detta inte är vår produktionskod, eftersom vi bestämde oss för att optimera plånboksbytekoden och skrev den i opcodes.

Författare Pavel Kondratenkov, Ethereum-specialist

Källa: will.com

Lägg en kommentar