قرارداد هوشمند کیف پول ساده در Solidity

قرارداد هوشمند کیف پول ساده در سالیدیتی (Solidity)، یک نمونه ساده از چگونگی پیاده‌سازی کارکرد ابتدایی کیف پول بر روی بلاکچین اتریوم است.

این قرارداد به کاربران اجازه می‌دهد تا اتری را در کیف پول واریز کنند و تنها مالک کیف پول می‌تواند اتر را برداشت کند.

pragma solidity ^0.8.0;

contract Wallet {
    address public owner;

    event Deposit(address indexed sender, uint256 amount);
    event Withdrawal(address indexed recipient, uint256 amount);

    constructor() {
        owner = msg.sender;
    }

    modifier onlyOwner() {
        require(msg.sender == owner, "Only the owner can call this function");
        _;
    }

    function deposit() payable public {
        emit Deposit(msg.sender, msg.value);
    }

    function withdraw(address payable _recipient, uint256 _amount) public onlyOwner {
        require(address(this).balance >= _amount, "Not enough balance in the wallet");
        _recipient.transfer(_amount);
        emit Withdrawal(_recipient, _amount);
    }

    function getBalance() public view returns (uint256) {
        return address(this).balance;
    }
}

بیایید کد را به قطعات کوچکتر تقسیم کنیم.

pragma solidity ^0.8.0;

این خط نسخه زبان برنامه‌نویسی سالیدیتی استفاده شده در قرارداد را مشخص می‌کند. علامت ^ بدین معناست که قرارداد با هر نسخه از سالیدیتی بزرگتر یا مساوی با 0.8.0 و کمتر از 0.9.0 (در صورت انتشار آن) سازگار است.

contract Wallet {
    address public owner;

    event Deposit(address indexed sender, uint256 amount);
    event Withdrawal(address indexed recipient, uint256 amount);

    constructor() {
        owner = msg.sender;
    }

این بخش، قرارداد کیف پول را تعریف می‌کند.

متغیر owner، که یک متغیر آدرس عمومی است که آدرس مالک قرارداد را ذخیره می‌کند.

ایونت‌های Deposit وWithdrawal، که هرگاه اتری به کیف پول واریز یا از آن برداشت شود، فعال می‌شوند.

تابع کانستراکتر، که هنگام ایجاد قرارداد فراخوانی می‌شود و متغیرowner را به آدرس ایجاد کننده قرارداد (یعنی شخصی که قرارداد را پیاده‌سازی کرده است) می‌دهد.

modifier onlyOwner() {
    require(msg.sender == owner, "Only the owner can call this function");
    _;
}

در این بخش، یک مادیفایر به نام onlyOwner تعریف شده است. مادیفایر یک نوع خاص از تابع است که می‌تواند برای تغییر رفتار توابع دیگر استفاده شود.

در این حالت، مادیفایرonlyOwner برای محدود کردن دسترسی به برخی توابع (در این حالت، تابع برداشت) برای تنها مالک قرارداد استفاده می‌شود.

تغییردهنده از دستورrequire استفاده می‌کند تا بررسی کند که msg.sender (یعنی شخصی که تابع را فراخوانی می‌کند) با متغیر اونر برابر است و در صورت عدم برقراری شرط، یک پیام خطای ارسال می‌کند.

function deposit() payable public {
    emit Deposit(msg.sender, msg.value);
}

این بخش تابع واریز را تعریف می‌کند. این یک تابع عمومی است که هرکسی می‌تواند آن را فراخوانی کند و اجازه می‌دهد تا اتر در کیف پول واریز شود. این تابع به صورت قابل پرداخت (payable) تعریف شده است، به این معنی که می‌تواند اتر دریافت کند. این تابع یک رویداد واریز را با آدرس فرستنده (به عبارتی کسی که اتر را واریز می‌کند) و مقدار اتر واریز شده ارسال می‌کند.

function withdraw(address payable _recipient, uint256 _amount) public onlyOwner {
    require(address(this).balance >= _amount, "Not enough balance in the wallet");
    _recipient.transfer(_amount);
    emit Withdrawal(_recipient, _amount);
}

این بخش تابع برداشت را تعریف می‌کند. این تابع عمومی است که می‌تواند توسط مالک قرارداد (با استفاده از مادیفایر onlyOwner) فراخوانی شود. تابع دو آرگومان را به عنوان ورودی می‌پذیرد: _recipient که آدرس حسابی است که اتر به آن انتقال داده خواهد شد، و _amount که میزان اتری است که باید انتقال داده شود.

تابع ابتدا بررسی می‌کند که موجودی قرارداد بیشتر یا مساوی مقدار اتر درخواستی برای برداشت باشد. اگر موجودی کافی نباشد، یک پیام خطایی نشان داده می‌شود.

در صورتی که موجودی کافی باشد، تابع مقدار درخواستی اتر را با استفاده از تابع transfer به آدرس گیرنده مشخص شده منتقل می‌کند. سپس تابع یک رویداد برداشت با آدرس گیرنده و مقدار اتری که برداشت شده است، ارسال می‌کند.

function getBalance() public view returns (uint256) {
    return address(this).balance;
}

در این قسمت تابع getBalance تعریف شده است. این یک تابع عمومی است که هر کسی می‌تواند آن را صدا بزند و موجودی کنونی قرارداد (یعنی میزان اتری که در کیف پول نگهداری می‌شود) را برگرداند.

به طور کل، این قرارداد به هر کسی اجازه می‌دهد تا اتری را به کیف پول واریز کند، اما تنها مالک قرارداد می‌تواند اتر را از کیف پول برداشت کند. قرارداد همچنین یک تابع برای بررسی موجودی کنونی کیف پول ارائه می‌دهد. این کارکرد ابتدایی می‌تواند در آینده برای موارد استفاده پیچیده‌تر و سفارشی‌شده بیشتر گسترش یابد.