文章介绍了如何在Solidity中与以太坊互动,特别是如何通过payable
函数接收和发送以太币,并解释了以太币的单位及在区块链中的处理方式。
到目前为止,我们一直在使用代币来表示价值,但以太坊(Ether)呢?让我们介绍一下智能合约如何与以太坊进行交互。
contract ExampleContract {
function payMe()
public
payable {
}
function howMuchEtherIHave()
public
view
returns (uint256) {
return address(this).balance;
}
}
在你在 Remix 上部署此合约后,你会注意到与 payMe 交互的按钮变为红色。这意味着你可以在上面的字段中指定在调用此函数时要发送多少价值(以太坊)。
你可以以 Wei、Gwei、Finney 或以太坊为单位发送以太坊。
1 Wei 是 1/10^18 以太坊,1 gwei 是以太坊的十亿分之一,而 1 Finney 是十分之一。
让我们简单一点,直接发送一个以太坊。
当我们点击 “howMuchEtherIHave” 时,实际上我们会得到
1000000000000000000
这并不意味着我们凭空创造了大量以太坊。记住,浮点数在区块链上并不存在,因此以太坊使用与 ERC20 代币相同的小数策略。以太坊的一个单位实际上是一 Wei,而我们传统上认为的一个以太坊是 10^18 Wei。
顺便说一下,.balance
结构可以用于任意地址。智能合约可以通过以下函数确定你有多富有(或多贫穷)
function howMuchEtherYouHave()
public
view
returns (uint256) {
return msg.sender.balance;
}
function howMuchEtherTheyHave(address them)
public
view
returns (uint256) {
return them.balance;
}
10000000000000000000
除非函数具有 payable 修饰符,否则如果它们接收以太坊,则会 revert。
为什么要有这样的结构?如果有人想要给我们发送以太坊,为什么不接受呢?
这一直是一个争论的话题,但一般的想法是,一个函数应该被限制成具有极其明确定义的行为。任何超出这一范围的内容都应该受到限制。行为越受限,越容易理清智能合约的功能。
顺便说一下,solidity 提供了一个非常方便的关键字来处理与以太坊有关的所有零。这两个函数做的是同一件事,但一个更具可读性。
function moreThanOneEtherV1()
public
view
returns (bool) {
if (msg.sender.balance > 1 ether) {
return true;
}
return false;
}
function moreThanOneEtherV2()
public
view
returns (bool) {
if (msg.sender.balance > 10**18) {
return true;
}
return false;
}
如果你希望你的智能合约一开始就有特权和优势,可以将构造函数设为 payable。但你仍需在构造时显式发送以太坊。
仅仅因为一个函数是 payable,并不意味着调用该函数的人必须发送以太坊。
contract ExampleContract {
constructor() payable {
// 以资金开始生活
}
}
发送以太坊
如果你从 Remix 发起交易,很清楚如何发送以太坊,但是如果另一个智能合约想要发送以太坊呢?
你将使用我们之前描述的 call 函数,但增加一个“元参数”。一开始可能看起来很奇怪,但你会习惯的。
contract ReceiveEther {
function takeMoney()
public
payable {
}
function myBalance()
public
view
returns (uint256) {
return address(this).balance;
}
}
contract SendMoney {
constructor()
payable {
}
function sendMoney(address receiveEtherContract)
public
payable {
uint256 amount = myBalance();
(bool ok, ) = receiveEtherContract.call{value: amount}(
abi.encodeWithSignature("takeMoney()")
);
require(ok, "转账失败");
}
function myBalance()
public
view
returns (uint256) {
return address(this).balance;
}
}
让我们拆解一下我们所看到的内容。
一些实验
Payable 函数不能是 view 或 pure
改变智能合约的以太坊余额是区块链上的“状态变化”。这是一个永久性改变,甚至在交易结束后仍会保留,类似于更新一个存储变量。因此,payable 函数不能是 view 或 pure。编译器不接受这一点。
练习问题
请查看 区块链培训营, 以了解更多有关智能合约开发和代币标准的信息。
- 原文链接: rareskills.io/learn-soli...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!