实战案例三:ICO 初始代币销售与空投

最近 APE 空投这么火,是时候说到如何为我们之前做的 UseWeb3NFT 发行代币,在进入编码之前,我们先梳理一下具体的需求:

  • 假设令牌的最大数量为 10000 个

  • 每一个 UseWeb3NFT 持有者可以免费领取 10个

  • ICO 时每一个令牌的初始价格为 0.0001 eth

ERC-20

由于空投部分需要依赖 UseWeb3NFT,所以我们需要写一个接口,使用外部调用的方式获取一些数据

interface IUseWeb3NFT {
  function balanceOf(address owner) external view returns (uint256 balance);
  function ownerOf(uint256 tokenId) external view returns (address ownerAddress);
}

首先,我们需要去定义价格

uint256 public constant tokenPrice = 0.0001 ether;
uint256 public constant tokenMax = 10000 * 10**18;
uint256 public constant nftClaimTokenValue = 10 * 10**18;

初始代币销售的价格为 0.0001 eth,代币总数为 10000 个,一个 NFT 可以获取空投的数量为 10 个

接下来我们需要一个 map 去存储已经 Claim 的 tokenId,你总不希望每一个 tokenId 都能重复获取空投吧?

mapping (uint256 => bool) claimed;

对于销售部分:

function mint(uint256 amount) public payable{
  uint256 requireAmount = tokenPrice * amount;
  require(msg.value >= requireAmount, "sent is incorrect");
  uint256 amountAll = amount * 10**18;
  require((totalSupply() + amountAll) <= tokenMax, "! max");
  _mint(msg.sender, amountAll);
}

对于空投部分:

function claim(uint256[] calldata tokenIds) external{
  require(tokenIds.length > 0, "Shortage TokenId");
  address sender = msg.sender;
  uint256 balance = useweb3NFT.balanceOf(sender);
  require(balance > 0, "Not Balance");
  uint256 amount = 0;
  for (uint i = 0; i < tokenIds.length; i++) {
    address ownerAddress = useweb3NFT.ownerOf(tokenIds[i]);
    if (sender == ownerAddress && !claimed[tokenIds[i]]) {
      amount++;
      claimed[tokenIds[i]] = true;
    }
  }
  require(amount > 0, "claimed all the tokens");
  _mint(sender, amount * nftClaimTokenValue);
}

提款方法:

function withdraw() public onlyOwner {
  address _owner = owner();
  uint256 amount = address(this).balance;
  (bool sendStatus, ) = _owner.call{value: amount}("");
  require(sendStatus, "Failed send");
}