Solidity / Constructor

Constructor

constructor бол contract deploy хийх үед нэг удаа автоматаар ажилладаг тусгай функц. Дараа нь хэзээ ч дахин дуудаж болохгүй. Contract-ийн анхны тохиргоог — owner тодорхойлох, анхны утга оноох — constructor дотор хийнэ.

Хамгийн энгийн constructor

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

contract MyContract {
    address public owner;

    constructor() {
        owner = msg.sender;   // deploy хийсэн данс → owner болно
    }
}

Deploy дарах мөчид:

  1. constructor() ажиллана
  2. msg.sender — deploy хийсэн таны данс
  3. owner = msg.sender — тэр данс owner болж хадгалагдана
  4. Дараа хэзээ ч constructor дахин ажиллахгүй

Owner загвар

Smart contract-ийн хамгийн түгээмэл загвар бол owner загвар — зөвхөн contract-г deploy хийсэн хүн тодорхой үйлдлийг хийж чаддаг.

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

contract Owned {
    address public owner;

    constructor() {
        owner = msg.sender;
    }

    // modifier — дараагийн хичээлд дэлгэрэнгүй үзнэ
    modifier onlyOwner() {
        require(msg.sender == owner, "Зөвхөн эзэмшигч");
        _;
    }

    // зөвхөн owner дуудаж болно
    function setOwner(address newOwner) public onlyOwner {
        require(newOwner != address(0), "Хүчингүй хаяг");
        owner = newOwner;
    }

    function sensitiveAction() public onlyOwner {
        // зөвхөн owner-д зориулсан логик
    }
}

address(0) нь 0x0000...0000 — хоосон хаяг. Owner-г энэ хаягт шилжүүлбэл contract "эзэнгүй" болно — зарим тохиолдолд зориуд хийдэг (renounce ownership).

Параметртэй constructor

Constructor нь параметр авч болно — deploy хийх үед анхны утгуудыг гаднаас дамжуулах боломж олгодог.

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

contract Token {
    string  public name;
    string  public symbol;
    uint256 public totalSupply;
    address public owner;

    mapping(address => uint256) public balances;

    constructor(string memory _name, string memory _symbol, uint256 _initialSupply) {
        name        = _name;
        symbol      = _symbol;
        totalSupply = _initialSupply;
        owner       = msg.sender;

        // бүх нийлүүлэлтийг deploy хийгчид өгнө
        balances[msg.sender] = _initialSupply;
    }
}

Remix дээр deploy хийхэд "Deploy" товчны хажууд параметрийн талбар гарна:

код
_name:           "Монгол Токен"
_symbol:         "MNT"
_initialSupply:  1000000

Параметрийн нэрэнд _ угтвар ашиглах нь заншил — state variable-тай нэр давхцахаас зайлсхийдэг:

solidity
string public name;

constructor(string memory _name) {
    name = _name;   // _name (параметр) → name (state variable)
}

Constructor байхгүй бол

Constructor тодорхойлоогүй бол Solidity үндсэн (default) constructor автоматаар нэмнэ — параметргүй, хоосон бие бүхий.

solidity
contract NoConstructor {
    uint256 public value;
    // constructor() {} гэж автоматаар нэмэгдсэн гэж үзнэ
}

Удамшлын constructor

Contract өвлөсөн бол эцэг contract-ийн constructor-г дуудах шаардлагатай:

solidity
contract Ownable {
    address public owner;

    constructor(address _owner) {
        owner = _owner;
    }
}

contract MyToken is Ownable {
    string public name;

    // эцэг contract-ийн constructor-г дуудна
    constructor(string memory _name) Ownable(msg.sender) {
        name = _name;
    }
}

Практик жишээ: Crowdfund contract

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

contract Crowdfund {
    address public owner;
    uint256 public goal;
    uint256 public deadline;
    uint256 public raised;
    bool    public goalReached;

    mapping(address => uint256) public contributions;

    constructor(uint256 _goalInEther, uint256 _durationDays) {
        owner    = msg.sender;
        goal     = _goalInEther * 1 ether;                    // wei болгон хөрвүүлнэ
        deadline = block.timestamp + (_durationDays * 1 days); // хугацаа тогтооно
        raised   = 0;
        goalReached = false;
    }

    function contribute() public payable {
        require(block.timestamp < deadline, "Хугацаа дууссан");
        require(msg.value > 0, "ETH илгээх ёстой");

        contributions[msg.sender] += msg.value;
        raised += msg.value;

        if (raised >= goal) {
            goalReached = true;
        }
    }

    function getTimeLeft() public view returns (uint256) {
        if (block.timestamp >= deadline) return 0;
        return deadline - block.timestamp;
    }
}

Remix дээр deploy:

код
_goalInEther:  10       (10 ETH цуглуулах зорилго)
_durationDays: 30       (30 хоногийн хугацаа)

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

solidity
// ❌ constructor-г дахин дуудах гэвэл compile error
contract Bad {
    constructor() { }

    function reinitialize() public {
        constructor();   // ❌ Syntax error
    }
}

// ✅ Шаардлагатай бол initialize загвар ашигла (upgradeable contract-д)
contract Good {
    bool private _initialized;
    address public owner;

    function initialize() public {
        require(!_initialized, "Аль хэдийн тохируулагдсан");
        owner = msg.sender;
        _initialized = true;
    }
}

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

mapping — түлхүүр-утга хосоор өгөгдөл хадгалах Solidity-ийн хамгийн чухал өгөгдлийн бүтцийг судална.