title | tags | |||||
---|---|---|---|---|---|---|
32. 代币水龙头 |
|
我最近在重新学 Solidity,巩固一下细节,也写一个“WTF Solidity极简入门”,供小白们使用(编程大佬可以另找教程),每周更新 1-3 讲。
所有代码和教程开源在 github: github.com/AmazingAng/WTF-Solidity
我们在第31讲学习了ERC20
代币标准。这一讲,我们将学习ERC20
水龙头的智能合约。在这个合约中,用户可以领到免费的ERC20
代币。
当人渴的时候,就要去水龙头接水;当人想要免费代币的时候,就要去代币水龙头领。代币水龙头就是让用户免费领代币的网站/应用。
最早的代币水龙头是比特币(BTC)水龙头:现在BTC一枚要$30,000,但是在2010年,BTC的价格只有不到$0.1,并且持有人很少。为了扩大影响力,比特币社区的Gavin Andresen开发了BTC水龙头,让别人可以免费领BTC。撸羊毛大家都喜欢,当时就有很多人去撸,一部分变为了BTC的信徒。BTC水龙头一共送出了超过19,700枚BTC,现在价值约6亿美元!
这里,我们实现一个简版的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
代币地址。// 部署时设定ERC20代币合约 constructor(address _tokenContract) { tokenContract = _tokenContract; // set token contract }
-
requestTokens()
函数,用户调用它可以领取ERC20
代币。// 用户领取代币函数 function requestTokens() external { require(!requestedAddress[msg.sender], "Can't Request Multiple Times!"); // 每个地址只能领一次 IERC20 token = IERC20(tokenContract); // 创建IERC20合约对象 require(token.balanceOf(address(this)) >= amountAllowed, "Faucet Empty!"); // 水龙头空了 token.transfer(msg.sender, amountAllowed); // 发送token requestedAddress[msg.sender] = true; // 记录领取地址 emit SendToken(msg.sender, amountAllowed); // 释放SendToken事件 }
这一讲,我们介绍了代币水龙头的历史和ERC20
水龙头合约。大家觉得下一个BTC
水龙头会在哪里?