base.py (5227B)
1 # standard imports 2 import logging 3 import os 4 import math 5 6 # external imports 7 from chainlib.eth.unittest.ethtester import EthTesterCase 8 from chainlib.eth.tx import ( 9 receipt, 10 ) 11 from chainlib.eth.block import ( 12 block_latest, 13 block_by_number, 14 ) 15 from chainlib.eth.nonce import RPCNonceOracle 16 from chainlib.eth.constant import ZERO_ADDRESS 17 18 # local imports 19 from erc20_demurrage_token import ( 20 DemurrageTokenSettings, 21 DemurrageToken, 22 ) 23 from dexif import * 24 25 logg = logging.getLogger() 26 27 #BLOCKTIME = 5 # seconds 28 TAX_LEVEL = int(10000 * 2) # 2% 29 # calc "1-(0.98)^(1/518400)" <- 518400 = 30 days of blocks 30 # 0.00000003897127107225 31 PERIOD = 43200 32 33 34 class TestTokenDeploy: 35 36 """tax level is ppm, 1000000 = 100%""" 37 def __init__(self, rpc, token_symbol='FOO', token_name='Foo Token', sink_address=ZERO_ADDRESS, tax_level=TAX_LEVEL, period=PERIOD): 38 self.tax_level = tax_level 39 self.period_seconds = period * 60 40 41 self.settings = DemurrageTokenSettings() 42 self.settings.name = token_name 43 self.settings.symbol = token_symbol 44 self.settings.decimals = 6 45 tax_level_input = to_fixed((1 - (tax_level / 1000000)) ** (1 / period)) 46 self.settings.demurrage_level = tax_level_input 47 self.settings.period_minutes = period 48 self.settings.sink_address = sink_address 49 self.sink_address = self.settings.sink_address 50 logg.debug('using demurrage token settings: {}'.format(self.settings)) 51 52 o = block_latest() 53 self.start_block = rpc.do(o) 54 55 o = block_by_number(self.start_block, include_tx=False) 56 r = rpc.do(o) 57 58 try: 59 self.start_time = int(r['timestamp'], 16) 60 except TypeError: 61 self.start_time = int(r['timestamp']) 62 63 64 def publish(self, rpc, publisher_address, interface, supply_cap=0): 65 tx_hash = None 66 o = None 67 (tx_hash, o) = interface.constructor(publisher_address, self.settings) 68 69 r = rpc.do(o) 70 o = receipt(tx_hash) 71 r = rpc.do(o) 72 assert r['status'] == 1 73 self.start_block = r['block_number'] 74 self.address = r['contract_address'] 75 76 o = block_by_number(r['block_number']) 77 r = rpc.do(o) 78 self.start_time = r['timestamp'] 79 80 return self.address 81 82 83 class TestDemurrage(EthTesterCase): 84 85 def setUp(self): 86 super(TestDemurrage, self).setUp() 87 period = PERIOD 88 try: 89 period = getattr(self, 'period') 90 except AttributeError as e: 91 pass 92 self.publisher = TestTokenDeploy(self.rpc, period=period, sink_address=self.accounts[9]) 93 self.default_supply = 0 94 self.default_supply_cap = 0 95 self.start_block = None 96 self.address = None 97 self.start_time = None 98 99 100 def publish(self, interface): 101 self.address = self.publisher.publish(self.rpc, self.accounts[0], interface, supply_cap=self.default_supply_cap) 102 self.start_block = self.publisher.start_block 103 self.start_time = self.publisher.start_time 104 self.tax_level = self.publisher.tax_level 105 self.period_seconds = self.publisher.period_seconds 106 self.sink_address = self.publisher.sink_address 107 108 logg.debug('contract address {} start block {} start time {}'.format(self.address, self.start_block, self.start_time)) 109 110 111 def assert_within(self, v, target, tolerance_ppm): 112 lower_target = target - (target * (tolerance_ppm / 1000000)) 113 higher_target = target + (target * (tolerance_ppm / 1000000)) 114 #self.assertGreaterEqual(v, lower_target) 115 #self.assertLessEqual(v, higher_target) 116 if v >= lower_target and v <= higher_target: 117 logg.debug('asserted within {} <= {} <= {}'.format(lower_target, v, higher_target)) 118 return 119 raise AssertionError('{} not within lower {} and higher {}'.format(v, lower_target, higher_target)) 120 121 122 def assert_within_greater(self, v, target, tolerance_ppm): 123 greater_target = target + (target * (tolerance_ppm / 1000000)) 124 self.assertLessEqual(v, greater_target) 125 self.assertGreaterEqual(v, target) 126 logg.debug('asserted within greater {} >= {} >= {}'.format(greater_target, v, target)) 127 128 129 def assert_within_lower(self, v, target, tolerance_ppm): 130 lower_target = target - (target * (tolerance_ppm / 1000000)) 131 self.assertGreaterEqual(v, lower_target) 132 self.assertLessEqual(v, target) 133 logg.debug('asserted within lower {} <= {} <= {}'.format(lower_target, v, target)) 134 135 136 def assert_equal_decimals(self, v, target, precision): 137 target = int(target * (10 ** precision)) 138 target = target / (10 ** precision) 139 self.assertEqual(v, target) 140 141 142 def tearDown(self): 143 pass 144 145 146 class TestDemurrageDefault(TestDemurrage): 147 148 def setUp(self): 149 super(TestDemurrageDefault, self).setUp() 150 151 nonce_oracle = RPCNonceOracle(self.accounts[0], self.rpc) 152 c = DemurrageToken(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle) 153 154 self.publish(c) 155 156 self.default_supply = 10**12 157 self.default_supply_cap = self.default_supply