2023-03-26 09:07:41 +02:00
|
|
|
pragma solidity >=0.8.0;
|
2020-12-06 14:12:49 +01:00
|
|
|
|
2023-03-26 09:07:41 +02:00
|
|
|
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
|
|
// File-Version: 3
|
2020-12-06 14:12:49 +01:00
|
|
|
|
|
|
|
contract GiftableToken {
|
|
|
|
|
2023-02-22 11:48:32 +01:00
|
|
|
// Implements EIP173
|
2021-12-09 06:23:21 +01:00
|
|
|
address public owner;
|
2023-02-22 11:48:32 +01:00
|
|
|
|
|
|
|
// Implements Writer
|
|
|
|
mapping(address => bool) writer;
|
2020-12-06 14:12:49 +01:00
|
|
|
|
2021-05-02 16:33:00 +02:00
|
|
|
// Implements ERC20
|
2020-12-06 14:12:49 +01:00
|
|
|
string public name;
|
2021-05-02 16:33:00 +02:00
|
|
|
// Implements ERC20
|
2020-12-06 14:12:49 +01:00
|
|
|
string public symbol;
|
2021-05-02 16:33:00 +02:00
|
|
|
// Implements ERC20
|
2020-12-06 14:12:49 +01:00
|
|
|
uint8 public decimals;
|
2021-05-02 16:33:00 +02:00
|
|
|
// Implements ERC20
|
2020-12-06 14:12:49 +01:00
|
|
|
mapping (address => uint256) public balanceOf;
|
2021-05-02 16:33:00 +02:00
|
|
|
// Implements ERC20
|
2020-12-11 16:42:47 +01:00
|
|
|
mapping (address => mapping (address => uint256)) public allowance;
|
2020-12-06 14:12:49 +01:00
|
|
|
|
2023-02-22 11:48:32 +01:00
|
|
|
// Implements Burner
|
|
|
|
uint256 public totalMinted;
|
|
|
|
// Implements Burner
|
2023-03-21 21:28:39 +01:00
|
|
|
uint256 public totalBurned;
|
2023-02-22 11:48:32 +01:00
|
|
|
|
2023-03-26 09:07:41 +02:00
|
|
|
// Implements Expire
|
2023-02-21 21:28:25 +01:00
|
|
|
uint256 public expires;
|
|
|
|
bool expired;
|
|
|
|
|
2023-02-22 11:48:32 +01:00
|
|
|
// Implements ERC20
|
2020-12-06 14:12:49 +01:00
|
|
|
event Transfer(address indexed _from, address indexed _to, uint256 _value);
|
2023-02-22 11:48:32 +01:00
|
|
|
// Implements ERC20
|
2020-12-06 14:12:49 +01:00
|
|
|
event TransferFrom(address indexed _from, address indexed _to, address indexed _spender, uint256 _value);
|
2023-02-22 11:48:32 +01:00
|
|
|
// Implements ERC20
|
2020-12-06 14:12:49 +01:00
|
|
|
event Approval(address indexed _owner, address indexed _spender, uint256 _value);
|
2023-02-22 11:48:32 +01:00
|
|
|
|
|
|
|
// Implements Minter
|
2021-05-02 16:33:00 +02:00
|
|
|
event Mint(address indexed _minter, address indexed _beneficiary, uint256 _value);
|
2023-02-22 11:48:32 +01:00
|
|
|
|
|
|
|
// Implement Expire
|
2023-02-21 21:28:25 +01:00
|
|
|
event Expired(uint256 _timestamp);
|
2020-12-06 14:12:49 +01:00
|
|
|
|
2023-02-22 11:48:32 +01:00
|
|
|
// Implements Writer
|
|
|
|
event WriterAdded(address _writer);
|
|
|
|
// Implements Writer
|
|
|
|
event WriterRemoved(address _writer);
|
|
|
|
|
|
|
|
// Implements Burner
|
|
|
|
event Burn(uint256 _value);
|
|
|
|
|
2023-03-21 21:08:17 +01:00
|
|
|
constructor(string memory _name, string memory _symbol, uint8 _decimals, uint256 _expireTimestamp) {
|
2020-12-06 14:12:49 +01:00
|
|
|
owner = msg.sender;
|
|
|
|
name = _name;
|
|
|
|
symbol = _symbol;
|
|
|
|
decimals = _decimals;
|
2023-02-21 21:28:25 +01:00
|
|
|
expires = _expireTimestamp;
|
2020-12-06 14:12:49 +01:00
|
|
|
}
|
|
|
|
|
2023-02-22 11:48:32 +01:00
|
|
|
// Implements ERC20
|
2023-03-21 21:08:17 +01:00
|
|
|
function totalSupply() public view returns (uint256) {
|
2023-03-21 21:28:39 +01:00
|
|
|
return totalMinted - totalBurned;
|
2023-02-22 11:48:32 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
mapping(address => bool) writers;
|
2023-05-30 18:38:56 +02:00
|
|
|
|
|
|
|
// Implements Minter
|
2021-04-04 14:47:32 +02:00
|
|
|
function mintTo(address _to, uint256 _value) public returns (bool) {
|
2023-02-22 11:48:32 +01:00
|
|
|
require(writers[msg.sender] || msg.sender == owner);
|
2020-12-06 14:12:49 +01:00
|
|
|
|
2021-04-04 14:47:32 +02:00
|
|
|
balanceOf[_to] += _value;
|
2023-02-22 11:48:32 +01:00
|
|
|
totalMinted += _value;
|
2020-12-06 14:12:49 +01:00
|
|
|
|
2021-05-02 16:33:00 +02:00
|
|
|
emit Mint(msg.sender, _to, _value);
|
|
|
|
|
2020-12-06 14:12:49 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2023-03-26 09:07:41 +02:00
|
|
|
// Implements Minter
|
|
|
|
// Implements ERC5679Ext20
|
|
|
|
function mint(address _to, uint256 _value, bytes calldata _data) public {
|
|
|
|
_data;
|
|
|
|
mintTo(_to, _value);
|
|
|
|
}
|
|
|
|
|
2023-02-22 11:48:32 +01:00
|
|
|
// Implements Writer
|
2023-02-21 21:28:25 +01:00
|
|
|
function addWriter(address _minter) public returns (bool) {
|
2020-12-06 14:12:49 +01:00
|
|
|
require(msg.sender == owner);
|
|
|
|
|
2023-02-22 11:48:32 +01:00
|
|
|
writers[_minter] = true;
|
2020-12-06 14:12:49 +01:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2023-02-22 11:48:32 +01:00
|
|
|
// Implements Writer
|
2023-03-26 09:07:41 +02:00
|
|
|
function deleteWriter(address _minter) public returns (bool) {
|
2020-12-06 14:12:49 +01:00
|
|
|
require(msg.sender == owner || msg.sender == _minter);
|
|
|
|
|
2023-02-22 11:48:32 +01:00
|
|
|
writers[_minter] = false;
|
2020-12-06 14:12:49 +01:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2023-02-22 11:48:32 +01:00
|
|
|
// Implements Writer
|
2023-02-21 21:28:25 +01:00
|
|
|
function isWriter(address _minter) public view returns(bool) {
|
2023-02-22 11:48:32 +01:00
|
|
|
return writers[_minter] || _minter == owner;
|
2023-02-21 21:28:25 +01:00
|
|
|
}
|
|
|
|
|
2023-02-22 11:48:32 +01:00
|
|
|
// Implements Expire
|
2023-02-21 21:28:25 +01:00
|
|
|
function applyExpiry() public returns(uint8) {
|
|
|
|
if (expires == 0) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (expired) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
if (block.timestamp >= expires) {
|
|
|
|
expired = true;
|
|
|
|
emit Expired(block.timestamp);
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2021-05-02 16:33:00 +02:00
|
|
|
// Implements ERC20
|
2020-12-06 14:12:49 +01:00
|
|
|
function transfer(address _to, uint256 _value) public returns (bool) {
|
2023-02-21 21:28:25 +01:00
|
|
|
require(applyExpiry() == 0);
|
2020-12-06 17:37:50 +01:00
|
|
|
require(balanceOf[msg.sender] >= _value);
|
2020-12-06 14:12:49 +01:00
|
|
|
balanceOf[msg.sender] -= _value;
|
|
|
|
balanceOf[_to] += _value;
|
|
|
|
emit Transfer(msg.sender, _to, _value);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2023-02-22 11:48:32 +01:00
|
|
|
// Implements Burner
|
|
|
|
function burn(uint256 _value) public returns (bool) {
|
|
|
|
require(msg.sender == owner, 'ERR_ACCESS');
|
|
|
|
require(balanceOf[msg.sender] >= _value, 'ERR_FUNDS');
|
|
|
|
|
|
|
|
balanceOf[msg.sender] -= _value;
|
2023-03-21 21:28:39 +01:00
|
|
|
totalBurned += _value;
|
2023-02-22 11:48:32 +01:00
|
|
|
|
|
|
|
emit Burn(_value);
|
2023-03-21 21:08:17 +01:00
|
|
|
return true;
|
2023-02-22 11:48:32 +01:00
|
|
|
}
|
|
|
|
|
2023-03-26 09:07:41 +02:00
|
|
|
// Implements Burner
|
|
|
|
function burn() public returns(bool) {
|
|
|
|
return burn(balanceOf[msg.sender]);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Implements Burner
|
|
|
|
// Implements ERC5679Ext20
|
|
|
|
function burn(address _from, uint256 _value, bytes calldata _data) public {
|
|
|
|
require(msg.sender == _from, 'ERR_NOT_SELF');
|
|
|
|
_data;
|
|
|
|
burn(_value);
|
|
|
|
}
|
|
|
|
|
2021-05-02 16:33:00 +02:00
|
|
|
// Implements ERC20
|
2020-12-06 14:12:49 +01:00
|
|
|
function transferFrom(address _from, address _to, uint256 _value) public returns (bool) {
|
2023-02-21 21:28:25 +01:00
|
|
|
require(applyExpiry() == 0);
|
2020-12-11 16:42:47 +01:00
|
|
|
require(allowance[_from][msg.sender] >= _value);
|
2020-12-06 17:37:50 +01:00
|
|
|
require(balanceOf[_from] >= _value);
|
2020-12-11 16:42:47 +01:00
|
|
|
allowance[_from][msg.sender] = allowance[_from][msg.sender] - _value;
|
2020-12-06 14:12:49 +01:00
|
|
|
balanceOf[_from] -= _value;
|
|
|
|
balanceOf[_to] += _value;
|
|
|
|
emit TransferFrom(_from, _to, msg.sender, _value);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2021-05-02 16:33:00 +02:00
|
|
|
// Implements ERC20
|
2020-12-06 14:12:49 +01:00
|
|
|
function approve(address _spender, uint256 _value) public returns (bool) {
|
2023-02-21 21:28:25 +01:00
|
|
|
require(applyExpiry() == 0);
|
2021-06-26 10:30:17 +02:00
|
|
|
if (_value > 0) {
|
|
|
|
require(allowance[msg.sender][_spender] == 0);
|
|
|
|
}
|
|
|
|
allowance[msg.sender][_spender] = _value;
|
2020-12-06 14:12:49 +01:00
|
|
|
emit Approval(msg.sender, _spender, _value);
|
|
|
|
return true;
|
|
|
|
}
|
2021-05-02 16:33:00 +02:00
|
|
|
|
2021-12-09 06:23:21 +01:00
|
|
|
// Implements EIP173
|
|
|
|
function transferOwnership(address _newOwner) public returns (bool) {
|
2022-03-11 06:55:16 +01:00
|
|
|
require(msg.sender == owner);
|
2021-12-09 06:23:21 +01:00
|
|
|
owner = _newOwner;
|
2023-03-21 21:08:17 +01:00
|
|
|
return true;
|
2021-12-09 06:23:21 +01:00
|
|
|
}
|
|
|
|
|
2021-05-02 16:33:00 +02:00
|
|
|
// Implements EIP165
|
2023-03-21 21:08:17 +01:00
|
|
|
function supportsInterface(bytes4 _sum) public pure returns (bool) {
|
2023-03-21 21:28:39 +01:00
|
|
|
if (_sum == 0xb61bc941) { // ERC20
|
2021-05-02 16:33:00 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if (_sum == 0x449a52f8) { // Minter
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if (_sum == 0x01ffc9a7) { // EIP165
|
|
|
|
return true;
|
|
|
|
}
|
2021-12-09 06:23:21 +01:00
|
|
|
if (_sum == 0x9493f8b2) { // EIP173
|
|
|
|
return true;
|
|
|
|
}
|
2023-02-22 11:48:32 +01:00
|
|
|
if (_sum == 0xabe1f1f5) { // Writer
|
|
|
|
return true;
|
|
|
|
}
|
2023-03-21 21:28:39 +01:00
|
|
|
if (_sum == 0xb1110c1b) { // Burner
|
2023-02-22 11:48:32 +01:00
|
|
|
return true;
|
|
|
|
}
|
2023-03-26 09:07:41 +02:00
|
|
|
if (_sum == 0x841a0e94) { // Expire
|
|
|
|
return true;
|
|
|
|
}
|
2021-05-02 16:33:00 +02:00
|
|
|
return false;
|
|
|
|
}
|
2020-12-06 14:12:49 +01:00
|
|
|
}
|