Lanjut ke konten utama

Anatomi kontrak pintar

Terakhir diedit: , Invalid DateTime

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}
6
📋 Salin
1# Vyper example
2storedData: int128
3
📋 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}
5
📋 Salin
  • value 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}
5
📋 Salin
1dappName: public(string)
2
3@view
4@public
5def readName() -> string:
6 return dappName
7
📋 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 `owner`
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}
11
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
8
📋 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
3kontrak 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}
21
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 `public` 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}
33
Tampilkan semua
📋 Salin

Token

1pragma solidity ^0.5.10;
2
3contract Token {
4 //Sebuah `address` 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 `owner`
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 `false`, 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}
59
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 // Pelajari lebih banyak: 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 // Tipe Struct memungkinkan Anda menentukan tipe Anda
28 //Pelajari lebih banyak: https://solidity.readthedocs.io/en/v0.5.10/types.html#structs
29 struct Pizza {
30 string name;
31 uint256 dna;
32 }
33
34 // Buat satu array kosong dari struct Pizza
35 Pizza[] public pizzas;
36
37 // Mapping dari ID pizza ke alamat pemiliknya
38 mapping(uint256 => address) public pizzaToOwner;
39
40 // Mapping dari alamat pemilik ke nomor dari token yang dimiliki
41 mapping(address => uint256) public ownerPizzaCount;
42
43 // Mapping dari ID token ke alamat yang disetujui
44 mapping(uint256 => address) pizzaApprovals;
45
46 // Anda bisa melakukan nest pada mapping, contoh ini melakukan map ke persetujuan operator
47 mapping(address => mapping(address => bool)) private operatorApprovals;
48
49 // Fungsi internal untuk membentuk satu Pizza acak dari (nama) string dan DNA
50 function _createPizza(string memory _name, uint256 _dna)
51 // Kata kunci `internal` berarti fungsi ini hanya terlihat
52 // dalam kontrak ini dan kontrak yang diturunkan dari kontrak ini
53 // Pelajari lebih banyak: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#visibility-and-getters
54 internal
55 // `isUnique` adalah satu fungsi modifier yang memeriksa apakah pizza sudah ada
56 // Pelajari lebih banyak: https://solidity.readthedocs.io/en/v0.5.10/structure-of-a-contract.html#function-modifiers
57 isUnique(_name, _dna)
58 {
59 // Menambahkan Pizza ke array dari Pizza dan mendapatkan id
60 uint256 id = SafeMath.sub(pizzas.push(Pizza(_name, _dna)), 1);
61
62 // Periksa pemilik Pizza sama dengan pengguna saat ini
63 // Learn more: https://solidity.readthedocs.io/en/v0.5.10/control-structures.html#error-handling-assert-require-revert-and-exceptions
64 assert(pizzaToOwner[id] == address(0));
65
66 // Lakukan map pada Pizza ke pemiliknya
67 pizzaToOwner[id] = msg.sender;
68 ownerPizzaCount[msg.sender] = SafeMath.add(
69 ownerPizzaCount[msg.sender],
70 1
71 );
72 }
73
74 // Buat satu Pizza acak dari (nama) string
75 function createRandomPizza(string memory _name) public {
76 uint256 randDna = generateRandomDna(_name, msg.sender);
77 _createPizza(_name, randDna);
78 }
79
80 // Hasilkan DNA acak dari (nama) string dan alamat dari pemilik (pembuat)
81 function generateRandomDna(string memory _str, address _owner)
82 public
83 // Fungsi yang ditandai `pure` berjanji tidak membaca dari atau memodifikasi state
84 // Pelajari lebih banyak: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#pure-functions
85 pure
86 returns (uint256)
87 {
88 // Buat uint acak dari (nama) string + (pemilik) alamat
89 uint256 rand = uint256(keccak256(abi.encodePacked(_str))) +
90 uint256(_owner);
91 rand = rand % dnaModulus;
92 return rand;
93 }
94
95 // Kembalikan array Pizza yang ditemukan pemilik
96 function getPizzasByOwner(address _owner)
97 public
98 // Fungsi yang ditandai `view` berjanji tidak memodifikasi state
99 // Pelajari lebih banyak: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#view-functions
100 view
101 returns (uint256[] memory)
102 {
103 // Gunakan lokasi penyimpanan `memory` untuk menyimpan nilai hanya untuk
104 // siklus hidup dari pemanggilan fungsi ini.
105 // Pelajari lebih banyak: https://solidity.readthedocs.io/en/v0.5.10/introduction-to-smart-contracts.html#storage-memory-and-the-stack
106 uint256[] memory result = new uint256[](ownerPizzaCount[_owner]);
107 uint256 counter = 0;
108 for (uint256 i = 0; i < pizzas.length; i++) {
109 if (pizzaToOwner[i] == _owner) {
110 result[counter] = i;
111 counter++;
112 }
113 }
114 return result;
115 }
116
117 // Mentransfer Pizza dan kepemilikan ke alamat lain
118 function transferFrom(address _from, address _to, uint256 _pizzaId) public {
119 require(_from != address(0) && _to != address(0), "Invalid address.");
120 require(_exists(_pizzaId), "Pizza does not exist.");
121 require(_from != _to, "Cannot transfer to the same address.");
122 require(_isApprovedOrOwner(msg.sender, _pizzaId), "Address is not approved.");
123
124 ownerPizzaCount[_to] = SafeMath.add(ownerPizzaCount[_to], 1);
125 ownerPizzaCount[_from] = SafeMath.sub(ownerPizzaCount[_from], 1);
126 pizzaToOwner[_pizzaId] = _to;
127
128 // Terbitkan aksi yang ditentukan di kontrak IERC721 yang diimpor
129 emit Transfer(_from, _to, _pizzaId);
130 _clearApproval(_to, _pizzaId);
131 }
132
133 /**
134 * Transfer dengan aman kepemilikan dari ID token yang disediakan ke alamat lain
135 * Jika alamat target adalah sebuah kontrak, ia harus mengimplementasi ``onERC721Received`,
136 * yang dipanggil saat satu transfer aman, dan mengembalikan nilai ajaib
137 * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`;
138 * jika tidak, transfer dibalikkan.
139 */
140 function safeTransferFrom(address from, address to, uint256 pizzaId)
141 public
142 {
143 // solium-disable-next-line arg-overflow
144 this.safeTransferFrom(from, to, pizzaId, "");
145 }
146
147 /**
148 * Transfer dengan aman kepemilikan dari ID token yang disediakan ke alamat lain
149 * Jika alamat target adalah satu kontrak, ia harus mengimplementasi `onERC721Received`,
150 * yang dipanggil saat satu transfer aman, dan mengembalikan nilai ajaib
151 * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`;
152 * jika tidak, transfer dibalikkan.
153 */
154 function safeTransferFrom(
155 address from,
156 address to,
157 uint256 pizzaId,
158 bytes memory _data
159 ) public {
160 this.transferFrom(from, to, pizzaId);
161 require(_checkOnERC721Received(from, to, pizzaId, _data), "Must implmement onERC721Received.");
162 }
163
164 /**
165 * Fungsi internal untuk memohon `onERC721Received` pada satu alamat target
166 * Pemanggilan tidak dieksekusi jika alamat target bukan sebuah kontrak
167 */
168 function _checkOnERC721Received(
169 address from,
170 address to,
171 uint256 pizzaId,
172 bytes memory _data
173 ) internal returns (bool) {
174 if (!isContract(to)) {
175 return true;
176 }
177
178 bytes4 retval = IERC721Receiver(to).onERC721Received(
179 msg.sender,
180 from,
181 pizzaId,
182 _data
183 );
184 return (retval == _ERC721_RECEIVED);
185 }
186
187 // Bakar satu Pizza - hancurkan Token secara total
188 // Modifier fungsi `external` berarti fungsi ini adalah
189 // bagian dari antarmuka kontrak dan kontrak lain bisa memanggilnya
190 function burn(uint256 _pizzaId) external {
191 require(msg.sender != address(0), "Invalid address.");
192 require(_exists(_pizzaId), "Pizza does not exist.");
193 require(_isApprovedOrOwner(msg.sender, _pizzaId), "Address is not approved.");
194
195 ownerPizzaCount[msg.sender] = SafeMath.sub(
196 ownerPizzaCount[msg.sender],
197 1
198 );
199 pizzaToOwner[_pizzaId] = address(0);
200 }
201
202 // Kembalikan penghitungan Pizza lewat alamat
203 function balanceOf(address _owner) public view returns (uint256 _balance) {
204 return ownerPizzaCount[_owner];
205 }
206
207 // Kembalikan pemilik Pizza yang ditemukan id
208 function ownerOf(uint256 _pizzaId) public view returns (address _owner) {
209 address owner = pizzaToOwner[_pizzaId];
210 require(owner != address(0), "Invalid Pizza ID.");
211 return owner;
212 }
213
214 // Setujui alamat lain untuk mentransfer kepemilikan Pizza
215 function approve(address _to, uint256 _pizzaId) public {
216 require(msg.sender == pizzaToOwner[_pizzaId], "Must be the Pizza owner.");
217 pizzaApprovals[_pizzaId] = _to;
218 emit Approval(msg.sender, _to, _pizzaId);
219 }
220
221 // Kembalikan alamat yang disetujui untuk Pizza spesifik
222 function getApproved(uint256 _pizzaId)
223 public
224 view
225 returns (address operator)
226 {
227 require(_exists(_pizzaId), "Pizza does not exist.");
228 return pizzaApprovals[_pizzaId];
229 }
230
231 /**
232 * Fungsi privat untuk menghapus persetujuan saat ini dari ID token yang disediakan
233 * Balikkan jika alamat yang disediakan memang bukan pemilik token
234 */
235 function _clearApproval(address owner, uint256 _pizzaId) private {
236 require(pizzaToOwner[_pizzaId] == owner, "Must be pizza owner.");
237 require(_exists(_pizzaId), "Pizza does not exist.");
238 if (pizzaApprovals[_pizzaId] != address(0)) {
239 pizzaApprovals[_pizzaId] = address(0);
240 }
241 }
242
243 /*
244 * Siapkan atau batalkan persetujuan untuk operator yang disediakan
245 * Seorang operator diizinkan untuk mentransfer semua token dari pengirim atas nama mereka
246 */
247 function setApprovalForAll(address to, bool approved) public {
248 require(to != msg.sender, "Cannot approve own address");
249 operatorApprovals[msg.sender][to] = approved;
250 emit ApprovalForAll(msg.sender, to, approved);
251 }
252
253 // Beritahu apakah seorang operator disetujui oleh seorang pemilik yang disediakan
254 function isApprovedForAll(address owner, address operator)
255 public
256 view
257 returns (bool)
258 {
259 return operatorApprovals[owner][operator];
260 }
261
262 // Ambil kepemilikan Pizza - hanya untuk pengguna yang disetujui
263 function takeOwnership(uint256 _pizzaId) public {
264 require(_isApprovedOrOwner(msg.sender, _pizzaId), "Address is not approved.");
265 address owner = this.ownerOf(_pizzaId);
266 this.transferFrom(owner, msg.sender, _pizzaId);
267 }
268
269 // Periksa apakah Pizza ada
270 function _exists(uint256 pizzaId) internal view returns (bool) {
271 address owner = pizzaToOwner[pizzaId];
272 return owner != address(0);
273 }
274
275 // Periksa apakah alamat adalah pemilik atau disetujui untuk mentransfer Pizza
276 function _isApprovedOrOwner(address spender, uint256 pizzaId)
277 internal
278 view
279 returns (bool)
280 {
281 address owner = pizzaToOwner[pizzaId];
282 // Disable solium check because of
283 // https://github.com/duaraghav8/Solium/issues/175
284 // solium-disable-next-line operator-whitespace
285 return (spender == owner ||
286 this.getApproved(pizzaId) == spender ||
287 this.isApprovedForAll(owner, spender));
288 }
289
290 // Periksa apakah Pizza unik dan belum ada sama sekali
291 modifier isUnique(string memory _name, uint256 _dna) {
292 bool result = true;
293 for (uint256 i = 0; i < pizzas.length; i++) {
294 if (
295 keccak256(abi.encodePacked(pizzas[i].name)) ==
296 keccak256(abi.encodePacked(_name)) &&
297 pizzas[i].dna == _dna
298 ) {
299 result = false;
300 }
301 }
302 require(result, "Pizza with such name already exists.");
303 _;
304 }
305
306 // Kembalikan apakah alamat target adalah sebuah kontrak
307 function isContract(address account) internal view returns (bool) {
308 uint256 size;
309 // Currently there is no better way to check if there is a contract in an address
310 // than to check the size of the code at that address.
311 // Kunjungi https://ethereum.stackexchange.com/a/14016/36603
312 // untuk lebih banyak detail tentang bagaimana ini bekerja.
313 // UNTUK DILAKUKAN Periksa ini lagi sebelum pelepasan Serenity, karena semua alamat akan menjadi
314 // kontrak kemudian.
315 // solium-disable-next-line security/no-inline-assembly
316 assembly {
317 size := extcodesize(account)
318 }
319 return size > 0;
320 }
321}
322
Tampilkan semua
📋 Salin

Bacaan lebih lanjut

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

Apakah artikel ini membantu?