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 }