Přeskočit na hlavní obsah
Change page

Anatomie chytrých kontraktů

Stránka naposledy aktualizována: 23. února 2026

Chytrý kontrakt je program běžící na adrese na Ethereu. Skládá se z dat a funkcí, které se mohou spustit po přijetí transakce. Zde je přehled toho, co tvoří chytrý kontrakt.

Předpoklady

Ujistěte se, že jste si nejprve přečetli o chytrých kontraktech. Tento dokument předpokládá, že již znáte programovací jazyky, jako je JavaScript nebo Python.

Data

Jakákoli data kontraktu musí být přiřazena k umístění: buď do storage nebo memory. Úprava storage v chytrém kontraktu je nákladná, takže je třeba zvážit, kde by měla být vaše data uložena.

Úložiště

Trvalá data se označují jako storage a jsou reprezentována stavovými proměnnými. Tyto hodnoty se trvale uloží na blockchain. Datový typ je třeba deklarovat, aby kontrakt mohl při kompilaci sledovat, kolik potřebuje na blockchainu úložiště.

1// Příklad v Solidity
2contract SimpleStorage {
3 uint storedData; // Stavová proměnná
4 // ...
5}
1# Příklad ve Vyperu
2storedData: int128

Pokud jste již programovali v objektově orientovaných jazycích, většinu typů pravděpodobně znáte. Nicméně address by pro vás mělo být novinkou, pokud s vývojem na Ethereu teprve začínáte.

Datový typ address může obsahovat adresu Ethereum, která odpovídá 20 bajtům nebo 160 bitům. Návratová hodnota je v hexadecimálním zápisu začínajícím 0x.

Mezi další datové typy patří:

  • boolean
  • integer
  • čísla s pevnou řádovou čárkou
  • pole bajtů s pevnou velikostí
  • pole bajtů s dynamickou velikostí
  • racionální a celočíselné literály
  • řetězcové literály
  • hexadecimální literály
  • enumy

Další vysvětlení najdete v těchto dokumentech:

Paměť

Hodnoty, které jsou uloženy pouze po dobu provádění funkce kontraktu, se nazývají paměťové proměnné. Protože nejsou trvale uloženy na blockchainu, je jejich používání mnohem levnější.

Dozvíte se více o tom, jak EVM ukládá data (úložiště, paměť a zásobník) v dokumentaci Solidity (opens in a new tab).

Proměnné prostředí

Kromě proměnných, které definujete v kontraktu, existují i speciální globální proměnné. Ty slouží především k poskytování informací o blockchainu nebo aktuální transakci.

Příklady:

VlastnostStavová proměnnáPopis
block.timestampuint256Časové razítko aktuální epochy bloku
msg.senderadresaOdesílatel zprávy (aktuální volání)

Funkce

Nejjednodušeji řečeno, funkce mohou získávat informace nebo nastavovat informace v reakci na příchozí transakce.

Existují dva typy volání funkcí:

  • internal – nevytvářejí volání EVM
    • K interním funkcím a stavovým proměnným lze přistupovat pouze interně (tj. v rámci aktuálního kontraktu nebo kontraktů z něho odvozených).
  • external – vytvářejí volání EVM
    • Externí funkce jsou součástí rozhraní kontraktu, což znamená, že je lze volat z jiných kontraktů a prostřednictvím transakcí. Externí funkci f nelze volat interně (tzn. f() nefunguje, ale this.f() ano).

Mohou být také public nebo private.

  • public funkce lze volat interně z kontraktu nebo externě prostřednictvím zpráv
  • private funkce jsou viditelné pouze pro kontrakt, ve kterém jsou definovány, a ne v odvozených kontraktech

Funkce i stavové proměnné mohou být veřejné nebo soukromé.

Zde je funkce pro aktualizaci stavové proměnné v kontraktu:

1// Příklad v Solidity
2function update_name(string value) public {
3 dapp_name = value;
4}
  • Parametr value typu string je předán do funkce update_name.
  • Je deklarována jako public, což znamená, že k ní má kdokoli přístup.
  • Není deklarována jako view, takže může měnit stav kontraktu.

Funkce view

Tyto funkce slibují, že nebudou měnit stav dat kontraktu. Běžným příkladem jsou „getter“ funkce – můžete je použít například k získání zůstatku uživatele.

1// Příklad v Solidity
2function balanceOf(address _owner) public view returns (uint256 _balance) {
3 return ownerPizzaCount[_owner];
4}
1dappName: public(string)
2
3@view
4@public
5def readName() -> string:
6 return dappName

Co se považuje jako změna stavu:

  1. Zápis do stavových proměnných.
  2. Vysílání událostí (opens in a new tab).
  3. Vytváření dalších kontraktů (opens in a new tab).
  4. Použití selfdestruct.
  5. Posílání etheru pomocí volání.
  6. Volání jakékoli funkce, která není označena jako view nebo pure.
  7. Používání nízkoúrovňových volání.
  8. Používání inline assembly, která obsahuje určité operační kódy.

Konstruktory

Funkce constructor se provedou pouze jednou, při prvním nasazení kontraktu. Podobně jako constructor v mnoha programovacích jazycích založených na třídách, tyto funkce často inicializují stavové proměnné na zadané hodnoty.

1// Příklad v Solidity
2// Inicializuje data kontraktu, nastaví `owner`
3// na adresu tvůrce kontraktu.
4constructor() public {
5 // Všechny chytré kontrakty spoléhají na externí transakce, které spouští jejich funkce.
6 // `msg` je globální proměnná, která obsahuje relevantní údaje o dané transakci,
7 // jako je adresa odesílatele a hodnota ETH obsažená v transakci.
8 // Více informací: https://solidity.readthedocs.io/en/v0.5.10/units-and-global-variables.html#block-and-transaction-properties
9 owner = msg.sender;
10}
Zobrazit vše
1# Příklad ve Vyperu
2
3@external
4def __init__(_beneficiary: address, _bidding_time: uint256):
5 self.beneficiary = _beneficiary
6 self.auctionStart = block.timestamp
7 self.auctionEnd = self.auctionStart + _bidding_time

Vestavěné funkce

Kromě proměnných a funkcí, které definujete v kontraktu, existují i speciální vestavěné funkce. Nejzřetelnějším příkladem je:

  • address.send() – Solidity
  • send(address) – Vyper

Ty umožňují posílat ETH na jiné účty.

Psaní funkcí

Vaše funkce potřebuje:

  • parametr a jeho datový typ (pokud parametry přijímá)
  • deklaraci, zda je internal/external
  • deklaraci, zda je pure/view/payable
  • datový typ návratové hodnoty (pokud nějakou vrací)
1pragma solidity >=0.4.0 <=0.6.0;
2
3contract ExampleDapp {
4 string dapp_name; // stavová proměnná
5
6 // Volá se při nasazení kontraktu a inicializuje hodnotu
7 constructor() public {
8 dapp_name = "My Example dapp";
9 }
10
11 // Funkce pro získání (Get)
12 function read_name() public view returns(string) {
13 return dapp_name;
14 }
15
16 // Funkce pro nastavení (Set)
17 function update_name(string value) public {
18 dapp_name = value;
19 }
20}
Zobrazit vše

Kompletní kontrakt může vypadat následovně. Zde funkce constructor poskytuje počáteční hodnotu proměnné dapp_name.

Události a záznamy

Události umožňují vašemu chytrému kontraktu komunikovat s vaším frontendem nebo jinými přihlášenými aplikacemi. Jakmile je transakce ověřena a přidána do bloku, mohou chytré kontrakty vysílat události a zaznamenávat informace, které pak frontend může zpracovat a využít.

Příklady s poznámkami

Zde jsou příklady napsané v Solidity. Pokud si chcete s kódem pohrát, můžete s ním interagovat v Remixu (opens in a new tab).

Hello world

1// Určuje verzi Solidity pomocí sémantického verzování.
2// Více informací: https://solidity.readthedocs.io/en/v0.5.10/layout-of-source-files.html#pragma
3pragma solidity ^0.5.10;
4
5// Definuje kontrakt s názvem `HelloWorld`.
6// Kontrakt je soubor funkcí a dat (jeho stav).
7// Po nasazení se kontrakt nachází na specifické adrese na ethereovém blockchainu.
8// Více informací: https://solidity.readthedocs.io/en/v0.5.10/structure-of-a-contract.html
9contract HelloWorld {
10
11 // Deklaruje stavovou proměnnou `message` typu `string`.
12 // Stavové proměnné jsou proměnné, jejichž hodnoty jsou trvale uloženy v úložišti kontraktu.
13 // Klíčové slovo `public` zpřístupňuje proměnné zvenčí kontraktu
14 // a vytváří funkci, kterou mohou jiné kontrakty nebo klienti volat pro přístup k hodnotě.
15 string public message;
16
17 // Podobně jako v mnoha objektově orientovaných jazycích založených na třídách je konstruktor
18 // speciální funkce, která se provádí pouze při vytvoření kontraktu.
19 // Konstruktory se používají k inicializaci dat kontraktu.
20 // Více informací: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#constructors
21 constructor(string memory initMessage) public {
22 // Přijímá argument `initMessage` typu string a nastavuje hodnotu
23 // do úložné proměnné kontraktu `message`.
24 message = initMessage;
25 }
26
27 // Veřejná funkce, která přijímá argument typu string
28 // a aktualizuje úložnou proměnnou `message`.
29 function update(string memory newMessage) public {
30 message = newMessage;
31 }
32}
Zobrazit vše

Token

1pragma solidity ^0.5.10;
2
3contract Token {
4 // Typ `address` je srovnatelný s e-mailovou adresou – používá se k identifikaci účtu na Ethereu.
5 // Adresy mohou představovat chytrý kontrakt nebo externí (uživatelské) účty.
6 // Více informací: https://solidity.readthedocs.io/en/v0.5.10/types.html#address
7 address public owner;
8
9 // `mapping` je v podstatě datová struktura hašovací tabulky.
10 // Tento `mapping` přiřazuje celé číslo bez znaménka (zůstatek tokenů) k adrese (držiteli tokenů).
11 // Více informací: https://solidity.readthedocs.io/en/v0.5.10/types.html#mapping-types
12 mapping (address => uint) public balances;
13
14 // Události umožňují zaznamenávat aktivitu na blockchainu.
15 // Klienti Etherea mohou naslouchat událostem, aby mohli reagovat na změny stavu kontraktu.
16 // Více informací: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#events
17 event Transfer(address from, address to, uint amount);
18
19 // Inicializuje data kontraktu, nastaví `owner`
20 // na adresu tvůrce kontraktu.
21 constructor() public {
22 // Všechny chytré kontrakty spoléhají na externí transakce, které spouští jejich funkce.
23 // `msg` je globální proměnná, která obsahuje relevantní údaje o dané transakci,
24 // jako je adresa odesílatele a hodnota ETH obsažená v transakci.
25 // Více informací: https://solidity.readthedocs.io/en/v0.5.10/units-and-global-variables.html#block-and-transaction-properties
26 owner = msg.sender;
27 }
28
29 // Vytvoří množství nových tokenů a pošle je na adresu.
30 function mint(address receiver, uint amount) public {
31 // `require` je řídicí struktura používaná k vynucení určitých podmínek.
32 // Pokud se příkaz `require` vyhodnotí jako `false`, dojde k výjimce,
33 // která vrátí všechny změny stavu provedené během aktuálního volání.
34 // Více informací: https://solidity.readthedocs.io/en/v0.5.10/control-structures.html#error-handling-assert-require-revert-and-exceptions
35
36 // Tuto funkci může volat pouze vlastník kontraktu
37 require(msg.sender == owner, "You are not the owner.");
38
39 // Vynucuje maximální množství tokenů
40 require(amount < 1e60, "Maximum issuance exceeded");
41
42 // Zvýší zůstatek `receiver` o `amount`
43 balances[receiver] += amount;
44 }
45
46 // Odesílá množství existujících tokenů od libovolného volajícího na adresu.
47 function transfer(address receiver, uint amount) public {
48 // Odesílatel musí mít dostatek tokenů k odeslání
49 require(amount <= balances[msg.sender], "Insufficient balance.");
50
51 // Upravuje zůstatky tokenů na obou adresách
52 balances[msg.sender] -= amount;
53 balances[receiver] += amount;
54
55 // Vysílá dříve definovanou událost
56 emit Transfer(msg.sender, receiver, amount);
57 }
58}
Zobrazit vše

Unikátní digitální aktivum

1pragma solidity ^0.5.10;
2
3// Importuje symboly z jiných souborů do aktuálního kontraktu.
4// V tomto případě se jedná o sérii pomocných kontraktů z OpenZeppelin.
5// Více informací: https://solidity.readthedocs.io/en/v0.5.10/layout-of-source-files.html#importing-other-source-files
6
7import "../node_modules/@openzeppelin/contracts/token/ERC721/IERC721.sol";
8import "../node_modules/@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";
9import "../node_modules/@openzeppelin/contracts/introspection/ERC165.sol";
10import "../node_modules/@openzeppelin/contracts/math/SafeMath.sol";
11
12// Klíčové slovo `is` se používá k dědění funkcí a klíčových slov z externích kontraktů.
13// V tomto případě `CryptoPizza` dědí z kontraktů `IERC721` a `ERC165`.
14// Více informací: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#inheritance
15contract CryptoPizza is IERC721, ERC165 {
16 // Používá knihovnu SafeMath od OpenZeppelin k bezpečnému provádění aritmetických operací.
17 // Více informací: https://docs.openzeppelin.com/contracts/2.x/api/math#SafeMath
18 using SafeMath for uint256;
19
20 // Konstantní stavové proměnné v Solidity jsou podobné jako v jiných jazycích
21 // ale musíte je přiřadit z výrazu, který je konstantní v době kompilace.
22 // Více informací: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#constant-state-variables
23 uint256 constant dnaDigits = 10;
24 uint256 constant dnaModulus = 10 ** dnaDigits;
25 bytes4 private constant _ERC721_RECEIVED = 0x150b7a02;
26
27 // Typy `struct` umožňují definovat vlastní typ
28 // Více informací: https://solidity.readthedocs.io/en/v0.5.10/types.html#structs
29 struct Pizza {
30 string name;
31 uint256 dna;
32 }
33
34 // Vytvoří prázdné pole struktur Pizza
35 Pizza[] public pizzas;
36
37 // Mapování z ID pizzy na adresu jejího vlastníka
38 mapping(uint256 => address) public pizzaToOwner;
39
40 // Mapování z adresy vlastníka na počet vlastněných tokenů
41 mapping(address => uint256) public ownerPizzaCount;
42
43 // Mapování z ID tokenu na schválenou adresu
44 mapping(uint256 => address) pizzaApprovals;
45
46 // Mapování lze vnořovat, tento příklad mapuje vlastníka na schválení operátora
47 mapping(address => mapping(address => bool)) private operatorApprovals;
48
49 // Interní funkce pro vytvoření náhodné pizzy z řetězce (jméno) a DNA
50 function _createPizza(string memory _name, uint256 _dna)
51 // Klíčové slovo `internal` znamená, že tato funkce je viditelná pouze
52 // v rámci tohoto kontraktu a kontraktů, které z něj dědí
53 // Více informací: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#visibility-and-getters
54 internal
55 // `isUnique` je modifikátor funkce, který kontroluje, zda pizza již existuje
56 // Více informací: https://solidity.readthedocs.io/en/v0.5.10/structure-of-a-contract.html#function-modifiers
57 isUnique(_name, _dna)
58 {
59 // Přidá pizzu do pole pizz a získá ID
60 uint256 id = SafeMath.sub(pizzas.push(Pizza(_name, _dna)), 1);
61
62 // Kontroluje, zda je vlastník pizzy stejný jako aktuální uživatel
63 // Více informací: https://solidity.readthedocs.io/en/v0.5.10/control-structures.html#error-handling-assert-require-revert-and-exceptions
64
65 // Všimněte si, že address(0) je nulová adresa,
66 // což znamená, že pizza[id] ještě není přidělena konkrétnímu uživateli.
67
68 assert(pizzaToOwner[id] == address(0));
69
70 // Mapuje pizzu na vlastníka
71 pizzaToOwner[id] = msg.sender;
72 ownerPizzaCount[msg.sender] = SafeMath.add(
73 ownerPizzaCount[msg.sender],
74 1
75 );
76 }
77
78 // Vytvoří náhodnou pizzu z řetězce (jméno)
79 function createRandomPizza(string memory _name) public {
80 uint256 randDna = generateRandomDna(_name, msg.sender);
81 _createPizza(_name, randDna);
82 }
83
84 // Generuje náhodné DNA z řetězce (jméno) a adresy vlastníka (tvůrce)
85 function generateRandomDna(string memory _str, address _owner)
86 public
87 // Funkce označené jako `pure` slibují, že nebudou číst ani upravovat stav
88 // Více informací: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#pure-functions
89 pure
90 returns (uint256)
91 {
92 // Generuje náhodné uint z řetězce (jméno) + adresy (vlastník)
93 uint256 rand = uint256(keccak256(abi.encodePacked(_str))) +
94 uint256(_owner);
95 rand = rand % dnaModulus;
96 return rand;
97 }
98
99 // Vrací pole pizz nalezených podle vlastníka
100 function getPizzasByOwner(address _owner)
101 public
102 // Funkce označené jako `view` slibují, že nebudou upravovat stav
103 // Více informací: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#view-functions
104 view
105 returns (uint256[] memory)
106 {
107 // Používá `memory` jako umístění úložiště pro uložení hodnot pouze pro
108 // životní cyklus tohoto volání funkce.
109 // Více informací: https://solidity.readthedocs.io/en/v0.5.10/introduction-to-smart-contracts.html#storage-memory-and-the-stack
110 uint256[] memory result = new uint256[](ownerPizzaCount[_owner]);
111 uint256 counter = 0;
112 for (uint256 i = 0; i < pizzas.length; i++) {
113 if (pizzaToOwner[i] == _owner) {
114 result[counter] = i;
115 counter++;
116 }
117 }
118 return result;
119 }
120
121 // Převádí pizzu a vlastnictví na jinou adresu
122 function transferFrom(address _from, address _to, uint256 _pizzaId) public {
123 require(_from != address(0) && _to != address(0), "Invalid address.");
124 require(_exists(_pizzaId), "Pizza does not exist.");
125 require(_from != _to, "Cannot transfer to the same address.");
126 require(_isApprovedOrOwner(msg.sender, _pizzaId), "Address is not approved.");
127
128 ownerPizzaCount[_to] = SafeMath.add(ownerPizzaCount[_to], 1);
129 ownerPizzaCount[_from] = SafeMath.sub(ownerPizzaCount[_from], 1);
130 pizzaToOwner[_pizzaId] = _to;
131
132 // Vysílá událost definovanou v importovaném kontraktu IERC721
133 emit Transfer(_from, _to, _pizzaId);
134 _clearApproval(_to, _pizzaId);
135 }
136
137 /**
138 * Bezpečně převede vlastnictví daného ID tokenu na jinou adresu
139 * Pokud je cílová adresa kontrakt, musí implementovat `onERC721Received`,
140 * která se volá při bezpečném převodu a vrátí magickou hodnotu
141 * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`;
142 * jinak se převod vrátí zpět.
143 */
144 function safeTransferFrom(address from, address to, uint256 pizzaId)
145 public
146 {
147 // solium-disable-next-line arg-overflow
148 this.safeTransferFrom(from, to, pizzaId, "");
149 }
150
151 /**
152 * Bezpečně převede vlastnictví daného ID tokenu na jinou adresu
153 * Pokud je cílová adresa kontrakt, musí implementovat `onERC721Received`,
154 * která se volá při bezpečném převodu a vrátí magickou hodnotu
155 * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`;
156 * jinak se převod vrátí zpět.
157 */
158 function safeTransferFrom(
159 address from,
160 address to,
161 uint256 pizzaId,
162 bytes memory _data
163 ) public {
164 this.transferFrom(from, to, pizzaId);
165 require(_checkOnERC721Received(from, to, pizzaId, _data), "Must implement onERC721Received.");
166 }
167
168 /**
169 * Interní funkce pro vyvolání `onERC721Received` na cílové adrese
170 * Volání se neprovede, pokud cílová adresa není kontrakt
171 */
172 function _checkOnERC721Received(
173 address from,
174 address to,
175 uint256 pizzaId,
176 bytes memory _data
177 ) internal returns (bool) {
178 if (!isContract(to)) {
179 return true;
180 }
181
182 bytes4 retval = IERC721Receiver(to).onERC721Received(
183 msg.sender,
184 from,
185 pizzaId,
186 _data
187 );
188 return (retval == _ERC721_RECEIVED);
189 }
190
191 // Spálí pizzu - kompletně zničí token
192 // Modifikátor funkce `external` znamená, že tato funkce je
193 // součástí rozhraní kontraktu a mohou ji volat jiné kontrakty
194 function burn(uint256 _pizzaId) external {
195 require(msg.sender != address(0), "Invalid address.");
196 require(_exists(_pizzaId), "Pizza does not exist.");
197 require(_isApprovedOrOwner(msg.sender, _pizzaId), "Address is not approved.");
198
199 ownerPizzaCount[msg.sender] = SafeMath.sub(
200 ownerPizzaCount[msg.sender],
201 1
202 );
203 pizzaToOwner[_pizzaId] = address(0);
204 }
205
206 // Vrací počet pizz podle adresy
207 function balanceOf(address _owner) public view returns (uint256 _balance) {
208 return ownerPizzaCount[_owner];
209 }
210
211 // Vrací vlastníka pizzy nalezeného podle ID
212 function ownerOf(uint256 _pizzaId) public view returns (address _owner) {
213 address owner = pizzaToOwner[_pizzaId];
214 require(owner != address(0), "Invalid Pizza ID.");
215 return owner;
216 }
217
218 // Schvaluje jinou adresu k převodu vlastnictví pizzy
219 function approve(address _to, uint256 _pizzaId) public {
220 require(msg.sender == pizzaToOwner[_pizzaId], "Must be the Pizza owner.");
221 pizzaApprovals[_pizzaId] = _to;
222 emit Approval(msg.sender, _to, _pizzaId);
223 }
224
225 // Vrací schválenou adresu pro konkrétní pizzu
226 function getApproved(uint256 _pizzaId)
227 public
228 view
229 returns (address operator)
230 {
231 require(_exists(_pizzaId), "Pizza does not exist.");
232 return pizzaApprovals[_pizzaId];
233 }
234
235 /**
236 * Soukromá funkce pro zrušení aktuálního schválení daného ID tokenu
237 * Vrátí se zpět, pokud daná adresa není skutečně vlastníkem tokenu
238 */
239 function _clearApproval(address owner, uint256 _pizzaId) private {
240 require(pizzaToOwner[_pizzaId] == owner, "Must be pizza owner.");
241 require(_exists(_pizzaId), "Pizza does not exist.");
242 if (pizzaApprovals[_pizzaId] != address(0)) {
243 pizzaApprovals[_pizzaId] = address(0);
244 }
245 }
246
247 /*
248 * Nastavuje nebo ruší schválení daného operátora
249 * Operátor má povoleno převádět všechny tokeny odesílatele jeho jménem
250 */
251 function setApprovalForAll(address to, bool approved) public {
252 require(to != msg.sender, "Cannot approve own address");
253 operatorApprovals[msg.sender][to] = approved;
254 emit ApprovalForAll(msg.sender, to, approved);
255 }
256
257 // Sdělí, zda je operátor schválen daným vlastníkem
258 function isApprovedForAll(address owner, address operator)
259 public
260 view
261 returns (bool)
262 {
263 return operatorApprovals[owner][operator];
264 }
265
266 // Přebírá vlastnictví pizzy - pouze pro schválené uživatele
267 function takeOwnership(uint256 _pizzaId) public {
268 require(_isApprovedOrOwner(msg.sender, _pizzaId), "Address is not approved.");
269 address owner = this.ownerOf(_pizzaId);
270 this.transferFrom(owner, msg.sender, _pizzaId);
271 }
272
273 // Kontroluje, zda pizza existuje
274 function _exists(uint256 pizzaId) internal view returns (bool) {
275 address owner = pizzaToOwner[pizzaId];
276 return owner != address(0);
277 }
278
279 // Kontroluje, zda je adresa vlastníkem nebo je schválena k převodu pizzy
280 function _isApprovedOrOwner(address spender, uint256 pizzaId)
281 internal
282 view
283 returns (bool)
284 {
285 address owner = pizzaToOwner[pizzaId];
286 // Vypnout kontrolu solium kvůli
287 // https://github.com/duaraghav8/Solium/issues/175
288 // solium-disable-next-line operator-whitespace
289 return (spender == owner ||
290 this.getApproved(pizzaId) == spender ||
291 this.isApprovedForAll(owner, spender));
292 }
293
294 // Zkontrolujte, zda je pizza jedinečná a ještě neexistuje
295 modifier isUnique(string memory _name, uint256 _dna) {
296 bool result = true;
297 for (uint256 i = 0; i < pizzas.length; i++) {
298 if (
299 keccak256(abi.encodePacked(pizzas[i].name)) ==
300 keccak256(abi.encodePacked(_name)) &&
301 pizzas[i].dna == _dna
302 ) {
303 result = false;
304 }
305 }
306 require(result, "Pizza with such name already exists.");
307 _;
308 }
309
310 // Vrací, zda je cílová adresa kontrakt
311 function isContract(address account) internal view returns (bool) {
312 uint256 size;
313 // V současné době neexistuje lepší způsob, jak zkontrolovat, zda je na adrese kontrakt
314 // než zkontrolovat velikost kódu na dané adrese.
315 // Viz https://ethereum.stackexchange.com/a/14016/36603
316 // pro více detailů o tom, jak to funguje.
317 // TODO Zkontrolovat znovu před vydáním Serenity, protože všechny adresy budou
318 // poté kontrakty.
319 // solium-disable-next-line security/no-inline-assembly
320 assembly {
321 size := extcodesize(account)
322 }
323 return size > 0;
324 }
325}
Zobrazit vše

Další čtení

Kompletní přehled chytrých kontraktů najdete v dokumentaci Solidity a Vyper:

Byl tento článek užitečný?