mirror of
git://holbrook.no/erc20-demurrage-token
synced 2024-12-22 03:57:31 +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 160-254: (Unused)
|
||||
- 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
|
||||
|
||||
|
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)
|
||||
|
||||
|
||||
|
||||
def test_apply_demurrage(self):
|
||||
modifier = 10 * (10 ** 37)
|
||||
demurrage_modifier = self.contract.functions.demurrageModifier().call()
|
||||
demurrage_modifier &= (1 << 128) - 1
|
||||
self.assertEqual(modifier, demurrage_modifier)
|
||||
#demurrage_modifier = self.contract.functions.demurrageModifier().call()
|
||||
#demurrage_modifier &= (1 << 128) - 1
|
||||
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)
|
||||
demurrage_modifier = self.contract.functions.demurrageModifier().call()
|
||||
demurrage_modifier &= (1 << 128) - 1
|
||||
self.assertEqual(modifier, demurrage_modifier)
|
||||
#demurrage_modifier = self.contract.functions.demurrageModifier().call()
|
||||
demurrage_amount = self.contract.functions.demurrageAmount().call()
|
||||
#demurrage_modifier &= (1 << 128) - 1
|
||||
#self.assertEqual(modifier, demurrage_modifier)
|
||||
self.assertEqual(modifier, demurrage_amount)
|
||||
|
||||
self.eth_tester.time_travel(self.start_time + 61)
|
||||
tx_hash = self.contract.functions.applyDemurrage().transact()
|
||||
r = self.w3.eth.getTransactionReceipt(tx_hash)
|
||||
|
||||
demurrage_modifier = self.contract.functions.demurrageModifier().call()
|
||||
demurrage_modifier &= (1 << 128) - 1
|
||||
self.assertEqual(int(98 * (10 ** 36)), demurrage_modifier)
|
||||
#demurrage_modifier = self.contract.functions.demurrageModifier().call()
|
||||
demurrage_amount = self.contract.functions.demurrageAmount().call()
|
||||
#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):
|
||||
@ -138,6 +143,7 @@ class Test(unittest.TestCase):
|
||||
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]})
|
||||
|
||||
|
||||
def test_base_amount(self):
|
||||
tx_hash = self.contract.functions.mintTo(self.w3.eth.accounts[1], 1000).transact()
|
||||
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.contract.functions.applyDemurrage().transact()
|
||||
demurrage_modifier = self.contract.functions.demurrageModifier().call()
|
||||
demurrage_amount = self.contract.functions.toDemurrageAmount(demurrage_modifier).call()
|
||||
logg.debug('d {} {}'.format(demurrage_modifier.to_bytes(32, 'big').hex(), demurrage_amount))
|
||||
#demurrage_modifier = self.contract.functions.demurrageModifier().call()
|
||||
#demurrage_amount = self.contract.functions.toDemurrageAmount(demurrage_modifier).call()
|
||||
demurrage_amount = self.contract.functions.demurrageAmount().call()
|
||||
|
||||
a = self.contract.functions.toBaseAmount(1000).call();
|
||||
self.assertEqual(a, 1020)
|
||||
|
@ -26,14 +26,11 @@ contract RedistributedDemurrageToken {
|
||||
uint8 constant shiftAccountPeriod = 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
|
||||
// Demurrage cache bit field, with associated shifts and masks
|
||||
uint256 public demurrageModifier; // PPM uint128(block) | uint128(periodppm)
|
||||
uint8 constant shiftDemurrageValue = 0;
|
||||
uint256 constant maskDemurrageValue = 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff;
|
||||
uint8 constant shiftDemurragePeriod = 128;
|
||||
uint256 constant maskDemurragePeriod = 0xffffffffffffffffffffffffffffffff00000000000000000000000000000000;
|
||||
// Cached demurrage period; the period for which demurrageAmount was calculated
|
||||
uint128 public demurragePeriod;
|
||||
|
||||
// Implements EIP172
|
||||
address public owner;
|
||||
@ -109,8 +106,8 @@ contract RedistributedDemurrageToken {
|
||||
// Demurrage setup
|
||||
periodStart = block.timestamp;
|
||||
periodDuration = _periodMinutes * 60;
|
||||
demurrageModifier = ppmDivider * 1000000; // Represents 38 decimal places
|
||||
demurrageModifier |= (1 << 128);
|
||||
demurrageAmount = uint128(ppmDivider * 1000000); // Represents 38 decimal places
|
||||
demurragePeriod = 1;
|
||||
taxLevel = _taxLevelMinute; // Represents 38 decimal places
|
||||
bytes32 initialRedistribution = toRedistribution(0, 1000000, 0, 1);
|
||||
redistributions.push(initialRedistribution);
|
||||
@ -137,20 +134,16 @@ contract RedistributedDemurrageToken {
|
||||
/// Implements ERC20
|
||||
function balanceOf(address _account) public view returns (uint256) {
|
||||
uint256 baseBalance;
|
||||
uint256 anchorDemurrageAmount;
|
||||
uint256 anchorDemurragePeriod;
|
||||
uint256 currentDemurrageAmount;
|
||||
uint256 currentDemurragedAmount;
|
||||
uint256 periodCount;
|
||||
|
||||
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
|
||||
@ -283,8 +276,8 @@ contract RedistributedDemurrageToken {
|
||||
}
|
||||
|
||||
// Get the demurrage period of the current block number
|
||||
function actualPeriod() public view returns (uint256) {
|
||||
return (block.timestamp - periodStart) / periodDuration + 1;
|
||||
function actualPeriod() public view returns (uint128) {
|
||||
return uint128((block.timestamp - periodStart) / periodDuration + 1);
|
||||
}
|
||||
|
||||
// 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
|
||||
function applyDemurrage() public returns (bool) {
|
||||
uint256 epochPeriodCount;
|
||||
uint256 periodCount;
|
||||
uint128 epochPeriodCount;
|
||||
uint128 periodCount;
|
||||
uint256 lastDemurrageAmount;
|
||||
uint256 newDemurrageAmount;
|
||||
|
||||
epochPeriodCount = actualPeriod();
|
||||
periodCount = epochPeriodCount - toDemurragePeriod(demurrageModifier);
|
||||
periodCount = epochPeriodCount - demurragePeriod;
|
||||
if (periodCount == 0) {
|
||||
return false;
|
||||
}
|
||||
lastDemurrageAmount = toDemurrageAmount(demurrageModifier);
|
||||
newDemurrageAmount = decayBy(lastDemurrageAmount, periodCount);
|
||||
demurrageModifier = 0;
|
||||
demurrageModifier |= (newDemurrageAmount & maskDemurrageValue);
|
||||
demurrageModifier |= ((epochPeriodCount << shiftDemurragePeriod) & maskDemurragePeriod);
|
||||
emit Decayed(epochPeriodCount, periodCount, lastDemurrageAmount, newDemurrageAmount);
|
||||
lastDemurrageAmount = demurrageAmount;
|
||||
demurrageAmount = uint128(decayBy(lastDemurrageAmount, periodCount));
|
||||
demurragePeriod = epochPeriodCount;
|
||||
emit Decayed(epochPeriodCount, periodCount, lastDemurrageAmount, demurrageAmount);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -436,7 +417,7 @@ contract RedistributedDemurrageToken {
|
||||
periodTimestamp = getPeriodTimeDelta(currentPeriod);
|
||||
|
||||
applyDemurrage();
|
||||
currentDemurrageAmount = toDemurrageAmount(demurrageModifier);
|
||||
currentDemurrageAmount = demurrageAmount;
|
||||
|
||||
demurrageCounts = demurrageCycles(periodTimestamp);
|
||||
if (demurrageCounts > 0) {
|
||||
@ -524,7 +505,8 @@ contract RedistributedDemurrageToken {
|
||||
|
||||
// Inflates the given amount according to the current demurrage modifier
|
||||
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
|
||||
|
Loading…
Reference in New Issue
Block a user