require, revert, assert
Smart contract-д алдааг зөв зохицуулах нь аюулгүй байдлын чухал хэсэг юм. Solidity-д гурван үндсэн механизм байдаг: require, revert, assert.
require — оролтыг шалгах
require нь хамгийн түгээмэл хэрэглэгддэг алдааны шалгалт. Нөхцөл биелэхгүй бол гүйлгээ буцаагдаж, мессеж харуулна.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Bank {
mapping(address => uint256) public balances;
function deposit() public payable {
require(msg.value > 0, "Дүн 0-ээс их байх ёстой");
balances[msg.sender] += msg.value;
}
function withdraw(uint256 amount) public {
require(amount > 0, "Дүн 0-ээс их байх ёстой");
require(balances[msg.sender] >= amount, "Үлдэгдэл хүрэлцэхгүй байна");
balances[msg.sender] -= amount;
payable(msg.sender).transfer(amount);
}
}
require буцаагдвал газ зарцуулсан хэсгийг буцаана — үлдсэн gas-ийг хэрэглэгчид буцаана.
revert — нарийн алдаа
revert нь нарийн нөхцөлтэй алдаа гаргахад хэрэглэгдэнэ. if блоктой хослуулж уян хатан логик бичиж болно.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Auction {
uint256 public highestBid;
address public highestBidder;
function bid() public payable {
if (msg.value == 0) {
revert("Дуусгавар үнэ 0 байж болохгүй");
}
if (msg.value <= highestBid) {
revert("Одоогийн хамгийн өндөр үнээс их байх ёстой");
}
highestBid = msg.value;
highestBidder = msg.sender;
}
}
assert — дотоод инвариант
assert нь хэзээ ч худал болж болохгүй нөхцөлийг шалгана. Ихэвчлэн хөгжүүлэлтийн алдааг илрүүлэхэд хэрэглэнэ.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Counter {
uint256 public count;
function increment() public {
count += 1;
// Тоолуур хэзээ ч буурахгүй байх ёстой — дотоод шалгалт
assert(count > 0);
}
}
assert буцаагдвал бүх gas зарцуулагдана — тиймээс зөвхөн дотоод логикийн алдааг шалгахад хэрэглэ.
Custom error — gas хэмнэлт
Solidity 0.8.4-өөс custom error нэвтэрсэн. String мессежтэй харьцуулахад gas хэмнэнэ.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
error InsufficientBalance(uint256 available, uint256 required);
error Unauthorized(address caller);
contract Vault {
mapping(address => uint256) public balances;
address public owner;
constructor() {
owner = msg.sender;
}
function withdraw(uint256 amount) public {
if (msg.sender != owner) {
revert Unauthorized(msg.sender);
}
if (balances[msg.sender] < amount) {
revert InsufficientBalance(balances[msg.sender], amount);
}
balances[msg.sender] -= amount;
payable(msg.sender).transfer(amount);
}
}
Custom error нь алдааны шалтгааныг нарийн мэдээлэлтэй дамжуулж, gas-ийн зардлыг бууруулна.
Хэзээ юуг ашиглах вэ?
| Механизм | Хэрэглэх үе |
| -------------- | --------------------------------------------- |
| require | Гаднаас ирж буй оролт, нөхцөл шалгах |
| revert | Нарийн нөхцөлтэй алдаа гаргах |
| assert | Хэзээ ч худал болохгүй дотоод нөхцөл |
| custom error | Gas хэмнэж, нарийн алдааны мэдээлэл дамжуулах |
Дараагийн хичээлд:
Өвлөлт (inheritance) ашиглан кодоо дахин ашиглах аргыг судална.