eth-erc20

ERC20 interface and example giftable token contract
Info | Log | Files | Refs | LICENSE

GiftableToken.sol (5211B)


      1 pragma solidity >=0.8.0;
      2 
      3 // SPDX-License-Identifier: AGPL-3.0-or-later
      4 // File-Version: 3
      5 
      6 contract GiftableToken {
      7 
      8 	// Implements EIP173
      9 	address public owner;
     10 
     11 	// Implements Writer
     12 	mapping(address => bool) writer;
     13 
     14 	// Implements ERC20
     15 	string public name;
     16 	// Implements ERC20
     17 	string public symbol;
     18 	// Implements ERC20
     19 	uint8 public decimals;
     20 	// Implements ERC20
     21 	mapping (address => uint256) public balanceOf;
     22 	// Implements ERC20
     23 	mapping (address => mapping (address => uint256)) public allowance;
     24 
     25 	// Implements Burner
     26 	uint256 public totalMinted;
     27 	// Implements Burner
     28 	uint256 public totalBurned;
     29 
     30 	// Implements Expire
     31 	uint256 public expires;
     32 	bool expired;
     33 
     34 	// Implements ERC20
     35 	event Transfer(address indexed _from, address indexed _to, uint256 _value);
     36 	// Implements ERC20
     37 	event TransferFrom(address indexed _from, address indexed _to, address indexed _spender, uint256 _value);
     38 	// Implements ERC20
     39 	event Approval(address indexed _owner, address indexed _spender, uint256 _value);
     40 
     41 	// Implements Minter
     42 	event Mint(address indexed _minter, address indexed _beneficiary, uint256 _value);
     43 
     44 	// Implement Expire
     45 	event Expired(uint256 _timestamp);
     46 
     47 	// Implements Writer
     48 	event WriterAdded(address _writer);
     49 	// Implements Writer
     50 	event WriterRemoved(address _writer);
     51 
     52 	// Implements Burner
     53 	event Burn(uint256 _value);
     54 
     55 	constructor(string memory _name, string memory _symbol, uint8 _decimals, uint256 _expireTimestamp) {
     56 		owner = msg.sender;
     57 		name = _name;
     58 		symbol = _symbol;
     59 		decimals = _decimals;
     60 		expires = _expireTimestamp;
     61 	}
     62 
     63 	// Implements ERC20
     64 	function totalSupply() public view returns (uint256) {
     65 		return totalMinted - totalBurned;
     66 	}
     67 
     68 	mapping(address => bool) writers;
     69 
     70 	// Implements Minter
     71 	function mintTo(address _to, uint256 _value) public returns (bool) {
     72 		require(writers[msg.sender] || msg.sender == owner);
     73 
     74 		balanceOf[_to] += _value;
     75 		totalMinted += _value;
     76 
     77 		emit Mint(msg.sender, _to, _value);
     78 
     79 		return true;
     80 	}
     81 
     82 	// Implements Minter
     83 	// Implements ERC5679Ext20
     84 	function mint(address _to, uint256 _value, bytes calldata _data) public {
     85 		_data;
     86 		mintTo(_to, _value);
     87 	}
     88 
     89 	// Implements Writer
     90 	function addWriter(address _minter) public returns (bool) {
     91 		require(msg.sender == owner);
     92 
     93 		writers[_minter] = true;
     94 
     95 		return true;
     96 	}
     97 
     98 	// Implements Writer
     99 	function deleteWriter(address _minter) public returns (bool) {
    100 		require(msg.sender == owner || msg.sender == _minter);
    101 
    102 		writers[_minter] = false;
    103 
    104 		return true;
    105 	}
    106 
    107 	// Implements Writer
    108 	function isWriter(address _minter) public view returns(bool) {
    109 		return writers[_minter] || _minter == owner;
    110 	}
    111 
    112 	// Implements Expire
    113 	function applyExpiry() public returns(uint8) {
    114 		if (expires == 0) {
    115 			return 0;
    116 		}
    117 		if (expired) {
    118 			return 1;
    119 		}
    120 		if (block.timestamp >= expires) {
    121 			expired = true;
    122 			emit Expired(block.timestamp);
    123 			return 2;
    124 		}
    125 		return 0;
    126 
    127 	}
    128 
    129 	// Implements ERC20
    130 	function transfer(address _to, uint256 _value) public returns (bool) {
    131 		require(applyExpiry() == 0);
    132 		require(balanceOf[msg.sender] >= _value);
    133 		balanceOf[msg.sender] -= _value; 
    134 		balanceOf[_to] += _value;
    135 		emit Transfer(msg.sender, _to, _value);
    136 		return true;
    137 	}
    138 
    139 	// Implements Burner
    140 	function burn(uint256 _value) public returns (bool) {
    141 		require(msg.sender == owner, 'ERR_ACCESS');
    142 		require(balanceOf[msg.sender] >= _value, 'ERR_FUNDS');
    143 
    144 		balanceOf[msg.sender] -= _value;
    145 		totalBurned += _value;
    146 
    147 		emit Burn(_value);
    148 		return true;
    149 	}
    150 
    151 	// Implements Burner
    152 	function burn() public returns(bool) {
    153 		return burn(balanceOf[msg.sender]);
    154 	}
    155 
    156 	// Implements Burner
    157 	// Implements ERC5679Ext20
    158 	function burn(address _from, uint256 _value, bytes calldata _data) public {
    159 		require(msg.sender == _from, 'ERR_NOT_SELF');
    160 		_data;
    161 		burn(_value);
    162 	}
    163 
    164 	// Implements ERC20
    165 	function transferFrom(address _from, address _to, uint256 _value) public returns (bool) {
    166 		require(applyExpiry() == 0);
    167 		require(allowance[_from][msg.sender] >= _value);
    168 		require(balanceOf[_from] >= _value);
    169 		allowance[_from][msg.sender] = allowance[_from][msg.sender] - _value;
    170 		balanceOf[_from] -= _value; 
    171 		balanceOf[_to] += _value;
    172 		emit TransferFrom(_from, _to, msg.sender, _value);
    173 		return true;
    174 	}
    175 
    176 	// Implements ERC20
    177 	function approve(address _spender, uint256 _value) public returns (bool) {
    178 		require(applyExpiry() == 0);
    179 		if (_value > 0) {
    180 			require(allowance[msg.sender][_spender] == 0);
    181 		}
    182 		allowance[msg.sender][_spender] = _value;
    183 		emit Approval(msg.sender, _spender, _value);
    184 		return true;
    185 	}
    186 
    187 	// Implements EIP173
    188 	function transferOwnership(address _newOwner) public returns (bool) {
    189 		require(msg.sender == owner);
    190 		owner = _newOwner;
    191 		return true;
    192 	}
    193 
    194 	// Implements EIP165
    195 	function supportsInterface(bytes4 _sum) public pure returns (bool) {
    196 		if (_sum == 0xb61bc941) { // ERC20
    197 			return true;
    198 		}
    199 		if (_sum == 0x449a52f8) { // Minter
    200 			return true;
    201 		}
    202 		if (_sum == 0x01ffc9a7) { // EIP165
    203 			return true;
    204 		}
    205 		if (_sum == 0x9493f8b2) { // EIP173
    206 			return true;
    207 		}
    208 		if (_sum == 0xabe1f1f5) { // Writer
    209 			return true;
    210 		}
    211 		if (_sum == 0xb1110c1b) { // Burner
    212 			return true;
    213 		}
    214 		if (_sum == 0x841a0e94) { // Expire
    215 			return true;
    216 		}
    217 		return false;
    218 	}
    219 }