GiftableToken.sol (5210B)
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 // Implements Minter 69 mapping(address => bool) writers; 70 function mintTo(address _to, uint256 _value) public returns (bool) { 71 require(writers[msg.sender] || msg.sender == owner); 72 73 balanceOf[_to] += _value; 74 totalMinted += _value; 75 76 emit Mint(msg.sender, _to, _value); 77 78 return true; 79 } 80 81 // Implements Minter 82 // Implements ERC5679Ext20 83 function mint(address _to, uint256 _value, bytes calldata _data) public { 84 _data; 85 mintTo(_to, _value); 86 } 87 88 // Implements Writer 89 function addWriter(address _minter) public returns (bool) { 90 require(msg.sender == owner); 91 92 writers[_minter] = true; 93 94 return true; 95 } 96 97 // Implements Writer 98 function deleteWriter(address _minter) public returns (bool) { 99 require(msg.sender == owner || msg.sender == _minter); 100 101 writers[_minter] = false; 102 103 return true; 104 } 105 106 // Implements Writer 107 function isWriter(address _minter) public view returns(bool) { 108 return writers[_minter] || _minter == owner; 109 } 110 111 // Implements Expire 112 function applyExpiry() public returns(uint8) { 113 if (expires == 0) { 114 return 0; 115 } 116 if (expired) { 117 return 1; 118 } 119 if (block.timestamp >= expires) { 120 expired = true; 121 emit Expired(block.timestamp); 122 return 2; 123 } 124 return 0; 125 126 } 127 128 // Implements ERC20 129 function transfer(address _to, uint256 _value) public returns (bool) { 130 require(applyExpiry() == 0); 131 require(balanceOf[msg.sender] >= _value); 132 balanceOf[msg.sender] -= _value; 133 balanceOf[_to] += _value; 134 emit Transfer(msg.sender, _to, _value); 135 return true; 136 } 137 138 // Implements Burner 139 function burn(uint256 _value) public returns (bool) { 140 require(msg.sender == owner, 'ERR_ACCESS'); 141 require(balanceOf[msg.sender] >= _value, 'ERR_FUNDS'); 142 143 balanceOf[msg.sender] -= _value; 144 totalBurned += _value; 145 146 emit Burn(_value); 147 return true; 148 } 149 150 // Implements Burner 151 function burn() public returns(bool) { 152 return burn(balanceOf[msg.sender]); 153 } 154 155 // Implements Burner 156 // Implements ERC5679Ext20 157 function burn(address _from, uint256 _value, bytes calldata _data) public { 158 require(msg.sender == _from, 'ERR_NOT_SELF'); 159 _data; 160 burn(_value); 161 } 162 163 // Implements ERC20 164 function transferFrom(address _from, address _to, uint256 _value) public returns (bool) { 165 require(applyExpiry() == 0); 166 require(allowance[_from][msg.sender] >= _value); 167 require(balanceOf[_from] >= _value); 168 allowance[_from][msg.sender] = allowance[_from][msg.sender] - _value; 169 balanceOf[_from] -= _value; 170 balanceOf[_to] += _value; 171 emit TransferFrom(_from, _to, msg.sender, _value); 172 return true; 173 } 174 175 // Implements ERC20 176 function approve(address _spender, uint256 _value) public returns (bool) { 177 require(applyExpiry() == 0); 178 if (_value > 0) { 179 require(allowance[msg.sender][_spender] == 0); 180 } 181 allowance[msg.sender][_spender] = _value; 182 emit Approval(msg.sender, _spender, _value); 183 return true; 184 } 185 186 // Implements EIP173 187 function transferOwnership(address _newOwner) public returns (bool) { 188 require(msg.sender == owner); 189 owner = _newOwner; 190 return true; 191 } 192 193 // Implements EIP165 194 function supportsInterface(bytes4 _sum) public pure returns (bool) { 195 if (_sum == 0xb61bc941) { // ERC20 196 return true; 197 } 198 if (_sum == 0x449a52f8) { // Minter 199 return true; 200 } 201 if (_sum == 0x01ffc9a7) { // EIP165 202 return true; 203 } 204 if (_sum == 0x9493f8b2) { // EIP173 205 return true; 206 } 207 if (_sum == 0xabe1f1f5) { // Writer 208 return true; 209 } 210 if (_sum == 0xb1110c1b) { // Burner 211 return true; 212 } 213 if (_sum == 0x841a0e94) { // Expire 214 return true; 215 } 216 return false; 217 } 218 }