ERC20の関数

2022/04/18に公開

Openzeppelin

https://docs.openzeppelin.com/contracts/2.x/api/token/erc20

説明

コントラクト作成時

以下3つの情報が必要

uint256 private _totalSupply; // 総発行数
string private _name; // トークン名
string private _symbol; // トークンのシンボル

constructorでmintしている

constructor(string memory name_, string memory symbol_, uint256 totalSupply_) {
   _mint(_msgSender(), totalSupply_);
   _name = name_;
  _symbol = symbol_;
}

mint時に発行者のアドレスで全数量を送金
※最初の送金先をどこに送るかはコントラクトの書き方次第でいかようにもできる

function _mint(address account, uint256 amount) internal virtual {
   require(account != address(0), "ERC20: mint to the zero address");

   _beforeTokenTransfer(address(0), account, amount);

   _totalSupply += amount;
   _balances[account] += amount;
   emit Transfer(address(0), account, amount);

   _afterTokenTransfer(address(0), account, amount);
}

どんな感じに動くのか

OpenZeppelinのコントラクトとは少しだけ違うがJPYCのERC20のコントラクトで見てみる

https://etherscan.io/token/0x2370f9d504c7a6e775bf6e14b3f12846b594cd53#readContract

EtherescanのContractで実際にコントラクトの処理を実行できる

まずはReadContract(値を取得するだけ、ガスが発生しない)

name()

コントラクト作成時にセットしたnameを取得

function name() public view virtual override returns (string memory) {
   return _name;
}

symbol()

コントラクト作成時に指定したsymbolを取得

function symbol() public view virtual override returns (string memory) {
   return _symbol;
}

desimal()

小数点以下の桁数を取得
※ここは18を指定しているがコントラクト作成時に自由に設定していいよ

function decimals() public view virtual override returns (uint8) {
   return 18;
}

totalSupply()

総発行枚数を取得
コントラクトの作成時に指定したやつ

function totalSupply() public view virtual override returns (uint256) {
   return _totalSupply;
}

balanceOf(address account)

渡したadressの所持枚数を取得する

function balanceOf(address account) public view virtual override returns (uint256) {
   return _balances[account];
}


※decimalが18なので10000 JPYCです。

allowOnce(address owner, address spender)

後に出てくるapproveでowner(token所持者)からspender(token受取者)に対に何枚のtoken送付許可を与えているかを確認する

function allowance(address owner, address spender) public view virtual override returns (uint256) {
   return _allowances[owner][spender];
}


approveしてないから0枚だけどapproveした場合はその枚数が表示される

次にWriteContract(ブロックチェーンへの書き込みを伴う、ガスが発生する)

transfer(address to, uint256 amount)

実行者がtoへ送金するための処理

function transfer(address to, uint256 amount) public virtual override returns (bool) {
   address owner = _msgSender();
   _transfer(owner, to, amount);
   return true;
}

approve(address spender, uint256 amount)

spenderに対しamount(トークンの枚数)分の送金許可を与える。
主にspenderはコントラクトのアドレスになるかなと。

function approve(address spender, uint256 amount) public virtual override returns (bool) {
   address owner = _msgSender();
   _approve(owner, spender, amount);
   return true;
}
mapping(address => mapping(address => uint256)) private _allowances;

のマップへ書き込み

transferFrom(address from, address to, uint256 amount)

fromからtoへamount(枚数)分のtokenを送金する
transferとは違い第3者がfromからtoへ送金する為の処理
approveとセットで使う
https://zenn.dev/mkurita/articles/992478d507e1f2

function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) {
   address spender = _msgSender();
   _spendAllowance(from, spender, amount);
   _transfer(from, to, amount);
   return true;
}

increaseAllowance(address spender, uint256 addedValue)

approveで委任した許容量を増やすだけ

function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
   address owner = _msgSender();
   _approve(owner, spender, allowance(owner, spender) + addedValue);
   return true;
}

decreaseAllowance(address spender, uint256 subtractedValue)

approveで委任した許容量を減らすだけ

function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
   address owner = _msgSender();
   uint256 currentAllowance = allowance(owner, spender);
   require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
   unchecked {
      _approve(owner, spender, currentAllowance - subtractedValue);
   }

   return true;
}

mint(address to, uint256 amount)

追加でTokenを発行する

function mint(address to, uint256 amount) public virtual onlyOwner  {
   _mint(to, amount);
}

Discussion