Cấu trúc hợp đồng (Contract structure)
Biến trạng thái và biến cục bộ (State and local variables)
Biến trạng thái
là các biến được khai báo ở phần đầu tiên của contract, bên ngoài phạm vi của biến cục bộ
được khai báo trong function
.
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.0;
contract Bank {
uint public totalDeposits; // Biến trạng thái toàn cục
function deposit(uint amount) public {
uint fee = amount / 100; // 1% fee, biến cục bộ
uint netAmount = amount - fee;
totalDeposits += netAmount; // cập nhật biến trạng thái
}
function getNetAmount() public view returns (uint) {
// return netAmount; // Lỗi: netAmount chỉ tồn tại trong hàm deposit
return totalDeposits; // Đúng: totalDeposits là biến trạng thái
}
}
[Giải thích]
totalDeposits là biến trạng thái – tồn tại trên blockchain và có thể được truy cập từ bất kỳ hàm nào trong contract.
fee và netAmount là biến cục bộ – chỉ tồn tại trong nội bộ hàm deposit.
Nếu bạn cố truy cập netAmount từ hàm khác như getNetAmount, trình biên dịch sẽ báo lỗi giống như ví dụ bạn đã đưa ra.
Hàm (Functions)
Hàm
là các function được khai báo để thực hiện tính toán, thay đổi giá trị biến, v.v. Một ví dụ về function
như sau.
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.1 <0.9.0;
contract GradeBook {
mapping(address => uint) public scores;
function submitScore(uint score) public {
require(score <= 100, "Score must be between 0 and 100");
scores[msg.sender] = score;
}
function getGrade() public view returns (string memory) {
uint score = scores[msg.sender];
return convertToGrade(score);
}
}
// Hàm trợ giúp nằm ngoài contract
function convertToGrade(uint score) pure returns (string memory) {
if (score >= 90) return "A";
else if (score >= 80) return "B";
else if (score >= 70) return "C";
else if (score >= 60) return "D";
else return "F";
}
[Giải thích]
GradeBook lưu trữ điểm của mỗi người dùng trong một mapping.
getGrade() sử dụng convertToGrade(score) – một helper function nằm ngoài contract – để xác định hạng điểm.
Hàm helper không thể truy cập vào trạng thái của contract
Bộ sửa đổi hàm (Function modifiers)
Function modifier
là các khai báo cho function
để tạo điều kiện cho việc thực thi hành động của hàm đó.
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.22 <0.9.0;
contract Voting {
address public chairperson;
mapping(address => bool) public voters;
constructor() {
chairperson = msg.sender;
}
// hàm Modifier chỉ cho phép người dùng là chairperson mới có thể thực hiện hàm addVoter
modifier onlyChairperson() {
require(msg.sender == chairperson, "Only chairperson can perform this action");
_;
}
function addVoter(address voter) public onlyChairperson {
require(!voters[voter], "Already registered");
voters[voter] = true;
}
function isRegistered(address voter) public view returns (bool) {
return voters[voter];
}
}
[Giải thích]
onlyChairperson là một modifier dùng để giới hạn quyền truy cập – chỉ cho phép chairperson gọi một số hàm nhất định.
Hàm addVoter() sử dụng modifier này để đảm bảo chỉ người triển khai hợp đồng (Chair person) mới được phép đăng ký cử tri.
Sự kiện (Events) và lỗi (Errors)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Bank {
mapping(address => uint) private balances;
// 🔔 Sự kiện được phát khi người dùng nạp tiền
event Deposited(address indexed user, uint amount);
// 🔔 Sự kiện được phát khi người dùng rút tiền thành công
event Withdrawn(address indexed user, uint amount);
// ❌ Lỗi tùy chỉnh khi không đủ số dư
error InsufficientBalance(uint requested, uint available);
// Hàm nạp tiền
function deposit() public payable {
balances[msg.sender] += msg.value;
emit Deposited(msg.sender, msg.value); // Phát sự kiện
}
// Hàm rút tiền có xử lý lỗi tùy chỉnh
function withdraw(uint amount) public {
uint balance = balances[msg.sender];
if (amount > balance) {
revert InsufficientBalance(amount, balance); // Gọi lỗi tùy chỉnh
}
balances[msg.sender] -= amount;
payable(msg.sender).transfer(amount);
emit Withdrawn(msg.sender, amount); // Phát sự kiện
}
// Hàm xem số dư
function getBalance() public view returns (uint) {
return balances[msg.sender];
}
}
Giải thích
Sự kiện:
- event Deposited(address, uint) – ghi lại các giao dịch nạp tiền
- event Withdrawn(address, uint) – ghi lại các giao dịch rút tiền
- Sự kiện được dùng để giao tiếp với frontend hoặc theo dõi lịch sử giao dịch qua logs.
Lỗi tùy chỉnh:
- error InsufficientBalance(uint requested, uint available);