mirror of
git://holbrook.no/erc20-demurrage-token
synced 2024-11-16 14:16:46 +01:00
Simplify demurrage cache properties
This commit is contained in:
parent
aab0bc243c
commit
8f11bdc2cc
@ -76,9 +76,6 @@
|
|||||||
- bits 140-159: demurrage modifier
|
- bits 140-159: demurrage modifier
|
||||||
- bits 160-254: (Unused)
|
- bits 160-254: (Unused)
|
||||||
- bits 255: Set if individual redistribution amounts are fractions
|
- bits 255: Set if individual redistribution amounts are fractions
|
||||||
* One word for the `demurrageModifier` (should be replaced with 2 x uint128 instead):
|
|
||||||
- bits 000-127: Accumulated demurrage modifier from last calculation
|
|
||||||
- bits 128-255: Period of last calculated demurrage modifier
|
|
||||||
|
|
||||||
### Notes
|
### Notes
|
||||||
|
|
||||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -71,25 +71,30 @@ class Test(unittest.TestCase):
|
|||||||
self.assertEqual(self.contract.functions.actualPeriod().call(), 2)
|
self.assertEqual(self.contract.functions.actualPeriod().call(), 2)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def test_apply_demurrage(self):
|
def test_apply_demurrage(self):
|
||||||
modifier = 10 * (10 ** 37)
|
modifier = 10 * (10 ** 37)
|
||||||
demurrage_modifier = self.contract.functions.demurrageModifier().call()
|
#demurrage_modifier = self.contract.functions.demurrageModifier().call()
|
||||||
demurrage_modifier &= (1 << 128) - 1
|
#demurrage_modifier &= (1 << 128) - 1
|
||||||
self.assertEqual(modifier, demurrage_modifier)
|
demurrage_amount = self.contract.functions.demurrageAmount().call()
|
||||||
|
#self.assertEqual(modifier, demurrage_modifier)
|
||||||
|
self.assertEqual(modifier, demurrage_amount)
|
||||||
|
|
||||||
self.eth_tester.time_travel(self.start_time + 59)
|
self.eth_tester.time_travel(self.start_time + 59)
|
||||||
demurrage_modifier = self.contract.functions.demurrageModifier().call()
|
#demurrage_modifier = self.contract.functions.demurrageModifier().call()
|
||||||
demurrage_modifier &= (1 << 128) - 1
|
demurrage_amount = self.contract.functions.demurrageAmount().call()
|
||||||
self.assertEqual(modifier, demurrage_modifier)
|
#demurrage_modifier &= (1 << 128) - 1
|
||||||
|
#self.assertEqual(modifier, demurrage_modifier)
|
||||||
|
self.assertEqual(modifier, demurrage_amount)
|
||||||
|
|
||||||
self.eth_tester.time_travel(self.start_time + 61)
|
self.eth_tester.time_travel(self.start_time + 61)
|
||||||
tx_hash = self.contract.functions.applyDemurrage().transact()
|
tx_hash = self.contract.functions.applyDemurrage().transact()
|
||||||
r = self.w3.eth.getTransactionReceipt(tx_hash)
|
r = self.w3.eth.getTransactionReceipt(tx_hash)
|
||||||
|
|
||||||
demurrage_modifier = self.contract.functions.demurrageModifier().call()
|
#demurrage_modifier = self.contract.functions.demurrageModifier().call()
|
||||||
demurrage_modifier &= (1 << 128) - 1
|
demurrage_amount = self.contract.functions.demurrageAmount().call()
|
||||||
self.assertEqual(int(98 * (10 ** 36)), demurrage_modifier)
|
#demurrage_modifier &= (1 << 128) - 1
|
||||||
|
#self.assertEqual(int(98 * (10 ** 36)), demurrage_modifier)
|
||||||
|
self.assertEqual(int(98 * (10 ** 36)), demurrage_amount)
|
||||||
|
|
||||||
|
|
||||||
def test_mint(self):
|
def test_mint(self):
|
||||||
@ -138,6 +143,7 @@ class Test(unittest.TestCase):
|
|||||||
with self.assertRaises(eth_tester.exceptions.TransactionFailed):
|
with self.assertRaises(eth_tester.exceptions.TransactionFailed):
|
||||||
tx_hash = self.contract.functions.mintTo(self.w3.eth.accounts[2], 1024).transact({'from': self.w3.eth.accounts[1]})
|
tx_hash = self.contract.functions.mintTo(self.w3.eth.accounts[2], 1024).transact({'from': self.w3.eth.accounts[1]})
|
||||||
|
|
||||||
|
|
||||||
def test_base_amount(self):
|
def test_base_amount(self):
|
||||||
tx_hash = self.contract.functions.mintTo(self.w3.eth.accounts[1], 1000).transact()
|
tx_hash = self.contract.functions.mintTo(self.w3.eth.accounts[1], 1000).transact()
|
||||||
r = self.w3.eth.getTransactionReceipt(tx_hash)
|
r = self.w3.eth.getTransactionReceipt(tx_hash)
|
||||||
@ -146,9 +152,9 @@ class Test(unittest.TestCase):
|
|||||||
self.eth_tester.time_travel(self.start_time + 61)
|
self.eth_tester.time_travel(self.start_time + 61)
|
||||||
|
|
||||||
self.contract.functions.applyDemurrage().transact()
|
self.contract.functions.applyDemurrage().transact()
|
||||||
demurrage_modifier = self.contract.functions.demurrageModifier().call()
|
#demurrage_modifier = self.contract.functions.demurrageModifier().call()
|
||||||
demurrage_amount = self.contract.functions.toDemurrageAmount(demurrage_modifier).call()
|
#demurrage_amount = self.contract.functions.toDemurrageAmount(demurrage_modifier).call()
|
||||||
logg.debug('d {} {}'.format(demurrage_modifier.to_bytes(32, 'big').hex(), demurrage_amount))
|
demurrage_amount = self.contract.functions.demurrageAmount().call()
|
||||||
|
|
||||||
a = self.contract.functions.toBaseAmount(1000).call();
|
a = self.contract.functions.toBaseAmount(1000).call();
|
||||||
self.assertEqual(a, 1020)
|
self.assertEqual(a, 1020)
|
||||||
|
@ -26,14 +26,11 @@ contract RedistributedDemurrageToken {
|
|||||||
uint8 constant shiftAccountPeriod = 72;
|
uint8 constant shiftAccountPeriod = 72;
|
||||||
uint256 constant maskAccountPeriod = 0x00000000000000000000000000000000000000ffffffff000000000000000000; // ((1 << 32) - 1) << 72
|
uint256 constant maskAccountPeriod = 0x00000000000000000000000000000000000000ffffffff000000000000000000; // ((1 << 32) - 1) << 72
|
||||||
|
|
||||||
|
// Cached demurrage amount, ppm with 38 digit resolution
|
||||||
|
uint128 public demurrageAmount;
|
||||||
|
|
||||||
// TODO: use 2 x uint128 instead
|
// Cached demurrage period; the period for which demurrageAmount was calculated
|
||||||
// Demurrage cache bit field, with associated shifts and masks
|
uint128 public demurragePeriod;
|
||||||
uint256 public demurrageModifier; // PPM uint128(block) | uint128(periodppm)
|
|
||||||
uint8 constant shiftDemurrageValue = 0;
|
|
||||||
uint256 constant maskDemurrageValue = 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff;
|
|
||||||
uint8 constant shiftDemurragePeriod = 128;
|
|
||||||
uint256 constant maskDemurragePeriod = 0xffffffffffffffffffffffffffffffff00000000000000000000000000000000;
|
|
||||||
|
|
||||||
// Implements EIP172
|
// Implements EIP172
|
||||||
address public owner;
|
address public owner;
|
||||||
@ -109,8 +106,8 @@ contract RedistributedDemurrageToken {
|
|||||||
// Demurrage setup
|
// Demurrage setup
|
||||||
periodStart = block.timestamp;
|
periodStart = block.timestamp;
|
||||||
periodDuration = _periodMinutes * 60;
|
periodDuration = _periodMinutes * 60;
|
||||||
demurrageModifier = ppmDivider * 1000000; // Represents 38 decimal places
|
demurrageAmount = uint128(ppmDivider * 1000000); // Represents 38 decimal places
|
||||||
demurrageModifier |= (1 << 128);
|
demurragePeriod = 1;
|
||||||
taxLevel = _taxLevelMinute; // Represents 38 decimal places
|
taxLevel = _taxLevelMinute; // Represents 38 decimal places
|
||||||
bytes32 initialRedistribution = toRedistribution(0, 1000000, 0, 1);
|
bytes32 initialRedistribution = toRedistribution(0, 1000000, 0, 1);
|
||||||
redistributions.push(initialRedistribution);
|
redistributions.push(initialRedistribution);
|
||||||
@ -137,20 +134,16 @@ contract RedistributedDemurrageToken {
|
|||||||
/// Implements ERC20
|
/// Implements ERC20
|
||||||
function balanceOf(address _account) public view returns (uint256) {
|
function balanceOf(address _account) public view returns (uint256) {
|
||||||
uint256 baseBalance;
|
uint256 baseBalance;
|
||||||
uint256 anchorDemurrageAmount;
|
uint256 currentDemurragedAmount;
|
||||||
uint256 anchorDemurragePeriod;
|
|
||||||
uint256 currentDemurrageAmount;
|
|
||||||
uint256 periodCount;
|
uint256 periodCount;
|
||||||
|
|
||||||
baseBalance = baseBalanceOf(_account);
|
baseBalance = baseBalanceOf(_account);
|
||||||
anchorDemurrageAmount = toDemurrageAmount(demurrageModifier);
|
|
||||||
anchorDemurragePeriod = toDemurragePeriod(demurrageModifier);
|
|
||||||
|
|
||||||
periodCount = actualPeriod() - toDemurragePeriod(demurrageModifier);
|
periodCount = actualPeriod() - demurragePeriod;
|
||||||
|
|
||||||
currentDemurrageAmount = decayBy(anchorDemurrageAmount, periodCount);
|
currentDemurragedAmount = uint128(decayBy(demurrageAmount, periodCount));
|
||||||
|
|
||||||
return (baseBalance * currentDemurrageAmount) / (ppmDivider * 1000000);
|
return (baseBalance * currentDemurragedAmount) / (ppmDivider * 1000000);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Balance unmodified by demurrage
|
/// Balance unmodified by demurrage
|
||||||
@ -283,8 +276,8 @@ contract RedistributedDemurrageToken {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get the demurrage period of the current block number
|
// Get the demurrage period of the current block number
|
||||||
function actualPeriod() public view returns (uint256) {
|
function actualPeriod() public view returns (uint128) {
|
||||||
return (block.timestamp - periodStart) / periodDuration + 1;
|
return uint128((block.timestamp - periodStart) / periodDuration + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add an entered demurrage period to the redistribution array
|
// Add an entered demurrage period to the redistribution array
|
||||||
@ -371,34 +364,22 @@ contract RedistributedDemurrageToken {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Deserialize demurrage amount from demurrage bitfield
|
|
||||||
function toDemurrageAmount(uint256 _demurrage) public pure returns (uint256) {
|
|
||||||
return _demurrage & maskDemurrageValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deserialize demurrage period from demurrage bitfield
|
|
||||||
function toDemurragePeriod(uint256 _demurrage) public pure returns (uint256) {
|
|
||||||
return (_demurrage & maskDemurragePeriod) >> shiftDemurragePeriod;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate and cache the demurrage value corresponding to the (period of the) time of the method call
|
// Calculate and cache the demurrage value corresponding to the (period of the) time of the method call
|
||||||
function applyDemurrage() public returns (bool) {
|
function applyDemurrage() public returns (bool) {
|
||||||
uint256 epochPeriodCount;
|
uint128 epochPeriodCount;
|
||||||
uint256 periodCount;
|
uint128 periodCount;
|
||||||
uint256 lastDemurrageAmount;
|
uint256 lastDemurrageAmount;
|
||||||
uint256 newDemurrageAmount;
|
uint256 newDemurrageAmount;
|
||||||
|
|
||||||
epochPeriodCount = actualPeriod();
|
epochPeriodCount = actualPeriod();
|
||||||
periodCount = epochPeriodCount - toDemurragePeriod(demurrageModifier);
|
periodCount = epochPeriodCount - demurragePeriod;
|
||||||
if (periodCount == 0) {
|
if (periodCount == 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
lastDemurrageAmount = toDemurrageAmount(demurrageModifier);
|
lastDemurrageAmount = demurrageAmount;
|
||||||
newDemurrageAmount = decayBy(lastDemurrageAmount, periodCount);
|
demurrageAmount = uint128(decayBy(lastDemurrageAmount, periodCount));
|
||||||
demurrageModifier = 0;
|
demurragePeriod = epochPeriodCount;
|
||||||
demurrageModifier |= (newDemurrageAmount & maskDemurrageValue);
|
emit Decayed(epochPeriodCount, periodCount, lastDemurrageAmount, demurrageAmount);
|
||||||
demurrageModifier |= ((epochPeriodCount << shiftDemurragePeriod) & maskDemurragePeriod);
|
|
||||||
emit Decayed(epochPeriodCount, periodCount, lastDemurrageAmount, newDemurrageAmount);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -436,7 +417,7 @@ contract RedistributedDemurrageToken {
|
|||||||
periodTimestamp = getPeriodTimeDelta(currentPeriod);
|
periodTimestamp = getPeriodTimeDelta(currentPeriod);
|
||||||
|
|
||||||
applyDemurrage();
|
applyDemurrage();
|
||||||
currentDemurrageAmount = toDemurrageAmount(demurrageModifier);
|
currentDemurrageAmount = demurrageAmount;
|
||||||
|
|
||||||
demurrageCounts = demurrageCycles(periodTimestamp);
|
demurrageCounts = demurrageCycles(periodTimestamp);
|
||||||
if (demurrageCounts > 0) {
|
if (demurrageCounts > 0) {
|
||||||
@ -524,7 +505,8 @@ contract RedistributedDemurrageToken {
|
|||||||
|
|
||||||
// Inflates the given amount according to the current demurrage modifier
|
// Inflates the given amount according to the current demurrage modifier
|
||||||
function toBaseAmount(uint256 _value) public view returns (uint256) {
|
function toBaseAmount(uint256 _value) public view returns (uint256) {
|
||||||
return (_value * ppmDivider * 1000000) / toDemurrageAmount(demurrageModifier);
|
//return (_value * ppmDivider * 1000000) / toDemurrageAmount(demurrageModifier);
|
||||||
|
return (_value * ppmDivider * 1000000) / demurrageAmount;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ERC20, triggers tax and/or redistribution
|
// ERC20, triggers tax and/or redistribution
|
||||||
|
Loading…
Reference in New Issue
Block a user