3. Membuat Smart Contract TaskManager
Setelah berhasil mengkonfigurasi lingkungan pengembangan, sekarang kita akan membuat smart contract TaskManager yang akan mengajarkan konsep fundamental Solidity seperti visibility functions, state variables, dan berbagai jenis functions.
1. Membuat File Contract TaskManager
Pertama, mari kita buat file smart contract baru. Hapus file Lock.sol
yang dibuat otomatis oleh Hardhat dan buat file baru bernama TaskManager.sol
.
Langkah-langkah:
- Buka folder
contracts/
di VS Code - Hapus file
Lock.sol
(klik kanan → Delete) - Buat file baru dengan nama
TaskManager.sol
- Salin dan tempel kode berikut:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;
contract TaskManager {
// State Variables & Scope
address public owner; // public: bisa dibaca siapa saja
uint256 public taskCount; // counter tasks
bool private isActive; // private: hanya contract ini
// Mapping: alamat -> jumlah task user
mapping(address => uint256) public userTaskCount;
// Functions dengan berbagai visibility
constructor() {
owner = msg.sender; // yang deploy = owner
isActive = true;
taskCount = 0;
}
// View function: baca data, no gas (kecuali dipanggil dari contract)
function getOwner() public view returns(address) {
return owner;
}
// Pure function: no read/write state, hanya komputasi
function calculateFee(uint256 amount) public pure returns(uint256) {
return amount * 2 / 100; // 2% fee
}
// Public function: bisa dipanggil dari mana saja
function addTask() public {
require(isActive, "Contract not active");
taskCount++;
userTaskCount[msg.sender]++;
}
// Private function: hanya dari dalam contract
function _updateStatus() private {
isActive = taskCount < 1000;
}
}
2. Memahami Komponen Smart Contract
Mari kita analisis setiap bagian dari smart contract TaskManager untuk memahami konsep Solidity yang diterapkan:
License dan Pragma
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;
- SPDX-License-Identifier: Menentukan lisensi untuk smart contract
- pragma solidity: Menentukan versi compiler Solidity yang digunakan
State Variables dengan Visibility
address public owner; // public: bisa dibaca siapa saja
uint256 public taskCount; // counter tasks
bool private isActive; // private: hanya contract ini
Visibility | Deskripsi | Akses |
---|---|---|
public | Bisa diakses dari mana saja | External, Internal, Public |
private | Hanya bisa diakses dari contract ini | Internal saja |
internal | Bisa diakses contract ini & turunannya | Internal & Inherited |
external | Hanya bisa dipanggil dari luar | External saja |
Mapping
mapping(address => uint256) public userTaskCount;
Mapping adalah struktur data key-value di Solidity yang memungkinkan kita menyimpan dan mengakses data berdasarkan kunci (key). Dalam contoh ini, kita memetakan alamat pengguna dengan jumlah task yang mereka miliki.
Constructor
constructor() {
owner = msg.sender; // yang deploy = owner
isActive = true;
taskCount = 0;
}
Constructor adalah function khusus yang:
- Dipanggil sekali saat contract di-deploy
- Digunakan untuk inisialisasi state variables
msg.sender
adalah alamat yang melakukan deploy contract
Function Visibility dan Types
1. View Function
function getOwner() public view returns(address) {
return owner;
}
- view: Function hanya membaca state, tidak mengubah
- Tidak memerlukan gas saat dipanggil dari luar blockchain
- Mengembalikan data tanpa mengubah state
2. Pure Function
function calculateFee(uint256 amount) public pure returns(uint256) {
return amount * 2 / 100; // 2% fee
}
- pure: Function tidak membaca atau mengubah state
- Hanya melakukan komputasi dengan parameter input
- Bersifat deterministik (input sama = output sama)
3. Public Function dengan State Changes
function addTask() public {
require(isActive, "Contract not active");
taskCount++;
userTaskCount[msg.sender]++;
}
- public: Bisa dipanggil dari mana saja
- Mengubah state variables (memerlukan gas)
- Menggunakan
require()
untuk validasi
4. Private Function
function _updateStatus() private {
isActive = taskCount < 1000;
}
- private: Hanya bisa dipanggil dari dalam contract ini
- Biasanya diawali dengan underscore (_) sebagai konvensi
- Digunakan untuk logic internal
3. Global Variables dan Keywords Penting
msg.sender
owner = msg.sender;
userTaskCount[msg.sender]++;
msg.sender
adalah alamat yang memanggil function saat ini. Ini adalah salah satu global variable paling penting dalam Solidity.
require()
require(isActive, "Contract not active");
require()
digunakan untuk validasi kondisi. Jika kondisi false
, transaksi akan dibatalkan dan gas dikembalikan (sebagian).
4. Kompilasi Smart Contract
Setelah menulis smart contract, mari kita kompilasi untuk memastikan tidak ada error:
npx hardhat compile
Jika berhasil, Anda akan melihat output:
Compiled 1 Solidity file successfully
Jika ada error, periksa:
- Syntax Solidity sudah benar
- Import dan pragma sudah sesuai
- Tidak ada typo dalam kode
5. Memahami Hasil Kompilasi
Setelah kompilasi berhasil, Hardhat akan membuat beberapa folder dan file:
monad-taskmanager/
├── artifacts/
│ └── contracts/
│ └── TaskManager.sol/
│ ├── TaskManager.json # ABI dan bytecode
│ └── TaskManager.dbg.json # Debug info
├── cache/ # Cache kompilasi
└── typechain-types/ # TypeScript bindings
├── contracts/
│ └── TaskManager.ts
└── index.ts
File Penting:
- TaskManager.json: Berisi ABI (Application Binary Interface) dan bytecode
- typechain-types/: TypeScript bindings untuk interaksi yang type-safe
6. Analisis Gas Usage
Smart contract yang baik harus mempertimbangkan efisiensi gas. Mari kita analisis fungsi-fungsi dalam TaskManager:
Function | Gas Usage | Alasan |
---|---|---|
getOwner() | ~23,000 gas | View function, hanya baca storage |
calculateFee() | ~21,000 gas | Pure function, hanya komputasi |
addTask() | ~43,000-68,000 gas | Menulis ke storage (dua kali) |
- Minimize Storage Writes: Setiap write ke storage memakan banyak gas
- Use View/Pure Functions: Lebih murah untuk operasi baca/komputasi
- Batch Operations: Gabungkan beberapa operasi dalam satu transaksi
- Use Events: Lebih murah daripada menyimpan data di storage
7. Best Practices yang Diterapkan
Smart contract TaskManager menerapkan beberapa best practices:
Security
- ✅ Menggunakan
require()
untuk validasi input - ✅ Proper visibility modifiers
- ✅ Immutable owner (set di constructor)
Code Organization
- ✅ Clear naming conventions
- ✅ Logical grouping of functions
- ✅ Appropriate comments
Gas Efficiency
- ✅ Menggunakan view/pure functions saat memungkinkan
- ✅ Minimal storage operations
8. Konsep Lanjutan yang Akan Dipelajari
Dalam pengembangan selanjutnya, kita dapat memperluas TaskManager dengan:
- Events: Untuk logging aktivitas
- Modifiers: Untuk reusable access control
- Structs: Untuk data task yang lebih kompleks
- Arrays: Untuk menyimpan daftar tasks
- Error Handling: Custom errors yang lebih efisien
Kesimpulan
Pada bagian ini, kita telah berhasil:
- Membuat smart contract TaskManager dengan berbagai konsep Solidity
- Memahami visibility functions (public, private, view, pure)
- Menerapkan state variables dengan scope yang tepat
- Menggunakan mapping untuk penyimpanan data key-value
- Menerapkan validasi dengan require()
- Mengkompilasi contract tanpa error
Smart contract TaskManager ini memberikan fondasi yang solid untuk memahami konsep fundamental Solidity. Pada bagian selanjutnya, kita akan membuat comprehensive testing untuk memastikan contract berfungsi dengan benar sebelum deployment ke Monad Testnet.