# Solidity极简入门: 32. 代币水龙头

By [0xAA](https://paragraph.com/@wtfacademy) · 2022-06-28

---

我最近在重新学solidity，巩固一下细节，也写一个“Solidity极简入门”，供小白们使用（编程大佬可以另找教程），每周更新1-3讲。

欢迎关注我的推特：[@0xAA\_Science](https://twitter.com/0xAA_Science)

欢迎加入WTF科学家社区，内有加微信群方法：[链接](https://discord.gg/5akcruXrsk)

所有代码和教程开源在github（1024个star发课程认证，2048个star发社群NFT）: [github.com/AmazingAng/WTFSolidity](https://github.com/AmazingAng/WTFSolidity)

* * *

我们在第31讲学习了`ERC20`代币标准。这一讲，我们将学习`ERC20`水龙头的智能合约。在这个合约中，用户可以领到免费的`ERC20`代币。

代币水龙头
-----

当人渴的时候，就要去水龙头接水；当人想要免费代币的时候，就要去代币水龙头领。代币水龙头就是让用户免费领代币的网站/应用。

最早的代币水龙头是比特币（BTC）水龙头：现在BTC一枚要$30,000，但是在2010年，BTC的价格只有不到$0.1，并且持有人很少。为了扩大影响力，比特币社区的Gavin Andresen开发了BTC水龙头，让别人可以免费领BTC。撸羊毛大家都喜欢，当时就有很多人去撸，一部分变为了BTC的信徒。BTC水龙头一共送出了超过19,700枚BTC，现在价值约6亿美元！

ERC20水龙头合约
----------

这里，我们实现一个简版的`ERC20`水龙头，逻辑非常简单：我们将一些`ERC20`代币转到水龙头合约里，用户可以通过合约的`requestToken()`函数来领取`100`单位的代币，每个地址只能领一次。

### 状态变量

我们在水龙头合约中定义3个状态变量

*   `amountAllowed`设定每次能领取代币数量（默认为`100`。不是一百枚，因为代币有小数位数）。
    
*   `tokenContract`记录发放的`ERC20`代币合约地址。
    
*   `requestedAddress`记录领取过代币的地址。
    

        uint256 public amountAllowed = 100; // 每次领 100 单位代币
        address public tokenContract;   // token合约地址
        mapping(address => bool) public requestedAddress;   // 记录领取过代币的地址
    

### 事件

水龙头合约中定义了1个`SendToken`事件，记录了每次领取代币的地址和数量，在`requestTokens()`函数被调用时释放。

        // SendToken事件    
        event SendToken(address indexed Receiver, uint256 indexed Amount); 
    

### 函数

合约中只有两个函数：

*   构造函数：初始化`tokenContract`状态变量，确定发放的`ERC20`代币地址。
    

        // 部署时设定ERC2代币合约
        constructor(address _tokenContract) {
            tokenContract = _tokenContract; // set token contract
        }
    

*   `requestTokens()`函数，用户调用它可以领取`ERC20`代币。
    

Remix演示
-------

1 首先，部署`ERC20`代币合约，并给自己`mint` 10000 单位代币。

![部署\`ERC20\`](https://storage.googleapis.com/papyrus_images/232b583da23c541926da433e8237ac03f4ed12096d3698aad8d4dd772bef0b76.png)

部署\\\`ERC20\\\`

2 部署`Faucet`水龙头合约，初始化的参数填上面`ERC20`代币的合约地址。

![部署水龙头合约](https://storage.googleapis.com/papyrus_images/b4fd63f0d9ef81be1d32d2498b43f400c17bd2251df0bd7eceb1bc9400dc604e.png)

部署水龙头合约

3 利用`ERC20`代币合约的`trasnfer()`函数，将 10000 单位代币转账到`Faucet`合约地址。

![给水龙头转账](https://storage.googleapis.com/papyrus_images/3cb76725868a2475b2a091e19444e752b4b3b88d8215ef4ffa5f4704ff4a2838.png)

给水龙头转账

4 换一个新账户，调用`Faucet`合约`requestTokens()`函数，领取代币。可以在终端看到`SendToken`事件被释放。

![领取代币](https://storage.googleapis.com/papyrus_images/ead32c61eb2fe01d76fa5a8bebccd897843e50ec14ebd7262ffb14c27bd7e6f8.png)

领取代币

5 在`ERC20`代币合约上利用`balanceOf`查询账户余额，可以看到余额变为`100`，领取成功！

![领取成功](https://storage.googleapis.com/papyrus_images/438e37083d4bdccf3d749c6213737f4aa489652cb31609e237046955ad30927f.png)

领取成功

总结
--

这一讲，我们介绍了代币水龙头的历史和`ERC20`水龙头合约。大家觉得下一个`BTC`水龙头会在哪里？

---

*Originally published on [0xAA](https://paragraph.com/@wtfacademy/solidity-32)*
