Simplify demurrage cache properties

This commit is contained in:
nolash 2021-03-01 10:53:02 +01:00
parent aab0bc243c
commit 8f11bdc2cc
Signed by: lash
GPG Key ID: 21D2E7BB88C2A746
5 changed files with 43 additions and 58 deletions

View File

@ -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

View File

@ -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)

View File

@ -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