Lanjut ke konten utama
Change page

Anatomi kontrak pintar

Terakhir diedit: @yeremiaryangunadi(opens in a new tab), 14 Juni 2024

Kontrak pintar adalah program yang dijalankan pada sebuah alamat di Ethereum. Kontrak pintar terbuat dari data dan fungsi yang bisa dieksekusi saat menerima sebuah transaksi. Berikut adalah gambaran umum dari komponen yang menyusun sebuah kontrak pintar.

Prasyarat

Pastikan Anda telah membaca tentang kontrak pintar terlebih dahulu. Dokumen ini menganggap Anda telah terbiasa dengan bahasa pemrograman seperti JavaScript atau Python.

Data

Setiap data kontrak harus ditetapkan ke suatu lokasi: baik ke storage atau memory. Untuk memodifikasi penyimpanan di sebuah kontrak pintar biayanya mahal, jadi Anda perlu mempertimbangkan tempat untuk menyimpan data Anda.

Penyimpanan

Data yang persisten dirujuk sebagai penyimpanan dan diwakilkan oleh variabel state. Nilai-nilai ini disimpan secara permanen di blockchain. Anda perlu mendeklarasikan jenisnya sehingga kontrak bisa tetap melacak kapasitas penyimpanan pada blockchain yang diperlukan kontrak ketika dikompilasi.

1// Contoh Solidity
2contract SimpleStorage {
3 uint storedData; // State variable
4 // ...
5}
Salin
1# Vyper example
2storedData: int128
Salin

Jika Anda telah memprogram bahasa yang berorientasi objek, Anda mungkin akan lebih mengenal sebagian besar jenisnya. Namun address mungkin terdengar asing jika Anda seorang pengembang pemula di Ethereum.

Suatu jenis address bisa menampung alamat Ethereum yang setara dengan 20 bita atau 160 bit. Alamat kembali dalam notasi heksadesimal dengan awalan 0x.

Jenis lainnya meliputi:

  • boolean
  • bilangan bulat
  • angka poin tetap
  • array bita berukuran tetap
  • array bita berukuran dinamis
  • Literal rasional dan bilangan bulat
  • Literal string
  • Literal heksadesimal
  • Enum

Untuk penjelasan lebih lanjut, lihat dokumen:

Memori

Nilai yang hanya disimpan selama masa eksekusi fungsi kontrak disebut variabel memori. Karena nilai ini tidak disimpan secara permanen di blockchain, lebih murah untuk digunakan.

Pelajari selengkapnya tentang cara EVM menyimpan data (Penyimpanan, Memori, dan Tumpukan) di dokumen Solidity(opens in a new tab).

Variabel lingkungan

Selain variabel yang Anda tetapkan pada kontrak, ada beberapa variabel global khusus. Variabel ini terutama digunakan untuk memberikan informasi tentang blockchain atau transaksi saat ini.

Contoh:

PropVariabel stateDeskripsi
block.timestampuint256Stempel waktu epoch blok saat ini
msg.senderalamatPengirim pesan (pemanggilan saat ini)

Fungsi

Dalam istilah yang paling sederhana, fungsi bisa mendapatkan informasi atau mengatur informasi dalam menanggapi transaksi yang masuk.

Ada dua jenis pemanggilan fungsi:

  • internal - ini tidak menghasilkan pemanggilan EVM
    • Fungsi internal dan variabel state hanya bisa diakses secara internal (yaitu dari dalam kontrak saat ini atau kontrak yang diturunkan darinya)
  • external - ini menghasilkan pemanggilan EVM
    • Fungsi eksternal adalah bagian dari antarmuka kontrak, yang berarti bisa dipanggil dari kontrak lain dan melalui transaksi. Fungsi eksternal f tidak bisa dipanggil secara internal (yaitu f() tidak berfungsi, tapi this.f() dapat berfungsi).

Fungsi pemanggilan juga bisa bersifat public atau private

  • Fungsi public bisa dipanggil secara internal dari dalam kontrak atau secara eksternal melalui message
  • Fungsi private hanya terlihat untuk kontrak yang ditetapkan di dalam dan bukan dalam kontrak turunan

Kedua fungsi dan variabel state ini bisa dibuat menjadi publik atau privat

Berikut adalah fungsi untuk memperbarui variabel state dalam sebuah kontrak:

1// Contoh Solidity
2function update_name(string value) public {
3 dapp_name = value;
4}
Salin
  • Nilai parameter dari string jenis diteruskan ke dalam fungsi: update_name
  • Fungsi dideklarasikan sebagai public, berarti siapa pun bisa mengaksesnya
  • Fungsi tidak dideklarasikan sebagai view, sehingga bisa memodifikasi state kontrak

Fungsi view

Fungsi ini berjanji untuk tidak memodifikasi state dari data kontrak. Contoh umumnya adalah fungsi "pengambil" – Anda mungkin menggunakan ini untuk mendapatkan saldo pengguna sebagai contohnya.

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

Apa yang dianggap sebagai memodifikasi state:

  1. Menulis ke dalam variabel state.
  2. Menerbitkan aksi(opens in a new tab).
  3. Membuat kontrak lain(opens in a new tab).
  4. Menggunakan selfdestruct.
  5. Mengirim eter melalui panggilan.
  6. Memanggil fungsi apa pun yang tidak bertanda view atau pure.
  7. Menggunakan pemanggilan level rendah.
  8. Menggunakan perakitan sebaris yang berisi opcode tertentu.

Fungsi pembangun

Fungsi constructor hanya dijalankan sekali saat kontrak digunakan untuk pertama kalinya. Seperti constructor di banyak bahasa pemrograman berbasis kelas, fungsi ini sering menjalankan variabel state sesuai dengan nilai yang telah ditentukan.

1// Contoh Solidity
2// Jalankan data kontrak, siapkan `pemilik`
3// sesuai dengan alamat dari pembuat kontrak.
4constructor() public {
5 // Semua kontrak pintar bergantung pada transaksi eksternal untuk memicu fungsinya.
6 // `msg` adalah sebuah variabel global yang mencakup data relevan sesuai dengan transaksi yang telah disiapkan,
7 // seperti alamat dari pengirim dan nilai ETH yang termasuk dalam transaksi.
8 // Pelajari lebih banyak: https://solidity.readthedocs.io/en/v0.5.10/units-and-global-variables.html#block-and-transaction-properties
9 owner = msg.sender;
10}
Tampilkan semua
Salin
1# contoh Vyper
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
Salin

Fungsi bawaan

Selain dari variabel dan fungsi yang Anda tetapkan pada kontrak Anda, ada beberapa fungsi bawaan spesial. Contoh paling jelas adalah:

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

Ini memungkinkan kontrak untuk mengirim ETH ke akun lain.

Menulis fungsi

Fungsi Anda memerlukan:

  • variabel dan tipe parameter (jika fungsi menerima parameter)
  • deklarasi internal/eksternal
  • deklarasi pure/view/payable
  • tipe pengembalian (jika fungsi mengembalikan nilai)
1pragma solidity >=0.4.0 <=0.6.0;
2
3contract ExampleDapp {
4 string dapp_name; // state variable
5
6 // Dipanggil saat kontrak disebarkan dan jalankan nilai
7 constructor() public {
8 dapp_name = "My Example dapp";
9 }
10
11 // Fungsi Get
12 function read_name() public view returns(string) {
13 return dapp_name;
14 }
15
16 // Tetapkan Fungsi
17 function update_name(string value) public {
18 dapp_name = value;
19 }
20}
Tampilkan semua
Salin

Sebuah kontrak lengkap mungkin tampak seperti ini. Di sini, fungsi constructor menyediakan nilai awal untuk variabel dapp_name.

Aksi dan log

Aksi memungkinkan Anda berkomunikasi dengan kontrak pintar dari frontend Anda atau aplikasi berbayar lainnya. Ketika sebuah transaksi ditambang, kontrak pintar bisa menerbitkan aksi dan menulis log pada blockchain yang kemudian dapat diproses frontend.

Contoh dengan anotasi

Ini adalah beberapa contoh yang ditulis dalam Solidity. Jika Anda ingin bermain dengan kode tersebut, Anda dapat berinteraksi dengannya di Remix(opens in a new tab).

Hello world

1// Tentukan versi Solidity, gunakan pembuatan versi semantik.
2// Pelajari lebih banyak: https://solidity.readthedocs.io/en/v0.5.10/layout-of-source-files.html#pragma
3pragma solidity ^0.5.10;
4
5// Tentukan sebuah kontak bernama `HaloDunia`.
6// Satu kontrak adalah koleksi dari fungsi dan data (statenya).
7// Setelah disebarkan, sebuah kontrak tinggal di alamat spesifik pada blockchain Ethereum.
8// Pelajari lebih banyak: https://solidity.readthedocs.io/en/v0.5.10/structure-of-a-contract.html
9contract HelloWorld {
10
11 // Deklarasikan `message` variabel state dari `string` tipe.
12 // Variabel state adalah variabel yang nilainya secara permanen disimpan dalam penyimpanan kontrak.
13 // Kata kunci `publik` membuat variabel dapat diakses dari luar kontrak
14 //dan menciptakan fungsi yang dengannya kontrak atau klien lain bisa memanggil untuk mengakses nilai.
15 string public message;
16
17 // Sama seperti banyak bahasa berorientasi objek yang berbasis kelas, sebuah pembangun adalah
18 // sebuah fungsi spesial yang hanya dieksekusi saat pembuatan kontrak.
19 // Pembangun digunakan untuk menjalankan data kontrak.
20 // Pelajari lebih banyak: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#constructors
21 constructor(string memory initMessage) public {
22 // Menerima satu argumen string `initMessage` dan tetapkan nilai
23 // ke dalam variabel penyimpanan `message` kontrak).
24 message = initMessage;
25 }
26
27 // Sebuah fungsi publik yang menerima argumen string
28 // dan memperbarui variabel penyimpanan`message`.
29 function update(string memory newMessage) public {
30 message = newMessage;
31 }
32}
Tampilkan semua
Salin

Token

1pragma solidity ^0.5.10;
2
3contract Token {
4 //Sebuah `alamat` dapat disamakan dengan sebuah alamat email - ia digunakan untuk mengidentifikasi sebuah akun di Ethereum.
5 // Alamat bisa mewakilkan sebuah kontrak pintar atau satu akun (pengguna) eksternal.
6 // Pelajari lebih banyak: https://solidity.readthedocs.io/en/v0.5.10/types.html#address
7 address public owner;
8
9 // Sebuah `mapping` adalah satu struktur data tabel hash.
10 // `mapping` ini menetapkan sebuah integer yang tidak ditentukan (saldo token) pada sebuah alamat (pemilik token).
11 // Pelajari lebih banyak: https://solidity.readthedocs.io/en/v0.5.10/types.html#mapping-types
12 mapping (address => uint) public balances;
13
14 // Aksi memungkinkan logging aktivitas pada blockchain.
15 // Klien Ethereum bisa mendengarkan aksi untuk bereaksi dengan perubahan state kontrak.
16 // Pelajari lebih banyak: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#events
17 event Transfer(address from, address to, uint amount);
18
19 // Jalankan data kontrak, siapkan `pemilik`
20 // di alamat dari pembuat kontrak.
21 constructor() public {
22 // Semua kontrak pintar bergantung pada transaksi eksternal untuk memicu fungsinya.
23 // `msg` adalah sebuah variabel global yang telah mencakup data relevan sesuai dengan transaksi yang telah disiapkan,
24 // seperti alamat dari pengirim dan nilai ETH yang termasuk dalam transaksi.
25 // Pelajari lebih banyak: https://solidity.readthedocs.io/en/v0.5.10/units-and-global-variables.html#block-and-transaction-properties
26 owner = msg.sender;
27 }
28
29 // Membuat sejumlah token baru dan mengirimkan mereka ke satu alamat.
30 function mint(address receiver, uint amount) public {
31 // `require` is struktur kontrol yang digunakan untuk melaksanakan kondisi tertentu.
32 // Jika sebuah pernyataan `require` mengevaluasi ke `palsu`, satu pengecualian terpicu,
33 // yang membalikkan semua perubahan yang dibuat pada state selama pemanggilan saat ini.
34 //Pelajari lebih banyak: https://solidity.readthedocs.io/en/v0.5.10/control-structures.html#error-handling-assert-require-revert-and-exceptions
35
36 // Hanya pemilik kontrak yang bisa memanggil fungsi ini
37 require(msg.sender == owner, "You are not the owner.");
38
39 // Melaksanakan sejumlah maksimum token
40 require(amount < 1e60, "Maximum issuance exceeded");
41
42 // Meningkatkan saldo dari `receiver` dalam `amount`
43 balances[receiver] += amount;
44 }
45
46 // Mengirim sejumlah token yang ada dari pemanggil manapun ke satu alamat.
47 function transfer(address receiver, uint amount) public {
48 // Pengirim harus punya token cukup untuk mengirim
49 require(amount <= balances[msg.sender], "Insufficient balance.");
50
51 // Sesuaikan saldo token dari dua alamat
52 balances[msg.sender] -= amount;
53 balances[receiver] += amount;
54
55 // Terbitkan aksi yang telah ditentukan sebelumnya
56 emit Transfer(msg.sender, receiver, amount);
57 }
58}
Tampilkan semua
Salin

Aset digital unik

1pragma solidity ^0.5.10;
2
3// Impor simbol dari berkas lain ke dalam kontrak saat ini.
4// Dalam kasus ini, sejumlah kontrak penolong dari OpenZeppelin.
5// Pelajari lebih banyak: 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// Kata kunci `is` digunakan untuk mewarisi fungsi dan kata kunci dari kontrak eksternal.
13// Dalam kasus ini, `CryptoPizza` mewarisi dari kontrak `IERC721` dan `ERC165`.
14// Pelajari lebih banyak: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#inheritance
15contract CryptoPizza is IERC721, ERC165 {
16 // Gunakan pustaka Safe Math OpenZeppelin untuk melakukan operasi aritmatika dengan aman.
17 // Pelajari lebih banyak: https://docs.openzeppelin.com/contracts/2.x/api/math#SafeMath
18 using SafeMath for uint256;
19
20 // Variabel state konstan di Solidity sama dengan bahasa lainnya
21 // tapi Anda harus menetapkan satu ekpresi yang konstan pada waktu pengompilasian.
22 // Learn more: 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 // Struct types let you define your own type
28 // Learn more: https://solidity.readthedocs.io/en/v0.5.10/types.html#structs
29 struct Pizza {
30 string name;
31 uint256 dna;
32 }
33
34 // Creates an empty array of Pizza structs
35 Pizza[] public pizzas;
36
37 // Mapping from pizza ID to its owner's address
38 mapping(uint256 => address) public pizzaToOwner;
39
40 // Mapping from owner's address to number of owned token
41 mapping(address => uint256) public ownerPizzaCount;
42
43 // Mapping from token ID to approved address
44 mapping(uint256 => address) pizzaApprovals;
45
46 // You can nest mappings, this example maps owner to operator approvals
47 mapping(address => mapping(address => bool)) private operatorApprovals;
48
49 // Internal function to create a random Pizza from string (name) and DNA
50 function _createPizza(string memory _name, uint256 _dna)
51 // The `internal` keyword means this function is only visible
52 // within this contract and contracts that derive this contract
53 // Learn more: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#visibility-and-getters
54 internal
55 // `isUnique` is a function modifier that checks if the pizza already exists
56 // Learn more: https://solidity.readthedocs.io/en/v0.5.10/structure-of-a-contract.html#function-modifiers
57 isUnique(_name, _dna)
58 {
59 // Adds Pizza to array of Pizzas and get id
60 uint256 id = SafeMath.sub(pizzas.push(Pizza(_name, _dna)), 1);
61
62 // Checks that Pizza owner is the same as current user
63 // Learn more: https://solidity.readthedocs.io/en/v0.5.10/control-structures.html#error-handling-assert-require-revert-and-exceptions
64
65 // note that address(0) is the zero address,
66 // indicating that pizza[id] is not yet allocated to a particular user.
67
68 assert(pizzaToOwner[id] == address(0));
69
70 // Maps the Pizza to the owner
71 pizzaToOwner[id] = msg.sender;
72 ownerPizzaCount[msg.sender] = SafeMath.add(
73 ownerPizzaCount[msg.sender],
74 1
75 );
76 }
77
78 // Creates a random Pizza from string (name)
79 function createRandomPizza(string memory _name) public {
80 uint256 randDna = generateRandomDna(_name, msg.sender);
81 _createPizza(_name, randDna);
82 }
83
84 // Generates random DNA from string (name) and address of the owner (creator)
85 function generateRandomDna(string memory _str, address _owner)
86 public
87 // Functions marked as `pure` promise not to read from or modify the state
88 // Learn more: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#pure-functions
89 pure
90 returns (uint256)
91 {
92 // Generates random uint from string (name) + address (owner)
93 uint256 rand = uint256(keccak256(abi.encodePacked(_str))) +
94 uint256(_owner);
95 rand = rand % dnaModulus;
96 return rand;
97 }
98
99 // Returns array of Pizzas found by owner
100 function getPizzasByOwner(address _owner)
101 public
102 // Functions marked as `view` promise not to modify state
103 // Learn more: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#view-functions
104 view
105 returns (uint256[] memory)
106 {
107 // Uses the `memory` storage location to store values only for the
108 // lifecycle of this function call.
109 // Pelajari lebih banyak: 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 // Mentransfer Pizza dan kepemilikan ke alamat lain
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 // Terbitkan aksi yang ditentukan di kontrak IERC721 yang diimpor
133 emit Transfer(_from, _to, _pizzaId);
134 _clearApproval(_to, _pizzaId);
135 }
136
137 /**
138 * Transfer dengan aman kepemilikan dari ID token yang disediakan ke alamat lain
139 * Jika alamat target adalah sebuah kontrak, ia harus mengimplementasi ``onERC721Received`,
140 * yang dipanggil saat satu transfer aman, dan mengembalikan nilai ajaib
141 * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`;
142 * jika tidak, transfer dibalikkan.
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 * Transfer dengan aman kepemilikan dari ID token yang disediakan ke alamat lain
153 * Jika alamat target adalah satu kontrak, ia harus mengimplementasi `onERC721Received`,
154 * yang dipanggil saat satu transfer aman, dan mengembalikan nilai ajaib
155 * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`;
156 * jika tidak, transfer dibalikkan.
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 implmement onERC721Received.");
166 }
167
168 /**
169 * Fungsi internal untuk memohon `onERC721Received` pada satu alamat target
170 * Pemanggilan tidak dieksekusi jika alamat target bukan sebuah kontrak
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 // Bakar satu Pizza - hancurkan Token secara total
192 // Modifier fungsi `external` berarti fungsi ini adalah
193 // bagian dari antarmuka kontrak dan kontrak lain bisa memanggilnya
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 // Kembalikan penghitungan Pizza lewat alamat
207 function balanceOf(address _owner) public view returns (uint256 _balance) {
208 return ownerPizzaCount[_owner];
209 }
210
211 // Kembalikan pemilik Pizza yang ditemukan 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 // Setujui alamat lain untuk mentransfer kepemilikan Pizza
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 // Kembalikan alamat yang disetujui untuk Pizza spesifik
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 * Fungsi privat untuk menghapus persetujuan saat ini dari ID token yang disediakan
237 * Balikkan jika alamat yang disediakan memang bukan pemilik token
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 * Siapkan atau batalkan persetujuan untuk operator yang disediakan
249 * Seorang operator diizinkan untuk mentransfer semua token dari pengirim atas nama mereka
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 // Beritahu apakah seorang operator disetujui oleh seorang pemilik yang disediakan
258 function isApprovedForAll(address owner, address operator)
259 public
260 view
261 returns (bool)
262 {
263 return operatorApprovals[owner][operator];
264 }
265
266 // Ambil kepemilikan Pizza - hanya untuk pengguna yang disetujui
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 // Periksa apakah Pizza ada
274 function _exists(uint256 pizzaId) internal view returns (bool) {
275 address owner = pizzaToOwner[pizzaId];
276 return owner != address(0);
277 }
278
279 // Periksa apakah alamat adalah pemilik atau disetujui untuk mentransfer Pizza
280 function _isApprovedOrOwner(address spender, uint256 pizzaId)
281 internal
282 view
283 returns (bool)
284 {
285 address owner = pizzaToOwner[pizzaId];
286 // Disable solium check because of
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 // Periksa apakah Pizza unik dan belum ada sama sekali
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 // Kembalikan apakah alamat target adalah sebuah kontrak
311 function isContract(address account) internal view returns (bool) {
312 uint256 size;
313 // Currently there is no better way to check if there is a contract in an address
314 // than to check the size of the code at that address.
315 // Kunjungi https://ethereum.stackexchange.com/a/14016/36603
316 // untuk lebih banyak detail tentang bagaimana ini bekerja.
317 // UNTUK DILAKUKAN Periksa ini lagi sebelum pelepasan Serenity, karena semua alamat akan menjadi
318 // kontrak kemudian.
319 // solium-disable-next-line security/no-inline-assembly
320 assembly {
321 size := extcodesize(account)
322 }
323 return size > 0;
324 }
325}
Tampilkan semua
Salin

Bacaan lebih lanjut

Lihat dokumentasi Solidity dan Vyper untuk gambaran umum yang lebih lengkap tentang kontrak pintar:

  • Kontrak pintar
  • Mesin Virtual Ethereum
  • Memperkecil kontrak untuk mengatasi batas ukuran kontrak – Beberapa tips praktis untuk mengurangi ukuran kontrak pintar Anda.
  • Pembuatan log data dari kontrak pintar dengan aksi – Pengantar aksi kontrak pintar dan cara menggunakannya untuk log data.
  • Berinteraksi dengan kontrak lain dari Solidity – Cara menggunakan kontrak pintar dari kontrak yang sudah ada dan berinteraksi dengan kontrak pintar tersebut.

Apakah artikel ini membantu?