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 Solidity2contract SimpleStorage {3 uint storedData; // State variable4 // ...5}Salin
1# Vyper example2storedData: int128Salin
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:
Prop | Variabel state | Deskripsi |
---|---|---|
block.timestamp | uint256 | Stempel waktu epoch blok saat ini |
msg.sender | alamat | Pengirim 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 (yaituf()
tidak berfungsi, tapithis.f()
dapat berfungsi).
- Fungsi eksternal adalah bagian dari antarmuka kontrak, yang berarti bisa dipanggil dari kontrak lain dan melalui transaksi. Fungsi eksternal
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 Solidity2function update_name(string value) public {3 dapp_name = value;4}Salin
Nilai
parameter daristring
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 Solidity2function balanceOf(address _owner) public view returns (uint256 _balance) {3 return ownerPizzaCount[_owner];4}Salin
1dappName: public(string)23@view4@public5def readName() -> string:6 return dappNameSalin
Apa yang dianggap sebagai memodifikasi state:
- Menulis ke dalam variabel state.
- Menerbitkan aksi(opens in a new tab).
- Membuat kontrak lain(opens in a new tab).
- Menggunakan
selfdestruct
. - Mengirim eter melalui panggilan.
- Memanggil fungsi apa pun yang tidak bertanda
view
ataupure
. - Menggunakan pemanggilan level rendah.
- 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 Solidity2// 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-properties9 owner = msg.sender;10}Tampilkan semuaSalin
1# contoh Vyper23@external4def __init__(_beneficiary: address, _bidding_time: uint256):5 self.beneficiary = _beneficiary6 self.auctionStart = block.timestamp7 self.auctionEnd = self.auctionStart + _bidding_timeSalin
Fungsi bawaan
Selain dari variabel dan fungsi yang Anda tetapkan pada kontrak Anda, ada beberapa fungsi bawaan spesial. Contoh paling jelas adalah:
address.send()
– Soliditysend(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;23contract ExampleDapp {4 string dapp_name; // state variable56 // Dipanggil saat kontrak disebarkan dan jalankan nilai7 constructor() public {8 dapp_name = "My Example dapp";9 }1011 // Fungsi Get12 function read_name() public view returns(string) {13 return dapp_name;14 }1516 // Tetapkan Fungsi17 function update_name(string value) public {18 dapp_name = value;19 }20}Tampilkan semuaSalin
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#pragma3pragma solidity ^0.5.10;45// 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.html9contract HelloWorld {1011 // 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 kontrak14 //dan menciptakan fungsi yang dengannya kontrak atau klien lain bisa memanggil untuk mengakses nilai.15 string public message;1617 // Sama seperti banyak bahasa berorientasi objek yang berbasis kelas, sebuah pembangun adalah18 // 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#constructors21 constructor(string memory initMessage) public {22 // Menerima satu argumen string `initMessage` dan tetapkan nilai23 // ke dalam variabel penyimpanan `message` kontrak).24 message = initMessage;25 }2627 // Sebuah fungsi publik yang menerima argumen string28 // dan memperbarui variabel penyimpanan`message`.29 function update(string memory newMessage) public {30 message = newMessage;31 }32}Tampilkan semuaSalin
Token
1pragma solidity ^0.5.10;23contract 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#address7 address public owner;89 // 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-types12 mapping (address => uint) public balances;1314 // 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#events17 event Transfer(address from, address to, uint amount);1819 // 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-properties26 owner = msg.sender;27 }2829 // 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-exceptions3536 // Hanya pemilik kontrak yang bisa memanggil fungsi ini37 require(msg.sender == owner, "You are not the owner.");3839 // Melaksanakan sejumlah maksimum token40 require(amount < 1e60, "Maximum issuance exceeded");4142 // Meningkatkan saldo dari `receiver` dalam `amount`43 balances[receiver] += amount;44 }4546 // 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 mengirim49 require(amount <= balances[msg.sender], "Insufficient balance.");5051 // Sesuaikan saldo token dari dua alamat52 balances[msg.sender] -= amount;53 balances[receiver] += amount;5455 // Terbitkan aksi yang telah ditentukan sebelumnya56 emit Transfer(msg.sender, receiver, amount);57 }58}Tampilkan semuaSalin
Aset digital unik
1pragma solidity ^0.5.10;23// 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-files67import "../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";1112// 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#inheritance15contract 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#SafeMath18 using SafeMath for uint256;1920 // Variabel state konstan di Solidity sama dengan bahasa lainnya21 // 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-variables23 uint256 constant dnaDigits = 10;24 uint256 constant dnaModulus = 10 ** dnaDigits;25 bytes4 private constant _ERC721_RECEIVED = 0x150b7a02;2627 // Struct types let you define your own type28 // Learn more: https://solidity.readthedocs.io/en/v0.5.10/types.html#structs29 struct Pizza {30 string name;31 uint256 dna;32 }3334 // Creates an empty array of Pizza structs35 Pizza[] public pizzas;3637 // Mapping from pizza ID to its owner's address38 mapping(uint256 => address) public pizzaToOwner;3940 // Mapping from owner's address to number of owned token41 mapping(address => uint256) public ownerPizzaCount;4243 // Mapping from token ID to approved address44 mapping(uint256 => address) pizzaApprovals;4546 // You can nest mappings, this example maps owner to operator approvals47 mapping(address => mapping(address => bool)) private operatorApprovals;4849 // Internal function to create a random Pizza from string (name) and DNA50 function _createPizza(string memory _name, uint256 _dna)51 // The `internal` keyword means this function is only visible52 // within this contract and contracts that derive this contract53 // Learn more: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#visibility-and-getters54 internal55 // `isUnique` is a function modifier that checks if the pizza already exists56 // Learn more: https://solidity.readthedocs.io/en/v0.5.10/structure-of-a-contract.html#function-modifiers57 isUnique(_name, _dna)58 {59 // Adds Pizza to array of Pizzas and get id60 uint256 id = SafeMath.sub(pizzas.push(Pizza(_name, _dna)), 1);6162 // Checks that Pizza owner is the same as current user63 // Learn more: https://solidity.readthedocs.io/en/v0.5.10/control-structures.html#error-handling-assert-require-revert-and-exceptions6465 // note that address(0) is the zero address,66 // indicating that pizza[id] is not yet allocated to a particular user.6768 assert(pizzaToOwner[id] == address(0));6970 // Maps the Pizza to the owner71 pizzaToOwner[id] = msg.sender;72 ownerPizzaCount[msg.sender] = SafeMath.add(73 ownerPizzaCount[msg.sender],74 175 );76 }7778 // 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 }8384 // Generates random DNA from string (name) and address of the owner (creator)85 function generateRandomDna(string memory _str, address _owner)86 public87 // Functions marked as `pure` promise not to read from or modify the state88 // Learn more: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#pure-functions89 pure90 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 }9899 // Returns array of Pizzas found by owner100 function getPizzasByOwner(address _owner)101 public102 // Functions marked as `view` promise not to modify state103 // Learn more: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#view-functions104 view105 returns (uint256[] memory)106 {107 // Uses the `memory` storage location to store values only for the108 // 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-stack110 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 }120121 // Mentransfer Pizza dan kepemilikan ke alamat lain122 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.");127128 ownerPizzaCount[_to] = SafeMath.add(ownerPizzaCount[_to], 1);129 ownerPizzaCount[_from] = SafeMath.sub(ownerPizzaCount[_from], 1);130 pizzaToOwner[_pizzaId] = _to;131132 // Terbitkan aksi yang ditentukan di kontrak IERC721 yang diimpor133 emit Transfer(_from, _to, _pizzaId);134 _clearApproval(_to, _pizzaId);135 }136137 /**138 * Transfer dengan aman kepemilikan dari ID token yang disediakan ke alamat lain139 * Jika alamat target adalah sebuah kontrak, ia harus mengimplementasi ``onERC721Received`,140 * yang dipanggil saat satu transfer aman, dan mengembalikan nilai ajaib141 * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`;142 * jika tidak, transfer dibalikkan.143 */144 function safeTransferFrom(address from, address to, uint256 pizzaId)145 public146 {147 // solium-disable-next-line arg-overflow148 this.safeTransferFrom(from, to, pizzaId, "");149 }150151 /**152 * Transfer dengan aman kepemilikan dari ID token yang disediakan ke alamat lain153 * Jika alamat target adalah satu kontrak, ia harus mengimplementasi `onERC721Received`,154 * yang dipanggil saat satu transfer aman, dan mengembalikan nilai ajaib155 * `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 _data163 ) public {164 this.transferFrom(from, to, pizzaId);165 require(_checkOnERC721Received(from, to, pizzaId, _data), "Must implmement onERC721Received.");166 }167168 /**169 * Fungsi internal untuk memohon `onERC721Received` pada satu alamat target170 * Pemanggilan tidak dieksekusi jika alamat target bukan sebuah kontrak171 */172 function _checkOnERC721Received(173 address from,174 address to,175 uint256 pizzaId,176 bytes memory _data177 ) internal returns (bool) {178 if (!isContract(to)) {179 return true;180 }181182 bytes4 retval = IERC721Receiver(to).onERC721Received(183 msg.sender,184 from,185 pizzaId,186 _data187 );188 return (retval == _ERC721_RECEIVED);189 }190191 // Bakar satu Pizza - hancurkan Token secara total192 // Modifier fungsi `external` berarti fungsi ini adalah193 // bagian dari antarmuka kontrak dan kontrak lain bisa memanggilnya194 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.");198199 ownerPizzaCount[msg.sender] = SafeMath.sub(200 ownerPizzaCount[msg.sender],201 1202 );203 pizzaToOwner[_pizzaId] = address(0);204 }205206 // Kembalikan penghitungan Pizza lewat alamat207 function balanceOf(address _owner) public view returns (uint256 _balance) {208 return ownerPizzaCount[_owner];209 }210211 // Kembalikan pemilik Pizza yang ditemukan id212 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 }217218 // Setujui alamat lain untuk mentransfer kepemilikan Pizza219 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 }224225 // Kembalikan alamat yang disetujui untuk Pizza spesifik226 function getApproved(uint256 _pizzaId)227 public228 view229 returns (address operator)230 {231 require(_exists(_pizzaId), "Pizza does not exist.");232 return pizzaApprovals[_pizzaId];233 }234235 /**236 * Fungsi privat untuk menghapus persetujuan saat ini dari ID token yang disediakan237 * Balikkan jika alamat yang disediakan memang bukan pemilik token238 */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 }246247 /*248 * Siapkan atau batalkan persetujuan untuk operator yang disediakan249 * Seorang operator diizinkan untuk mentransfer semua token dari pengirim atas nama mereka250 */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 }256257 // Beritahu apakah seorang operator disetujui oleh seorang pemilik yang disediakan258 function isApprovedForAll(address owner, address operator)259 public260 view261 returns (bool)262 {263 return operatorApprovals[owner][operator];264 }265266 // Ambil kepemilikan Pizza - hanya untuk pengguna yang disetujui267 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 }272273 // Periksa apakah Pizza ada274 function _exists(uint256 pizzaId) internal view returns (bool) {275 address owner = pizzaToOwner[pizzaId];276 return owner != address(0);277 }278279 // Periksa apakah alamat adalah pemilik atau disetujui untuk mentransfer Pizza280 function _isApprovedOrOwner(address spender, uint256 pizzaId)281 internal282 view283 returns (bool)284 {285 address owner = pizzaToOwner[pizzaId];286 // Disable solium check because of287 // https://github.com/duaraghav8/Solium/issues/175288 // solium-disable-next-line operator-whitespace289 return (spender == owner ||290 this.getApproved(pizzaId) == spender ||291 this.isApprovedForAll(owner, spender));292 }293294 // Periksa apakah Pizza unik dan belum ada sama sekali295 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 == _dna302 ) {303 result = false;304 }305 }306 require(result, "Pizza with such name already exists.");307 _;308 }309310 // Kembalikan apakah alamat target adalah sebuah kontrak311 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 address314 // than to check the size of the code at that address.315 // Kunjungi https://ethereum.stackexchange.com/a/14016/36603316 // untuk lebih banyak detail tentang bagaimana ini bekerja.317 // UNTUK DILAKUKAN Periksa ini lagi sebelum pelepasan Serenity, karena semua alamat akan menjadi318 // kontrak kemudian.319 // solium-disable-next-line security/no-inline-assembly320 assembly {321 size := extcodesize(account)322 }323 return size > 0;324 }325}Tampilkan semuaSalin
Bacaan lebih lanjut
Lihat dokumentasi Solidity dan Vyper untuk gambaran umum yang lebih lengkap tentang kontrak pintar:
Topik terkait
Tutorial terkait
- 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.