Solidity / require, revert, assert

require, revert, assert

Smart contract-д алдааг зөв зохицуулах нь аюулгүй байдлын чухал хэсэг юм. Solidity-д гурван үндсэн механизм байдаг: require, revert, assert.

require — оролтыг шалгах

require нь хамгийн түгээмэл хэрэглэгддэг алдааны шалгалт. Нөхцөл биелэхгүй бол гүйлгээ буцаагдаж, мессеж харуулна.

solidity
// 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 блоктой хослуулж уян хатан логик бичиж болно.

solidity
// 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 нь хэзээ ч худал болж болохгүй нөхцөлийг шалгана. Ихэвчлэн хөгжүүлэлтийн алдааг илрүүлэхэд хэрэглэнэ.

solidity
// 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 хэмнэнэ.

solidity
// 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) ашиглан кодоо дахин ашиглах аргыг судална.