Lompat ke konten utama
Change page

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 Solidity
2contract SimpleStorage {
3 uint storedData; // State variable // Variabel state
4 // ... // ...
5}
1# Vyper example # Contoh Vyper
2storedData: int128

Jika 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:

PropertiVariabel statusDeskripsi
block.timestampuint256Stempel waktu epoch blok saat ini
msg.senderaddressPengirim 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 f tidak dapat dipanggil secara internal (yaitu, f() tidak berfungsi, tetapi this.f() berfungsi).

Fungsi juga dapat bersifat public (publik) atau private (pribadi)

  • Fungsi public dapat dipanggil secara internal dari dalam kontrak atau secara eksternal melalui pesan
  • Fungsi private hanya 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 Solidity
2function update_name(string value) public {
3 dapp_name = value;
4}
  • Parameter value bertipe string diteruskan 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 Solidity
2function balanceOf(address _owner) public view returns (uint256 _balance) {
3 return ownerPizzaCount[_owner];
4}
1dappName: public(string)
2
3@view
4@public
5def readName() -> string:
6 return dappName

Apa yang dianggap memodifikasi status:

  1. Menulis ke variabel status.
  2. Memancarkan peristiwa (emitting events) (opens in a new tab).
  3. Membuat kontrak lain (opens in a new tab).
  4. Menggunakan selfdestruct.
  5. Mengirim ether melalui panggilan.
  6. Memanggil fungsi apa pun yang tidak ditandai view atau pure.
  7. Menggunakan panggilan tingkat rendah.
  8. 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 Solidity
2// 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-properties
9 owner = msg.sender;
10}
Tampilkan semua
1# Vyper example # 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

Fungsi bawaan

Selain variabel dan fungsi yang Anda tentukan pada kontrak Anda, ada beberapa fungsi bawaan khusus. Contoh yang paling jelas adalah:

  • address.send() – Solidity
  • send(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;
2
3contract ExampleDapp {
4 string dapp_name; // state variable // variabel state
5
6 // Called when the contract is deployed and initializes the value // Dipanggil saat kontrak disebarkan dan menginisialisasi nilai
7 constructor() public {
8 dapp_name = "My Example dapp";
9 }
10
11 // Get Function // Fungsi Get
12 function read_name() public view returns(string) {
13 return dapp_name;
14 }
15
16 // Set Function // Fungsi Set
17 function update_name(string value) public {
18 dapp_name = value;
19 }
20}
Tampilkan semua

Kontrak 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#pragma
3pragma solidity ^0.5.10;
4
5// 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.html
9contract HelloWorld {
10
11 // 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 kontrak
14 // 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;
16
17 // Similar to many class-based object-oriented languages, a constructor is // Mirip dengan banyak bahasa berorientasi objek berbasis kelas, konstruktor adalah
18 // 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#constructors
21 constructor(string memory initMessage) public {
22 // Accepts a string argument `initMessage` and sets the value // Menerima argumen string `initMessage` dan mengatur nilainya
23 // into the contract's `message` storage variable). // ke dalam variabel penyimpanan `message` kontrak).
24 message = initMessage;
25 }
26
27 // A public function that accepts a string argument // Fungsi publik yang menerima argumen string
28 // and updates the `message` storage variable. // dan memperbarui variabel penyimpanan `message`.
29 function update(string memory newMessage) public {
30 message = newMessage;
31 }
32}
Tampilkan semua

Token

1pragma solidity ^0.5.10;
2
3contract 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#address
7 address public owner;
8
9 // 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-types
12 mapping (address => uint) public balances;
13
14 // 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#events
17 event Transfer(address from, address to, uint amount);
18
19 // 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-properties
26 owner = msg.sender;
27 }
28
29 // 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-exceptions
35
36 // Only the contract owner can call this function // Hanya pemilik kontrak yang dapat memanggil fungsi ini
37 require(msg.sender == owner, "You are not the owner.");
38
39 // Enforces a maximum amount of tokens // Memaksakan jumlah maksimum token
40 require(amount < 1e60, "Maximum issuance exceeded");
41
42 // Increases the balance of `receiver` by `amount` // Meningkatkan saldo `receiver` sebesar `amount`
43 balances[receiver] += amount;
44 }
45
46 // 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 dikirim
49 require(amount <= balances[msg.sender], "Insufficient balance.");
50
51 // Adjusts token balances of the two addresses // Menyesuaikan saldo token dari kedua alamat
52 balances[msg.sender] -= amount;
53 balances[receiver] += amount;
54
55 // Emits the event defined earlier // Memancarkan event yang didefinisikan sebelumnya
56 emit Transfer(msg.sender, receiver, amount);
57 }
58}
Tampilkan semua

Aset digital unik

1pragma solidity ^0.5.10;
2
3// 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-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// 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#inheritance
15contract 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#SafeMath
18 using SafeMath for uint256;
19
20 // Constant state variables in Solidity are similar to other languages // Variabel state konstan di Solidity mirip dengan bahasa lain
21 // 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-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 // Tipe struct memungkinkan Anda mendefinisikan tipe Anda sendiri
28 // 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#structs
29 struct Pizza {
30 string name;
31 uint256 dna;
32 }
33
34 // Creates an empty array of Pizza structs // Membuat array kosong dari struct Pizza
35 Pizza[] public pizzas;
36
37 // Mapping from pizza ID to its owner's address // Pemetaan dari ID pizza ke alamat pemiliknya
38 mapping(uint256 => address) public pizzaToOwner;
39
40 // Mapping from owner's address to number of owned token // Pemetaan dari alamat pemilik ke jumlah token yang dimiliki
41 mapping(address => uint256) public ownerPizzaCount;
42
43 // Mapping from token ID to approved address // Pemetaan dari ID token ke alamat yang disetujui
44 mapping(uint256 => address) pizzaApprovals;
45
46 // You can nest mappings, this example maps owner to operator approvals // Anda dapat menyarangkan pemetaan, contoh ini memetakan pemilik ke persetujuan operator
47 mapping(address => mapping(address => bool)) private operatorApprovals;
48
49 // Internal function to create a random Pizza from string (name) and DNA // Fungsi internal untuk membuat Pizza acak dari string (nama) dan DNA
50 function _createPizza(string memory _name, uint256 _dna)
51 // The `internal` keyword means this function is only visible // Kata kunci `internal` berarti fungsi ini hanya terlihat
52 // within this contract and contracts that derive this contract // di dalam kontrak ini dan kontrak yang diturunkan dari kontrak ini
53 // 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-getters
54 internal
55 // `isUnique` is a function modifier that checks if the pizza already exists // `isUnique` adalah pengubah fungsi yang memeriksa apakah pizza sudah ada
56 // 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-modifiers
57 isUnique(_name, _dna)
58 {
59 // Adds Pizza to array of Pizzas and get id // Menambahkan Pizza ke array Pizza dan mendapatkan id
60 uint256 id = SafeMath.sub(pizzas.push(Pizza(_name, _dna)), 1);
61
62 // Checks that Pizza owner is the same as current user // Memeriksa bahwa 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 // Pelajari lebih lanjut: 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, // 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.
67
68 assert(pizzaToOwner[id] == address(0));
69
70 // Maps the Pizza to the owner // Memetakan Pizza ke pemilik
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) // 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 }
83
84 // 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 public
87 // 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 state
88 // 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-functions
89 pure
90 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 }
98
99 // Returns array of Pizzas found by owner // Mengembalikan array Pizza yang ditemukan oleh pemilik
100 function getPizzasByOwner(address _owner)
101 public
102 // Functions marked as `view` promise not to modify state // Fungsi yang ditandai sebagai `view` berjanji untuk tidak memodifikasi state
103 // 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-functions
104 view
105 returns (uint256[] memory)
106 {
107 // Uses the `memory` storage location to store values only for the // Menggunakan lokasi penyimpanan `memory` untuk menyimpan nilai hanya untuk
108 // 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-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 // Transfers Pizza and ownership to other address // 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 // Emits event defined in the imported IERC721 contract // Memancarkan event yang didefinisikan dalam kontrak IERC721 yang diimpor
133 emit Transfer(_from, _to, _pizzaId);
134 _clearApproval(_to, _pizzaId);
135 }
136
137 /* *
138 * Mentransfer kepemilikan ID token yang diberikan dengan aman ke alamat lain
139 * Jika alamat target adalah kontrak, ia harus mengimplementasikan `onERC721Received`,
140 * yang dipanggil saat transfer aman, dan mengembalikan nilai ajaib
141 * `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 address
145 * If the target address is a contract, it must implement `onERC721Received`,
146 * which is called upon a safe transfer, and return the magic value
147 * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`;
148 * otherwise, the transfer is reverted.
149 */
150 function safeTransferFrom(address from, address to, uint256 pizzaId)
151 public
152 {
153 // solium-disable-next-line arg-overflow // solium-disable-next-line arg-overflow
154 this.safeTransferFrom(from, to, pizzaId, "");
155 }
156
157 /* *
158 * Mentransfer kepemilikan ID token yang diberikan dengan aman ke alamat lain
159 * Jika alamat target adalah kontrak, ia harus mengimplementasikan `onERC721Received`,
160 * yang dipanggil saat transfer aman, dan mengembalikan nilai ajaib
161 * `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 address
165 * If the target address is a contract, it must implement `onERC721Received`,
166 * which is called upon a safe transfer, and return the magic value
167 * `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 _data
175 ) public {
176 this.transferFrom(from, to, pizzaId);
177 require(_checkOnERC721Received(from, to, pizzaId, _data), "Must implement onERC721Received.");
178 }
179
180 /* *
181 * Fungsi internal untuk memanggil `onERC721Received` pada alamat target
182 * Panggilan tidak dieksekusi jika alamat target bukan kontrak */
183 /**
184 * Internal function to invoke `onERC721Received` on a target address
185 * The call is not executed if the target address is not a contract
186 */
187 function _checkOnERC721Received(
188 address from,
189 address to,
190 uint256 pizzaId,
191 bytes memory _data
192 ) internal returns (bool) {
193 if (!isContract(to)) {
194 return true;
195 }
196
197 bytes4 retval = IERC721Receiver(to).onERC721Received(
198 msg.sender,
199 from,
200 pizzaId,
201 _data
202 );
203 return (retval == _ERC721_RECEIVED);
204 }
205
206 // Burns a Pizza - destroys Token completely // Membakar Pizza - menghancurkan Token sepenuhnya
207 // The `external` function modifier means this function is // Pengubah fungsi `external` berarti fungsi ini adalah
208 // part of the contract interface and other contracts can call it // bagian dari antarmuka kontrak dan kontrak lain dapat memanggilnya
209 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.");
213
214 ownerPizzaCount[msg.sender] = SafeMath.sub(
215 ownerPizzaCount[msg.sender],
216 1
217 );
218 pizzaToOwner[_pizzaId] = address(0);
219 }
220
221 // Returns count of Pizzas by address // Mengembalikan jumlah Pizza berdasarkan alamat
222 function balanceOf(address _owner) public view returns (uint256 _balance) {
223 return ownerPizzaCount[_owner];
224 }
225
226 // Returns owner of the Pizza found by id // Mengembalikan pemilik Pizza yang ditemukan berdasarkan id
227 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 }
232
233 // Approves other address to transfer ownership of Pizza // Menyetujui alamat lain untuk mentransfer kepemilikan Pizza
234 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 }
239
240 // Returns approved address for specific Pizza // Mengembalikan alamat yang disetujui untuk Pizza tertentu
241 function getApproved(uint256 _pizzaId)
242 public
243 view
244 returns (address operator)
245 {
246 require(_exists(_pizzaId), "Pizza does not exist.");
247 return pizzaApprovals[_pizzaId];
248 }
249
250 /* *
251 * Fungsi privat untuk menghapus persetujuan saat ini dari ID token yang diberikan
252 * Dikembalikan jika alamat yang diberikan memang bukan pemilik token */
253 /**
254 * Private function to clear current approval of a given token ID
255 * Reverts if the given address is not indeed the owner of the token
256 */
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 }
264
265 /* * Mengatur atau membatalkan persetujuan dari operator yang diberikan
266 * Operator diizinkan untuk mentransfer semua token pengirim atas nama mereka */
267 /*
268 * Sets or unsets the approval of a given operator
269 * An operator is allowed to transfer all tokens of the sender on their behalf
270 */
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 }
276
277 // Tells whether an operator is approved by a given owner // Memberi tahu apakah operator disetujui oleh pemilik yang diberikan
278 function isApprovedForAll(address owner, address operator)
279 public
280 view
281 returns (bool)
282 {
283 return operatorApprovals[owner][operator];
284 }
285
286 // Takes ownership of Pizza - only for approved users // Mengambil kepemilikan Pizza - hanya untuk pengguna yang disetujui
287 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 }
292
293 // Checks if Pizza exists // Memeriksa apakah Pizza ada
294 function _exists(uint256 pizzaId) internal view returns (bool) {
295 address owner = pizzaToOwner[pizzaId];
296 return owner != address(0);
297 }
298
299 // Checks if address is owner or is approved to transfer Pizza // Memeriksa apakah alamat adalah pemilik atau disetujui untuk mentransfer Pizza
300 function _isApprovedOrOwner(address spender, uint256 pizzaId)
301 internal
302 view
303 returns (bool)
304 {
305 address owner = pizzaToOwner[pizzaId];
306 // Disable solium check because of // Nonaktifkan pemeriksaan solium karena
307 // https://github.com/duaraghav8/Solium/issues/175 // https://github.com/duaraghav8/Solium/issues/175
308 // solium-disable-next-line operator-whitespace // solium-disable-next-line operator-whitespace
309 return (spender == owner ||
310 this.getApproved(pizzaId) == spender ||
311 this.isApprovedForAll(owner, spender));
312 }
313
314 // Check if Pizza is unique and doesn't exist yet // Periksa apakah Pizza unik dan belum ada
315 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 == _dna
322 ) {
323 result = false;
324 }
325 }
326 require(result, "Pizza with such name already exists.");
327 _;
328 }
329
330 // Returns whether the target address is a contract // Mengembalikan apakah alamat target adalah kontrak
331 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 alamat
334 // 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/36603
336 // 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 menjadi
338 // contracts then. // kontrak pada saat itu.
339 // solium-disable-next-line security/no-inline-assembly // solium-disable-next-line security/no-inline-assembly
340 assembly {
341 size := extcodesize(account)
342 }
343 return size > 0;
344 }
345}
Tampilkan semua

Bacaan lebih lanjut

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

Apakah artikel ini membantu?