D20Token
code:D20Token.sol
pragma solidity ^0.4.24;
contract D20Token {
/***************************************************************************
* Public Variables
***************************************************************************/
// Ether と トークンの交換レート
uint public constant rate = 1000000; // 1 Ether = 1000000 D20
// このコントラクトから Ether を引き出すことのできるアドレス
address public constant contractOwner = 0xee8779531B0693d518D707dfB41675c056fE8c70;
/***************************************************************************
* Private Variables
***************************************************************************/
// トークン名を保持
string private _name;
// トークンシンボルを保持
string private _symbol;
// トークンの小数点以下桁数を保持
uint8 private _decimals;
// トークンの供給量を保持
uint256 private _totalSupply;
// アドレス毎のトークン残高を保持
mapping (address => uint256) private _balances;
// アドレス毎の nonce を保持
mapping(address => uint256) private _nonces;
// トークン所有者 owner が別アドレス spender に移動を許可したトークン残高を保持
mapping (address => mapping (address => uint256)) private _allowed;
/***************************************************************************
* Event
***************************************************************************/
// トークン送金時に実行されるイベント
event Transfer(
address indexed from,
address indexed to,
uint256 value
);
// トークンの送金許可承認時に実行されるイベント
event Approval(
address indexed owner,
address indexed spender,
uint256 value
);
/***************************************************************************
* Constructor
***************************************************************************/
// コントラクトのデプロイ時に1度のみ実行されるメソッドです。
constructor ()
public
{
_name = "D20Token";
_symbol = "D20";
_decimals = 18;
_totalSupply = 1000000000000000000000000000; // 1000000000 D20
emit Transfer(0x0, msg.sender, _totalSupply);
}
/***************************************************************************
* Internal Methods
***************************************************************************/
// トークンを追加発行します。
function _mint(address account, uint256 amount)
internal
{
// 追加発行したトークンを転送するアカウントが 0x0 でないことをチェック
require(account != 0);
// トークン供給量と追加発行トークン数の合計値が、現在のトークン供給量以上であることをチェック
// オーバーフロー対策
require(_totalSupply + amount >= _totalSupply);
// トークン供給量に追加発行トークン数を加える
_totalSupply = _totalSupply + amount;
// 送金先の残高と送金トークン数の合計値が、現在の残高以上であることをチェック
// オーバーフロー対策
// 送金先の残高に追加発行トークン数を加える
// イベントを発火
emit Transfer(address(0), account, amount);
}
/***************************************************************************
* Public Methods
***************************************************************************/
// トークン名を返します。
function name()
public
view
returns(string)
{
return _name;
}
// トークンシンボルを返します。
function symbol()
public
view
returns(string)
{
return _symbol;
}
// トークンの小数点以下桁数を返します。
function decimals()
public
view
returns(uint8)
{
return _decimals;
}
// 現在のトークン供給量を返します。
function totalSupply()
public
view
returns (uint256)
{
return _totalSupply;
}
// アドレスのトークン残高を返します。
function balanceOf(address owner)
public
view
returns (uint256)
{
}
// アドレスの nonce を返します。
function nonceOf(address owner)
public
view
returns (uint256)
{
}
// トークン所有者 owner が別アドレス spender に送金を許可したトークン残高を返します。
function allowance(address owner, address spender)
public
view
returns (uint256)
{
}
// トークンを別のアドレスに送金します。
function transfer(address to, uint256 value)
public
returns (bool)
{
// 送金トークン数が残高以下であることをチェック
// 送金先が 0x0 でないことチェック
require(to != address(0));
// メソッド実行者(送金元)の残高から送金トークン数を差し引く
// 送金先の残高と送金トークン数の合計値が、現在の残高以上であることをチェック
// オーバーフロー対策
require(_balancesto + value >= _balancesto); // 送金先の残高に送金トークン数を加える
_balancesto = _balancesto + value; // イベントを発火
emit Transfer(msg.sender, to, value);
return true;
}
// トークン所有者 owner が別アドレス spender に、指定した数のトークン送金を許可します。
function approve(address spender, uint256 value)
public
returns (bool)
{
// spender のアドレスが 0x0 でないことをチェック
require(spender != address(0));
// spender に送金を許可するトークン数をセット
// イベントを発火
emit Approval(msg.sender, spender, value);
return true;
}
// 任意のアドレスから任意のアドレスにトークンを送金します。
// 送金できるトークン数は、メソッドの実行者がトークンの所有者に送金を許可されている
// トークン数の範囲内です。
function transferFrom(address from, address to, uint256 value)
public
returns (bool)
{
// 送金トークン数が残高以下であることをチェック
require(value <= _balancesfrom); // 送金トークン数が、トークン所有者がこのメソッドの実行者に許可した送金トークン数以下であることをチェック
// 送金先が 0x0 でないことチェック
require(to != address(0));
// 送金元の残高から送金トークン数を差し引く
// require(value <= _balancesfrom); により、 // value が _balancesfrom 以下であることが保証済 // 送金先の残高と送金トークン数の合計値が、現在の残高以上であることをチェック
// オーバーフロー対策
require(_balancesto + value >= _balancesto); // 送金先の残高に送金トークン数を加える
_balancesto = _balancesto + value; // トークン所有者がこのメソッドの実行者に許可した送金トークン数から送金トークン数を差し引く
// イベントを発火
emit Transfer(from, to, value);
return true;
}
function delegatedTransfer(bytes delegatedTx, bytes sig)
public
returns (bool)
{
// 署名 sig を分割して、r,s,v を取り出す
bytes32 r;
bytes32 s;
uint8 v;
assembly {
r := mload(add(sig, 32))
s := mload(add(sig, 64))
v := byte(0, mload(add(sig, 96)))
}
// ecrecover を使用して、署名者のアドレスを得る
bytes32 txHash = keccak256(bytes(delegatedTx));
address signer = ecrecover(txHash, v, r, s);
require(signer != address(0));
// 独自フォーマットのトークントランザクションをデコード
uint256 nonce;
uint256 value;
address to;
address tokenAddress;
assembly {
nonce := mload(add(delegatedTx, 32))
value := mload(add(delegatedTx, 64))
to := mload(add(delegatedTx, 84))
tokenAddress := mload(add(delegatedTx, 116))
}
// トークンのアドレスとコントラクトのアドレスが一致しているかどうかをチェック
require(tokenAddress == address(this));
// トークン送金先が 0x0 でないことをチェック
require(to != address(0));
// nonce をチェック
require(nonce == _noncessigner); // 送金トークン数が残高以下であることをチェック
require(value <= _balancessigner); // nonce インクリメントのオーバーフロー対策
// nonce をインクリメント
// 送金元の残高から送金トークン数を差し引く
// require(value <= _balancessigner); により、 // value が _balancessigner 以下であることが保証済 // 送金先の残高と送金トークン数の合計値が、現在の残高以上であることをチェック
// オーバーフロー対策
require(_balancesto + value >= _balancesto); // 送金先の残高に送金トークン数を加える
_balancesto = _balancesto + value; // イベントを発火
emit Transfer(signer, to, value);
return true;
}
function mint(address to)
public
payable
returns (bool)
{
require(msg.value > 0);
require (to != address(0));
uint256 amount = msg.value * rate;
// オーバーフロー対策
require(amount / msg.value == rate);
_mint(to, amount);
}
function withdraw(uint256 amount)
public
{
require (msg.sender == contractOwner);
msg.sender.transfer(amount);
}
}
Ropsten