mirror of
git://holbrook.no/erc20-demurrage-token
synced 2024-11-22 00:06:46 +01:00
Update interfaces, add ERC5679 aliases
This commit is contained in:
parent
badfa4838a
commit
d4906529a3
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,6 +1,6 @@
|
|||||||
[metadata]
|
[metadata]
|
||||||
name = erc20-demurrage-token
|
name = erc20-demurrage-token
|
||||||
version = 0.5.0
|
version = 0.5.1
|
||||||
description = ERC20 token with redistributed continual demurrage
|
description = ERC20 token with redistributed continual demurrage
|
||||||
author = Louis Holbrook
|
author = Louis Holbrook
|
||||||
author_email = dev@holbrook.no
|
author_email = dev@holbrook.no
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
pragma solidity >= 0.8.0;
|
pragma solidity >= 0.8.0;
|
||||||
|
|
||||||
|
|
||||||
import "aux/ABDKMath64x64.sol";
|
import "aux/ABDKMath64x64.sol";
|
||||||
|
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
|
||||||
contract DemurrageTokenSingleNocap {
|
contract DemurrageTokenSingleNocap {
|
||||||
|
|
||||||
struct redistributionItem {
|
struct redistributionItem {
|
||||||
@ -11,7 +11,7 @@ contract DemurrageTokenSingleNocap {
|
|||||||
uint72 value;
|
uint72 value;
|
||||||
uint64 demurrage;
|
uint64 demurrage;
|
||||||
}
|
}
|
||||||
redistributionItem[] public redistributions; // uint51(unused) | uint64(demurrageModifier) | uint36(participants) | uint72(value) | uint32(period)
|
redistributionItem[] public redistributions;
|
||||||
|
|
||||||
// Account balances
|
// Account balances
|
||||||
mapping (address => uint256) account;
|
mapping (address => uint256) account;
|
||||||
@ -23,7 +23,7 @@ contract DemurrageTokenSingleNocap {
|
|||||||
// Cached demurrage timestamp; the timestamp for which demurrageAmount was last calculated
|
// Cached demurrage timestamp; the timestamp for which demurrageAmount was last calculated
|
||||||
uint256 public demurrageTimestamp;
|
uint256 public demurrageTimestamp;
|
||||||
|
|
||||||
// Implements EIP172
|
// Implements EIP173
|
||||||
address public owner;
|
address public owner;
|
||||||
|
|
||||||
address newOwner;
|
address newOwner;
|
||||||
@ -37,8 +37,6 @@ contract DemurrageTokenSingleNocap {
|
|||||||
// Implements ERC20
|
// Implements ERC20
|
||||||
uint256 public immutable decimals;
|
uint256 public immutable decimals;
|
||||||
|
|
||||||
// Implements ERC20
|
|
||||||
//uint256 public totalSupply;
|
|
||||||
uint256 supply;
|
uint256 supply;
|
||||||
|
|
||||||
// Last executed period
|
// Last executed period
|
||||||
@ -48,7 +46,7 @@ contract DemurrageTokenSingleNocap {
|
|||||||
uint256 public totalSink;
|
uint256 public totalSink;
|
||||||
|
|
||||||
// Value of burnt tokens (burnt tokens do not decay)
|
// Value of burnt tokens (burnt tokens do not decay)
|
||||||
uint256 public burned;
|
uint256 burned;
|
||||||
|
|
||||||
// 128 bit resolution of the demurrage divisor
|
// 128 bit resolution of the demurrage divisor
|
||||||
// (this constant x 1000000 is contained within 128 bits)
|
// (this constant x 1000000 is contained within 128 bits)
|
||||||
@ -93,7 +91,7 @@ contract DemurrageTokenSingleNocap {
|
|||||||
// Implements ERC20
|
// Implements ERC20
|
||||||
event Approval(address indexed _owner, address indexed _spender, uint256 _value);
|
event Approval(address indexed _owner, address indexed _spender, uint256 _value);
|
||||||
|
|
||||||
// New tokens minted
|
// Implements Minter
|
||||||
event Mint(address indexed _minter, address indexed _beneficiary, uint256 _value);
|
event Mint(address indexed _minter, address indexed _beneficiary, uint256 _value);
|
||||||
|
|
||||||
// New demurrage cache milestone calculated
|
// New demurrage cache milestone calculated
|
||||||
@ -109,23 +107,27 @@ contract DemurrageTokenSingleNocap {
|
|||||||
//event Debug(bytes32 _foo);
|
//event Debug(bytes32 _foo);
|
||||||
event Debug(int128 indexed _foo, uint256 indexed _bar);
|
event Debug(int128 indexed _foo, uint256 indexed _bar);
|
||||||
|
|
||||||
// Emitted when tokens are burned
|
// Implements Burn
|
||||||
event Burn(address indexed _burner, uint256 _value);
|
event Burn(address indexed _burner, uint256 _value);
|
||||||
|
|
||||||
// EIP173
|
// EIP173
|
||||||
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); // EIP173
|
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); // EIP173
|
||||||
|
|
||||||
|
// Implements Expire
|
||||||
event Expired(uint256 _timestamp);
|
event Expired(uint256 _timestamp);
|
||||||
|
|
||||||
event Cap(uint256 indexed _oldCap, uint256 _newCap);
|
event Cap(uint256 indexed _oldCap, uint256 _newCap);
|
||||||
|
|
||||||
// Implements Sealer
|
// Implements Seal
|
||||||
uint256 public sealState;
|
uint256 public sealState;
|
||||||
uint8 constant WRITER_STATE = 1;
|
uint8 constant WRITER_STATE = 1;
|
||||||
uint8 constant SINK_STATE = 2;
|
uint8 constant SINK_STATE = 2;
|
||||||
uint8 constant EXPIRY_STATE = 4;
|
uint8 constant EXPIRY_STATE = 4;
|
||||||
uint8 constant CAP_STATE = 8;
|
uint8 constant CAP_STATE = 8;
|
||||||
|
// Implements Seal
|
||||||
uint256 constant public maxSealState = 15;
|
uint256 constant public maxSealState = 15;
|
||||||
|
|
||||||
|
// Implements Seal
|
||||||
event SealStateChange(bool indexed _final, uint256 _sealState);
|
event SealStateChange(bool indexed _final, uint256 _sealState);
|
||||||
|
|
||||||
|
|
||||||
@ -157,7 +159,6 @@ contract DemurrageTokenSingleNocap {
|
|||||||
sinkAddress = _defaultSinkAddress;
|
sinkAddress = _defaultSinkAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements Sealer
|
|
||||||
function seal(uint256 _state) public returns(uint256) {
|
function seal(uint256 _state) public returns(uint256) {
|
||||||
require(_state < 16, 'ERR_INVALID_STATE');
|
require(_state < 16, 'ERR_INVALID_STATE');
|
||||||
require(_state & sealState == 0, 'ERR_ALREADY_LOCKED');
|
require(_state & sealState == 0, 'ERR_ALREADY_LOCKED');
|
||||||
@ -166,7 +167,6 @@ contract DemurrageTokenSingleNocap {
|
|||||||
return uint256(sealState);
|
return uint256(sealState);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements Sealer
|
|
||||||
function isSealed(uint256 _state) public view returns(bool) {
|
function isSealed(uint256 _state) public view returns(bool) {
|
||||||
require(_state < maxSealState);
|
require(_state < maxSealState);
|
||||||
if (_state == 0) {
|
if (_state == 0) {
|
||||||
@ -175,6 +175,9 @@ contract DemurrageTokenSingleNocap {
|
|||||||
return _state & sealState == _state;
|
return _state & sealState == _state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set when token expires.
|
||||||
|
// Value is set it terms of redistribution periods.
|
||||||
|
// Cannot be set to a time in the past.
|
||||||
function setExpirePeriod(uint256 _expirePeriod) public {
|
function setExpirePeriod(uint256 _expirePeriod) public {
|
||||||
uint256 r;
|
uint256 r;
|
||||||
|
|
||||||
@ -185,7 +188,9 @@ contract DemurrageTokenSingleNocap {
|
|||||||
require(r > expires);
|
require(r > expires);
|
||||||
expires = r;
|
expires = r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Change max token supply.
|
||||||
|
// Can only increase supply cap, not decrease.
|
||||||
function setMaxSupply(uint256 _cap) public {
|
function setMaxSupply(uint256 _cap) public {
|
||||||
require(!isSealed(CAP_STATE));
|
require(!isSealed(CAP_STATE));
|
||||||
require(msg.sender == owner);
|
require(msg.sender == owner);
|
||||||
@ -222,6 +227,7 @@ contract DemurrageTokenSingleNocap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Given address will be allowed to call the mintTo() function
|
// Given address will be allowed to call the mintTo() function
|
||||||
|
// Implements Writer
|
||||||
function addWriter(address _minter) public returns (bool) {
|
function addWriter(address _minter) public returns (bool) {
|
||||||
require(!isSealed(WRITER_STATE));
|
require(!isSealed(WRITER_STATE));
|
||||||
require(msg.sender == owner);
|
require(msg.sender == owner);
|
||||||
@ -230,6 +236,7 @@ contract DemurrageTokenSingleNocap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Given address will no longer be allowed to call the mintTo() function
|
// Given address will no longer be allowed to call the mintTo() function
|
||||||
|
// Implements Writer
|
||||||
function deleteWriter(address _minter) public returns (bool) {
|
function deleteWriter(address _minter) public returns (bool) {
|
||||||
require(!isSealed(WRITER_STATE));
|
require(!isSealed(WRITER_STATE));
|
||||||
require(msg.sender == owner || _minter == msg.sender);
|
require(msg.sender == owner || _minter == msg.sender);
|
||||||
@ -237,6 +244,11 @@ contract DemurrageTokenSingleNocap {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Implements Writer
|
||||||
|
function isWriter(address _minter) public view returns(bool) {
|
||||||
|
return minter[_minter];
|
||||||
|
}
|
||||||
|
|
||||||
/// Implements ERC20
|
/// Implements ERC20
|
||||||
function balanceOf(address _account) public view returns (uint256) {
|
function balanceOf(address _account) public view returns (uint256) {
|
||||||
int128 baseBalance;
|
int128 baseBalance;
|
||||||
@ -301,7 +313,8 @@ contract DemurrageTokenSingleNocap {
|
|||||||
|
|
||||||
// Creates new tokens out of thin air, and allocates them to the given address
|
// Creates new tokens out of thin air, and allocates them to the given address
|
||||||
// Triggers tax
|
// Triggers tax
|
||||||
function mintTo(address _beneficiary, uint256 _amount) external returns (bool) {
|
// Implements Minter
|
||||||
|
function mintTo(address _beneficiary, uint256 _amount) public returns (bool) {
|
||||||
uint256 baseAmount;
|
uint256 baseAmount;
|
||||||
|
|
||||||
require(applyExpiry() == 0);
|
require(applyExpiry() == 0);
|
||||||
@ -320,6 +333,18 @@ contract DemurrageTokenSingleNocap {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Implements Minter
|
||||||
|
function mint(address _beneficiary, uint256 _amount, bytes calldata _data) public {
|
||||||
|
_data;
|
||||||
|
mintTo(_beneficiary, _amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implements Minter
|
||||||
|
function safeMint(address _beneficiary, uint256 _amount, bytes calldata _data) public {
|
||||||
|
_data;
|
||||||
|
mintTo(_beneficiary, _amount);
|
||||||
|
}
|
||||||
|
|
||||||
// Deserializes the redistribution word
|
// Deserializes the redistribution word
|
||||||
function toRedistribution(uint256 _participants, int128 _demurrageModifier, uint256 _value, uint256 _period) public pure returns(redistributionItem memory) {
|
function toRedistribution(uint256 _participants, int128 _demurrageModifier, uint256 _value, uint256 _period) public pure returns(redistributionItem memory) {
|
||||||
redistributionItem memory redistribution;
|
redistributionItem memory redistribution;
|
||||||
@ -508,6 +533,7 @@ contract DemurrageTokenSingleNocap {
|
|||||||
return (block.timestamp - _target) / 60;
|
return (block.timestamp - _target) / 60;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Equality check for empty redistribution data
|
||||||
function isEmptyRedistribution(redistributionItem memory _redistribution) public pure returns(bool) {
|
function isEmptyRedistribution(redistributionItem memory _redistribution) public pure returns(bool) {
|
||||||
if (_redistribution.period > 0) {
|
if (_redistribution.period > 0) {
|
||||||
return false;
|
return false;
|
||||||
@ -545,7 +571,8 @@ contract DemurrageTokenSingleNocap {
|
|||||||
return ABDKMath64x64.toUInt(r);
|
return ABDKMath64x64.toUInt(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements ERC20, triggers tax and/or redistribution
|
// Triggers tax and/or redistribution
|
||||||
|
// Implements ERC20
|
||||||
function approve(address _spender, uint256 _value) public returns (bool) {
|
function approve(address _spender, uint256 _value) public returns (bool) {
|
||||||
uint256 baseValue;
|
uint256 baseValue;
|
||||||
uint8 ex;
|
uint8 ex;
|
||||||
@ -595,7 +622,8 @@ contract DemurrageTokenSingleNocap {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements ERC20, triggers tax and/or redistribution
|
// Triggers tax and/or redistribution
|
||||||
|
// Implements ERC20
|
||||||
function transfer(address _to, uint256 _value) public returns (bool) {
|
function transfer(address _to, uint256 _value) public returns (bool) {
|
||||||
uint256 baseValue;
|
uint256 baseValue;
|
||||||
bool result;
|
bool result;
|
||||||
@ -615,7 +643,8 @@ contract DemurrageTokenSingleNocap {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements ERC20, triggers tax and/or redistribution
|
// Triggers tax and/or redistribution
|
||||||
|
// Implements ERC20
|
||||||
function transferFrom(address _from, address _to, uint256 _value) public returns (bool) {
|
function transferFrom(address _from, address _to, uint256 _value) public returns (bool) {
|
||||||
uint256 baseValue;
|
uint256 baseValue;
|
||||||
bool result;
|
bool result;
|
||||||
@ -649,26 +678,20 @@ contract DemurrageTokenSingleNocap {
|
|||||||
|
|
||||||
// Implements EIP173
|
// Implements EIP173
|
||||||
function transferOwnership(address _newOwner) public returns (bool) {
|
function transferOwnership(address _newOwner) public returns (bool) {
|
||||||
require(msg.sender == owner);
|
|
||||||
newOwner = _newOwner;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Implements OwnedAccepter
|
|
||||||
function acceptOwnership() public returns (bool) {
|
|
||||||
address oldOwner;
|
address oldOwner;
|
||||||
|
|
||||||
require(msg.sender == newOwner);
|
require(msg.sender == owner);
|
||||||
oldOwner = owner;
|
oldOwner = owner;
|
||||||
owner = newOwner;
|
owner = _newOwner;
|
||||||
newOwner = address(0);
|
|
||||||
emit OwnershipTransferred(oldOwner, owner);
|
emit OwnershipTransferred(oldOwner, owner);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Explicitly and irretrievably burn tokens
|
// Explicitly and irretrievably burn tokens
|
||||||
// Only token minters can burn tokens
|
// Only token minters can burn tokens
|
||||||
function burn(uint256 _value) public returns (bool) {
|
// Implements Burner
|
||||||
|
function burn(uint256 _value) public returns(bool) {
|
||||||
require(applyExpiry() == 0);
|
require(applyExpiry() == 0);
|
||||||
require(minter[msg.sender] || msg.sender == owner, 'ERR_ACCESS');
|
require(minter[msg.sender] || msg.sender == owner, 'ERR_ACCESS');
|
||||||
require(_value <= account[msg.sender]);
|
require(_value <= account[msg.sender]);
|
||||||
@ -681,17 +704,31 @@ contract DemurrageTokenSingleNocap {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Implements Burner
|
||||||
|
function burn(address _from, uint256 _value, bytes calldata _data) public {
|
||||||
|
require(_from == msg.sender, 'ERR_ONLY_SELF_BURN');
|
||||||
|
_data;
|
||||||
|
burn(_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implements Burner
|
||||||
|
function burn() public returns(bool) {
|
||||||
|
return burn(account[msg.sender]);
|
||||||
|
}
|
||||||
|
|
||||||
// Implements ERC20
|
// Implements ERC20
|
||||||
function totalSupply() public view returns (uint256) {
|
function totalSupply() public view returns (uint256) {
|
||||||
return supply - burned;
|
return supply - burned;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return total number of burned tokens
|
// Return total number of burned tokens
|
||||||
|
// Implements Burner
|
||||||
function totalBurned() public view returns (uint256) {
|
function totalBurned() public view returns (uint256) {
|
||||||
return burned;
|
return burned;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return total number of tokens ever minted
|
// Return total number of tokens ever minted
|
||||||
|
// Implements Burner
|
||||||
function totalMinted() public view returns (uint256) {
|
function totalMinted() public view returns (uint256) {
|
||||||
return supply;
|
return supply;
|
||||||
}
|
}
|
||||||
@ -699,16 +736,31 @@ contract DemurrageTokenSingleNocap {
|
|||||||
|
|
||||||
// Implements EIP165
|
// Implements EIP165
|
||||||
function supportsInterface(bytes4 _sum) public pure returns (bool) {
|
function supportsInterface(bytes4 _sum) public pure returns (bool) {
|
||||||
if (_sum == 0xc6bb4b70) { // ERC20
|
if (_sum == 0xb61bc941) { // ERC20
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (_sum == 0x449a52f8) { // Minter
|
if (_sum == 0x5878bcf4) { // Minter
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (_sum == 0x01ffc9a7) { // EIP165
|
if (_sum == 0xbc4babdd) { // Burner
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (_sum == 0x9493f8b2) { // EIP173
|
if (_sum == 0x0d7491f8) { // Seal
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (_sum == 0xabe1f1f5) { // Writer
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (_sum == 0xcb52c823) { // Expire
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (_sum == 0x01ffc9a7) { // ERC165
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (_sum == 0x9493f8b2) { // ERC173
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (_sum == 0xd0017968) { // ERC5678Ext20
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
Loading…
Reference in New Issue
Block a user