mirror of
git://holbrook.no/erc20-demurrage-token
synced 2024-11-25 09:16:46 +01:00
Test precision loss of 2 bytes in demurrage store in redistribution data
This commit is contained in:
parent
030cfdfc97
commit
c3a6a692ed
File diff suppressed because one or more lines are too long
@ -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)
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
|
|
||||||
|
|
||||||
|
@ -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):
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user