Praėjusį mėnesį paskelbiau straipsnį, kuriame pabrėžiama, kaip kūrėjai gali žymiai sumažinti dujų sąnaudas Pasirinkdami tinkamus saugojimo tipus savo „Solidity Smart“ sutartyse. Ši tema sulaukė didelio susidomėjimo, pabrėždamas vykstančius kūrėjų ieškojimus, kad būtų efektyvesnės dujomis taupančios sutarties operacijos.
Didėjant „Ethereum“ virtualios mašinos (EVM) tinklų populiarumui, taip pat svarbu sumažinti operacijų mokesčius, kad „Web3“ programos būtų prieinamesnės ir ekonomiškesnės.
Šiame tolesniame straipsnyje toliau tyrinėsiu Dujų optimizavimo metodai Solidumo išmaniosios sutartyse. Be saugojimo tipo pasirinkimo, yra daugybė kitų strategijų, kurias kūrėjai gali panaudoti siekdami padidinti savo išmaniųjų sutarčių efektyvumą.
Įdiegę šias technikas, kūrėjai gali ne tik Mažesni dujų mokesčiai Bet taip pat pagerinti bendrą našumą ir vartotojo patirtį jų decentralizuotų programų (DAPPS). Dujų optimizavimo siekimas yra labai svarbus EVM tinklų masteliui ir tvarumui, todėl tai yra pagrindinė „Web3“ plėtros ateities dėmesio sritis.
Dujų optimizavimo metodai
1. Sandėliavimo vietos
Kaip aptarta ankstesniame straipsnyje, tinkamo saugojimo tipo pasirinkimas yra labai svarbus atskaitos taškas, skirtas optimizuoti dujų sąnaudas „blockchain“ operacijose. „Ethereum Virtual Machine“ (EVM) siūlo penkias saugojimo sritis: saugyklą, atmintį, skambučio, kamino ir žurnalų.
Norėdami gauti daugiau informacijos, apsilankykite mano ankstesniame straipsnyje apie dujų optimizavimą „Solidy Smart“ sutartyse. Ten aptarti metodai pabrėžia atminties naudojimo, palyginti su saugyklomis, pranašumus. Praktiniame pavyzdyje venkite per daug skaitymo ir rašymo į saugyklą Sumažinkite dujų sąnaudas iki pusės!
2. Konstantos ir nekintami kintamieji
Paimkime šį intelektualųjį kontaktą kaip pavyzdį:
contract GasComparison {
uint256 public value = 250;
address public account;
constructor() {
account = msg.sender;
}
}
Šios sutarties sudarymo išlaidos yra 174,049 dujos. Kaip matome, mes naudojame saugyklą su egzemplioriaus kintamaisiais. Norėdami to išvengti, turėtume reaguoti į konstantas ir nekintamus kintamuosius.
Konstantos ir nekintami daiktai pridedami tiesiai prie išmaniosios sutarties baito kodo po kompiliacijos, todėl jos nenaudoja saugyklos.
Optimizuota ankstesnės intelektualiosios sutarties versija yra:
contract GasComparison {
uint256 public constant VALUE = 250;
address public immutable i_account;
constructor() {
i_account = msg.sender;
}
}
Šį kartą išmanios sutarties sudarymo išlaidos yra 129154 dujosAr 25% Mažiau nei pradinė vertė.
3. Privatus per viešus kintamuosius
Tęsdami ankstesnį pavyzdį, pastebime, kad egzempliorių kintamieji yra vieši, o tai yra problematiška dėl dviejų priežasčių. Pirma, tai pažeidžia duomenų kapsulę. Antra, jis sukuria papildomą „GetTER“ funkcijos baitų kodą, padidindamas bendrą sutarties dydį. Didesnis sutarties dydis reiškia didesnes dislokavimo išlaidas, nes dislokavimo dujų išlaidos yra proporcingos sutarties dydžiui.
Vienas iš būdų optimizuoti yra:
contract GasComparison {
uint256 private constant VALUE = 250;
address private immutable i_account;
constructor() {
i_account = msg.sender;
}
function getValue() public pure returns (uint256) {
return VALUE;
}
}
Visų kintamųjų privatūs kintamieji nepateikus „Getter“ funkcijų, intelektualioji sutartis būtų mažiau funkcionali, nes duomenys nebebūtų prieinami.
Net šiuo atveju kūrimo išlaidos buvo sumažintos iki 92,289 dujosAr 28% mažesnis nei ankstesnis atvejis ir 46% Mažesnis nei pirmasis atvejis!
PS Jei būtume išlaikę vertės kintamąjį viešą ir nepridedant „getValue“ funkcijos, tas pats dujų kiekis būtų sunaudotas kuriant sutartį.
4. Naudokite sąsajas
Sąsajų naudojimas tvirtinime gali žymiai sumažinti bendrą jūsų išmaniosios sutarties sudaryto baito kodą dydįKadangi sąsajose nėra jų funkcijų įgyvendinimo. Tai lemia mažesnį sutarties dydį, o tai savo ruožtu sumažina diegimo išlaidas, nes dujų diegimo išlaidos yra proporcingos sutarties dydžiui.
Be to, Skambinimo funkcijos per sąsajas gali būti efektyvesnis dujoms. Kadangi sąsajose yra tik funkcijų parašai, šių skambučių baitų kodas gali būti optimizuotas. Šis optimizavimas lemia galimą dujų taupymą, palyginti su skambučių funkcijomis, tiesiogiai apibrėžtomis pagal didesnę sutartį, kurioje yra papildoma logika ir būsena.
Nors sąsajos naudojimas gali būti naudingas sudėtingoms intelektualiosioms sutartims ir funkcijoms, tačiau tai ne visada gali būti naudinga paprastesnėms sutartims. Ankstesniuose skyriuose aptarti pavyzdyje sąsajos pridėjimas iš tikrųjų gali padidinti tiesioginių sutarčių dujų sąnaudas.
5. Paveldėjimas dėl kompozicijos
Tęsdami sąsajos idėją, kurią turime paveldėti. Pažvelkite į šias intelektualias sutartis:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;
contract Employee {
address public account;
constructor() {
account = msg.sender;
}
}
contract Manager {
Employee private employee;
constructor(address _employeeAddress) {
employee = Employee(_employeeAddress);
}
function getEmployeeAccount() external view returns (address) {
return employee.account();
}
}
contract Executable {
Manager public manager;
constructor(address _employeeAddress) {
manager = new Manager(_employeeAddress);
}
function getMangerAccount() external view returns (address) {
return manager.getEmployeeAccount();
}
}
Čia mes turime 2 intelektualias sutartis, kurios sąveikauja per kompoziciją. Naudojimo atvejis yra ne toks svarbus; Aš noriu pabrėžti išorinį skambutį, kurį vadybininkas turi atlikti, kad gautų darbuotojo sąskaitą. „GetManagerAccount“, iškviestas iš vykdomosios sąskaitos 13 545 dujos.
Mes galime tai optimizuoti naudodami paveldėjimą:
contract Employee {
address public account;
constructor() {
account = msg.sender;
}
}
contract Manager is Employee{
}
contract Executable {
Manager public manager;
constructor(){
manager = new Manager();
}
function getMangerAccount() external view returns (address) {
return manager.account();
}
}
Šį kartą „GetManagerAccount“ užtruks tik 8 014 dujos, 40% Mažiau nei ankstesnis atvejis!
6. Kintamųjų dydis
Baitai ir sveikieji skaičiai yra vieni iš dažniausiai naudojamų kintamųjų tipų. Nors „Ethereum“ virtualioji mašina (EVM) veikia su 32 baitų ilgiu, kiekvieno egzemplioriaus kintamųjų pasirinkimas nėra idealus, jei tikslas yra optimizuoti dujas.
Baitai
Pažvelkime į šią intelektualią sutartį:
contract BytesComparison {
bytes32 public constant LONG_MESSAGE="Hello, world! This is a longer .";
bytes32 public constant MEDIUM_MESSAGE="Hello, world!";
bytes32 public constant SHORT_MESSAGE="H";
function concatenateBytes32() public pure returns (bytes memory) {
bytes memory concatenated = new bytes(32 * 3);
for (uint i = 0; i
„ConcatenateByTes32“ vykdymo kaina yra 28 909 dujos.
Kalbant apie dujas, optimizuoti rekomenduojama dirbant su baitais, kad būtų susiaurinta dydis iki naudojamos vertės. Tokiu atveju būtų optimizuota šios sutarties versija:
contract BytesComparison {
bytes32 public constant LONG_MESSAGE="Hello, world! This is a longer .";
bytes16 public constant MEDIUM_MESSAGE="Hello, world!";
bytes1 public constant SHORT_MESSAGE="H";
function concatenateBytes() public pure returns (bytes memory) {
// Create a bytes array to hold the concatenated result
bytes memory concatenated = new bytes(32 + 16 + 1);
for (uint i = 0; i
Šiuo atveju vykdomas concatenateBytes
yra 12 011 dujosAr 59% mažesnis nei ankstesniu atveju.
Int
Tačiau tai netaikoma sveiko skaičiaus tipams. Nors gali atrodyti, kad naudojant int16
būtų efektyvesnis dujomis nei int256
taip nėra. Kalbant apie sveikųjų skaičių kintamuosius, rekomenduojama naudoti 256 bitų versijas: int256
ir uint256
.
„Ethereum“ virtualioji mašina (EVM) veikia su 256 bitų žodžio dydžiu. Paskelbiant juos įvairių dydžių, reikės tvirtumo, kad būtų galima atlikti papildomas operacijas, kad būtų įtrauktos į 256 bitų žodžių dydį, todėl dujų sunaudojimas bus daugiau.
Pažvelkime į šią paprastą intelektualią sutartį:
contract IntComparison {
int128 public a=-55;
uint256 public b=2;
uint8 public c=1;
//Method which does the addition of the variables.
}
Kūrimo kaina bus 147,373 dujos. Jei optimizuosime tai, kaip minėta aukščiau, taip jis atrodys:
contract IntComparison {
int256 public a=-55;
uint256 public b=2;
uint256 public c=1;
//Method which does the addition of the variables.
}
Kūrybos kaina šį kartą bus 131 632 dujos, 10% mažiau nei ankstesnis atvejis.
Apsvarstykite, kad pirmame scenarijuje mes sukūrėme tik paprastą sutartį be jokių sudėtingų funkcijų. Tokioms funkcijoms gali prireikti tipo konversijų, dėl kurių gali būti didesnė dujų suvartojimas.
Pakavimo egzemplioriaus kintamieji
Yra atvejų, kai rekomenduojama naudoti mažesnius tipus privatiems kintamiesiems. Šie mažesni tipai turėtų būti naudojami, kai jie nedalyvauja logikoje, kuriai reikia tvirtumo, kad būtų galima atlikti papildomas operacijas. Be to, jie turėtų būti paskelbti konkrečia tvarka, kad būtų galima optimizuoti saugyklą. Pakavę juos į vieną 32 baitų saugyklos lizdą, galime optimizuoti saugyklą ir sutaupyti dujų.
Jei ankstesnė intelektualioji sutartis nebuvo susiję su sudėtingais skaičiavimais, rekomenduojama ši optimizuota versija naudojant pakuotę:
contract PackingComparison {
uint8 public c=1;
int128 public a=-55;
uint256 public b=2;
}
Kūrybos kaina šį kartą bus 125,523 dujos, 15% mažiau nei ankstesnis atvejis.
7. Fiksuotas dydis per dinaminius kintamuosius
Fiksuoto dydžio kintamieji sunaudoja mažiau dujų nei dinamiški tvirtinami Pirmiausia dėl to, kaip „Ethereum“ virtualioji mašina (EVM) tvarko duomenų saugojimą ir prieigą. Fiksuoto dydžio kintamieji turi nuspėjamą saugojimo išdėstymą. EVM tiksliai žino, kur saugomas kiekvienas fiksuoto dydžio kintamasis, leidžiantis efektyviai pasiekti ir laikyti.
Priešingai, dinaminiai kintamieji, tokie kaip stygos, baitai ir masyvai, gali skirtis pagal dydį, todėl norint valdyti jų ilgį ir vietą saugojime, reikia papildomų pridėtinių išlaidų. Tai apima papildomas operacijas, norint apskaičiuoti poslinkius ir valdyti rodykles, o tai padidina dujų suvartojimą.
Nors tai taikoma dideliems masyvams ir sudėtingoms operacijoms, paprastais atvejais mes negalėsime pastebėti jokio skirtumo.
Naudokite optimizatorių
Įgalinkite „Solidy Compiler“ optimizavimo režimą! Tai supaprastina sudėtingas išraiškas, sumažindama kodo dydį ir vykdymo sąnaudas, o tai sumažina dujas, reikalingas dislokuoti sutartis ir išorinius skambučius. Tai taip pat specializuojasi ir integruotos funkcijos. Nors įvedimas gali padidinti kodo dydį, jis dažnai leidžia dar labiau supaprastinti ir padidinti efektyvumą.
Prieš diegdami sutartį, suaktyvinkite optimizatorių, kai kaupiate:
solc --optimize --bin sourceFile.sol
Pagal numatytuosius nustatymus optimizavimo priemonė optimizuos sutartį, darant prielaidą, kad ji vadinama 200 kartų per visą savo gyvenimą (konkrečiau, daroma prielaida, kad kiekvienas opkodas vykdomas maždaug 200 kartų). Jei norite, --optimize-runs=1
. Jei tikitės daug operacijų ir nesirūpinkite didesnėmis diegimo sąnaudomis ir išvesties dydžiu, nustatykite --optimize-runs
iki didelio skaičiaus.
Yra įvairių strategijų, kaip sumažinti dujų suvartojimą, optimizuojant tvirtumo kodą. Svarbiausia yra pasirinkti tinkamus metodus kiekvienam konkrečiam atvejui, kuriam reikia optimizuoti. Tinkamas pasirinkimas dažnai gali sumažinti dujų sąnaudas iki iki galo 50%.
Taikydami šiuos optimizavimus, kūrėjai gali padidinti decentralizuotų programų (DAPPS) efektyvumą, našumą ir vartotojo patirtį, prisidėdami prie „Ethereum“ virtualios mašinos (EVM) tinklų mastelio ir tvarumo.
Toliau tobulinant šią praktiką, „Web3“ plėtros ateitis atrodo vis perspektyvesnė.
Solidumo dokumentacija
„Cyfrin“ tinklaraštis: Solidumo dujų optimizavimo patarimai