Event ба emit
event нь Solidity-ийн мэдэгдлийн механизм — transaction хийгдэх үед blockchain-ийн log-д бичигддэг мэдээлэл. Фронтенд програм (ethers.js, viem) эдгээр event-г сонсож, шинэ үйл явдлыг бодит цагт ажиглах боломжтой.
Event тодорхойлох ба emit хийх
// Тодорхойлох
event EventName(Type1 param1, Type2 param2);
// Гаргах
emit EventName(value1, value2);
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;
contract SimpleToken {
mapping(address => uint256) public balances;
// event тодорхойлно
event Transfer(address from, address to, uint256 amount);
event Mint(address to, uint256 amount);
function mint(address to, uint256 amount) public {
balances[to] += amount;
emit Mint(to, amount); // log-д бичнэ
}
function transfer(address to, uint256 amount) public {
require(balances[msg.sender] >= amount, "Үлдэгдэл хүрэлцэхгүй");
balances[msg.sender] -= amount;
balances[to] += amount;
emit Transfer(msg.sender, to, amount); // log-д бичнэ
}
}
Event log хаана хадгалагддаг вэ?
Event нь storage-д биш, transaction log-д хадгалагддаг — storage-ийн ~1/5-ийн gas зарцуулдаг, гэхдээ Solidity-д уншиж чадахгүй. Зөвхөн гадны програм (фронтенд, indexer) унших боломжтой.
Transaction
├── from: 0xАбВГ...
├── to: contract
├── logs:
│ └── event Transfer(from=0xАбВГ, to=0хДЕЖ, amount=100)
│ ← gas хямд, contract дотроос уншигдахгүй
└── ...
Event ашиглах хэрэгцээ:
- Фронтенд шинэ үйл явдлыг бодит цагт харуулах
- DApp-ийн үйл ажиллагааг хянах (аудит)
- Дэд бүтцийн системүүд (The Graph, Etherscan) өгөгдөл цуглуулах
indexed параметр
indexed тэмдэглэгдсэн параметрийг хайх, шүүх боломжтой. Event-д дээд тал нь 3 indexed параметр тавьж болно.
event Transfer(
address indexed from, // хайж болно
address indexed to, // хайж болно
uint256 amount // indexed биш — хайж болохгүй
);
indexed параметр нь Ethereum-д topic болгон хадгалагддаг. Фронтенд эдгээр topic-р шүүдэг:
// ethers.js дээр: зөвхөн myAddress руу ирсэн Transfer-г сонсоно
contract.queryFilter(contract.filters.Transfer(null, myAddress));
indexed биш параметр нь data хэсэгт хадгалагддаг — шүүж болохгүй ч утгыг бүрэн харах боломжтой.
Бодит жишээ: NFT Marketplace
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;
contract NFTMarketplace {
struct Listing {
address seller;
uint256 price;
bool active;
}
mapping(uint256 => Listing) public listings;
// indexed: tokenId, seller — шүүж хайх боломжтой
event Listed(
uint256 indexed tokenId,
address indexed seller,
uint256 price
);
event Sold(
uint256 indexed tokenId,
address indexed seller,
address indexed buyer,
uint256 price
);
event Cancelled(
uint256 indexed tokenId,
address indexed seller
);
function listToken(uint256 tokenId, uint256 price) public {
require(price > 0, "Үнэ тэгээс их байх ёстой");
listings[tokenId] = Listing({
seller: msg.sender,
price: price,
active: true
});
emit Listed(tokenId, msg.sender, price);
}
function buyToken(uint256 tokenId) public payable {
Listing storage listing = listings[tokenId];
require(listing.active, "Зарагдахгүй байна");
require(msg.value == listing.price, "Үнэ таарахгүй байна");
require(listing.seller != msg.sender, "Өөрийн зүйлсээ худалдаж авах боломжгүй");
address seller = listing.seller;
listing.active = false;
payable(seller).transfer(msg.value);
emit Sold(tokenId, seller, msg.sender, msg.value);
}
function cancelListing(uint256 tokenId) public {
require(listings[tokenId].seller == msg.sender, "Зөвхөн эзэмшигч");
require(listings[tokenId].active, "Зарагдаагүй байна");
listings[tokenId].active = false;
emit Cancelled(tokenId, msg.sender);
}
}
Фронтенд дэх event сонсох (ethers.js)
import { ethers } from "ethers";
const provider = new ethers.BrowserProvider(window.ethereum);
const contract = new ethers.Contract(ADDRESS, ABI, provider);
// Шинэ Transfer бүрийг бодит цагт сонсох
contract.on("Transfer", (from, to, amount) => {
console.log(`${from} → ${to}: ${ethers.formatEther(amount)} ETH`);
});
// Өнгөрсөн event-г хайх
const filter = contract.filters.Transfer(null, myAddress);
const events = await contract.queryFilter(filter, fromBlock, toBlock);
events.forEach((e) => {
console.log("Хүлээн авсан:", e.args.amount.toString());
});
Event vs Storage харьцуулалт
| | Event (log) | Storage | | ------------------ | -------------- | -------------------- | | Gas | ~375+ (хямд) | ~20,000 (шинэ утга) | | Contract-аас унших | ❌ боломжгүй | ✅ болно | | Фронтендээс унших | ✅ болно | ✅ болно | | Байнга хадгалах | ✅ блокчейнд | ✅ блокчейнд | | Хайх, шүүх | indexed-ийг ✅ | mapping-ийн key-г ✅ |
Дүрэм: Contract дотроос уншиж хэрэггүй түүхийн мэдээлэл (үйл явдлын бүртгэл) → event. Contract дотроос уншиж ашиглах мэдээлэл (үлдэгдэл, эзэмшигч) → storage.
Дараагийн хичээлд:
modifier — кодын давталтгүй нөхцөл шалгалтын механизм, onlyOwner загварыг дэлгэрэнгүй судална.