fangmd/blogsource

web3

Opened this issue · 10 comments

web3

Vue web3

获取账户历史 eth balance

web3js 方案

let blockNum = web3.eth.blockNumber;
const historicTimestamp = new Date(historicDate).getTime();
while(true) {
  const block = web3.eth.getBlock(blockNum);
  if(block.timestamp < historicTimestamp) break;
  --blockNum;
}

//The blockNumber here is your required block number
web3.eth.getBalance(address, blockNumber).then(balance => `Balance at block number is ${balance}`);

ERC20

  • base contract: import '@openzeppelin/contracts/token/ERC20/ERC20.sol';
  • 基础合约数据
    • mapping(address => uint256) private _balances; 余额,记录每个地址有多少 token
    • mapping(address => mapping(address => uint256)) private _allowances 授权委托记录,记录 approve 信息
    • uint256 private _totalSupply 总供应量
    • _name, _symbol 合约名称,合约缩写

固定供应量并全解锁合约

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;

import '@openzeppelin/contracts/token/ERC20/ERC20.sol';

/**
 * 合约创建初始化总供应量并且全部解锁
 */
contract OneToken is ERC20 {
  string constant TOKEN_NAME = 'OneToken';
  string constant TOKEN_SYMBOL = 'OTK';

  constructor(uint256 initialSupply) ERC20(TOKEN_NAME, TOKEN_SYMBOL) {
    _mint(msg.sender, initialSupply);
  }
}

每年增发 20%

参考: ENS

contract OneToken is ERC20, Ownable {
  string constant TOKEN_NAME = 'OneToken';
  string constant TOKEN_SYMBOL = 'OTK';

  uint256 public constant minimumMintInterval = 365 days;
  uint256 public constant mintCap = 200; // 2%

  uint256 public nextMint; // Timestamp

  constructor(uint256 initialSupply) ERC20(TOKEN_NAME, TOKEN_SYMBOL) {
    _mint(msg.sender, initialSupply);

    nextMint = block.timestamp + minimumMintInterval;
  }

  function mint(address dest, uint256 amount) external onlyOwner {
    require(amount < (totalSupply() * mintCap) / 10000, 'OTK: Mint exceeds maximum amount');
    require(block.timestamp >= nextMint, 'OTK: Cannot mint yet');

    nextMint = block.timestamp + minimumMintInterval;
    _mint(dest, amount);
  }
}

Burnable

默认不支持销毁

import '@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol';

solidity tips

  1. address(0): 0 地址,用于销毁 token

mocha, chai

  • 执行某个交易后判断余额
await expect(() => oneToken.transfer(otherAccount, 1)).to.changeTokenBalance(oneToken, owner, '-1')
  • 报错检查
      await expect(oneToken.connect(otherAccount).mint(owner.address, 1000)).to.be.revertedWith(
        'Ownable: caller is not the owner'
      )

await expect(oneToken.mint(owner.address, 1000)).to.be.revertedWith('OTK: Cannot mint yet')
  • 不报错测试
await expect(oneToken.mint(owner.address, 1000)).not.to.be.reverted
  • 时间测试,修改时间
      const unlockTime = (await time.latest()) + ONE_YEAR_IN_SECS
      // We can increase the time in Hardhat Network
      await time.increaseTo(unlockTime)