ERC20のメモ
まとめ
誰から誰に、どれくらい送ることができるか、を定めたインターフェース
可能or不可能を判別することが可能
どうやってOwnerがspenderに許可を与えることができるのか、という点は拡張性があるような気もする
関数
任意関数
name()関数:
Input:無し
Return:String
名前データを返答
symbol()関数:
Input 無し
Return:string
トークンシンボルを返答
decimals()関数:
Input 無し
Return:uint8
分割トークンの単位数を規定
必須関数
totalSupply()関数:供給数規定
Input:無し
Return:uint256
発行合計トークン数を返答
balanceOf()関数:送信者が持つトークン数を規定
Input: address _owner
トークン所有者のアドレスを表示
REturn: uint256 balance
所有トークン数を返答
transfer()関数:相手方にトークンを送れるか判断
Input:
address _to: 送付先アドレス
uint256 _value:送付量
Return: bool success
送付が正常に行われたかを判断
もし_valueがOwnerのValueより多かった場合、falseを返答
Transferイベントを稼働させる必要有
transferFrom()関数:第三者が送付を行う場合に、トークン送付ができるかを判断
Input:
address _from: 送信者アドレス
address _to: 送付先アドレス
uint256 _value: 送付量
Return: bool success
_fromアドレスが、送付者を認証しない限り、falseを返答
approve()関数:第三者がtransferFrom()関数を一定数まで実行してよいかどうかを判別
Input:
address _spender: 送付を承認するアドレス
uint256 _value: 送付可能な限界量を表示
どういう場合にfalseを返答するのか???
allowance()関数:あとどれくらいの量spenderが送付できるのかを返答
Input:
address _owner: 保持者
address _spender:実際に送付する人
return:
uint256 remaining: 残高
イベント
Transfer()イベント:トークン移転が起こった時に通知
Input:
address indexed _from:誰から送られたかを整理
address indexed _to:誰へ送られたかを整理
uint256 _value: 送られた量を定義
Approval()イベント:approveが実施されたときに通知
Input:
address indexed _owner: 所有者
address indexed _ spender: 送信者
uin256 _value:認定量
OpenZepplinによる実装例
code:openzepplin-solidity(javascript)
pragma solidity ^0.4.24;
import "./IERC20.sol";
import "../../math/SafeMath.sol";
/**
* @title Standard ERC20 token
*
* @dev Implementation of the basic standard token.
* https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md
* Originally based on code by FirstBlood: https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol
*/
contract ERC20 is IERC20 {
using SafeMath for uint256;
mapping (address => uint256) private _balances;
mapping (address => mapping (address => uint256)) private _allowed;
uint256 private _totalSupply;
/**
* @dev Total number of tokens in existence
*/
function totalSupply() public view returns (uint256) {
return _totalSupply;
}
/**
* @dev Gets the balance of the specified address.
* @param owner The address to query the balance of.
* @return An uint256 representing the amount owned by the passed address.
*/
function balanceOf(address owner) public view returns (uint256) {
return _balancesowner;
}
/**
* @dev Function to check the amount of tokens that an owner allowed to a spender.
* @param owner address The address which owns the funds.
* @param spender address The address which will spend the funds.
* @return A uint256 specifying the amount of tokens still available for the spender.
*/
function allowance(
address owner,
address spender
)
public
view
returns (uint256)
{
return _allowedownerspender;
}
/**
* @dev Transfer token for a specified address
* @param to The address to transfer to.
* @param value The amount to be transferred.
*/
function transfer(address to, uint256 value) public returns (bool) {
require(value <= _balancesmsg.sender);
require(to != address(0));
_balancesmsg.sender = _balancesmsg.sender.sub(value);
_balancesto = _balancesto.add(value);
emit Transfer(msg.sender, to, value);
return true;
}
/**
* @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender.
* Beware that changing an allowance with this method brings the risk that someone may use both the old
* and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this
* race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
* @param spender The address which will spend the funds.
* @param value The amount of tokens to be spent.
*/
function approve(address spender, uint256 value) public returns (bool) {
require(spender != address(0));
_allowedmsg.senderspender = value;
emit Approval(msg.sender, spender, value);
return true;
}
/**
* @dev Transfer tokens from one address to another
* @param from address The address which you want to send tokens from
* @param to address The address which you want to transfer to
* @param value uint256 the amount of tokens to be transferred
*/
function transferFrom(
address from,
address to,
uint256 value
)
public
returns (bool)
{
require(value <= _balancesfrom);
require(value <= _allowedfrommsg.sender);
require(to != address(0));
_balancesfrom = _balancesfrom.sub(value);
_balancesto = _balancesto.add(value);
_allowedfrommsg.sender = _allowedfrommsg.sender.sub(value);
emit Transfer(from, to, value);
return true;
}
/**
* @dev Increase the amount of tokens that an owner allowed to a spender.
* approve should be called when allowed__spender == 0. To increment
* allowed value is better to use this function to avoid 2 calls (and wait until
* the first transaction is mined)
* From MonolithDAO Token.sol
* @param spender The address which will spend the funds.
* @param addedValue The amount of tokens to increase the allowance by.
*/
function increaseAllowance(
address spender,
uint256 addedValue
)
public
returns (bool)
{
require(spender != address(0));
_allowedmsg.senderspender = (
_allowedmsg.senderspender.add(addedValue));
emit Approval(msg.sender, spender, _allowedmsg.senderspender);
return true;
}
/**
* @dev Decrease the amount of tokens that an owner allowed to a spender.
* approve should be called when allowed__spender == 0. To decrement
* allowed value is better to use this function to avoid 2 calls (and wait until
* the first transaction is mined)
* From MonolithDAO Token.sol
* @param spender The address which will spend the funds.
* @param subtractedValue The amount of tokens to decrease the allowance by.
*/
function decreaseAllowance(
address spender,
uint256 subtractedValue
)
public
returns (bool)
{
require(spender != address(0));
_allowedmsg.senderspender = (
_allowedmsg.senderspender.sub(subtractedValue));
emit Approval(msg.sender, spender, _allowedmsg.senderspender);
return true;
}
/**
* @dev Internal function that mints an amount of the token and assigns it to
* an account. This encapsulates the modification of balances such that the
* proper events are emitted.
* @param account The account that will receive the created tokens.
* @param amount The amount that will be created.
*/
function _mint(address account, uint256 amount) internal {
require(account != 0);
_totalSupply = _totalSupply.add(amount);
_balancesaccount = _balancesaccount.add(amount);
emit Transfer(address(0), account, amount);
}
/**
* @dev Internal function that burns an amount of the token of a given
* account.
* @param account The account whose tokens will be burnt.
* @param amount The amount that will be burnt.
*/
function _burn(address account, uint256 amount) internal {
require(account != 0);
require(amount <= _balancesaccount);
_totalSupply = _totalSupply.sub(amount);
_balancesaccount = _balancesaccount.sub(amount);
emit Transfer(account, address(0), amount);
}
/**
* @dev Internal function that burns an amount of the token of a given
* account, deducting from the sender's allowance for said account. Uses the
* internal burn function.
* @param account The account whose tokens will be burnt.
* @param amount The amount that will be burnt.
*/
function _burnFrom(address account, uint256 amount) internal {
require(amount <= _allowedaccountmsg.sender);
// Should https://github.com/OpenZeppelin/zeppelin-solidity/issues/707 be accepted,
// this function needs to emit an event with the updated approval.
_allowedaccountmsg.sender = _allowedaccountmsg.sender.sub(
amount);
_burn(account, amount);
}
}
Source
https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md
[]
#トークン規格&IssuingPlatform