Solidity Cheat Sheet: ściąga z Solidity
Struktura kontraktu
Każdy plik zaczyna się od licencji i pragmy; kontrakt to jednostka wdrożenia.
| Składnia | Znaczenie |
|---|---|
// SPDX-License-Identifier: MIT | Komentarz z licencją, którego kompilator oczekuje w linii 1 |
pragma solidity ^0.8.0; | Wersja kompilatora, dla której napisano plik |
contract Counter { ... } | Deklaracja kontraktu (stan + funkcje) |
constructor(uint start) { count = start; } | Uruchamia się raz, przy wdrożeniu |
import "./Token.sol"; | Import innego pliku |
import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; | Import pakietu biblioteki |
interface IToken { function balanceOf(address a) external view returns (uint); } | Deklaracja interfejsu (bez ciał funkcji) |
library Math { function min(uint a, uint b) internal pure returns (uint) { ... } } | Biblioteka funkcji wielokrotnego użytku |
Typy wartościowe
Liczby całkowite mają stały rozmiar i nie mają części dziesiętnej; 0.8 cofa transakcję przy przepełnieniu.
| Typ | Co przechowuje |
|---|---|
uint256 / uint | Liczba całkowita bez znaku, od 0 do 2^256 - 1 (uint to uint256) |
uint8, uint16, ... uint128 | Mniejsze liczby bez znaku, w krokach co 8 bitów |
int256 / int | Liczba całkowita ze znakiem (dozwolone ujemne) |
bool | true lub false |
address | 20-bajtowy adres konta lub kontraktu |
address payable | Adres, który może otrzymać Ether przez transfer/send |
bytes32, bytes1... | Tablice bajtów o stałym rozmiarze |
enum Status { Open, Closed } | Nazwany zbiór stałych, przechowywany jako uint8 |
1 ether, 1 gwei, 1 wei | Jednostki Etheru: 1 ether = 10^18 wei |
1 days, 2 hours, 30 minutes | Jednostki czasu, w sekundach |
Typy referencyjne i lokalizacja danych
Tablice, stringi, bajty, struktury i mappingi znajdują się w storage, memory lub calldata.
| Składnia | Znaczenie |
|---|---|
string memory name | Dynamiczny string UTF-8 (kopia tymczasowa) |
bytes memory data | Dynamiczna tablica bajtów |
uint[] public scores; | Dynamiczna tablica w storage |
uint[3] fixed; | Tablica o stałym rozmiarze 3 |
uint[] memory tmp = new uint[](5); | Alokacja tablicy w memory |
scores.push(42); | Dodanie na końcu tablicy w storage |
scores.pop(); | Usunięcie ostatniego elementu |
scores.length | Liczba elementów |
storage | Trwałe, on-chain, drogie w zapisie |
memory | Tymczasowe, istnieje przez jedno wywołanie |
calldata | Tylko do odczytu, wejście funkcji external, najtańsze |
Mappingi i struktury
Mapping to tablica haszująca bez długości i bez iteracji; struktura grupuje pola.
| Składnia | Znaczenie |
|---|---|
mapping(address => uint) public balances; | Magazyn klucz-wartość, każdy klucz istnieje (domyślnie 0) |
balances[msg.sender] += 1; | Odczyt/zapis po kluczu |
mapping(address => mapping(address => uint)) allowance; | Zagnieżdżony mapping |
struct User { string name; uint age; bool active; } | Definicja struktury |
User memory u = User("Ada", 36, true); | Utworzenie struktury w memory |
User memory u = User({name: "Ada", age: 36, active: true}); | Utworzenie z nazwanymi polami |
users[msg.sender] = u; | Zapisanie struktury w mappingu |
users[msg.sender].age = 37; | Aktualizacja jednego pola w storage |
delete users[msg.sender]; | Przywrócenie wartości domyślnych |
Funkcje i widoczność
Każda funkcja określa, kto może ją wywołać i czy czyta lub zapisuje stan.
| Składnia | Znaczenie |
|---|---|
function add(uint a, uint b) public pure returns (uint) { return a + b; } | Funkcja z parametrami i wartością zwracaną |
public | Wywoływalna zewsząd (wewnątrz i z zewnątrz) |
external | Wywoływalna tylko spoza kontraktu |
internal | Ten kontrakt i kontrakty, które po nim dziedziczą |
private | Tylko ten kontrakt |
view | Czyta stan, nigdy go nie zapisuje |
pure | W ogóle nie czyta stanu |
payable | Może przyjąć Ether razem z wywołaniem |
returns (uint sum, bool ok) | Kilka nazwanych wartości zwracanych |
(uint s, bool ok) = f(); | Destrukturyzacja kilku wartości zwracanych |
uint public count; | Publiczna zmienna stanu dostaje automatyczny getter count() |
Modyfikatory, stałe i dziedziczenie
Powtarzane sprawdzenia zamykaj w modyfikatorach; wartości ustalaj na stałe przez constant i immutable.
| Składnia | Znaczenie |
|---|---|
modifier onlyOwner() { require(msg.sender == owner, "Not owner"); _; } | Definicja modyfikatora (_ = wykonaj ciało funkcji) |
function withdraw() public onlyOwner { ... } | Zastosowanie modyfikatora |
uint public constant MAX = 100; | Stała czasu kompilacji |
address public immutable owner; | Ustawiana raz w konstruktorze, potem niezmienna |
contract Token is ERC20, Ownable { ... } | Dziedziczenie po innych kontraktach |
function f() public virtual { ... } | Zezwolenie na nadpisanie |
function f() public override { ... } | Nadpisanie funkcji rodzica |
super.f(); | Wywołanie implementacji rodzica |
abstract contract Base { function f() public virtual; } | Kontrakt z niezaimplementowanymi funkcjami |
Instrukcje sterujące
Typowe instrukcje z rodziny C; nie ma switch, a pętle kosztują gaz za każdą iterację.
| Składnia | Znaczenie |
|---|---|
if (x > 5) { ... } else if (x > 2) { ... } else { ... } | Gałęzie warunkowe |
for (uint i = 0; i < n; i++) { ... } | Pętla z licznikiem |
while (x < 10) { x++; } | Pętla, dopóki warunek jest spełniony |
do { ... } while (cond); | Wykonuje się co najmniej raz |
break; / continue; | Wyjście z pętli / przejście do następnej iteracji |
x > 0 ? a : b | Wyrażenie trójargumentowe |
a / b | Dzielenie całkowite (odrzuca resztę) |
a % b | Reszta z dzielenia |
a ** 2 | Potęgowanie |
unchecked { x++; } | Pominięcie sprawdzania przepełnienia (oszczędza gaz, używaj ostrożnie) |
Błędy: require, revert, assert
Nieudane sprawdzenie cofa całą transakcję i zwraca niewykorzystany gaz.
| Składnia | Znaczenie |
|---|---|
require(amount > 0, "Amount must be positive"); | Walidacja wejścia lub stanu; cofnięcie z komunikatem |
revert("Not allowed"); | Bezwarunkowe przerwanie |
error Insufficient(uint available, uint requested); | Deklaracja własnego błędu (tańsza niż stringi) |
revert Insufficient(balance, amount); | Cofnięcie z własnym błędem |
assert(total == a + b); | Sprawdzenie niezmiennika, który nigdy nie powinien zawieść |
try token.transfer(to, amt) returns (bool ok) { ... } catch { ... } | Obsługa nieudanego wywołania zewnętrznego |
Eventy
Eventy zapisują logi, które mogą subskrybować aplikacje off-chain; kontrakty nie mogą ich odczytać.
| Składnia | Znaczenie |
|---|---|
event Transfer(address indexed from, address indexed to, uint value); | Deklaracja eventu |
emit Transfer(msg.sender, to, amount); | Emisja eventu |
indexed | Parametr do filtrowania (maksymalnie 3 na event) |
event Log(string message); | Można logować dowolny typ ABI |
Ether, adresy i zmienne globalne
Kontekst transakcji pochodzi z msg, block i tx.
| Składnia | Znaczenie |
|---|---|
msg.sender | Adres, który wywołał tę funkcję |
msg.value | Wei wysłane z wywołaniem (wymaga payable) |
block.timestamp | Czas bieżącego bloku (sekundy od epoki) |
block.number | Wysokość bieżącego bloku |
tx.origin | Konto zewnętrzne (EOA), które rozpoczęło transakcję (nie używaj do autoryzacji) |
address(this).balance | Saldo Etheru tego kontraktu |
payable(to).transfer(1 ether); | Wysłanie Etheru, cofa transakcję przy błędzie |
(bool ok, ) = to.call{value: amt}(""); | Niskopoziomowe wysłanie, zwraca flagę powodzenia |
receive() external payable {} | Uruchamia się przy zwykłym przelewie Etheru |
fallback() external payable {} | Uruchamia się, gdy żadna funkcja nie pasuje |
keccak256(abi.encodePacked(a, b)) | Haszowanie wartości |
abi.encode(x), abi.decode(data, (uint)) | Kodowanie / dekodowanie danych ABI |
Cała składnia Solidity, której potrzebujesz, na jednej stronie. Ten Solidity cheat sheet to szybka ściąga z języka smart kontraktów Ethereum i każdego łańcucha EVM: deklarowanie kontraktu, wybór typów, przechowywanie danych w mappingach i strukturach, pisanie funkcji z właściwą widocznością i mutowalnością oraz zabezpieczanie ich przez require, modyfikatory i eventy.
Składnia opisana tutaj to Solidity 0.8, który domyślnie sprawdza przepełnienie arytmetyczne i działa z Remix, Hardhat i Foundry. Skopiuj to, czego potrzebujesz, albo sprawdź na żywo w edytorze online Solidity: napisz kontrakt, skompiluj go i uruchom na EVM w przeglądarce.