Jak określić adres inteligentnej umowy przed wdrożeniem: użycie CREATE2 do wymiany kryptowalut

Temat blockchain nie przestaje być źródłem nie tylko wszelkiego rodzaju szumu, ale także pomysłów, które są bardzo cenne z technologicznego punktu widzenia. Nie ominęła zatem mieszkańców słonecznego miasta. Ludzie uważnie się przyglądają, studiują, próbują przenieść swoją wiedzę z zakresu tradycyjnego bezpieczeństwa informacji do systemów blockchain. Jak na razie wszystko się zgadza: jedno z rozwiązań Rostelecom-Solar może sprawdzić bezpieczeństwo oprogramowania opartego na blockchainie. Po drodze pojawiają się przemyślenia na temat rozwiązania stosowanych problemów społeczności blockchain. Jeden z tych lifehacków - jak określić adres inteligentnej umowy przed wdrożeniem za pomocą CREATE2 - dzisiaj chcę się z wami podzielić pod cięciem.

Jak określić adres inteligentnej umowy przed wdrożeniem: użycie CREATE2 do wymiany kryptowalut
Kod operacji CREATE2 został dodany podczas hard forku w Konstantynopolu 28 lutego tego roku. Jak stwierdzono w EIP, ten kod operacyjny został wprowadzony głównie dla kanałów państwowych. Jednak użyliśmy go do rozwiązania innego problemu.

Na giełdzie są użytkownicy posiadający salda. Musimy zapewnić każdemu użytkownikowi adres Ethereum, na który każdy może wysłać tokeny, uzupełniając w ten sposób swoje konto. Nazwijmy te adresy „portfelami”. Kiedy tokeny dotrą do portfeli, musimy je wysłać do jednego portfela (hotwallet).

W kolejnych sekcjach analizuję opcje rozwiązania tego problemu bez CREATE2 i wyjaśniam, dlaczego je porzuciliśmy. Jeśli interesuje Cię tylko efekt końcowy, znajdziesz go w dziale „Rozwiązanie końcowe”.

Adresy Ethereum

Najprostszym rozwiązaniem jest wygenerowanie nowych adresów Ethereum dla nowych użytkowników. Adresy te będą portfelami. Aby przenieść tokeny z portfela do hotwallet należy podpisać transakcję wywołując funkcję przenosić() z kluczem prywatnym portfela z backendu.

To podejście ma następujące zalety:

  • to tylko
  • koszt przeniesienia tokenów z portfela do hotwallet jest równy kosztowi wywołania funkcji przenosić()

Zdecydowaliśmy się jednak na to podejście, ponieważ ma ono jedną zasadniczą wadę: trzeba gdzieś przechowywać klucze prywatne. Nie tylko można je zgubić, ale także należy uważnie zarządzać dostępem do tych kluczy. Jeśli przynajmniej jeden z nich zostanie naruszony, tokeny danego użytkownika nie dotrą do gorącego portfela.

Jak określić adres inteligentnej umowy przed wdrożeniem: użycie CREATE2 do wymiany kryptowalut

Utwórz osobną inteligentną umowę dla każdego użytkownika

Wdrożenie osobnej inteligentnej umowy dla każdego użytkownika pozwala uniknąć przechowywania kluczy prywatnych do portfeli na serwerze. Giełda wywoła tę inteligentną umowę w celu przeniesienia tokenów do hotwalletu.

Również porzuciliśmy to rozwiązanie, ponieważ użytkownikowi nie można pokazać adresu portfela bez wdrożenia inteligentnej umowy (jest to w rzeczywistości możliwe, ale w dość złożony sposób, z innymi wadami, o których nie będziemy tutaj omawiać). Na giełdzie użytkownik może założyć dowolną liczbę kont, a każde z nich potrzebuje własnego portfela. Oznacza to, że musimy wydać pieniądze na wdrożenie umowy, nie mając nawet pewności, że użytkownik będzie korzystał z tego konta.

Kod operacji UTWÓRZ2

Aby rozwiązać problem z poprzednią metodą, zdecydowaliśmy się użyć kodu operacji CREATE2. CREATE2 umożliwia wstępne określenie adresu, pod którym zostanie wdrożony inteligentny kontrakt. Adres oblicza się według następującego wzoru:

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


, gdzie:

  • adres — adres inteligentnego kontraktu, który wywoła CREATE2
  • sól - wartość losowa
  • kod_inicjujący — kod bajtowy inteligentnego kontraktu do wdrożenia

Dzięki temu mamy pewność, że adres, który podajemy użytkownikowi, faktycznie zawiera żądany kod bajtowy. Co więcej, tę inteligentną umowę można wdrożyć w dowolnym momencie. Na przykład, gdy użytkownik po raz pierwszy zdecyduje się skorzystać ze swojego portfela.
Jak określić adres inteligentnej umowy przed wdrożeniem: użycie CREATE2 do wymiany kryptowalut
Co więcej, możesz za każdym razem obliczyć adres inteligentnej umowy, zamiast go przechowywać, ponieważ:

  • adres we wzorze jest stała, gdyż jest to adres naszej fabryki portfeli
  • sól — skrót identyfikatora użytkownika
  • kod_inicjujący jest stała, ponieważ używamy tego samego portfela

Więcej ulepszeń

Poprzednie rozwiązanie ma nadal jedną wadę: za wdrożenie inteligentnego kontraktu trzeba zapłacić. Można się jednak tego pozbyć. Aby to zrobić, możesz wywołać funkcję przenosić()a potem samounicestwienia() w konstruktorze portfela. A wtedy gaz do wdrożenia inteligentnego kontraktu zostanie zwrócony.

Wbrew powszechnemu przekonaniu, za pomocą kodu operacyjnego CREATE2 można wielokrotnie wdrożyć inteligentny kontrakt pod tym samym adresem. Dzieje się tak, ponieważ CREATE2 sprawdza, czy wartość jednorazowa adresu docelowego wynosi zero (na początku konstruktora przypisuje się mu wartość „1”). W tym przypadku funkcja samounicestwienia() resetuje adresy jednorazowe za każdym razem. Jeśli więc ponownie wywołasz CREATE2 z tymi samymi argumentami, sprawdzenie jednorazowe zakończy się pomyślnie.

Należy pamiętać, że to rozwiązanie jest podobne do opcji adresu Ethereum, ale bez konieczności przechowywania kluczy prywatnych. Koszt przesłania pieniędzy z portfela do hotwalletu jest w przybliżeniu równy kosztowi wywołania funkcji przenosić(), ponieważ nie płacimy za wdrożenie inteligentnych kontraktów.

Ostateczna decyzja

Jak określić adres inteligentnej umowy przed wdrożeniem: użycie CREATE2 do wymiany kryptowalut

Oryginalnie przygotowany przez:

  • funkcja zbierania soli user_id
  • inteligentny kontrakt, który wywoła opcode CREATE2 z odpowiednią solą (tj. fabryką portfela)
  • kod bajtowy portfela odpowiadający umowie z następującym konstruktorem:

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


Dla każdego nowego użytkownika pokazujemy jego adres portfela poprzez kalkulację

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


Kiedy użytkownik przesyła tokeny na odpowiedni adres portfela, nasz backend widzi zdarzenie Transfer z parametrem _dorówny adresowi portfela. W tym momencie możliwe jest już zwiększenie salda użytkownika na giełdzie przed wdrożeniem portfela.

Gdy pod adresem portfela zgromadzi się wystarczająca liczba tokenów, możemy je wszystkie przenieść na raz do hotwallet. W tym celu backend wywołuje funkcję fabryki inteligentnych kontraktów, która wykonuje następujące działania:

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


W ten sposób wywoływany jest konstruktor inteligentnego kontraktu portfela, który przesyła wszystkie swoje tokeny na adres hotwalletu, a następnie ulega samozniszczeniu.

Pełny kod można znaleźć tutaj. Należy pamiętać, że nie jest to nasz kod produkcyjny, ponieważ postanowiliśmy zoptymalizować kod bajtowy portfela i zapisaliśmy go w opkodach.

Autor Pavel Kondratenkov, specjalista Ethereum

Źródło: www.habr.com

Dodaj komentarz