Solidity / Struct
Struct
struct бол холбоотой өгөгдлийг нэг нэгжид бүлэглэх өгөгдлийн бүтэц. Жишээ нь хэрэглэгчийн нэр, хаяг, үлдэгдлийг тус тусдаа гурван mapping-д хадгалах бус, нэг User struct болгон цэгцэлж болно.
Struct тодорхойлох
solidity
struct StructName {
Type1 field1;
Type2 field2;
Type3 field3;
}
solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;
contract StudentRegistry {
struct Student {
string name;
uint256 age;
uint256 score;
bool isActive;
}
}
Struct үүсгэх
solidity
contract StudentRegistry {
struct Student {
string name;
uint256 age;
uint256 score;
bool isActive;
}
Student public topStudent;
function setTopStudent() public {
// Арга 1: field-ийн дарааллаар
topStudent = Student("Болд", 20, 95, true);
// Арга 2: нэрлэсэн field (илүү ойлгомжтой)
topStudent = Student({
name: "Болд",
age: 20,
score: 95,
isActive: true
});
}
function getScore() public view returns (uint256) {
return topStudent.score; // dot notation-оор хандана
}
}
Mapping дотор struct
Хамгийн түгээмэл хослол — mapping(address => Struct):
solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;
contract UserProfile {
struct Profile {
string username;
uint256 xp;
uint256 level;
bool registered;
}
mapping(address => Profile) public profiles;
function register(string memory _username) public {
require(!profiles[msg.sender].registered, "Аль хэдийн бүртгэлтэй");
require(bytes(_username).length > 0, "Нэр хоосон байж болохгүй");
profiles[msg.sender] = Profile({
username: _username,
xp: 0,
level: 1,
registered: true
});
}
function addXP(uint256 amount) public {
require(profiles[msg.sender].registered, "Эхлээд бүртгүүлэх шаардлагатай");
profiles[msg.sender].xp += amount;
// level ахиулах логик
if (profiles[msg.sender].xp >= profiles[msg.sender].level * 100) {
profiles[msg.sender].level += 1;
}
}
function getMyProfile() public view returns (Profile memory) {
return profiles[msg.sender];
}
}
Array дотор struct
solidity
contract TaskManager {
struct Task {
uint256 id;
string description;
address assignedTo;
bool completed;
}
Task[] public tasks;
uint256 private nextId;
function createTask(string memory desc, address assignee) public {
tasks.push(Task({
id: nextId++,
description: desc,
assignedTo: assignee,
completed: false
}));
}
function completeTask(uint256 taskId) public {
require(taskId < tasks.length, "Буруу ID");
require(tasks[taskId].assignedTo == msg.sender, "Энэ таны даалгавар биш");
tasks[taskId].completed = true;
}
function getTask(uint256 index) public view returns (Task memory) {
return tasks[index];
}
function getTaskCount() public view returns (uint256) {
return tasks.length;
}
}
Function параметрт struct
solidity
contract ProductStore {
struct Product {
string name;
uint256 price;
uint256 stock;
}
mapping(uint256 => Product) public products;
uint256 public productCount;
// struct параметрт авах — memory шаардана
function addProduct(Product memory newProduct) public {
products[productCount] = newProduct;
productCount++;
}
// хялбар дуудалт
function addSimple(string memory name, uint256 price, uint256 qty) public {
addProduct(Product(name, price, qty));
}
}
Storage vs Memory struct
Storage pointer — struct-г storage-д шууд засварлана. Gas хямд — sload нэг удаа:
solidity
mapping(address => Profile) public profiles;
function levelUpStorage() public {
// ✅ storage pointer — шууд storage-д бичнэ
Profile storage p = profiles[msg.sender];
p.xp += 50;
p.level += 1;
// нэг SSTORE хийгдэнэ
}
Memory copy — struct-г санах ойд хуулж ажилладаг. Storage-д бичихгүй:
solidity
function levelUpMemory() public {
// ❌ memory copy — storage-д буцаж бичигдэхгүй!
Profile memory p = profiles[msg.sender];
p.xp += 50; // зөвхөн memory-д өөрчлөгдөнө
p.level += 1;
// profiles[msg.sender] өөрчлөгдсөнгүй!
}
Storage pointer ашиглах нь хэд хэдэн field өөрчлөхөд gas хэмнэнэ:
solidity
// ❌ storage-д 3 удаа бичнэ
profiles[msg.sender].xp += 50;
profiles[msg.sender].level += 1;
profiles[msg.sender].active = true;
// ✅ нэг pointer-ээр 3 field өөрчилнө — gas хямд
Profile storage p = profiles[msg.sender];
p.xp += 50;
p.level += 1;
p.active = true;
Struct дотор mapping — хориотой
solidity
// ❌ БОЛОМЖГҮЙ — struct дотор mapping байж болохгүй (шууд)
struct BadUser {
string name;
mapping(address => bool) friends; // compile error
}
Ийм хэрэгцээнд тусдаа mapping ашигла:
solidity
// ✅ ЗӨВ
struct User {
string name;
uint256 friendCount;
}
mapping(address => User) public users;
mapping(address => mapping(address => bool)) public friendships;
Дараагийн хичээлд:
enum — тодорхой утгуудын жагсаалт, state machine загвар ашиглан contract-ийн төлөвийг удирдах аргыг судална.