跳转到主要内容

从 Solidity 智能合约转账和授权 ERC-20 代币

智能合约
代币
Solidity
erc-20
中级
jdourlens
2020年4月7日
9 分钟阅读

在上一篇教程中,我们学习了以太坊区块链上 Solidity 中 ERC-20 代币的剖析。在本文中,我们将了解如何使用 Solidity 语言通过智能合约与代币进行交互。

对于这个智能合约,我们将创建一个真正的虚拟去中心化交易所 (DEX),用户可以在其中用以太币兑换我们新部署的 ERC-20 代币

在本教程中,我们将使用在上一篇教程中编写的代码作为基础。我们的 DEX 将在其构造函数中实例化该合约的一个实例,并执行以下操作:

  • 将代币兑换为以太币
  • 将以太币兑换为代币

我们将通过添加简单的 ERC-20 代码库来开始编写去中心化交易所代码:

我们新的 DEX 智能合约将部署 ERC-20 并获取所有供应量:

现在我们有了 DEX,并且它拥有所有可用的代币储备。该合约有两个函数:

  • buy:用户可以发送以太币并兑换获得代币
  • sell:用户可以决定发送代币以换回以太币

buy(购买)函数

让我们编写 buy 函数。我们首先需要检查消息中包含的以太币数量,并验证合约是否拥有足够的代币,以及消息中是否包含一些以太币。如果合约拥有足够的代币,它将向用户发送相应数量的代币并触发 Bought 事件。

请注意,如果在发生错误时调用 require 函数,发送的以太币将被直接回滚并退还给用户。

为了保持简单,我们只按 1 个代币兑换 1 Wei 的比例进行兑换。

function buy() payable public {
    uint256 amountTobuy = msg.value;
    uint256 dexBalance = token.balanceOf(address(this));
    require(amountTobuy > 0, "You need to send some ether");
    require(amountTobuy <= dexBalance, "Not enough tokens in the reserve");
    token.transfer(msg.sender, amountTobuy);
    emit Bought(amountTobuy);
}

在购买成功的情况下,我们应该在交易中看到两个事件:代币的 Transfer 事件和 Bought 事件。

Two events in the transaction: Transfer and Bought

sell(出售)函数

负责出售的函数首先会要求用户事先调用 approve 函数来授权该金额。授权转账需要用户调用由 DEX 实例化的 ERC20Basic 代币。这可以通过首先调用 DEX 合约的 token() 函数来检索 DEX 部署名为 token 的 ERC20Basic 合约的地址来实现。然后,我们在会话中创建该合约的实例并调用其 approve 函数。接着,我们就可以调用 DEX 的 sell 函数并将我们的代币兑换回以太币。例如,在交互式 Brownie 会话中,它的过程如下所示:

然后,当调用 sell 函数时,我们将检查从调用者地址到合约地址的转账是否成功,然后将以太币发送回调用者地址。

function sell(uint256 amount) public {
    require(amount > 0, "You need to sell at least some tokens");
    uint256 allowance = token.allowance(msg.sender, address(this));
    require(allowance >= amount, "Check the token allowance");
    token.transferFrom(msg.sender, address(this), amount);
    payable(msg.sender).transfer(amount);
    emit Sold(amount);
}

如果一切正常,你应该会在交易中看到 2 个事件(一个 Transfer 和一个 Sold),并且你的代币余额和以太币余额也会更新。

Two events in the transaction: Transfer and Sold


通过本教程,我们了解了如何检查 ERC-20 代币的余额和授权额度,以及如何使用接口调用 ERC-20 智能合约的 TransferTransferFrom

一旦你进行了一笔交易,我们有一个 JavaScript 教程来教你如何等待并获取有关向你的合约发起的交易的详细信息 (opens in a new tab),以及一个教程来解码由代币转账或任何其他事件生成的事件 (opens in a new tab)(只要你有 ABI)。

以下是本教程的完整代码: