Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Solidity中的payable关键字 #57

Open
MagicalBridge opened this issue Jun 19, 2024 · 0 comments
Open

Solidity中的payable关键字 #57

MagicalBridge opened this issue Jun 19, 2024 · 0 comments
Labels
documentation Improvements or additions to documentation

Comments

@MagicalBridge
Copy link
Owner

基本概念

在Solidity中,payable关键字用于标识可以接收以太币的函数地址。只有带有payable关键字的函数才能接收以太币转账。默认情况下,地址类型是不可支付的,也就是说,你不能直接向一个普通的地址类型发送以太币。为了发送以太币,我们需要将地址转换为payable地址。这样可以防止意外转账到不支持接收以太币的函数,从而提高安全性。

代码示例

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

contract Crowdfunding {
    // 合约所有者
    address public owner;

    // 捐款记录
    mapping(address => uint256) public contributions;

    // 事件:当有人捐款时触发
    event DonationReceived(address indexed donor, uint256 amount);

    // 事件:当资金被提取时触发
    event FundsWithdrawn(address indexed owner, uint256 amount);

    // 构造函数:设置合约所有者
    constructor() {
        owner = msg.sender;
    }

    // 捐款函数:带有payable关键字,允许接收以太币
    function donate() external payable {
        // 捐款的金额必须大于0,否则会抛出异常
        require(msg.value > 0, "Donation amount must be greater than zero");
        contributions[msg.sender] += msg.value;
        emit DonationReceived(msg.sender, msg.value);
    }

    // 提取资金函数:仅合约所有者可以调用
    function withdraw(uint256 _amount) external onlyOwner {
        require(address(this).balance >= _amount, "Insufficient contract balance");
        payable(owner).transfer(_amount);
        emit FundsWithdrawn(owner, _amount);
    }

    // 获取合约当前余额
    function getContractBalance() external view returns (uint256) {
        return address(this).balance;
    }

    // 修饰符:限制只有合约所有者可以调用
    modifier onlyOwner() {
        require(msg.sender == owner, "Only the contract owner can call this function");
        _;
    }
}

合约整体的解释

  1. 合约所有者: 在合约部署时,部署者的地址被设置为合约的所有者。
  2. 捐款记录: 使用mapping记录每个地址的捐款金额。
  3. 事件: 定义两个事件,分别在捐款和提取资金时触发,以便前端应用程序监听并做出响应。
  4. 构造函数: 构造函数在合约部署时执行,将部署者地址设置为合约所有者。
  5. 捐款函数 (donate) : 该函数带有payable关键字,允许接收以太币。函数检查捐款金额是否大于零,并更新捐款记录。
  6. 提取资金函数 (withdraw) : 只有合约所有者可以调用此函数来提取指定金额的资金。函数检查合约余额是否足够,并使用payable(owner).transfer(_amount)将资金转账给合约所有者。
  7. 获取合约余额 (getContractBalance) : 提供一个只读函数来获取合约的当前余额。
  8. 修饰符 (onlyOwner) : 限制只有合约所有者可以调用某些函数。

提现函数withdraw的详细分析

在Solidity中,this关键字用于引用当前合约的实例address(this)表示当前合约的地址。通过使用address(this).balance,可以获取当前合约的余额,即合约持有的以太币数量。

当我们写address(this)时,实际上是将当前合约实例转换为一个地址类型,然后通过.balance属性获取该地址的余额。这个地址是合约在以太坊网络上的唯一标识。

例如,如果合约地址是0x1234567890abcdef1234567890abcdef12345678,那么address(this)将返回这个地址

require(address(this).balance >= _amount, "Insufficient contract balance");

这种用法在需要检查合约自身的状态或余额时非常常见,确保合约执行操作前有足够的资源(如以太币)来完成该操作。

解释

address(this).balance >= _amount:

  • address(this)获取当前合约的地址。
  • .balance获取该地址上的以太币余额。
  • require(address(this).balance >= _amount, "Insufficient contract balance")检查当前合约的余额是否大于或等于要提取的金额。如果不是,则会抛出一个错误,并显示错误消息"Insufficient contract balance"。

payable(owner).transfer(_amount) :

  • payable(owner)将合约所有者的地址转换为一个可支付地址(即允许发送以太币的地址)。
  • .transfer(_amount)从合约中提取指定数量的以太币,并发送到合约所有者的地址。

emit FundsWithdrawn(owner, _amount) :

  • 触发一个事件,记录提取的资金金额和提取资金的所有者。这对于日志记录和前端应用程序监听事件很有用。

总结

  • payable变量:用于将一个地址转换为可接收以太币的地址,以便能够安全地进行以太币转账。

  • payable函数:用于定义能够接收以太币的函数,确保函数能够处理以太币的接收和逻辑处理。

通过合理使用payable关键字,可以确保合约的安全性和功能性,避免意外转账和潜在的安全漏洞。

@MagicalBridge MagicalBridge added the documentation Improvements or additions to documentation label Jun 19, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation
Projects
None yet
Development

No branches or pull requests

1 participant