Anatomi kontrak pintar
Pembaruan terakhir halaman: 23 Februari 2026
Kontrak pintar adalah program yang berjalan pada sebuah alamat di Ethereum. Kontrak pintar terdiri dari data dan fungsi yang dapat dieksekusi setelah menerima transaksi. Berikut adalah gambaran umum tentang apa yang membentuk sebuah kontrak pintar.
Prasyarat
Pastikan Anda telah membaca tentang kontrak pintar terlebih dahulu. Dokumen ini mengasumsikan Anda sudah familier dengan bahasa pemrograman seperti JavaScript atau Python.
Data
Setiap data kontrak harus ditetapkan ke sebuah lokasi: baik ke storage (penyimpanan) maupun memory (memori). Memodifikasi penyimpanan dalam kontrak pintar membutuhkan biaya yang mahal, jadi Anda perlu mempertimbangkan di mana data Anda harus berada.
Penyimpanan
Data persisten disebut sebagai penyimpanan dan diwakili oleh variabel status. Nilai-nilai ini disimpan secara permanen di blockchain. Anda perlu mendeklarasikan tipenya sehingga kontrak dapat melacak berapa banyak penyimpanan di blockchain yang dibutuhkannya saat dikompilasi.
1// Solidity example // Contoh Solidity2contract SimpleStorage {3 uint storedData; // State variable // Variabel state4 // ... // ...5}1# Vyper example # Contoh Vyper2storedData: int128Jika Anda sudah pernah memprogram dengan bahasa berorientasi objek, Anda mungkin akan familier dengan sebagian besar tipenya. Namun, address (alamat) mungkin merupakan hal baru bagi Anda jika Anda baru dalam pengembangan Ethereum.
Tipe address dapat menampung alamat Ethereum yang setara dengan 20 bita atau 160 bit. Tipe ini mengembalikan nilai dalam notasi heksadesimal dengan awalan 0x.
Tipe lainnya meliputi:
- boolean
- integer (bilangan bulat)
- fixed point numbers (bilangan titik tetap)
- fixed-size byte arrays (larik bita berukuran tetap)
- dynamically sized byte arrays (larik bita berukuran dinamis)
- rational and integer literals (literal rasional dan bilangan bulat)
- string literals (literal string)
- hexadecimal literals (literal heksadesimal)
- enums
Untuk penjelasan lebih lanjut, lihat dokumentasinya:
Memori
Nilai yang hanya disimpan selama masa eksekusi fungsi kontrak disebut variabel memori. Karena tidak disimpan secara permanen di blockchain, variabel ini jauh lebih murah untuk digunakan.
Pelajari lebih lanjut tentang bagaimana EVM menyimpan data (Penyimpanan, Memori, dan Tumpukan) di dokumentasi Solidity (opens in a new tab).
Variabel lingkungan
Selain variabel yang Anda tentukan pada kontrak Anda, ada beberapa variabel global khusus. Variabel ini terutama digunakan untuk memberikan informasi tentang blockchain atau transaksi saat ini.
Contoh:
| Properti | Variabel status | Deskripsi |
|---|---|---|
block.timestamp | uint256 | Stempel waktu epoch blok saat ini |
msg.sender | address | Pengirim pesan (panggilan saat ini) |
Fungsi
Dalam istilah yang paling sederhana, fungsi dapat mengambil informasi atau mengatur informasi sebagai respons terhadap transaksi yang masuk.
Ada dua jenis panggilan fungsi:
internal– ini tidak membuat panggilan EVM- Fungsi internal dan variabel status hanya dapat diakses secara internal (yaitu, dari dalam kontrak saat ini atau kontrak yang diturunkan darinya)
external– ini membuat panggilan EVM- Fungsi eksternal adalah bagian dari antarmuka kontrak, yang berarti fungsi tersebut dapat dipanggil dari kontrak lain dan melalui transaksi. Fungsi eksternal
ftidak dapat dipanggil secara internal (yaitu,f()tidak berfungsi, tetapithis.f()berfungsi).
- Fungsi eksternal adalah bagian dari antarmuka kontrak, yang berarti fungsi tersebut dapat dipanggil dari kontrak lain dan melalui transaksi. Fungsi eksternal
Fungsi juga dapat bersifat public (publik) atau private (pribadi)
- Fungsi
publicdapat dipanggil secara internal dari dalam kontrak atau secara eksternal melalui pesan - Fungsi
privatehanya terlihat untuk kontrak tempat fungsi tersebut didefinisikan dan tidak dalam kontrak turunan
Baik fungsi maupun variabel status dapat dibuat publik atau pribadi
Berikut adalah fungsi untuk memperbarui variabel status pada sebuah kontrak:
1// Solidity example // Contoh Solidity2function update_name(string value) public {3 dapp_name = value;4}- Parameter
valuebertipestringditeruskan ke dalam fungsi:update_name - Fungsi ini dideklarasikan sebagai
public, yang berarti siapa pun dapat mengaksesnya - Fungsi ini tidak dideklarasikan sebagai
view, sehingga dapat memodifikasi status kontrak
Fungsi view
Fungsi-fungsi ini berjanji untuk tidak memodifikasi status data kontrak. Contoh umumnya adalah fungsi "getter" – Anda mungkin menggunakan ini untuk menerima saldo pengguna misalnya.
1// Solidity example // Contoh Solidity2function balanceOf(address _owner) public view returns (uint256 _balance) {3 return ownerPizzaCount[_owner];4}1dappName: public(string)23@view4@public5def readName() -> string:6 return dappNameApa yang dianggap memodifikasi status:
- Menulis ke variabel status.
- Memancarkan peristiwa (emitting events) (opens in a new tab).
- Membuat kontrak lain (opens in a new tab).
- Menggunakan
selfdestruct. - Mengirim ether melalui panggilan.
- Memanggil fungsi apa pun yang tidak ditandai
viewataupure. - Menggunakan panggilan tingkat rendah.
- Menggunakan perakitan sebaris (inline assembly) yang berisi opcode tertentu.
Fungsi konstruktor
Fungsi constructor hanya dieksekusi sekali saat kontrak pertama kali disebarkan. Seperti constructor dalam banyak bahasa pemrograman berbasis kelas, fungsi-fungsi ini sering kali menginisialisasi variabel status ke nilai yang ditentukannya.
1// Solidity example // Contoh Solidity2// Initializes the contract's data, setting the `owner` // Menginisialisasi data kontrak, mengatur `owner`3// to the address of the contract creator. // ke alamat pembuat kontrak.4constructor() public {5 // All smart contracts rely on external transactions to trigger its functions. // Semua kontrak pintar bergantung pada transaksi eksternal untuk memicu fungsinya.6 // `msg` is a global variable that includes relevant data on the given transaction, // `msg` adalah variabel global yang mencakup data relevan pada transaksi yang diberikan,7 // such as the address of the sender and the ETH value included in the transaction. // seperti alamat pengirim dan nilai ETH yang disertakan dalam transaksi.8 // Learn more: https://solidity.readthedocs.io/en/v0.5.10/units-and-global-variables.html#block-and-transaction-properties // Pelajari lebih lanjut: https://solidity.readthedocs.io/en/v0.5.10/units-and-global-variables.html#block-and-transaction-properties9 owner = msg.sender;10}Tampilkan semua1# Vyper example # Contoh Vyper23@external4def __init__(_beneficiary: address, _bidding_time: uint256):5 self.beneficiary = _beneficiary6 self.auctionStart = block.timestamp7 self.auctionEnd = self.auctionStart + _bidding_timeFungsi bawaan
Selain variabel dan fungsi yang Anda tentukan pada kontrak Anda, ada beberapa fungsi bawaan khusus. Contoh yang paling jelas adalah:
address.send()– Soliditysend(address)– Vyper
Fungsi-fungsi ini memungkinkan kontrak untuk mengirim ETH ke akun lain.
Menulis fungsi
Fungsi Anda membutuhkan:
- variabel parameter dan tipe (jika menerima parameter)
- deklarasi internal/eksternal
- deklarasi pure/view/payable
- tipe pengembalian (jika mengembalikan nilai)
1pragma solidity >=0.4.0 <=0.6.0;23contract ExampleDapp {4 string dapp_name; // state variable // variabel state56 // Called when the contract is deployed and initializes the value // Dipanggil saat kontrak disebarkan dan menginisialisasi nilai7 constructor() public {8 dapp_name = "My Example dapp";9 }1011 // Get Function // Fungsi Get12 function read_name() public view returns(string) {13 return dapp_name;14 }1516 // Set Function // Fungsi Set17 function update_name(string value) public {18 dapp_name = value;19 }20}Tampilkan semuaKontrak yang lengkap mungkin terlihat seperti ini. Di sini fungsi constructor memberikan nilai awal untuk variabel dapp_name.
Peristiwa dan log
Peristiwa (events) memungkinkan kontrak pintar Anda untuk berkomunikasi dengan frontend Anda atau aplikasi berlangganan lainnya. Setelah transaksi divalidasi dan ditambahkan ke sebuah blok, kontrak pintar dapat memancarkan peristiwa dan mencatat informasi, yang kemudian dapat diproses dan dimanfaatkan oleh frontend.
Contoh beranotasi
Berikut adalah beberapa contoh yang ditulis dalam Solidity. Jika Anda ingin bermain dengan kodenya, Anda dapat berinteraksi dengannya di Remix (opens in a new tab).
Halo dunia
1// Specifies the version of Solidity, using semantic versioning. // Menentukan versi Solidity, menggunakan pembuatan versi semantik.2// Learn more: https://solidity.readthedocs.io/en/v0.5.10/layout-of-source-files.html#pragma // Pelajari lebih lanjut: https://solidity.readthedocs.io/en/v0.5.10/layout-of-source-files.html#pragma3pragma solidity ^0.5.10;45// Defines a contract named `HelloWorld`. // Mendefinisikan kontrak bernama `HelloWorld`.6// A contract is a collection of functions and data (its state). // Kontrak adalah kumpulan fungsi dan data (state-nya).7// Once deployed, a contract resides at a specific address on the Ethereum blockchain. // Setelah disebarkan, kontrak berada di alamat tertentu di blockchain Ethereum.8// Learn more: https://solidity.readthedocs.io/en/v0.5.10/structure-of-a-contract.html // Pelajari lebih lanjut: https://solidity.readthedocs.io/en/v0.5.10/structure-of-a-contract.html9contract HelloWorld {1011 // Declares a state variable `message` of type `string`. // Mendeklarasikan variabel state `message` dengan tipe `string`.12 // State variables are variables whose values are permanently stored in contract storage. // Variabel state adalah variabel yang nilainya disimpan secara permanen di penyimpanan kontrak.13 // The keyword `public` makes variables accessible from outside a contract // Kata kunci `public` membuat variabel dapat diakses dari luar kontrak14 // and creates a function that other contracts or clients can call to access the value. // dan membuat fungsi yang dapat dipanggil oleh kontrak atau klien lain untuk mengakses nilainya.15 string public message;1617 // Similar to many class-based object-oriented languages, a constructor is // Mirip dengan banyak bahasa berorientasi objek berbasis kelas, konstruktor adalah18 // a special function that is only executed upon contract creation. // fungsi khusus yang hanya dieksekusi saat pembuatan kontrak.19 // Constructors are used to initialize the contract's data. // Konstruktor digunakan untuk menginisialisasi data kontrak.20 // Learn more: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#constructors // Pelajari lebih lanjut: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#constructors21 constructor(string memory initMessage) public {22 // Accepts a string argument `initMessage` and sets the value // Menerima argumen string `initMessage` dan mengatur nilainya23 // into the contract's `message` storage variable). // ke dalam variabel penyimpanan `message` kontrak).24 message = initMessage;25 }2627 // A public function that accepts a string argument // Fungsi publik yang menerima argumen string28 // and updates the `message` storage variable. // dan memperbarui variabel penyimpanan `message`.29 function update(string memory newMessage) public {30 message = newMessage;31 }32}Tampilkan semuaToken
1pragma solidity ^0.5.10;23contract Token {4 // An `address` is comparable to an email address - it's used to identify an account on Ethereum. // Sebuah `address` sebanding dengan alamat email - ini digunakan untuk mengidentifikasi akun di Ethereum.5 // Addresses can represent a smart contract or an external (user) accounts. // Alamat dapat mewakili kontrak pintar atau akun (pengguna) eksternal.6 // Learn more: https://solidity.readthedocs.io/en/v0.5.10/types.html#address // Pelajari lebih lanjut: https://solidity.readthedocs.io/en/v0.5.10/types.html#address7 address public owner;89 // A `mapping` is essentially a hash table data structure. // Sebuah `mapping` pada dasarnya adalah struktur data tabel hash.10 // This `mapping` assigns an unsigned integer (the token balance) to an address (the token holder). // `mapping` ini menetapkan bilangan bulat tak bertanda (saldo token) ke sebuah alamat (pemegang token).11 // Learn more: https://solidity.readthedocs.io/en/v0.5.10/types.html#mapping-types // Pelajari lebih lanjut: https://solidity.readthedocs.io/en/v0.5.10/types.html#mapping-types12 mapping (address => uint) public balances;1314 // Events allow for logging of activity on the blockchain. // Event memungkinkan pencatatan aktivitas di blockchain.15 // Ethereum clients can listen for events in order to react to contract state changes. // Klien Ethereum dapat mendengarkan event untuk bereaksi terhadap perubahan state kontrak.16 // Learn more: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#events // Pelajari lebih lanjut: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#events17 event Transfer(address from, address to, uint amount);1819 // Initializes the contract's data, setting the `owner` // Menginisialisasi data kontrak, mengatur `owner`20 // to the address of the contract creator. // ke alamat pembuat kontrak.21 constructor() public {22 // All smart contracts rely on external transactions to trigger its functions. // Semua kontrak pintar bergantung pada transaksi eksternal untuk memicu fungsinya.23 // `msg` is a global variable that includes relevant data on the given transaction, // `msg` adalah variabel global yang mencakup data relevan pada transaksi yang diberikan,24 // such as the address of the sender and the ETH value included in the transaction. // seperti alamat pengirim dan nilai ETH yang disertakan dalam transaksi.25 // Learn more: https://solidity.readthedocs.io/en/v0.5.10/units-and-global-variables.html#block-and-transaction-properties // Pelajari lebih lanjut: https://solidity.readthedocs.io/en/v0.5.10/units-and-global-variables.html#block-and-transaction-properties26 owner = msg.sender;27 }2829 // Creates an amount of new tokens and sends them to an address. // Membuat sejumlah token baru dan mengirimkannya ke sebuah alamat.30 function mint(address receiver, uint amount) public {31 // `require` is a control structure used to enforce certain conditions. // `require` adalah struktur kontrol yang digunakan untuk memaksakan kondisi tertentu.32 // If a `require` statement evaluates to `false`, an exception is triggered, // Jika pernyataan `require` dievaluasi menjadi `false`, pengecualian akan dipicu,33 // which reverts all changes made to the state during the current call. // yang mengembalikan semua perubahan yang dibuat pada state selama panggilan saat ini.34 // Learn more: https://solidity.readthedocs.io/en/v0.5.10/control-structures.html#error-handling-assert-require-revert-and-exceptions // Pelajari lebih lanjut: https://solidity.readthedocs.io/en/v0.5.10/control-structures.html#error-handling-assert-require-revert-and-exceptions3536 // Only the contract owner can call this function // Hanya pemilik kontrak yang dapat memanggil fungsi ini37 require(msg.sender == owner, "You are not the owner.");3839 // Enforces a maximum amount of tokens // Memaksakan jumlah maksimum token40 require(amount < 1e60, "Maximum issuance exceeded");4142 // Increases the balance of `receiver` by `amount` // Meningkatkan saldo `receiver` sebesar `amount`43 balances[receiver] += amount;44 }4546 // Sends an amount of existing tokens from any caller to an address. // Mengirim sejumlah token yang ada dari pemanggil mana pun ke sebuah alamat.47 function transfer(address receiver, uint amount) public {48 // The sender must have enough tokens to send // Pengirim harus memiliki cukup token untuk dikirim49 require(amount <= balances[msg.sender], "Insufficient balance.");5051 // Adjusts token balances of the two addresses // Menyesuaikan saldo token dari kedua alamat52 balances[msg.sender] -= amount;53 balances[receiver] += amount;5455 // Emits the event defined earlier // Memancarkan event yang didefinisikan sebelumnya56 emit Transfer(msg.sender, receiver, amount);57 }58}Tampilkan semuaAset digital unik
1pragma solidity ^0.5.10;23// Imports symbols from other files into the current contract. // Mengimpor simbol dari file lain ke dalam kontrak saat ini.4// In this case, a series of helper contracts from OpenZeppelin. // Dalam hal ini, serangkaian kontrak pembantu dari OpenZeppelin.5// Learn more: https://solidity.readthedocs.io/en/v0.5.10/layout-of-source-files.html#importing-other-source-files // Pelajari lebih lanjut: 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// The `is` keyword is used to inherit functions and keywords from external contracts. // Kata kunci `is` digunakan untuk mewarisi fungsi dan kata kunci dari kontrak eksternal.13// In this case, `CryptoPizza` inherits from the `IERC721` and `ERC165` contracts. // Dalam hal ini, `CryptoPizza` mewarisi dari kontrak `IERC721` dan `ERC165`.14// Learn more: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#inheritance // Pelajari lebih lanjut: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#inheritance15contract CryptoPizza is IERC721, ERC165 {16 // Uses OpenZeppelin's SafeMath library to perform arithmetic operations safely. // Menggunakan pustaka SafeMath OpenZeppelin untuk melakukan operasi aritmatika dengan aman.17 // Learn more: https://docs.openzeppelin.com/contracts/2.x/api/math#SafeMath // Pelajari lebih lanjut: https://docs.openzeppelin.com/contracts/2.x/api/math#SafeMath18 using SafeMath for uint256;1920 // Constant state variables in Solidity are similar to other languages // Variabel state konstan di Solidity mirip dengan bahasa lain21 // but you must assign from an expression which is constant at compile time. // tetapi Anda harus menetapkan dari ekspresi yang konstan pada waktu kompilasi.22 // Learn more: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#constant-state-variables // Pelajari lebih lanjut: 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 type // Tipe struct memungkinkan Anda mendefinisikan tipe Anda sendiri28 // Learn more: https://solidity.readthedocs.io/en/v0.5.10/types.html#structs // Pelajari lebih lanjut: 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 structs // Membuat array kosong dari struct Pizza35 Pizza[] public pizzas;3637 // Mapping from pizza ID to its owner's address // Pemetaan dari ID pizza ke alamat pemiliknya38 mapping(uint256 => address) public pizzaToOwner;3940 // Mapping from owner's address to number of owned token // Pemetaan dari alamat pemilik ke jumlah token yang dimiliki41 mapping(address => uint256) public ownerPizzaCount;4243 // Mapping from token ID to approved address // Pemetaan dari ID token ke alamat yang disetujui44 mapping(uint256 => address) pizzaApprovals;4546 // You can nest mappings, this example maps owner to operator approvals // Anda dapat menyarangkan pemetaan, contoh ini memetakan pemilik ke persetujuan operator47 mapping(address => mapping(address => bool)) private operatorApprovals;4849 // Internal function to create a random Pizza from string (name) and DNA // Fungsi internal untuk membuat Pizza acak dari string (nama) dan DNA50 function _createPizza(string memory _name, uint256 _dna)51 // The `internal` keyword means this function is only visible // Kata kunci `internal` berarti fungsi ini hanya terlihat52 // within this contract and contracts that derive this contract // di dalam kontrak ini dan kontrak yang diturunkan dari kontrak ini53 // Learn more: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#visibility-and-getters // Pelajari lebih lanjut: 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 exists // `isUnique` adalah pengubah fungsi yang memeriksa apakah pizza sudah ada56 // Learn more: https://solidity.readthedocs.io/en/v0.5.10/structure-of-a-contract.html#function-modifiers // Pelajari lebih lanjut: 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 id // Menambahkan Pizza ke array Pizza dan mendapatkan id60 uint256 id = SafeMath.sub(pizzas.push(Pizza(_name, _dna)), 1);6162 // Checks that Pizza owner is the same as current user // Memeriksa bahwa pemilik Pizza sama dengan pengguna saat ini63 // Learn more: https://solidity.readthedocs.io/en/v0.5.10/control-structures.html#error-handling-assert-require-revert-and-exceptions // Pelajari lebih lanjut: 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, // perhatikan bahwa address(0) adalah alamat nol,66 // indicating that pizza[id] is not yet allocated to a particular user. // menunjukkan bahwa pizza[id] belum dialokasikan ke pengguna tertentu.6768 assert(pizzaToOwner[id] == address(0));6970 // Maps the Pizza to the owner // Memetakan Pizza ke pemilik71 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) // Membuat Pizza acak dari string (nama)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) // Menghasilkan DNA acak dari string (nama) dan alamat pemilik (pembuat)85 function generateRandomDna(string memory _str, address _owner)86 public87 // Functions marked as `pure` promise not to read from or modify the state // Fungsi yang ditandai sebagai `pure` berjanji untuk tidak membaca dari atau memodifikasi state88 // Learn more: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#pure-functions // Pelajari lebih lanjut: 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) // Menghasilkan uint acak dari string (nama) + alamat (pemilik)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 owner // Mengembalikan array Pizza yang ditemukan oleh pemilik100 function getPizzasByOwner(address _owner)101 public102 // Functions marked as `view` promise not to modify state // Fungsi yang ditandai sebagai `view` berjanji untuk tidak memodifikasi state103 // Learn more: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#view-functions // Pelajari lebih lanjut: 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 the // Menggunakan lokasi penyimpanan `memory` untuk menyimpan nilai hanya untuk108 // lifecycle of this function call. // siklus hidup panggilan fungsi ini.109 // Learn more: https://solidity.readthedocs.io/en/v0.5.10/introduction-to-smart-contracts.html#storage-memory-and-the-stack // Pelajari lebih lanjut: 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 // Transfers Pizza and ownership to other address // 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 // Emits event defined in the imported IERC721 contract // Memancarkan event yang didefinisikan dalam kontrak IERC721 yang diimpor133 emit Transfer(_from, _to, _pizzaId);134 _clearApproval(_to, _pizzaId);135 }136137 /* *138 * Mentransfer kepemilikan ID token yang diberikan dengan aman ke alamat lain139 * Jika alamat target adalah kontrak, ia harus mengimplementasikan `onERC721Received`,140 * yang dipanggil saat transfer aman, dan mengembalikan nilai ajaib141 * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`;142 * jika tidak, transfer akan dikembalikan. */143 /**144 * Safely transfers the ownership of a given token ID to another address145 * If the target address is a contract, it must implement `onERC721Received`,146 * which is called upon a safe transfer, and return the magic value147 * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`;148 * otherwise, the transfer is reverted.149 */150 function safeTransferFrom(address from, address to, uint256 pizzaId)151 public152 {153 // solium-disable-next-line arg-overflow // solium-disable-next-line arg-overflow154 this.safeTransferFrom(from, to, pizzaId, "");155 }156157 /* *158 * Mentransfer kepemilikan ID token yang diberikan dengan aman ke alamat lain159 * Jika alamat target adalah kontrak, ia harus mengimplementasikan `onERC721Received`,160 * yang dipanggil saat transfer aman, dan mengembalikan nilai ajaib161 * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`;162 * jika tidak, transfer akan dikembalikan. */163 /**164 * Safely transfers the ownership of a given token ID to another address165 * If the target address is a contract, it must implement `onERC721Received`,166 * which is called upon a safe transfer, and return the magic value167 * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`;168 * otherwise, the transfer is reverted.169 */170 function safeTransferFrom(171 address from,172 address to,173 uint256 pizzaId,174 bytes memory _data175 ) public {176 this.transferFrom(from, to, pizzaId);177 require(_checkOnERC721Received(from, to, pizzaId, _data), "Must implement onERC721Received.");178 }179180 /* *181 * Fungsi internal untuk memanggil `onERC721Received` pada alamat target182 * Panggilan tidak dieksekusi jika alamat target bukan kontrak */183 /**184 * Internal function to invoke `onERC721Received` on a target address185 * The call is not executed if the target address is not a contract186 */187 function _checkOnERC721Received(188 address from,189 address to,190 uint256 pizzaId,191 bytes memory _data192 ) internal returns (bool) {193 if (!isContract(to)) {194 return true;195 }196197 bytes4 retval = IERC721Receiver(to).onERC721Received(198 msg.sender,199 from,200 pizzaId,201 _data202 );203 return (retval == _ERC721_RECEIVED);204 }205206 // Burns a Pizza - destroys Token completely // Membakar Pizza - menghancurkan Token sepenuhnya207 // The `external` function modifier means this function is // Pengubah fungsi `external` berarti fungsi ini adalah208 // part of the contract interface and other contracts can call it // bagian dari antarmuka kontrak dan kontrak lain dapat memanggilnya209 function burn(uint256 _pizzaId) external {210 require(msg.sender != address(0), "Invalid address.");211 require(_exists(_pizzaId), "Pizza does not exist.");212 require(_isApprovedOrOwner(msg.sender, _pizzaId), "Address is not approved.");213214 ownerPizzaCount[msg.sender] = SafeMath.sub(215 ownerPizzaCount[msg.sender],216 1217 );218 pizzaToOwner[_pizzaId] = address(0);219 }220221 // Returns count of Pizzas by address // Mengembalikan jumlah Pizza berdasarkan alamat222 function balanceOf(address _owner) public view returns (uint256 _balance) {223 return ownerPizzaCount[_owner];224 }225226 // Returns owner of the Pizza found by id // Mengembalikan pemilik Pizza yang ditemukan berdasarkan id227 function ownerOf(uint256 _pizzaId) public view returns (address _owner) {228 address owner = pizzaToOwner[_pizzaId];229 require(owner != address(0), "Invalid Pizza ID.");230 return owner;231 }232233 // Approves other address to transfer ownership of Pizza // Menyetujui alamat lain untuk mentransfer kepemilikan Pizza234 function approve(address _to, uint256 _pizzaId) public {235 require(msg.sender == pizzaToOwner[_pizzaId], "Must be the Pizza owner.");236 pizzaApprovals[_pizzaId] = _to;237 emit Approval(msg.sender, _to, _pizzaId);238 }239240 // Returns approved address for specific Pizza // Mengembalikan alamat yang disetujui untuk Pizza tertentu241 function getApproved(uint256 _pizzaId)242 public243 view244 returns (address operator)245 {246 require(_exists(_pizzaId), "Pizza does not exist.");247 return pizzaApprovals[_pizzaId];248 }249250 /* *251 * Fungsi privat untuk menghapus persetujuan saat ini dari ID token yang diberikan252 * Dikembalikan jika alamat yang diberikan memang bukan pemilik token */253 /**254 * Private function to clear current approval of a given token ID255 * Reverts if the given address is not indeed the owner of the token256 */257 function _clearApproval(address owner, uint256 _pizzaId) private {258 require(pizzaToOwner[_pizzaId] == owner, "Must be pizza owner.");259 require(_exists(_pizzaId), "Pizza does not exist.");260 if (pizzaApprovals[_pizzaId] != address(0)) {261 pizzaApprovals[_pizzaId] = address(0);262 }263 }264265 /* * Mengatur atau membatalkan persetujuan dari operator yang diberikan266 * Operator diizinkan untuk mentransfer semua token pengirim atas nama mereka */267 /*268 * Sets or unsets the approval of a given operator269 * An operator is allowed to transfer all tokens of the sender on their behalf270 */271 function setApprovalForAll(address to, bool approved) public {272 require(to != msg.sender, "Cannot approve own address");273 operatorApprovals[msg.sender][to] = approved;274 emit ApprovalForAll(msg.sender, to, approved);275 }276277 // Tells whether an operator is approved by a given owner // Memberi tahu apakah operator disetujui oleh pemilik yang diberikan278 function isApprovedForAll(address owner, address operator)279 public280 view281 returns (bool)282 {283 return operatorApprovals[owner][operator];284 }285286 // Takes ownership of Pizza - only for approved users // Mengambil kepemilikan Pizza - hanya untuk pengguna yang disetujui287 function takeOwnership(uint256 _pizzaId) public {288 require(_isApprovedOrOwner(msg.sender, _pizzaId), "Address is not approved.");289 address owner = this.ownerOf(_pizzaId);290 this.transferFrom(owner, msg.sender, _pizzaId);291 }292293 // Checks if Pizza exists // Memeriksa apakah Pizza ada294 function _exists(uint256 pizzaId) internal view returns (bool) {295 address owner = pizzaToOwner[pizzaId];296 return owner != address(0);297 }298299 // Checks if address is owner or is approved to transfer Pizza // Memeriksa apakah alamat adalah pemilik atau disetujui untuk mentransfer Pizza300 function _isApprovedOrOwner(address spender, uint256 pizzaId)301 internal302 view303 returns (bool)304 {305 address owner = pizzaToOwner[pizzaId];306 // Disable solium check because of // Nonaktifkan pemeriksaan solium karena307 // https://github.com/duaraghav8/Solium/issues/175 // https://github.com/duaraghav8/Solium/issues/175308 // solium-disable-next-line operator-whitespace // solium-disable-next-line operator-whitespace309 return (spender == owner ||310 this.getApproved(pizzaId) == spender ||311 this.isApprovedForAll(owner, spender));312 }313314 // Check if Pizza is unique and doesn't exist yet // Periksa apakah Pizza unik dan belum ada315 modifier isUnique(string memory _name, uint256 _dna) {316 bool result = true;317 for (uint256 i = 0; i < pizzas.length; i++) {318 if (319 keccak256(abi.encodePacked(pizzas[i].name)) ==320 keccak256(abi.encodePacked(_name)) &&321 pizzas[i].dna == _dna322 ) {323 result = false;324 }325 }326 require(result, "Pizza with such name already exists.");327 _;328 }329330 // Returns whether the target address is a contract // Mengembalikan apakah alamat target adalah kontrak331 function isContract(address account) internal view returns (bool) {332 uint256 size;333 // Currently there is no better way to check if there is a contract in an address // Saat ini tidak ada cara yang lebih baik untuk memeriksa apakah ada kontrak di sebuah alamat334 // than to check the size of the code at that address. // daripada memeriksa ukuran kode di alamat tersebut.335 // See https://ethereum.stackexchange.com/a/14016/36603 // Lihat https://ethereum.stackexchange.com/a/14016/36603336 // for more details about how this works. // untuk detail lebih lanjut tentang cara kerjanya.337 // TODO Check this again before the Serenity release, because all addresses will be // TODO Periksa ini lagi sebelum rilis Serenity, karena semua alamat akan menjadi338 // contracts then. // kontrak pada saat itu.339 // solium-disable-next-line security/no-inline-assembly // solium-disable-next-line security/no-inline-assembly340 assembly {341 size := extcodesize(account)342 }343 return size > 0;344 }345}Tampilkan semuaBacaan lebih lanjut
Lihat dokumentasi Solidity dan Vyper untuk gambaran umum yang lebih lengkap tentang kontrak pintar:
Topik terkait
Tutorial terkait
- Memperkecil ukuran kontrak untuk mengatasi batas ukuran kontrak – Beberapa kiat praktis untuk mengurangi ukuran kontrak pintar Anda.
- Mencatat data dari kontrak pintar dengan peristiwa – Pengantar peristiwa kontrak pintar dan bagaimana Anda dapat menggunakannya untuk mencatat data.
- Berinteraksi dengan kontrak lain dari Solidity – Cara menyebarkan kontrak pintar dari kontrak yang ada dan berinteraksi dengannya.