Buổi 5 — Hợp đồng thông minh (Smart Contracts)
Môn học: Blockchain: Nền tảng, Ứng dụng & Bảo mật
Giảng viên: Trần Tuấn Dũng
Mục tiêu buổi học
1. Smart Contract là gì?
1.1 Lịch sử & Ý tưởng sơ khai
Ý tưởng về Hợp đồng thông minh có từ rất lâu trước cả Bitcoin. Vào năm 1994, nhà mật mã học Nick Szabo đã đưa ra định nghĩa đầu tiên, ví von Hợp đồng thông minh với một chiếc máy bán hàng tự động.
1.2 Ví von kinh điển: Máy bán hàng tự động
Chiếc máy này có các đặc tính giống hệt một Hợp đồng thông minh:
1.3 Định nghĩa chính thức
2. Solidity
Solidity là ngôn ngữ lập trình chính để viết Hợp đồng thông minh trên Ethereum và các blockchain tương thích EVM khác.
2.1 Hello World
// 1. Khai báo phiên bản trình biên dịch
pragma solidity ^0.8.20;
// 2. Khai báo Hợp đồng
contract HelloWorld {
// 3. Khai báo một biến trạng thái (State Variable)
string public greet = "Hello, World!";
}2.2 Biến trạng thái (State Variables)
Biến trạng thái là các biến có giá trị được lưu trữ vĩnh viễn trên blockchain. Chúng đại diện cho “bộ nhớ” của hợp đồng.
contract SimpleStorage {
// Biến này sẽ được lưu mãi mãi trên blockchain
uint256 public favoriteNumber;
}2.3 Hàm (Functions)
Hàm là các khối mã có thể thực thi. Chúng là cách chúng ta tương tác và thay đổi trạng thái của hợp đồng.
contract SimpleStorage {
uint256 public favoriteNumber;
// Một hàm để thay đổi biến trạng thái
function store(uint256 _newNumber) public {
favoriteNumber = _newNumber;
}
// Một hàm chỉ để đọc biến trạng thái (không tốn gas)
function retrieve() public view returns (uint256) {
return favoriteNumber;
}
}So sánh Hàm Write vs. Hàm Read
| Tiêu chí | Hàm thay đổi trạng thái (Write) | Hàm chỉ đọc (Read) |
|---|---|---|
| Mục đích | Thay đổi dữ liệu trên blockchain | Đọc dữ liệu từ blockchain |
| Từ khóa | (không có) | view, pure |
| Chi phí Gas | CÓ, vì thay đổi trạng thái | KHÔNG, khi được gọi từ bên ngoài |
| Thực thi | Cần một giao dịch, được xác thực bởi toàn mạng lưới | Thực thi tức thì trên một node duy nhất |
| Ví dụ | transfer(), mint() | balanceOf(), ownerOf() |
2.4 Kiểu dữ liệu
Kiểu dữ liệu cơ bản
| Kiểu | Mô tả |
|---|---|
bool | true / false |
uint / int | Số nguyên không dấu và có dấu (ví dụ: uint256) |
address | Lưu trữ địa chỉ Ethereum (20 bytes). Có .balance, .transfer() |
string | Chuỗi ký tự |
bytes | Dãy byte động |
Kiểu dữ liệu phức hợp
Mảng (Arrays):
uint[] public numbers;Struct:
struct Person { string name; uint age; }Mappings — cấu trúc dữ liệu dạng key-value, giống hash table / dictionary. Rất hiệu quả về gas:
// Ánh xạ từ một địa chỉ tới một số dư
mapping(address => uint) public balances;2.5 Visibility (Phạm vi truy cập)
| Từ khóa | Ai có thể gọi? | Ghi chú |
|---|---|---|
public | Bất kỳ ai (bên ngoài hoặc nội bộ) | Tự động tạo ra một hàm getter |
private | Chỉ bên trong hợp đồng này | Không thể được truy cập bởi hợp đồng con |
internal | Bên trong hợp đồng này và các hợp đồng con kế thừa nó | Giống protected trong các ngôn ngữ khác |
external | Chỉ từ bên ngoài hợp đồng (qua giao dịch) | Tối ưu gas khi nhận dữ liệu lớn |
3. Vòng đời của một Smart Contract
4. Tiêu chuẩn Smart Contract (ERC)
4.1 ERC-20: Token Có thể thay thế (Fungible)
Fungible = mỗi đơn vị đều giống hệt nhau và có thể thay thế cho nhau. Ví dụ: một tờ 100.000 VNĐ này có giá trị y hệt một tờ 100.000 VNĐ khác.
ERC-20 định nghĩa một bộ hàm chung cho các token, cho phép chúng được niêm yết trên sàn giao dịch và được lưu trữ trong ví một cách dễ dàng.
Ví dụ: USDT, SHIB, UNI, LINK…
Các hàm cốt lõi của ERC-20
function totalSupply() public view returns (uint256);
function balanceOf(address account) public view returns (uint256);
function transfer(address recipient, uint256 amount) public returns (bool);
function allowance(address owner, address spender) public view returns (uint256);
function approve(address spender, uint256 amount) public returns (bool);
function transferFrom(address sender, address recipient, uint256 amount) public returns (bool);4.2 ERC-721: Token Không thể thay thế (Non-Fungible)
Non-Fungible = mỗi token là duy nhất và không thể thay thế cho token khác. Ví dụ: bức tranh Mona Lisa không giống với bất kỳ bức tranh nào khác.
ERC-721 cho phép tạo ra các tài sản số độc nhất, có thể chứng minh quyền sở hữu và nguồn gốc.
Ứng dụng: Tác phẩm nghệ thuật số, vật phẩm trong game, vé sự kiện, tên miền…
Các hàm cốt lõi của ERC-721
function balanceOf(address owner) public view returns (uint256);
function ownerOf(uint256 tokenId) public view returns (address);
function safeTransferFrom(address from, address to, uint256 tokenId) public;
function approve(address to, uint256 tokenId) public;
function getApproved(uint256 tokenId) public view returns (address);4.3 So sánh ERC-20 và ERC-721
| Tiêu chí | ERC-20 | ERC-721 |
|---|---|---|
| Loại token | Fungible (có thể thay thế) | Non-Fungible (không thể thay thế) |
| Tính duy nhất | Mọi token đều giống nhau | Mỗi token là duy nhất |
| Ví dụ thực tế | Tiền tệ, cổ phiếu | NFT, nghệ thuật số, vật phẩm game |
| Hàm định danh | balanceOf(address) | ownerOf(tokenId) |
| Ví dụ token | USDT, UNI, LINK | CryptoPunks, BAYC |
📝 50 Câu trắc nghiệm ôn tập
Phần 1: Smart Contract — Khái niệm & Lịch sử
Câu 1. Nick Szabo đưa ra khái niệm Hợp đồng thông minh vào năm nào?
- A. 1989
- B. 1994
- C. 2008
- D. 2015
Câu 2. Nick Szabo ví von Hợp đồng thông minh với thứ gì?
- A. Hợp đồng giấy tờ công chứng
- B. Máy tính lượng tử
- C. Máy bán hàng tự động
- D. Ngân hàng trung ương
Câu 3. Hợp đồng thông minh được định nghĩa chính thức là gì?
- A. Hợp đồng pháp lý số hóa được lưu trên máy chủ trung tâm
- B. Các chương trình máy tính lưu trên blockchain, tự động thực thi khi điều kiện được đáp ứng
- C. Ứng dụng web3 kết nối với ngân hàng
- D. Tài khoản người dùng trên Ethereum
Câu 4. Smart Contract về cơ bản là loại tài khoản nào?
- A. Tài khoản được điều khiển bởi ngân hàng
- B. Tài khoản được điều khiển bởi con người
- C. Tài khoản được điều khiển bởi mã nguồn
- D. Tài khoản ẩn danh
Câu 5. Đặc tính nào của Smart Contract đảm bảo rằng các quy tắc không thể bị một bên đơn phương thay đổi?
- A. Self-executing
- B. Transparent
- C. Immutable
- D. Disintermediated
Câu 6. Đặc tính nào của Smart Contract giúp loại bỏ sự cần thiết của bên trung gian?
- A. Immutable
- B. Disintermediated
- C. Transparent
- D. Compiled
Câu 7. Blockchain nào đầu tiên được thiết kế như một “Máy tính Thế giới” (World Computer) với khả năng lập trình Turing-complete?
- A. Bitcoin
- B. Litecoin
- C. Ethereum
- D. Solana
Phần 2: Solidity — Ngôn ngữ lập trình
Câu 8. Solidity chịu ảnh hưởng cú pháp từ những ngôn ngữ nào?
- A. Java, Ruby, Swift
- B. C++, Python, JavaScript
- C. Go, Rust, Kotlin
- D. PHP, Perl, Bash
Câu 9. Solidity là kiểu ngôn ngữ lập trình nào?
- A. Thông dịch, hướng thủ tục
- B. Biên dịch, hướng đối tượng
- C. Thông dịch, hướng đối tượng
- D. Biên dịch, hướng chức năng
Câu 10. Môi trường thực thi mà Solidity được thiết kế để hoạt động là gì?
- A. JVM (Java Virtual Machine)
- B. V8 Engine
- C. EVM (Ethereum Virtual Machine)
- D. WASM (WebAssembly)
Câu 11. Dòng pragma solidity ^0.8.20; có tác dụng gì?
- A. Import thư viện Solidity
- B. Khai báo tên hợp đồng
- C. Khai báo phiên bản trình biên dịch
- D. Định nghĩa hàm khởi tạo
Câu 12. Biến trạng thái (State Variable) trong Solidity được lưu trữ ở đâu?
- A. RAM của node
- B. Vĩnh viễn trên blockchain
- C. Trên máy chủ của Ethereum Foundation
- D. Trong bộ nhớ tạm thời
Câu 13. Hành động nào dưới đây tốn Gas nhiều nhất trong Solidity?
- A. Gọi hàm
view - B. Đọc một biến
public - C. Thay đổi giá trị biến trạng thái
- D. Gọi hàm
pure
Câu 14. Từ khóa view trong hàm Solidity có nghĩa là gì?
- A. Hàm có thể thay đổi trạng thái
- B. Hàm chỉ đọc dữ liệu, không thay đổi trạng thái
- C. Hàm được gọi nội bộ
- D. Hàm nhận ETH
Câu 15. Hàm Write khác hàm Read ở điểm gì về cách thực thi?
- A. Hàm Write chạy nhanh hơn
- B. Hàm Write cần một giao dịch, được xác thực bởi toàn mạng lưới
- C. Hàm Write không cần Gas
- D. Hàm Write chỉ chạy trên một node duy nhất
Câu 16. Kiểu dữ liệu nào trong Solidity dùng để lưu địa chỉ Ethereum?
- A.
string - B.
bytes32 - C.
address - D.
uint160
Câu 17. Kiểu address có những thuộc tính đặc biệt nào?
- A.
.lengthvà.push() - B.
.balancevà.transfer() - C.
.namevà.symbol() - D.
.ownervà.approve()
Câu 18. mapping(address => uint) trong Solidity tương đương với cấu trúc dữ liệu nào?
- A. Mảng (Array)
- B. Hàng đợi (Queue)
- C. Hash table / Dictionary
- D. Stack
Câu 19. struct trong Solidity dùng để làm gì?
- A. Khai báo hàm
- B. Tạo ra các kiểu dữ liệu phức tạp tùy chỉnh
- C. Định nghĩa sự kiện (event)
- D. Import thư viện
Câu 20. Visibility nào tương đương với protected trong các ngôn ngữ lập trình khác?
- A.
public - B.
private - C.
internal - D.
external
Câu 21. Visibility nào KHÔNG thể được truy cập bởi hợp đồng con?
- A.
public - B.
internal - C.
private - D.
external
Câu 22. Visibility nào tối ưu Gas nhất khi nhận dữ liệu lớn từ bên ngoài?
- A.
public - B.
private - C.
internal - D.
external
Câu 23. Khi khai báo biến trạng thái public, Solidity tự động làm gì?
- A. Tạo một hàm setter
- B. Tạo một hàm getter
- C. Mã hóa biến đó
- D. Emit một event
Câu 24. Hàm nào dưới đây là ví dụ của hàm Write (thay đổi trạng thái)?
- A.
balanceOf() - B.
ownerOf() - C.
totalSupply() - D.
transfer()
Câu 25. Kiểu dữ liệu bool trong Solidity nhận những giá trị nào?
- A. 0 và 1
- B.
truevàfalse - C.
yesvàno - D.
nullvàundefined
Phần 3: Vòng đời Smart Contract
Câu 26. Bước đầu tiên trong vòng đời của một Smart Contract là gì?
- A. Triển khai (Deploy)
- B. Biên dịch (Compile)
- C. Viết mã (Code)
- D. Tương tác (Interact)
Câu 27. Kết quả của bước Biên dịch (Compile) là gì?
- A. Token ERC-20 và ERC-721
- B. Bytecode và ABI
- C. Gas và Gwei
- D. Block và Transaction
Câu 28. Bytecode là gì?
- A. Mã Python đã được rút gọn
- B. File JSON mô tả các hàm của hợp đồng
- C. Mã máy cấp thấp mà EVM có thể hiểu và thực thi
- D. Địa chỉ của hợp đồng trên blockchain
Câu 29. ABI (Application Binary Interface) là gì?
- A. Mã máy cấp thấp cho EVM
- B. File JSON mô tả các hàm của hợp đồng để bên ngoài tương tác
- C. Địa chỉ public của hợp đồng
- D. Ngôn ngữ lập trình thay thế Solidity
Câu 30. Khi triển khai (Deploy) Smart Contract, điều gì xảy ra?
- A. Hợp đồng được lưu trên máy chủ của Infura
- B. Bytecode được gửi lên Ethereum và một tài khoản hợp đồng mới được tạo ra
- C. ABI được upload lên IPFS
- D. Token ERC-20 được mint tự động
Câu 31. Sau khi triển khai, người dùng tương tác với Smart Contract bằng cách nào?
- A. Gửi email đến nhà phát triển
- B. Gửi giao dịch đến địa chỉ của hợp đồng
- C. Gọi API REST truyền thống
- D. Chỉnh sửa trực tiếp mã nguồn
Câu 32. Sau khi Smart Contract được triển khai, mã nguồn có thể bị thay đổi không?
- A. Có, nếu người triển khai có private key
- B. Có, nếu có đủ 51% node đồng ý
- C. Không, mã nguồn không thể thay đổi sau khi triển khai (Immutable)
- D. Có, thông qua ABI
Phần 4: Tiêu chuẩn ERC
Câu 33. ERC là viết tắt của gì?
- A. Ethereum Research Community
- B. Ethereum Request for Comment
- C. Extended Request Contract
- D. Ethereum Runtime Code
Câu 34. Tại sao cần có các tiêu chuẩn ERC?
- A. Để thu phí Gas cho Ethereum Foundation
- B. Để các hợp đồng, ví, sàn giao dịch có thể hiểu và tương tác với nhau
- C. Để hạn chế số lượng token trên Ethereum
- D. Để mã hóa dữ liệu người dùng
Câu 35. ERC-20 là tiêu chuẩn cho loại token nào?
- A. Non-Fungible Token (NFT)
- B. Fungible Token (Token có thể thay thế)
- C. Governance Token
- D. Soulbound Token
Câu 36. “Fungible” có nghĩa là gì?
- A. Mỗi token là duy nhất
- B. Mỗi đơn vị đều giống hệt nhau và có thể thay thế cho nhau
- C. Token không thể chuyển nhượng
- D. Token được mã hóa bằng ZK-proof
Câu 37. Token nào dưới đây là ví dụ của ERC-20?
- A. CryptoPunks
- B. Bored Ape Yacht Club
- C. USDT
- D. ENS Domain
Câu 38. Hàm totalSupply() trong ERC-20 trả về gì?
- A. Số lượng người dùng đang giữ token
- B. Tổng cung của token
- C. Số dư token của một địa chỉ
- D. Lượng Gas đã tiêu thụ
Câu 39. Hàm balanceOf(address account) trong ERC-20 làm gì?
- A. Kiểm tra số ETH của một địa chỉ
- B. Trả về số lượng token ERC-20 mà địa chỉ đó đang nắm giữ
- C. Chuyển token từ địa chỉ này sang địa chỉ khác
- D. Phê duyệt quyền chi tiêu
Câu 40. Hàm approve() trong ERC-20 dùng để làm gì?
- A. Xác nhận giao dịch trên blockchain
- B. Phê duyệt cho một địa chỉ khác (spender) được phép chi tiêu một lượng token nhất định
- C. Tạo ra token mới
- D. Khóa token trong smart contract
Câu 41. Hàm transferFrom() trong ERC-20 được dùng khi nào?
- A. Người dùng tự chuyển token của mình
- B. Một hợp đồng thứ ba chuyển token thay mặt người dùng, sau khi đã được
approve - C. Mint token mới cho người dùng
- D. Đốt (burn) token
Câu 42. ERC-721 là tiêu chuẩn cho loại token nào?
- A. Fungible Token
- B. Stablecoin
- C. Non-Fungible Token (NFT)
- D. Wrapped Token
Câu 43. “Non-Fungible” có nghĩa là gì?
- A. Token có thể thay thế cho nhau
- B. Mỗi token là duy nhất và không thể thay thế cho token khác
- C. Token không thể giao dịch
- D. Token cố định giá trị
Câu 44. Hàm đặc trưng nhất của ERC-721, phân biệt nó với ERC-20, là hàm nào?
- A.
balanceOf() - B.
approve() - C.
ownerOf(uint256 tokenId) - D.
transfer()
Câu 45. Ứng dụng nào dưới đây phù hợp với ERC-721?
- A. Tiền ổn định (Stablecoin) như USDT
- B. Vé sự kiện độc nhất, tác phẩm nghệ thuật số
- C. Token quản trị (Governance)
- D. Token thanh khoản (LP Token)
Câu 46. Hàm safeTransferFrom() trong ERC-721 khác gì so với transfer() trong ERC-20?
- A.
safeTransferFrom()không tốn Gas - B.
safeTransferFrom()bao gồm tokenId vì mỗi NFT là duy nhất, không chỉ chuyển một lượng - C.
safeTransferFrom()chỉ hoạt động với ETH - D. Không có sự khác biệt
Câu 47. Trong ERC-20, allowance(owner, spender) trả về gì?
- A. Số dư token của owner
- B. Lượng token mà spender được phép dùng từ tài khoản của owner
- C. Tổng cung token
- D. Địa chỉ hợp đồng
Câu 48. Điểm khác biệt cơ bản nhất giữa ERC-20 và ERC-721 là gì?
- A. ERC-20 dùng Solidity, ERC-721 dùng ngôn ngữ khác
- B. ERC-20 là fungible (có thể thay thế), ERC-721 là non-fungible (độc nhất)
- C. ERC-20 rẻ Gas hơn ERC-721
- D. ERC-721 ra đời trước ERC-20
Phần 5: Tổng hợp & Nâng cao
Câu 49. Trong Solidity, hàm pure khác view ở điểm nào?
- A.
puretốn Gas hơnview - B.
purekhông đọc cũng không thay đổi trạng thái blockchain - C.
purechỉ dùng cho ERC-721 - D.
purekhông thể được gọi từ bên ngoài
Câu 50. Nếu muốn xây dựng một hệ thống điểm tích lũy (loyalty points) mà mỗi điểm có giá trị như nhau, bạn nên dùng tiêu chuẩn nào?
- A. ERC-721
- B. ERC-20
- C. Cả hai đều được
- D. Không dùng tiêu chuẩn nào
Câu 51. Tại sao khi gọi hàm view hoặc pure từ bên ngoài, người dùng không tốn Gas?
- A. Vì Ethereum miễn phí cho hàm đọc
- B. Vì không có thay đổi trạng thái nào được ghi lên blockchain, không cần sự đồng thuận của mạng lưới
- C. Vì hàm view chạy offline
- D. Vì Infura trả Gas thay cho người dùng
Câu 52. Để triển khai một Smart Contract, người triển khai cần gì?
- A. Được phép từ Ethereum Foundation
- B. Gửi một giao dịch đặc biệt chứa bytecode và trả Gas
- C. Có ít nhất 32 ETH để staking
- D. Chạy một Ethereum node đầy đủ
Câu 53. Trong vòng đời Smart Contract, bước nào tạo ra ABI?
- A. Viết mã (Code)
- B. Biên dịch (Compile)
- C. Triển khai (Deploy)
- D. Tương tác (Interact)
Câu 54. Mapping trong Solidity có nhược điểm gì so với Array?
- A. Mapping tốn Gas hơn Array
- B. Mapping không thể duyệt (iterate) qua tất cả phần tử
- C. Mapping chỉ hỗ trợ kiểu uint làm key
- D. Mapping không thể lưu dữ liệu vĩnh viễn
Câu 55. Smart Contract có thể nhận ETH không? Điều kiện là gì?
- A. Không, Smart Contract không thể nhận ETH
- B. Có, nhưng phải có hàm
receive()hoặcfallback()được khai báo - C. Có, mọi contract đều tự động nhận ETH
- D. Có, nhưng chỉ từ địa chỉ của người triển khai