Solidity 101 - Part 2: Security, Transaction & Integration
Chapter 0: Pendahuluan
Selamat datang kembali! Di pertemuan sebelumnya (Part 1), kita sudah berhasil membuat “Buku Tabungan” digital. Kita belajar cara menyimpan data (variabel) dan membuat catatan (struct/array).
Namun, ada satu hal yang kurang: Uang Asli.
Hari ini, kita akan mengubah kode mainan kita menjadi aplikasi Crowdfunding (Galang Dana) sungguhan yang bisa:
- Menerima uang donasi (Ethereum).
- Menolak donasi jika nominalnya tidak sesuai aturan.
- Memberi notifikasi ke website saat donasi masuk.
- Mengamankan uang agar hanya pemilik yang bisa menariknya.
Chapter 1: Error Handling (Satpam Kontrak)

Dalam smart contract, kita berurusan dengan uang. Jika ada bug atau celah keamanan, uang itu bisa hilang selamanya. Karena itu, kita butuh mekanisme validasi yang ketat.
Solidity menyediakan tiga “Satpam” untuk menjaga fungsi kita:
A. Require (Validasi Input)
require adalah validasi yang paling sering digunakan. Ia bertugas mengecek input dari user atau kondisi awal sebelum fungsi dijalankan. Jika syarat tidak terpenuhi, require akan membatalkan transaksi dan mengembalikan sisa gas fee ke user.
function setPassword(string memory _password) public {
// Cek apakah password lebih dari 5 karakter
require(bytes(_password).length > 5, "Password terlalu pendek!");
// Kode di bawah ini TIDAK AKAN dijalankan jika require gagal
password = _password;
}
B. Revert (Logika Kompleks)
revert mirip dengan require, tapi biasanya digunakan di dalam logika percabangan (if-else) yang kompleks.
function ambilUang(uint256 _jumlah) public {
if (_jumlah > saldo) {
// Stop proses jika saldo kurang
revert("Saldo tidak cukup");
}
saldo -= _jumlah;
}
C. Assert (Pengecekan Internal)
assert digunakan untuk mengecek kondisi yang seharusnya tidak mungkin terjadi jika kode kita benar. Ini digunakan untuk mencari bug internal developer (bukan kesalahan user).
function reset() public {
saldo = 0;
// Cek ulang (Sanity Check). Harusnya saldo 0.
assert(saldo == 0);
}
✏️ Checkpoint Chapter 1: Pondasi Galang Dana
[!NOTE] Saatnya Praktik! Kerjakan latihan di bawah ini untuk membangun fondasi smart contract Galang Dana.
Mari kita mulai proyek baru. Buka Remix IDE dan ikuti langkah ini:
- Buat file baru bernama
GalangDana.sol. - Tulis lisensi SPDX dan pragma version
^0.8.0. - Buat contract bernama
GalangDana. - Variabel Penting:
- Buat variabel
uint256 public totalDonasi(untuk mencatat uang terkumpul). - Buat variabel
address public admin(untuk mencatat admin/pemilik kontrak).
- Buat variabel
- Constructor:
- Buat constructor yang mengisi variabel
admindengan alamat pembuat kontrak (msg.sender).
- Buat constructor yang mengisi variabel
- Fungsi Donasi Awal:
- Buat fungsi bernama
donasi. - Di dalamnya, tambahkan validasi
requireyang mewajibkan nominal uang (msg.value) harus lebih besar atau sama dengan 0.0001 ether. Berikan pesan error “Minimal donasi 0.0001 ETH”.
- Buat fungsi bernama
Catatan: Abaikan dulu error merah terkait
msg.valueataupayable. Kita akan memperbaikinya di Chapter 3.
Chapter 2: Environment & Events
Sebelum lanjut ke kode, kamu perlu mempersiapkan alat tempur agar bisa berinteraksi dengan blockchain sungguhan.
A. Konsep Wallet & Scanner
-
Wallet (Dompet Digital): Di dunia Web3, kita tidak login menggunakan email/password, melainkan menggunakan Wallet (seperti MetaMask). Wallet menyimpan Private Key (tanda tangan rahasia) dan Public Address (nomor rekening) kamu.
-
Scanner (Block Explorer): Blockchain itu transparan. Semua transaksi yang terjadi bisa dilihat oleh siapa saja melalui “Scanner” (seperti Blockscout). Kamu bisa melacak uang masuk dan keluar secara real-time.

B. Persiapan Lingkungan Kerja
Lakukan langkah-langkah ini secara berurutan:
- Install MetaMask: Pasang extension MetaMask di browser Chrome/Brave/Edge kamu.
- Setup Akun: Buat akun baru dan simpan Seed Phrase dengan aman.
- Network Base Sepolia: Pergi ke RemixIDE, dan hubungkan wallet melalui metode WalletConnect dan cari jaringan Base Sepolia.
- Tambah Wallet Penerima:
- Di MetaMask, klik ikon profil -> Create Account.
- Beri nama “Yayasan Penerima”. Kita butuh akun ke-2 ini nanti untuk tes penarikan dana.
- Ambil Faucet (Uang Mainan):
- Berikan alamat wallet kamu ke instruktur dan minta Base Sepolia ETH.
- Persiapan Frontend:
- Install extension Live Server di VSCode.
- Buat file
index.htmldi VSCode.
C. Events (Interaksi Frontend)
Blockchain itu sunyi. Saat transaksi berhasil dicatat di blok, smart contract tidak memberi tahu siapa-siapa secara otomatis. Agar website kamu tahu ada donasi masuk, kita menggunakan Events.
Format Event:
// 'indexed' artinya data ini nanti bisa dicari/difilter dengan mudah
event DonasiMasuk(address indexed donatur, uint256 jumlah);
Memancarkan (Emit) Event:
function bayar() public payable {
// ... logika bayar ...
emit DonasiMasuk(msg.sender, msg.value);
}✏️ Checkpoint Chapter 2: Integrasi Frontend
[!NOTE] Saatnya Praktik! Hubungkan smart contract dengan frontend untuk melihat event secara real-time.
-
Kode Frontend: Download file HTML di bawah ini, lalu simpan sebagai
index.htmldi folder project VSCode kamu.index.htmlKode Frontend untuk Event ListenerDownload
-
Jalankan Frontend: Klik kanan
index.html-> Open with Live Server. Pastikan kamu bisa klik tombol “Connect Wallet” dan status berubah menjadi Connected. -
Update Smart Contract: Kembali ke Remix, update file
GalangDana.sol:- Di dalam contract, definisikan event:
event DonasiMasuk(address indexed donatur, uint256 jumlah); - Di dalam fungsi
donasi, tambahkan logikatotalDonasi += msg.value; - Panggil event tersebut:
emit DonasiMasuk(msg.sender, msg.value);
- Di dalam contract, definisikan event:
Chapter 3: Ether Manipulation (Uang Asli)
Sekarang kita masuk ke bagian inti: Memprogram Uang.
A. Satuan Uang di Ethereum (Wei vs Gwei vs Ether)
Karena Solidity tidak mengenal angka desimal (koma), kita menggunakan satuan terkecil. Bayangkan seperti Rupiah: kita tidak pakai “0.001 Ribu”, tapi “1 Rupiah”.
| Satuan | Nilai (Wei) | Keterangan |
|---|---|---|
| Wei | 1 | Satuan terkecil (seperti perak/sen). |
| Gwei | 1.000.000.000 (109) | Sering dipakai untuk Gas Fee. |
| Ether | 1.000.000.000.000.000.000 (1018) | Satuan utama (1 ETH). |
B. Keyword payable
Secara default, fungsi di Solidity menolak kiriman uang. Ini fitur keamanan agar uang tidak “nyangkut” di fungsi yang salah. Agar fungsi bisa menerima uang, kamu wajib menempelkan stiker payable.
// Fungsi ini ERROR jika dikirimi uang
function hello() public {}
// Fungsi ini BISA menerima uang (tombol jadi MERAH di Remix)
function setor() public payable {}
✏️ Checkpoint Chapter 3: Live Donation
[!NOTE] Saatnya Praktik! Deploy ke testnet dan lakukan donasi pertamamu dengan uang (testnet) sungguhan!
Saatnya tes kodingan kamu dengan uang testnet.
-
Update Fungsi Donasi: Tambahkan kata kunci
payablepada fungsi donasi.function donasi() public payable { ... } -
Deploy ke Testnet:
- Di panel kiri Remix, buka tab Deploy & Run Transactions.
- Ubah Environment menjadi Browser Extension > Sepolia Testnet - Metamask (atau Injected Provider).
- MetaMask akan muncul meminta konfirmasi. Klik Connect.
- Klik tombol Deploy (oranye). Konfirmasi transaksi di MetaMask.
-
Integrasi:
- Copy address kontrak yang baru saja di-deploy.
- Paste ke dalam file
index.htmlbagianCONTRACT_ADDRESS.
-
Uji Coba (Interaksi Donasi):
- Di panel Remix (bagian kiri bawah), cari bagian VALUE.
- Masukkan angka donasi, misalnya
100000. - PENTING: Ubah satuan di sebelah kanan kotak input dari
WeimenjadiGwei.
Lihat screenshot di materi instruktur
- Klik tombol donasi (Merah).
- Lihat notifikasi yang muncul di website kamu!
Chapter 4: Security & Withdraw
Uang donasi sudah terkumpul di dalam Smart Contract. Sekarang pertanyaannya: Siapa yang bisa mengambil uangnya?
Jangan sampai orang asing (hacker) membuat fungsi untuk menarik uang donasi tersebut. Kita harus mengamankannya menggunakan konsep Admin/Owner.
A. Transfer ETH (.call)
Ada beberapa cara mengirim ETH keluar dari kontrak. Cara yang paling direkomendasikan saat ini adalah .call.
// Mengirim uang ke 'penerima'
(bool sukses, ) = penerima.call{value: jumlahUang}("");
require(sukses, "Gagal transfer");✏️ Checkpoint Chapter 4: Fitur Tarik Tunai
[!NOTE] Saatnya Praktik! Implementasikan fitur keamanan agar hanya admin yang bisa menarik dana.
Kita akan membuat fitur dimana Admin bisa mengirim seluruh hasil donasi ke rekening Yayasan (Wallet ke-2 yang kamu buat tadi).
Tambahkan fungsi tarikDana ke dalam kontrak:
- Buat fungsi
tarikDanayang menerima parameteraddress payable _tujuan. - Validasi Admin: Tambahkan
requireuntuk memastikan yang memanggil fungsi ini adalahadmin. Jika bukan, tolak dengan pesan “Bukan Admin”. - Validasi Saldo: Cek apakah saldo kontrak (
address(this).balance) lebih besar dari 0. - Eksekusi:
- Lakukan transfer seluruh saldo kontrak ke alamat
_tujuan. - Reset
totalDonasimenjadi 0.
- Lakukan transfer seluruh saldo kontrak ke alamat
Chapter 5: Kode Lengkap (Studi Kasus: Galang Dana)
Berikut adalah hasil akhir dari kontrak GalangDana.sol yang sudah di-update. Pastikan kode kamu sesuai dengan struktur di bawah ini sebelum melakukan deploy final.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract GalangDana {
address public admin;
uint256 public totalDonasi;
// Event agar frontend tau ada uang masuk
event DonasiMasuk(address indexed donatur, uint256 jumlah, string message);
constructor() {
// Yang deploy kontrak otomatis jadi admin
admin = msg.sender;
}
// Fungsi Donasi (Menerima Uang)
function donasi(string memory _message) public payable {
// Minimal donasi 0.0001 ETH (sekitar seribu-an rupiah di mainnet)
require(msg.value >= 0.0001 ether, "Minimal donasi 0.0001 ETH");
// Catat donasi ke variabel
totalDonasi += msg.value;
// Kabari frontend lewat Event
emit DonasiMasuk(msg.sender, msg.value, _message);
}
// Fungsi Withdraw (Tarik Uang)
function tarikDana(address payable _tujuan) public {
// 1. Validasi: Hanya admin yang boleh tarik
require(msg.sender == admin, "Hanya admin yang bisa tarik dana!");
// 2. Validasi: Pastikan ada uang di kontrak
uint256 saldoSaatIni = address(this).balance;
require(saldoSaatIni > 0, "Saldo kontrak kosong");
// 3. Reset total donasi (opsional, untuk pembukuan ulang)
totalDonasi = 0;
// 4. Transfer uang
(bool sukses, ) = _tujuan.call{value: saldoSaatIni}("");
require(sukses, "Gagal transfer dana");
}
}
Tantangan Akhir
- Deploy kode lengkap di atas ke jaringan Sepolia.
- Gunakan Akun 1 di MetaMask untuk melakukan Donasi (ingat ganti unit ke Gwei!).
- Pindah ke Akun 2 (Yayasan) di MetaMask, coba panggil fungsi
tarikDana. Harusnya GAGAL. - Kembali ke Akun 1, panggil fungsi
tarikDanadan masukkan alamat Akun 2 sebagai tujuan. Harusnya BERHASIL.
Selamat! Kamu resmi menjadi Web3 Developer yang bisa menangani uang dan keamanan. 🚀