WIP avoid fractional truncation

This commit is contained in:
nolash 2021-06-07 15:32:50 +02:00
parent dd878aa5cd
commit 5f69a1d7a1
Signed by: lash
GPG Key ID: 21D2E7BB88C2A746
6 changed files with 74 additions and 36 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -65,7 +65,17 @@ class DemurrageTokenSimulation:
r = self.rpc.do(o) r = self.rpc.do(o)
if r['status'] != 1: if r['status'] != 1:
raise RuntimeError('failed gas transfer to account #{}: {} from {}'.format(i, address, self.accounts[idx])) raise RuntimeError('failed gas transfer to account #{}: {} from {}'.format(i, address, self.accounts[idx]))
logg.debug('added actor account #{}: {}'.format(i, address)) logg.info('added actor account #{}: {} block {}'.format(i, address, r['block_number']))
c = DemurrageToken(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
(tx_hash, o) = c.constructor(self.accounts[0], settings, redistribute=redistribute, cap=cap)
self.rpc.do(o)
o = receipt(tx_hash)
r = self.rpc.do(o)
if (r['status'] != 1):
raise RuntimeError('contract deployment failed')
self.address = r['contract_address']
logg.info('deployed contract to {} block {}'.format(self.address, r['block_number']))
o = block_latest() o = block_latest()
r = self.rpc.do(o) r = self.rpc.do(o)
@ -76,25 +86,14 @@ class DemurrageTokenSimulation:
r = self.rpc.do(o) r = self.rpc.do(o)
self.last_timestamp = r['timestamp'] self.last_timestamp = r['timestamp']
self.start_timestamp = self.last_timestamp self.start_timestamp = self.last_timestamp
nonce_oracle = RPCNonceOracle(self.accounts[0], conn=self.rpc) nonce_oracle = RPCNonceOracle(self.accounts[0], conn=self.rpc)
c = DemurrageToken(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
(tx_hash, o) = c.constructor(self.accounts[0], settings, redistribute=redistribute, cap=cap)
self.rpc.do(o)
o = receipt(tx_hash)
r = self.rpc.do(o)
if (r['status'] != 1):
raise RuntimeError('contract deployment failed')
self.address = r['contract_address']
o = c.decimals(self.address, sender_address=self.accounts[0]) o = c.decimals(self.address, sender_address=self.accounts[0])
r = self.rpc.do(o) r = self.rpc.do(o)
self.decimals = c.parse_decimals(r) self.decimals = c.parse_decimals(r)
self.period_seconds = settings.period_minutes * 60 self.period_seconds = settings.period_minutes * 60
self.last_block += 1
self.last_timestamp += 1
self.period = 1 self.period = 1
self.period_txs = [] self.period_txs = []
self.period_tx_limit = self.period_seconds - 1 self.period_tx_limit = self.period_seconds - 1
@ -146,12 +145,15 @@ class DemurrageTokenSimulation:
def get_period(self): def get_period(self):
return self.period o = self.caller_contract.actual_period(self.address, sender_address=self.caller_address)
r = self.rpc.do(o)
return self.caller_contract.parse_actual_period(r)
def get_demurrage(self): def get_demurrage(self):
o = self.caller_contract.demurrage_amount(self.address, sender_address=self.caller_address) o = self.caller_contract.demurrage_amount(self.address, sender_address=self.caller_address)
r = self.rpc.do(o) r = self.rpc.do(o)
logg.info('demrrage amount {}'.format(r))
return float(self.caller_contract.parse_demurrage_amount(r) / (10 ** 38)) return float(self.caller_contract.parse_demurrage_amount(r) / (10 ** 38))
@ -218,21 +220,54 @@ class DemurrageTokenSimulation:
def next(self): def next(self):
target_timestamp = self.start_timestamp + (self.period * self.period_seconds) target_timestamp = self.start_timestamp + (self.period * self.period_seconds)
logg.debug('warping to {}, {} from start'.format(target_timestamp, target_timestamp - self.start_timestamp)) logg.info('warping to {}, {} from start {}'.format(target_timestamp, target_timestamp - self.start_timestamp, self.start_timestamp))
self.last_timestamp = target_timestamp self.last_timestamp = target_timestamp
self.eth_helper.time_travel(self.last_timestamp) o = block_latest()
r = self.rpc.do(o)
self.last_block = r
o = block_by_number(r)
r = self.rpc.do(o)
cursor_timestamp = r['timestamp'] + 1
nonce_oracle = RPCNonceOracle(self.accounts[2], conn=self.rpc)
c = DemurrageToken(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle, gas_oracle=self.gas_oracle)
i = 0
while cursor_timestamp < target_timestamp:
logg.info('mining block on {}'.format(cursor_timestamp))
(tx_hash, o) = c.apply_demurrage(self.address, self.accounts[2])
self.rpc.do(o)
self.eth_helper.time_travel(cursor_timestamp + 60)
self.__next_block()
o = receipt(tx_hash)
r = self.rpc.do(o)
if r['status'] == 0:
raise RuntimeError('demurrage fast-forward failed on step {} timestamp {} block timestamp {} target {}'.format(i, cursor_timestamp, target_timestamp))
cursor_timestamp += 60*60 # 1 hour
o = block_by_number(r['block_number'])
b = self.rpc.do(o)
logg.info('block mined on timestamp {} (delta {}) block number {}'.format(b['timestamp'], b['timestamp'] - self.start_timestamp, b['number']))
i += 1
(tx_hash, o) = c.apply_demurrage(self.address, self.accounts[2])
self.rpc.do(o)
nonce_oracle = RPCNonceOracle(self.accounts[3], conn=self.rpc)
c = DemurrageToken(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle, gas_oracle=self.gas_oracle)
(tx_hash, o) = c.change_period(self.address, self.accounts[3])
self.rpc.do(o)
self.eth_helper.time_travel(target_timestamp + 1)
self.__next_block() self.__next_block()
o = block_latest()
r = self.rpc.do(o)
o = block_by_number(self.last_block) o = block_by_number(self.last_block)
r = self.rpc.do(o) r = self.rpc.do(o)
self.last_block = r['number'] self.last_block = r['number']
block_base = self.last_block block_base = self.last_block
logg.info('block before demurrage execution {} {}'.format(r['timestamp'], r['number']))
nonce_oracle = RPCNonceOracle(self.accounts[2], conn=self.rpc)
c = DemurrageToken(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle, gas_oracle=self.gas_oracle)
(tx_hash, o) = c.change_period(self.address, self.accounts[2])
self.rpc.do(o)
if self.redistribute: if self.redistribute:
for actor in self.actors: for actor in self.actors:

View File

@ -5,10 +5,10 @@ import logging
from erc20_demurrage_token import DemurrageTokenSettings from erc20_demurrage_token import DemurrageTokenSettings
from erc20_demurrage_token.sim import DemurrageTokenSimulation from erc20_demurrage_token.sim import DemurrageTokenSimulation
logging.basicConfig(level=logging.WARNING) logging.basicConfig(level=logging.INFO)
logg = logging.getLogger() logg = logging.getLogger()
decay_per_minute = 0.000050105908373373 # equals approx 2% per month decay_per_minute = 0.00000050105908373373 # equals approx 2% per month
# parameters for simulation object # parameters for simulation object
settings = DemurrageTokenSettings() settings = DemurrageTokenSettings()
@ -16,7 +16,8 @@ settings.name = 'Simulated Demurrage Token'
settings.symbol = 'SIM' 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 = 60*24*7*4
chain = 'evm:foochain:42' chain = 'evm:foochain:42'
cap = (10 ** 6) * (10 ** 12) cap = (10 ** 6) * (10 ** 12)
@ -49,8 +50,8 @@ print('sink balance: demurraged {:>9d} base {:>9d}'.format(sim.balance(sim.sink
# get times # get times
minutes = sim.get_minutes() minutes = sim.get_minutes()
start = sim.get_now() timestamp = sim.get_now()
timestamp = sim.get_start() start = sim.get_start()
period = sim.get_period() period = sim.get_period()
print('start {} now {} period {} minutes passed {}'.format(start, timestamp, period, minutes)) print('start {} now {} period {} minutes passed {}'.format(start, timestamp, period, minutes))

View File

@ -138,7 +138,7 @@ class TestRedistribution(TestDemurrageUnit):
o = c.demurrage_amount(self.address, sender_address=self.accounts[0]) o = c.demurrage_amount(self.address, sender_address=self.accounts[0])
r = self.rpc.do(o) r = self.rpc.do(o)
demurrage = c.parse_demurrage_amount(r) demurrage = c.parse_demurrage_amount(r)
logg.debug('\ndemurrage {}\nsupply {}'.format(demurrage, supply)) logg.debug('\nrediistribution {}\ndemurrage {}\nsupply {}'.format(redistribution, demurrage, supply))
expected_balance = int(supply * (self.tax_level / 1000000)) expected_balance = int(supply * (self.tax_level / 1000000))
expected_balance_tolerance = 1 expected_balance_tolerance = 1

View File

@ -270,15 +270,18 @@ contract DemurrageTokenSingleCap {
return lastRedistribution; return lastRedistribution;
} }
function getDistribution(uint256 _supply, uint256 _demurrageAmount) public view returns (uint256) {
return _supply * (ppmDivider - (_demurrageAmount / 1000000));
}
// Returns the amount sent to the sink address // Returns the amount sent to the sink address
function applyDefaultRedistribution(bytes32 _redistribution) private returns (uint256) { function applyDefaultRedistribution(bytes32 _redistribution) private returns (uint256) {
uint256 redistributionSupply; uint256 redistributionSupply;
uint256 unit; uint256 unit;
redistributionSupply = toRedistributionSupply(_redistribution); redistributionSupply = toRedistributionSupply(_redistribution);
unit = redistributionSupply * (ppmDivider - (demurrageAmount / 1000000)); unit = getDistribution(redistributionSupply, demurrageAmount);
increaseBaseBalance(sinkAddress, toBaseAmount(unit / ppmDivider));
increaseBaseBalance(sinkAddress, unit / ppmDivider);
return unit; return unit;
} }
@ -292,7 +295,6 @@ contract DemurrageTokenSingleCap {
uint128 epochPeriodCount; uint128 epochPeriodCount;
uint256 periodCount; uint256 periodCount;
uint256 lastDemurrageAmount; uint256 lastDemurrageAmount;
uint256 newDemurrageAmount;
//epochPeriodCount = actualPeriod(); //epochPeriodCount = actualPeriod();
//periodCount = epochPeriodCount - demurragePeriod; //periodCount = epochPeriodCount - demurragePeriod;
@ -304,8 +306,8 @@ contract DemurrageTokenSingleCap {
lastDemurrageAmount = demurrageAmount; lastDemurrageAmount = demurrageAmount;
demurrageAmount = uint128(decayBy(lastDemurrageAmount, periodCount)); demurrageAmount = uint128(decayBy(lastDemurrageAmount, periodCount));
//demurragePeriod = epochPeriodCount; //demurragePeriod = epochPeriodCount;
demurrageTimestamp = periodStart + (periodCount * 60); demurrageTimestamp = demurrageTimestamp + (periodCount * 60);
emit Decayed(block.timestamp, periodCount, lastDemurrageAmount, demurrageAmount); emit Decayed(demurrageTimestamp, periodCount, lastDemurrageAmount, demurrageAmount);
return true; return true;
} }