Test precision loss of 2 bytes in demurrage store in redistribution data

This commit is contained in:
nolash 2021-06-08 17:41:49 +02:00
parent 030cfdfc97
commit c3a6a692ed
Signed by: lash
GPG Key ID: 21D2E7BB88C2A746
7 changed files with 35 additions and 33 deletions

File diff suppressed because one or more lines are too long

View File

@ -17,9 +17,10 @@ settings.symbol = 'SIM'
settings.decimals = 6 settings.decimals = 6
settings.demurrage_level = int(decay_per_minute*(10**38)) settings.demurrage_level = int(decay_per_minute*(10**38))
#settings.period_minutes = 1 # 1 week in minutes #settings.period_minutes = 1 # 1 week in minutes
settings.period_minutes = 10 settings.period_minutes = 60*24*7
chain = 'evm:foochain:42' chain = 'evm:foochain:42'
cap = (10 ** 6) * (10 ** 12) cap = (10 ** 6) * (10 ** 12)
#cap = 0
# instantiate simulation # instantiate simulation
sim = DemurrageTokenSimulation(chain, settings, redistribute=False, cap=cap, actors=10) sim = DemurrageTokenSimulation(chain, settings, redistribute=False, cap=cap, actors=10)

View File

@ -7,10 +7,16 @@ export PYTHONPATH=.
#modes=(MultiNocap MultiCap SingleCap SingleNocap) #modes=(MultiNocap MultiCap SingleCap SingleNocap)
modes=(SingleCap SingleNocap) # other contracts need to be updted modes=(SingleCap SingleNocap) # other contracts need to be updted
for m in ${modes[@]}; do for m in ${modes[@]}; do
ERC20_DEMURRAGE_TOKEN_TEST_MODE=$m python tests/test_period.py
ERC20_DEMURRAGE_TOKEN_TEST_MODE=$m python tests/test_basic.py ERC20_DEMURRAGE_TOKEN_TEST_MODE=$m python tests/test_basic.py
ERC20_DEMURRAGE_TOKEN_TEST_MODE=$m python tests/test_growth.py ERC20_DEMURRAGE_TOKEN_TEST_MODE=$m python tests/test_growth.py
ERC20_DEMURRAGE_TOKEN_TEST_MODE=$m python tests/test_amounts.py ERC20_DEMURRAGE_TOKEN_TEST_MODE=$m python tests/test_amounts.py
ERC20_DEMURRAGE_TOKEN_TEST_MODE=$m python tests/test_single.py
done
modes=(SingleCap) # other contracts need to be updted
for m in ${modes[@]}; do
ERC20_DEMURRAGE_TOKEN_TEST_MODE=$m python tests/test_period.py
ERC20_DEMURRAGE_TOKEN_TEST_MODE=$m python tests/test_redistribution_unit.py
done done
modes=(MultiCap SingleCap) modes=(MultiCap SingleCap)
@ -18,12 +24,6 @@ for m in ${modes[@]}; do
ERC20_DEMURRAGE_TOKEN_TEST_MODE=$m python tests/test_cap.py ERC20_DEMURRAGE_TOKEN_TEST_MODE=$m python tests/test_cap.py
done done
modes=(SingleCap SingleNocap)
for m in ${modes[@]}; do
ERC20_DEMURRAGE_TOKEN_TEST_MODE=$m python tests/test_single.py
ERC20_DEMURRAGE_TOKEN_TEST_MODE=$m python tests/test_redistribution_unit.py
done
#modes=(MultiCap MultiNocap) #modes=(MultiCap MultiNocap)
#for m in ${modes[@]}; do #for m in ${modes[@]}; do
# ERC20_DEMURRAGE_TOKEN_TEST_MODE=$m python tests/test_remainder.py # ERC20_DEMURRAGE_TOKEN_TEST_MODE=$m python tests/test_remainder.py

View File

@ -70,10 +70,10 @@ class TestPeriod(TestDemurrageDefault):
# allow test code float rounding error to billionth # allow test code float rounding error to billionth
modifier = (1 - (self.tax_level / 1000000)) ** (self.period_seconds / 60) modifier = (1 - (self.tax_level / 1000000)) ** (self.period_seconds / 60)
modifier *= 10 ** 9 modifier *= 10 ** 9
modifier = int(modifier) * (10 ** (38 - 9)) modifier = int(modifier) * (10 ** (28 - 9))
period /= (10 ** (38 - 9)) period /= (10 ** (28 - 9))
period = int(period) * (10 ** (38 - 9)) period = int(period) * (10 ** (28 - 9))
self.assertEqual(modifier, period) self.assertEqual(modifier, period)
self.backend.time_travel(self.start_time + self.period_seconds * 2) self.backend.time_travel(self.start_time + self.period_seconds * 2)
@ -96,10 +96,10 @@ class TestPeriod(TestDemurrageDefault):
# allow test code float rounding error to billionth # allow test code float rounding error to billionth
modifier = (1 - (self.tax_level / 1000000)) ** ((self.period_seconds * 2) / 60) modifier = (1 - (self.tax_level / 1000000)) ** ((self.period_seconds * 2) / 60)
modifier *= 10 ** 9 modifier *= 10 ** 9
modifier = int(modifier) * (10 ** (38 - 9)) modifier = int(modifier) * (10 ** (28 - 9))
period /= (10 ** (38 - 9)) period /= (10 ** (28 - 9))
period = int(period) * (10 ** (38 - 9)) period = int(period) * (10 ** (28 - 9))
self.assertEqual(modifier, period) self.assertEqual(modifier, period)

View File

@ -36,21 +36,23 @@ class TestRedistribution(TestDemurrageUnit):
nonce_oracle = RPCNonceOracle(self.accounts[0], self.rpc) nonce_oracle = RPCNonceOracle(self.accounts[0], self.rpc)
c = DemurrageToken(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle) c = DemurrageToken(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
demurrage = (1 - (self.tax_level / 1000000)) * (10**38) #demurrage = (1 - (self.tax_level / 1000000)) * (10**38)
demurrage = (1 - (self.tax_level / 1000000)) * (10**28)
supply = self.default_supply supply = self.default_supply
o = c.get_distribution(self.address, supply, demurrage, sender_address=self.accounts[0]) o = c.get_distribution(self.address, supply, demurrage, sender_address=self.accounts[0])
r = self.rpc.do(o) r = self.rpc.do(o)
distribution = c.parse_get_distribution(r) distribution = c.parse_get_distribution(r)
expected_distribution = self.default_supply * (self.tax_level / 1000000) expected_distribution = self.default_supply * (self.tax_level / 1000000)
self.assertEqual(distribution, expected_distribution) self.assert_within_lower(distribution, expected_distribution, 1000)
def test_distribution_from_redistribution(self): def test_distribution_from_redistribution(self):
nonce_oracle = RPCNonceOracle(self.accounts[0], self.rpc) nonce_oracle = RPCNonceOracle(self.accounts[0], self.rpc)
c = DemurrageToken(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle) c = DemurrageToken(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
demurrage = (1 - (self.tax_level / 1000000)) * (10**38) #demurrage = (1 - (self.tax_level / 1000000)) * (10**38)
demurrage = (1 - (self.tax_level / 1000000)) * (10**28)
supply = self.default_supply supply = self.default_supply
o = c.to_redistribution(self.address, 0, demurrage, supply, 1, sender_address=self.accounts[0]) o = c.to_redistribution(self.address, 0, demurrage, supply, 1, sender_address=self.accounts[0])
@ -60,8 +62,7 @@ class TestRedistribution(TestDemurrageUnit):
r = self.rpc.do(o) r = self.rpc.do(o)
distribution = c.parse_get_distribution(r) distribution = c.parse_get_distribution(r)
expected_distribution = self.default_supply * (self.tax_level / 1000000) expected_distribution = self.default_supply * (self.tax_level / 1000000)
self.assertEqual(distribution, expected_distribution) self.assert_within_lower(distribution, expected_distribution, 1000)
def test_single_step(self): def test_single_step(self):

View File

@ -12,7 +12,7 @@ contract DemurrageTokenSingleCap {
uint8 constant shiftRedistributionValue = 32; uint8 constant shiftRedistributionValue = 32;
uint256 constant maskRedistributionValue = 0x00000000000000000000000000000000000000ffffffffffffffffff00000000; // ((1 << 72) - 1) << 32 uint256 constant maskRedistributionValue = 0x00000000000000000000000000000000000000ffffffffffffffffff00000000; // ((1 << 72) - 1) << 32
uint8 constant shiftRedistributionDemurrage = 104; uint8 constant shiftRedistributionDemurrage = 104;
uint256 constant maskRedistributionDemurrage = 0x000000ffffffffffffffffffffffffffffffff00000000000000000000000000; // ((1 << 20) - 1) << 140 uint256 constant maskRedistributionDemurrage = 0x0000000000ffffffffffffffffffffffffffff00000000000000000000000000; // ((1 << 20) - 1) << 140
// Account balances // Account balances
mapping (address => uint256) account; mapping (address => uint256) account;
@ -115,7 +115,8 @@ contract DemurrageTokenSingleCap {
periodStart = demurrageTimestamp; periodStart = demurrageTimestamp;
periodDuration = _periodMinutes * 60; periodDuration = _periodMinutes * 60;
//demurrageAmount = 100000000000000000000000000000000000000 - _taxLevelMinute; // Represents 38 decimal places, same as resolutionFactor //demurrageAmount = 100000000000000000000000000000000000000 - _taxLevelMinute; // Represents 38 decimal places, same as resolutionFactor
demurrageAmount = 100000000000000000000000000000000000000; //demurrageAmount = 100000000000000000000000000000000000000;
demurrageAmount = 10000000000000000000000000000;
//demurragePeriod = 1; //demurragePeriod = 1;
taxLevel = _taxLevelMinute; // Represents 38 decimal places taxLevel = _taxLevelMinute; // Represents 38 decimal places
bytes32 initialRedistribution = toRedistribution(0, demurrageAmount, 0, 1); bytes32 initialRedistribution = toRedistribution(0, demurrageAmount, 0, 1);
@ -152,7 +153,7 @@ contract DemurrageTokenSingleCap {
//periodCount = actualPeriod() - demurragePeriod; //periodCount = actualPeriod() - demurragePeriod;
periodCount = getMinutesDelta(demurrageTimestamp); periodCount = getMinutesDelta(demurrageTimestamp);
currentDemurragedAmount = uint128(decayBy(demurrageAmount, periodCount)); currentDemurragedAmount = uint128(decayBy(demurrageAmount * 10000000000, periodCount));
return (baseBalance * currentDemurragedAmount) / (nanoDivider * 1000000000000); return (baseBalance * currentDemurragedAmount) / (nanoDivider * 1000000000000);
} }
@ -281,7 +282,7 @@ contract DemurrageTokenSingleCap {
function getDistribution(uint256 _supply, uint256 _demurrageAmount) public view returns (uint256) { function getDistribution(uint256 _supply, uint256 _demurrageAmount) public view returns (uint256) {
uint256 difference; uint256 difference;
difference = _supply * (resolutionFactor - _demurrageAmount); //(nanoDivider - ((resolutionFactor - _demurrageAmount) / nanoDivider)); difference = _supply * (resolutionFactor - (_demurrageAmount * 10000000000)); //(nanoDivider - ((resolutionFactor - _demurrageAmount) / nanoDivider));
return difference / resolutionFactor; return difference / resolutionFactor;
} }
@ -407,7 +408,7 @@ contract DemurrageTokenSingleCap {
// 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 * resolutionFactor) / demurrageAmount; return (_value * resolutionFactor) / (demurrageAmount * 10000000000);
} }
// Implements ERC20, triggers tax and/or redistribution // Implements ERC20, triggers tax and/or redistribution

View File

@ -12,11 +12,7 @@ contract DemurrageTokenSingleCap {
uint8 constant shiftRedistributionValue = 32; uint8 constant shiftRedistributionValue = 32;
uint256 constant maskRedistributionValue = 0x00000000000000000000000000000000000000ffffffffffffffffff00000000; // ((1 << 72) - 1) << 32 uint256 constant maskRedistributionValue = 0x00000000000000000000000000000000000000ffffffffffffffffff00000000; // ((1 << 72) - 1) << 32
uint8 constant shiftRedistributionDemurrage = 104; uint8 constant shiftRedistributionDemurrage = 104;
uint256 constant maskRedistributionDemurrage = 0x000000ffffffffffffffffffffffffffffffff00000000000000000000000000; // ((1 << 20) - 1) << 140 uint256 constant maskRedistributionDemurrage = 0x0000000000ffffffffffffffffffffffffffff00000000000000000000000000; // ((1 << 20) - 1) << 140
uint8 constant shiftRedistributionIsUsed = 255;
uint256 constant maskRedistributionIsUsed = 0x4000000000000000000000000000000000000000000000000000000000000000; // 1 << 255
// Account balances // Account balances
mapping (address => uint256) account; mapping (address => uint256) account;
@ -116,7 +112,8 @@ contract DemurrageTokenSingleCap {
periodStart = demurrageTimestamp; periodStart = demurrageTimestamp;
periodDuration = _periodMinutes * 60; periodDuration = _periodMinutes * 60;
//demurrageAmount = 100000000000000000000000000000000000000 - _taxLevelMinute; // Represents 38 decimal places, same as resolutionFactor //demurrageAmount = 100000000000000000000000000000000000000 - _taxLevelMinute; // Represents 38 decimal places, same as resolutionFactor
demurrageAmount = 100000000000000000000000000000000000000; //demurrageAmount = 100000000000000000000000000000000000000;
demurrageAmount = 10000000000000000000000000000;
//demurragePeriod = 1; //demurragePeriod = 1;
taxLevel = _taxLevelMinute; // Represents 38 decimal places taxLevel = _taxLevelMinute; // Represents 38 decimal places
bytes32 initialRedistribution = toRedistribution(0, demurrageAmount, 0, 1); bytes32 initialRedistribution = toRedistribution(0, demurrageAmount, 0, 1);
@ -152,7 +149,8 @@ contract DemurrageTokenSingleCap {
//periodCount = actualPeriod() - demurragePeriod; //periodCount = actualPeriod() - demurragePeriod;
periodCount = getMinutesDelta(demurrageTimestamp); periodCount = getMinutesDelta(demurrageTimestamp);
currentDemurragedAmount = uint128(decayBy(demurrageAmount, periodCount)); //currentDemurragedAmount = uint128(decayBy(demurrageAmount, periodCount));
currentDemurragedAmount = uint128(decayBy(demurrageAmount * 10000000000, periodCount));
return (baseBalance * currentDemurragedAmount) / (nanoDivider * 1000000000000); return (baseBalance * currentDemurragedAmount) / (nanoDivider * 1000000000000);
} }
@ -406,7 +404,8 @@ contract DemurrageTokenSingleCap {
// 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 * resolutionFactor) / demurrageAmount; //return (_value * resolutionFactor) / demurrageAmount;
return (_value * resolutionFactor) / (demurrageAmount * 10000000000);
} }
// Implements ERC20, triggers tax and/or redistribution // Implements ERC20, triggers tax and/or redistribution