学习Solidity中可支付函数的相关知识,了解它们在处理以太币存款方面的重要性,以及如何在智能合约中创建和使用它们。
目标
通过本指南,您应该能够:
- 理解Solidity中可支付函数的目的和用法
- 学习如何向智能合约发送Ether
- 编写Solidity中的可支付函数
- 创建带有条件的可撤销可支付函数
- 在可支付函数中实现自定义逻辑
- 了解消息调用及其在以太坊虚拟机(EVM)中的相关性
Payable 函数
在Solidity中,可支付函数是一种能让智能合约接受以太币的函数。它们帮助开发人员管理接收到的以太币并在接收到时采取行动。例如,一个简单的可支付函数可以为筹款活动收集以太币捐款。以下是一个基本的代码示例:
pragma solidity ^0.8.0;
contract Fundraiser {
function donate() external payable {
// Ether is received and stored in the contract's balance
// You can perform any other actions with the Ether received here - for example, sending it to some other address etc.
}
}
在这个例子中,当调用donate
函数时,它会接受捐赠者发送的Ether并将其添加到合约的余额中。
关键字payable
允许某个人向合约发送ether并运行代码来处理此存款。
这段代码可能会记录事件,修改存储以记录存款,或者如果选择这样做,甚至可能撤销交易。
当开发人员显式标记一个带有可支付类型的智能合约时,他们表示“我希望将ether发送到这个函数”。要理解这为什么很重要,想象一下如果有人将ether发送到一个合约中,但开发人员没有编写代码处理该事件,那将会有多糟糕。在那种情况下,ether可能会永久锁定,或者无法被其预期的接收方提取。
如何向智能合约发送以太币
发送以太币是以太坊虚拟机(EVM)的本地功能。这与在EVM中进行任何其他转账不同,该转账需要开发人员编写自定义逻辑来处理转账(例如NFT或ERC20)。
当有人向智能合约发送以太币时,他们通过交易本身的“value”字段进行操作。让我们看看JSON格式的交易内容:
{
"to": "0x5baf84167cad405ce7b2e8458af73975f9489291",
"value": "0xb1a2bc2ec50000", // 1 ether
"data": "0xd0e30db0" // deposit()
// ... other properties
}
此交易将1个以太币发送到地址0x5baf84167cad405ce7b2e8458af73975f9489291
。如果此地址是一个智能合约,它将尝试解析calldata(data)以确定此用户试图调用哪个智能合约函数(在这种情况下是deposit())。
根据函数支付或非支付的情况,将发生以下两种情况之一:
- 如果函数是一个可支付函数,那么它将运行逻辑。
- 如果函数不可支付,则交易将恢复并返回资金,减去交易的燃气成本。
什么是 Solidity 可支付函数的示例?
这是一个使用Solidity的基本可支付函数示例,其中包括“deposit”函数:
function deposit() payable external {
// no need to write anything here!
}
注意,在这种情况下,我们没有在 deposit
函数主体中编写任何代码。编写一个可支付的函数就足以接收以太币,您可能不需要编写任何逻辑。
例如,如果这是一个可支付的智能合约,由慈善机构控制,接受加密货币捐款,也许用户只需调用 deposit
,慈善机构最终就能够将这些捐款提取到他们选择的地址。在这种情况下,编写一个 receive
函数可能更好:
receive() external payable {
// this built-in function doesn't require any calldata,
// it will get called if the data field is empty and
// the value field is not empty.
// this allows the smart contract to receive ether just like a
// regular user account controlled by a private key would.
}
什么是一个Solidity可支付函数的反转示例?
一个可付款的智能合约函数可以回滚。这是一个可回滚的可付款函数示例,它使用两个require语句来验证msg.value
和balances[msg.sender]
。
mapping(address => uint) balances;
function deposit() payable external {
// deposit sizes are restricted to 1 ether
require(msg.value == 1 ether);
// an address cannot deposit twice
require(balances[msg.sender] == 0);
balances[msg.sender] += msg.value;
}
如果任何一个require
语句不为真,则交易将回滚并发送者将收回他们的资金。
为什么我们要在可支付函数中编写逻辑?
如果我们有一个智能合约,需要跟踪谁存入了哪些以太币,我们可以在存储中跟踪它:
mapping(address => uint) balances;
function deposit() payable external {
// record the value sent
// to the address that sent it
balances[msg.sender] += msg.value;
}
这里的msg.value
对应着我们在“如何发送以太币”部分看到的交易中编码的value
字段。作为Solidity开发人员,我们可以利用消息值来记录存款并将其映射到该交易地址的某些内部余额。
为什么叫做msg.value?
在以太坊虚拟机(EVM)中,与智能合约的交互被称为“消息调用”。这适用于用户直接调用智能合约的情况,也适用于智能合约调用另一个智能合约的情况(内部交易)。
可支付的Solidity函数
简而言之,一个可支付的函数是一个可以接收以太币的函数。它为开发者提供了回应以太币存款进行记录或任何其他必要逻辑的机会。
本文由mdnice多平台发布
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net
Maven 本地仓库,中央仓库,远程仓库 配置 下载地址:https://maven.apache.org/download.cgi apache-maven-3.9.2-bin.zip 解压安装 配置仓库 配置Maven环境变量 2.Maven私服搭建: 本…