Solidity / Enum

Enum

enum бол тодорхой нэрлэгдсэн утгуудын жагсаалт тодорхойлдог өгөгдлийн төрөл. Contract-ийн төлөвийг 0, 1, 2 тоогоор биш утга учиртай нэрээр (Pending, Shipped, Delivered) илэрхийлэх боломж олгодог.

Enum тодорхойлох

solidity
enum EnumName {
    Value1,
    Value2,
    Value3
}
solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;

contract OrderSystem {
    enum OrderStatus {
        Pending,    // 0
        Confirmed,  // 1
        Shipped,    // 2
        Delivered,  // 3
        Cancelled   // 4
    }
}

Enum дотоодоо uint8 хэлбэрээр хадгалагддаг — Pending = 0, Confirmed = 1 гэх мэт. Гэхдээ кодод тоо биш нэрийг ашиглана.

Default утга

Enum-ийн default утга нь жагсаалтын эхний элемент — тоогоор бол 0.

solidity
contract StatusExample {
    enum Status { Inactive, Active, Banned }

    Status public userStatus;   // default: Inactive (0)

    function activate() public {
        userStatus = Status.Active;
    }

    function isActive() public view returns (bool) {
        return userStatus == Status.Active;
    }
}

State machine загвар

State machine бол тодорхой төлөвүүдтэй, тэдгээр хоорондоо шилжих дүрэмтэй систем. Enum нь state machine-г хэрэгжүүлэхэд хамгийн тохиромжтой.

код
Pending → Confirmed → Shipped → Delivered
   ↓                               ↑
Cancelled ←←←←←←←←←←←←←←←←←←←←←←
solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;

contract OrderTracking {
    enum OrderStatus {
        Pending,    // захиалга өгсөн, баталгаажаагүй
        Confirmed,  // худалдагч баталгаажуулсан
        Shipped,    // тээвэрт гарсан
        Delivered,  // хүргэгдсэн
        Cancelled   // цуцлагдсан
    }

    struct Order {
        uint256     id;
        address     buyer;
        uint256     amount;
        OrderStatus status;
        uint256     createdAt;
    }

    mapping(uint256 => Order) public orders;
    uint256 public orderCount;
    address public owner;

    constructor() {
        owner = msg.sender;
    }

    function placeOrder() public payable returns (uint256 orderId) {
        require(msg.value > 0, "ETH илгээх ёстой");

        orderId = orderCount++;
        orders[orderId] = Order({
            id:        orderId,
            buyer:     msg.sender,
            amount:    msg.value,
            status:    OrderStatus.Pending,    // анхдагч төлөв
            createdAt: block.timestamp
        });
    }

    function confirmOrder(uint256 orderId) public {
        require(msg.sender == owner, "Зөвхөн эзэмшигч");
        require(orders[orderId].status == OrderStatus.Pending, "Pending төлөвт байх ёстой");

        orders[orderId].status = OrderStatus.Confirmed;
    }

    function shipOrder(uint256 orderId) public {
        require(msg.sender == owner, "Зөвхөн эзэмшигч");
        require(orders[orderId].status == OrderStatus.Confirmed, "Confirmed төлөвт байх ёстой");

        orders[orderId].status = OrderStatus.Shipped;
    }

    function confirmDelivery(uint256 orderId) public {
        require(orders[orderId].buyer == msg.sender, "Зөвхөн худалдан авагч");
        require(orders[orderId].status == OrderStatus.Shipped, "Shipped төлөвт байх ёстой");

        orders[orderId].status = OrderStatus.Delivered;
        // ETH-г худалдагчид шилжүүлэх логик...
    }

    function cancelOrder(uint256 orderId) public {
        Order storage order = orders[orderId];
        require(order.buyer == msg.sender, "Зөвхөн худалдан авагч");
        require(
            order.status == OrderStatus.Pending ||
            order.status == OrderStatus.Confirmed,
            "Энэ үед цуцлах боломжгүй"
        );

        order.status = OrderStatus.Cancelled;
        payable(msg.sender).transfer(order.amount);   // буцааж өгнө
    }

    function getStatus(uint256 orderId) public view returns (OrderStatus) {
        return orders[orderId].status;
    }
}

Enum харьцуулах ба шилжүүлэх

solidity
enum Phase { Setup, Active, Closed }
Phase public phase = Phase.Setup;

// харьцуулах
function isSetup() public view returns (bool) {
    return phase == Phase.Setup;
}

// uint8 болгон хөрвүүлэх
function getPhaseNumber() public view returns (uint8) {
    return uint8(phase);   // Setup=0, Active=1, Closed=2
}

// uint8-аас enum болгон хөрвүүлэх
function setPhaseByNumber(uint8 n) public {
    require(n <= uint8(Phase.Closed), "Хүчингүй утга");
    phase = Phase(n);
}

Enum-г contract-ийн гадна тодорхойлох

Олон contract ашиглах тохиолдолд enum-г дахин ашиглах боломжтой:

solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;

// Тусдаа файлд тодорхойлж, import хийж болно
enum UserRole {
    Guest,
    Member,
    Moderator,
    Admin
}

contract Forum {
    mapping(address => UserRole) public roles;

    function assignRole(address user, UserRole role) public {
        roles[user] = role;
    }

    function canPost(address user) public view returns (bool) {
        return roles[user] >= UserRole.Member;
    }

    function canModerate(address user) public view returns (bool) {
        return roles[user] >= UserRole.Moderator;
    }
}

Enum-ийн утгуудыг >=, <= операторуудаар харьцуулж болно — дотооддоо uint8 тул тооны харьцуулалт хийдэг.

Нийтлэг алдаа

solidity
enum Color { Red, Green, Blue }

// ❌ хүрээнээс гадуур хөрвүүлэх — runtime revert
Color c = Color(5);   // 0,1,2 л хүчинтэй

// ✅ шалгаад хөрвүүлэх
function setColor(uint8 n) public {
    require(n <= uint8(Color.Blue), "Хүчингүй өнгө");
    myColor = Color(n);
}

Дараагийн хичээлд:

event ба emit — blockchain-д log бичих, frontend-д мэдэгдэл илгээх аргыг судална.