Być może natknąłeś się na pewne wskazówki dotyczące Solidity, dzięki którym możesz poprawić swoje umiejętności kodowania i zaoszczędzić trochę paliwa, ale dziś chciałbym skupić się bardziej na tym, jak zrozumienie maszyny wirtualnej Ethereum może skutecznie pomóc Ci zaoszczędzić paliwo na inteligentnych kontraktach.
Ponieważ zagłębiamy się w temat Ethereum, zostawię tutaj fragment Żółtej Księgi, w którym określono koszty gazu dla kodów operacyjnych. W dalszej części artykułu będziemy się do nich odwoływać.
Wskazówka nr 1: Dostęp na zimno kontra dostęp na ciepło
Gcoldsload: 2100 gazu
Gwarmaccess: 100 benzyny
Oto nasze pierwsze OPCODY, pierwszy określa, ile kosztuje dostęp do zmiennej po raz pierwszy (lub zimny dostęp), podczas gdy drugi określa, ile kosztuje dostęp do zmiennej po raz drugi i kolejny (ciepły dostęp). Jak widać, różnica w cenie jest dość duża, więc zrozumienie tego może mieć duże znaczenie dla kosztów transakcji Twojego inteligentnego kontraktu. Zobaczmy przykład.
Buforowanie danych wewnątrz funkcji w Solidity może skutkować mniejszym zużyciem gazu, nawet jeśli wymaga to większej liczby linii kodu. W tym przypadku następuje to poprzez zmianę lokalizacji tablicy i zamiast korzystania z niej z pamięci masowej, a co za tym idzie, uzyskiwania do niej dostępu za każdym razem w pętli, tablica jest przechowywana w pamięci, gdzie dostęp do niej jest tańszy.
Wskazówka nr 2: Wartości zerowe i niezerowe oraz zwroty kosztów benzyny
Gsset = 20 000 gazu
Rsclear = {rabat na cenę wykonania}
Zmiana wartości z 0 na wartość różną od zera w blockchainie Ethereum jest kosztowna, jak widać po cenie Gsset, ale zmiana wartości z wartości różnej od zera na 0 może skutkować zwrotem wartości gazu zgodnie z kodem operacji Rsclear. Aby nie skorzystać ze zwrotu, ustalono, że można uzyskać zwrot maksymalnie do 20% całkowitego kosztu transakcji.
Taki scenariusz można znaleźć w bardzo powszechnym scenariuszu na blockchain, który polega na aktualizowaniu salda adresów w inteligentnych kontraktach. Zobaczmy przykład każdego z nich:
W pierwszym przykładzie kontraktu ZeroToNonZero, wartość różna od zera do wartości różnej od zera (5000 gazu*) + wartość różna od zera (20 000 gazu) = 25 000 gazu
W drugim przykładzie kontrakt NonZeroToZero, Non-zero do zera (5000 gazu*) + zero do niezera (20 000 gazu) — zwrot (4800 gazu) = 21 200 gazu
*2100 (Gcolssload) + 2900 (Gsreset) = 5000 gazu
Wskazówka nr 3: Kolejność zmiennych stanu ma znaczenie
Storage jest czymś w rodzaju struktury danych typu klucz-wartość, która przechowuje wartości zmiennych stanu inteligentnego kontraktu Solidity.
Możesz myśleć o pamięci masowej jako o tablicy, co pomoże to zwizualizować. Każda przestrzeń w tej „tablicy” pamięci masowej nazywana jest slotem i zawiera 32 bajty (256 bitów) danych, a każda zmienna stanu zadeklarowana w inteligentnym kontrakcie zajmie slot w zależności od jej pozycji deklaracji i typu.
Nie wszystkie typy danych zajmują wszystkie 32 bajty każdego slotu, gdyż istnieją pewne typy danych (bool, uint8, address…), które zajmują mniej miejsca.
Sztuczka polega na tym, że jeśli dwie/trzy lub więcej zmiennych ma razem 32 bajty lub mniej, kompilator Solidity spróbuje spakować je razem w jednym slocie, ale zmienne te muszą być zdefiniowane obok siebie.
Tutaj używamy typów danych bool (1 bajt), address (20 bajtów) i uint256 (32 bajty). Tak więc, znając rozmiar tych zmiennych można łatwo zrozumieć, że w pierwszym przykładzie w kontrakcie TwoSlots, ponieważ mamy bool i address razem (1 + 20 = 21 bajtów, co jest mniejsze niż 32 bajty), zajmą one jeden slot. W kontrakcie ThreeSlots, ponieważ bool i uint256 nie mogą znajdować się w tym samym slocie (1 + 32 = 33 bajty, co jest większe niż pojemność slotu), w sumie będziemy używać trzech slotów.
Dlaczego to jest takie ważne?
Kod operacji SLOAD kosztuje 2100 gazu i jest używany do odczytu ze slotów pamięci masowej, więc jeśli możesz przechowywać zmienne w mniejszej liczbie slotów, zaoszczędzisz trochę gazu.
Wskazówka nr 4: uint256 jest tańszy niż uint8
W wskazówce nr 3 dowiedzieliśmy się, że uint256 (256 bitów = 32 bajty) zajmuje samodzielnie slot, a także, że uint8 ma mniej niż 32 bajty. Tak więc, chociaż jest dość oczywiste, że 8 bitów jest mniejszych niż 256 bitów, to dlaczego uint256 jest tańszy?
Aby to zrozumieć, ważne jest, aby wiedzieć, że jeśli zmienna nie wypełnia całego pola i pole to nie jest wypełnione przez żadną inną zmienną, EVM wypełni resztę pozostałych bitów „0”, aby móc nią manipulować.
Dodanie „0” wykonane przez maszynę EVM będzie kosztowało gaz, co oznacza, że aby zaoszczędzić gaz transakcyjny, lepiej jest użyć uint256 zamiast uint8.
__________________
Mam nadzieję, że podczas lektury tych wskazówek dotyczących obniżania kosztów gazu w inteligentnych kontraktach dowiedziałeś się także trochę o tym, jak działa EVM.
__________________
Odwiedź Twittera @TheBlockChainer, aby codziennie otrzymywać aktualności na temat inteligentnych kontraktów, zabezpieczeń Web3, Solidity, audytu inteligentnych kontraktów i nie tylko.
__________________


