erc20-demurrage-token

ERC20 token with redistributed continual demurrage
Log | Files | Refs | README

token.py (23772B)


      1 # standard imports
      2 import os
      3 import logging
      4 
      5 # external imports
      6 from chainlib.eth.tx import (
      7         TxFactory,
      8         TxFormat,
      9         )
     10 from chainlib.hash import keccak256_string_to_hex
     11 from chainlib.eth.contract import (
     12         ABIContractEncoder,
     13         ABIContractDecoder,
     14         ABIContractType,
     15         abi_decode_single,
     16         )
     17 from chainlib.eth.constant import ZERO_ADDRESS
     18 from chainlib.jsonrpc import JSONRPCRequest
     19 from eth_erc20 import ERC20
     20 from hexathon import (
     21         add_0x,
     22         strip_0x,
     23         )
     24 from dexif import from_fixed
     25 
     26 # local imports
     27 from erc20_demurrage_token.data import data_dir
     28 from erc20_demurrage_token.seal import SealedContract
     29 from erc20_demurrage_token.expiry import ExpiryContract
     30 
     31 logg = logging.getLogger(__name__)
     32 
     33 
     34 class DemurrageRedistribution:
     35     
     36     def __init__(self, v):
     37         d = ABIContractDecoder()
     38         v = strip_0x(v)
     39         d.typ(ABIContractType.UINT256)
     40         d.typ(ABIContractType.UINT256)
     41         d.typ(ABIContractType.BYTES32)
     42         d.val(v[:64])
     43         d.val(v[64:128])
     44         d.val(v[128:192])
     45         r = d.decode()
     46 
     47         self.period = r[0]
     48         self.value = r[1]
     49         self.demurrage = from_fixed(r[2])
     50 
     51 
     52     def __str__(self):
     53         return 'period {} value {} demurrage {}'.format(self.period, self.value, self.demurrage)
     54 
     55 
     56 class DemurrageTokenSettings:
     57 
     58     def __init__(self):
     59         self.name = None
     60         self.symbol = None
     61         self.decimals = None
     62         self.demurrage_level = None
     63         self.period_minutes = None
     64         self.sink_address = None
     65 
     66 
     67     def __str__(self):
     68         return 'name {} demurrage level {} period minutes {} sink address {}'.format(
     69                 self.name,
     70                 self.demurrage_level,
     71                 self.period_minutes,
     72                 self.sink_address,
     73                 )
     74 
     75 
     76 class DemurrageToken(ERC20, SealedContract, ExpiryContract):
     77 
     78     __abi = {}
     79     __bytecode = {}
     80 
     81     def constructor(self, sender_address, settings, tx_format=TxFormat.JSONRPC, version=None):
     82         code = self.cargs(settings.name, settings.symbol, settings.decimals, settings.demurrage_level, settings.period_minutes, settings.sink_address, version=version)
     83         tx = self.template(sender_address, None, use_nonce=True)
     84         tx = self.set_code(tx, code)
     85         return self.finalize(tx, tx_format)
     86 
     87 
     88     @staticmethod
     89     def cargs(name, symbol, decimals, demurrage_level, period_minutes, sink_address, version=None):
     90         code = DemurrageToken.bytecode()
     91         enc = ABIContractEncoder()
     92         enc.string(name)
     93         enc.string(symbol)
     94         enc.uint256(decimals)
     95         enc.uint256(demurrage_level)
     96         enc.uint256(period_minutes)
     97         enc.address(sink_address)
     98         code += enc.get()
     99         return code
    100 
    101 
    102     @staticmethod
    103     def gas(code=None):
    104         return 7000000
    105 
    106 
    107     @staticmethod
    108     def abi():
    109         name = 'DemurrageTokenSingleNocap'
    110         if DemurrageToken.__abi.get(name) == None:
    111             f = open(os.path.join(data_dir, name + '.json'), 'r')
    112             DemurrageToken.__abi[name] = json.load(f)
    113             f.close()
    114         return DemurrageToken.__abi[name]
    115 
    116 
    117     @staticmethod
    118     def bytecode(version=None):
    119         name = 'DemurrageTokenSingleNocap'
    120         if DemurrageToken.__bytecode.get(name) == None:
    121             f = open(os.path.join(data_dir, name + '.bin'), 'r')
    122             DemurrageToken.__bytecode[name] = f.read()
    123             f.close()
    124         return DemurrageToken.__bytecode[name]
    125 
    126 
    127     def increase_allowance(self, contract_address, sender_address, address, value, tx_format=TxFormat.JSONRPC):
    128         enc = ABIContractEncoder()
    129         enc.method('increaseAllowance')
    130         enc.typ(ABIContractType.ADDRESS)
    131         enc.typ(ABIContractType.UINT256)
    132         enc.address(address)
    133         enc.uint256(value)
    134         data = enc.get()
    135         tx = self.template(sender_address, contract_address, use_nonce=True)
    136         tx = self.set_code(tx, data)
    137         tx = self.finalize(tx, tx_format)
    138         return tx
    139 
    140 
    141     def decrease_allowance(self, contract_address, sender_address, address, value, tx_format=TxFormat.JSONRPC):
    142         enc = ABIContractEncoder()
    143         enc.method('decreaseAllowance')
    144         enc.typ(ABIContractType.ADDRESS)
    145         enc.typ(ABIContractType.UINT256)
    146         enc.address(address)
    147         enc.uint256(value)
    148         data = enc.get()
    149         tx = self.template(sender_address, contract_address, use_nonce=True)
    150         tx = self.set_code(tx, data)
    151         tx = self.finalize(tx, tx_format)
    152         return tx
    153 
    154 
    155     # backwards compatibility
    156     def add_minter(self, contract_address, sender_address, address, tx_format=TxFormat.JSONRPC):
    157         return self.add_writer(contract_address, sender_address, address, tx_format=tx_format)
    158 
    159 
    160     def add_writer(self, contract_address, sender_address, address, tx_format=TxFormat.JSONRPC):
    161         enc = ABIContractEncoder()
    162         enc.method('addWriter')
    163         enc.typ(ABIContractType.ADDRESS)
    164         enc.address(address)
    165         data = enc.get()
    166         tx = self.template(sender_address, contract_address, use_nonce=True)
    167         tx = self.set_code(tx, data)
    168         tx = self.finalize(tx, tx_format)
    169         return tx
    170 
    171 
    172     def set_max_supply(self, contract_address, sender_address, cap, tx_format=TxFormat.JSONRPC):
    173         enc = ABIContractEncoder()
    174         enc.method('setMaxSupply')
    175         enc.typ(ABIContractType.UINT256)
    176         enc.uint256(cap)
    177         data = enc.get()
    178         tx = self.template(sender_address, contract_address, use_nonce=True)
    179         tx = self.set_code(tx, data)
    180         tx = self.finalize(tx, tx_format)
    181         return tx
    182 
    183 
    184     # backwards compatibility
    185     def remove_minter(self, contract_address, sender_address, address, tx_format=TxFormat.JSONRPC):
    186         return self.delete_writer(contract_address, sender_address, address, tx_format=tx_format)
    187 
    188 
    189     def delete_writer(self, contract_address, sender_address, address, tx_format=TxFormat.JSONRPC):
    190         enc = ABIContractEncoder()
    191         enc.method('deleteWriter')
    192         enc.typ(ABIContractType.ADDRESS)
    193         enc.address(address)
    194         data = enc.get()
    195         tx = self.template(sender_address, contract_address, use_nonce=True)
    196         tx = self.set_code(tx, data)
    197         tx = self.finalize(tx, tx_format)
    198         return tx
    199 
    200 
    201     def mint_to(self, contract_address, sender_address, address, value, tx_format=TxFormat.JSONRPC):
    202         enc = ABIContractEncoder()
    203         enc.method('mintTo')
    204         enc.typ(ABIContractType.ADDRESS)
    205         enc.typ(ABIContractType.UINT256)
    206         enc.address(address)
    207         enc.uint256(value)
    208         data = enc.get()
    209         tx = self.template(sender_address, contract_address, use_nonce=True)
    210         tx = self.set_code(tx, data)
    211         tx = self.finalize(tx, tx_format)
    212         return tx
    213 
    214 
    215     def burn(self, contract_address, sender_address, value, tx_format=TxFormat.JSONRPC):
    216         enc = ABIContractEncoder()
    217         enc.method('burn')
    218         enc.typ(ABIContractType.UINT256)
    219         enc.uint256(value)
    220         data = enc.get()
    221         tx = self.template(sender_address, contract_address, use_nonce=True)
    222         tx = self.set_code(tx, data)
    223         tx = self.finalize(tx, tx_format)
    224         return tx
    225 
    226 
    227     def total_burned(self, contract_address, sender_address=ZERO_ADDRESS, id_generator=None):
    228         j = JSONRPCRequest(id_generator)
    229         o = j.template()
    230         o['method'] = 'eth_call'
    231         enc = ABIContractEncoder()
    232         enc.method('totalBurned')
    233         data = add_0x(enc.get())
    234         tx = self.template(sender_address, contract_address)
    235         tx = self.set_code(tx, data)
    236         o['params'].append(self.normalize(tx))
    237         o['params'].append('latest')
    238         o = j.finalize(o)
    239         return o
    240 
    241 
    242     def to_base_amount(self, contract_address, value, sender_address=ZERO_ADDRESS, id_generator=None):
    243         j = JSONRPCRequest(id_generator)
    244         o = j.template()
    245         o['method'] = 'eth_call'
    246         enc = ABIContractEncoder()
    247         enc.method('toBaseAmount')
    248         enc.typ(ABIContractType.UINT256)
    249         enc.uint256(value)
    250         data = add_0x(enc.get())
    251         tx = self.template(sender_address, contract_address)
    252         tx = self.set_code(tx, data)
    253         o['params'].append(self.normalize(tx))
    254         o['params'].append('latest')
    255         o = j.finalize(o)
    256         return o
    257 
    258 
    259     def remainder(self, contract_address, parts, whole, sender_address=ZERO_ADDRESS, id_generator=None):
    260         j = JSONRPCRequest(id_generator)
    261         o = j.template()
    262         o['method'] = 'eth_call'
    263         enc = ABIContractEncoder()
    264         enc.method('remainder')
    265         enc.typ(ABIContractType.UINT256)
    266         enc.typ(ABIContractType.UINT256)
    267         enc.uint256(parts)
    268         enc.uint256(whole)
    269         data = add_0x(enc.get())
    270         tx = self.template(sender_address, contract_address)
    271         tx = self.set_code(tx, data)
    272         o['params'].append(self.normalize(tx))
    273         o['params'].append('latest')
    274         o = j.finalize(o)
    275         return o
    276 
    277 
    278     def redistributions(self, contract_address, idx, sender_address=ZERO_ADDRESS, id_generator=None):
    279         j = JSONRPCRequest(id_generator)
    280         o = j.template()
    281         o['method'] = 'eth_call'
    282         enc = ABIContractEncoder()
    283         enc.method('redistributions')
    284         enc.typ(ABIContractType.UINT256)
    285         enc.uint256(idx)
    286         data = add_0x(enc.get())
    287         tx = self.template(sender_address, contract_address)
    288         tx = self.set_code(tx, data)
    289         o['params'].append(self.normalize(tx))
    290         o['params'].append('latest')
    291         o = j.finalize(o)
    292         return o
    293 
    294 
    295     def account_period(self, contract_address, address, sender_address=ZERO_ADDRESS, id_generator=None):
    296         j = JSONRPCRequest(id_generator)
    297         o = j.template()
    298         o['method'] = 'eth_call'
    299         enc = ABIContractEncoder()
    300         enc.method('accountPeriod')
    301         enc.typ(ABIContractType.ADDRESS)
    302         enc.address(address)
    303         data = add_0x(enc.get())
    304         tx = self.template(sender_address, contract_address)
    305         tx = self.set_code(tx, data)
    306         o['params'].append(self.normalize(tx))
    307         o['params'].append('latest')
    308         o = j.finalize(o)
    309         return o
    310 
    311 
    312     def to_redistribution(self, contract_address, participants, demurrage_modifier, value, period, sender_address=ZERO_ADDRESS, id_generator=None):
    313         j = JSONRPCRequest(id_generator)
    314         o = j.template()
    315         o['method'] = 'eth_call'
    316         enc = ABIContractEncoder()
    317         enc.method('toRedistribution')
    318         enc.typ(ABIContractType.UINT256)
    319         enc.typ_literal('int128')
    320         enc.typ(ABIContractType.UINT256)
    321         enc.typ(ABIContractType.UINT256)
    322         enc.uint256(participants)
    323         enc.uint256(demurrage_modifier)
    324         enc.uint256(value)
    325         enc.uint256(period)
    326         data = add_0x(enc.get())
    327         tx = self.template(sender_address, contract_address)
    328         tx = self.set_code(tx, data)
    329         o['params'].append(self.normalize(tx))
    330         o['params'].append('latest')
    331         o = j.finalize(o)
    332         return o
    333 
    334 
    335 
    336     def to_redistribution_period(self, contract_address, redistribution, sender_address=ZERO_ADDRESS, id_generator=None):
    337         j = JSONRPCRequest(id_generator)
    338         o = j.template()
    339         o['method'] = 'eth_call'
    340         enc = ABIContractEncoder()
    341         enc.method('toRedistributionPeriod')
    342         v = strip_0x(redistribution)
    343         enc.typ_literal('(uint32,uint72,uint64)')
    344         enc.bytes32(v[:64])
    345         enc.bytes32(v[64:128])
    346         enc.bytes32(v[128:192])
    347         data = add_0x(enc.get())
    348         tx = self.template(sender_address, contract_address)
    349         tx = self.set_code(tx, data)
    350         o['params'].append(self.normalize(tx))
    351         o['params'].append('latest')
    352         o = j.finalize(o)
    353         return o
    354 
    355 
    356 #    def to_redistribution_participants(self, contract_address, redistribution, sender_address=ZERO_ADDRESS, id_generator=None):
    357 #        j = JSONRPCRequest(id_generator)
    358 #        o = j.template()
    359 #        o['method'] = 'eth_call'
    360 #        enc = ABIContractEncoder()
    361 #        enc.method('toRedistributionParticipants')
    362 #        v = strip_0x(redistribution)
    363 #        enc.typ_literal('(uint32,uint72,uint104)')
    364 #        #enc.typ(ABIContractType.BYTES32)
    365 #        enc.bytes32(v[:64])
    366 #        enc.bytes32(v[64:128])
    367 #        enc.bytes32(v[128:192])
    368 #        data = add_0x(enc.get())
    369 #        tx = self.template(sender_address, contract_address)
    370 #        tx = self.set_code(tx, data)
    371 #        o['params'].append(self.normalize(tx))
    372 #        o['params'].append('latest')
    373 #        o = j.finalize(o)
    374 #        return o
    375 #
    376 
    377     def to_redistribution_supply(self, contract_address, redistribution, sender_address=ZERO_ADDRESS, id_generator=None):
    378         j = JSONRPCRequest(id_generator)
    379         o = j.template()
    380         o['method'] = 'eth_call'
    381         enc = ABIContractEncoder()
    382         enc.method('toRedistributionSupply')
    383         v = strip_0x(redistribution)
    384         enc.typ_literal('(uint32,uint72,uint64)')
    385         enc.bytes32(v[:64])
    386         enc.bytes32(v[64:128])
    387         enc.bytes32(v[128:192])
    388         data = add_0x(enc.get())
    389         tx = self.template(sender_address, contract_address)
    390         tx = self.set_code(tx, data)
    391         o['params'].append(self.normalize(tx))
    392         o['params'].append('latest')
    393         o = j.finalize(o)
    394         return o
    395 
    396 
    397     def to_redistribution_demurrage_modifier(self, contract_address, redistribution, sender_address=ZERO_ADDRESS, id_generator=None):
    398         j = JSONRPCRequest(id_generator)
    399         o = j.template()
    400         o['method'] = 'eth_call'
    401         enc = ABIContractEncoder()
    402         enc.method('toRedistributionDemurrageModifier')
    403         v = strip_0x(redistribution)
    404         enc.typ_literal('(uint32,uint72,uint64)')
    405         enc.bytes32(v[:64])
    406         enc.bytes32(v[64:128])
    407         enc.bytes32(v[128:192])
    408         data = add_0x(enc.get())
    409         tx = self.template(sender_address, contract_address)
    410         tx = self.set_code(tx, data)
    411         o['params'].append(self.normalize(tx))
    412         o['params'].append('latest')
    413         o = j.finalize(o)
    414         return o
    415 
    416 
    417     def base_balance_of(self, contract_address, address, sender_address=ZERO_ADDRESS, id_generator=None):
    418         j = JSONRPCRequest(id_generator)
    419         o = j.template()
    420         o['method'] = 'eth_call'
    421         enc = ABIContractEncoder()
    422         enc.method('baseBalanceOf')
    423         enc.typ(ABIContractType.ADDRESS)
    424         enc.address(address)
    425         data = add_0x(enc.get())
    426         tx = self.template(sender_address, contract_address)
    427         tx = self.set_code(tx, data)
    428         o['params'].append(self.normalize(tx))
    429         o['params'].append('latest')
    430         o = j.finalize(o)
    431         return o
    432 
    433 
    434     def set_sink_address(self, contract_address, sender_address, address, tx_format=TxFormat.JSONRPC):
    435         enc = ABIContractEncoder()
    436         enc.method('setSinkAddress')
    437         enc.typ(ABIContractType.ADDRESS)
    438         enc.address(address)
    439         data = enc.get()
    440         tx = self.template(sender_address, contract_address, use_nonce=True)
    441         tx = self.set_code(tx, data)
    442         tx = self.finalize(tx, tx_format)
    443         return tx
    444 
    445 
    446     def sweep(self, contract_address, sender_address, recipient_address, tx_format=TxFormat.JSONRPC):
    447         enc = ABIContractEncoder()
    448         enc.method('sweep')
    449         enc.typ(ABIContractType.ADDRESS)
    450         enc.address(recipient_address)
    451         data = enc.get()
    452         tx = self.template(sender_address, contract_address, use_nonce=True)
    453         tx = self.set_code(tx, data)
    454         tx = self.finalize(tx, tx_format)
    455         return tx
    456 
    457 
    458 
    459     def apply_demurrage(self, contract_address, sender_address, limit=0, tx_format=TxFormat.JSONRPC):
    460         if limit == 0:
    461             return self.transact_noarg('applyDemurrage', contract_address, sender_address)
    462 
    463         enc = ABIContractEncoder()
    464         enc.method('applyDemurrageLimited')
    465         enc.typ(ABIContractType.UINT256)
    466         enc.uint256(limit)
    467         data = enc.get()
    468         tx = self.template(sender_address, contract_address, use_nonce=True)
    469         tx = self.set_code(tx, data)
    470         tx = self.finalize(tx, tx_format)
    471         return tx
    472 
    473 
    474     def change_period(self, contract_address, sender_address):
    475         return self.transact_noarg('changePeriod', contract_address, sender_address)
    476 
    477 
    478     def apply_redistribution_on_account(self, contract_address, sender_address, address, tx_format=TxFormat.JSONRPC):
    479         enc = ABIContractEncoder()
    480         enc.method('applyRedistributionOnAccount')
    481         enc.typ(ABIContractType.ADDRESS)
    482         enc.address(address)
    483         data = enc.get()
    484         tx = self.template(sender_address, contract_address, use_nonce=True)
    485         tx = self.set_code(tx, data)
    486         tx = self.finalize(tx, tx_format)
    487         return tx
    488 
    489 
    490     def decay_level(self, contract_address, sender_address=ZERO_ADDRESS):
    491         return self.call_noarg('decayLevel', contract_address, sender_address=sender_address)
    492 
    493 
    494     def resolution_factor(self, contract_address, sender_address=ZERO_ADDRESS):
    495         return self.call_noarg('resolutionFactor', contract_address, sender_address=sender_address)
    496 
    497 
    498     def actual_period(self, contract_address, sender_address=ZERO_ADDRESS):
    499         return self.call_noarg('actualPeriod', contract_address, sender_address=sender_address)
    500 
    501 
    502     def period_start(self, contract_address, sender_address=ZERO_ADDRESS):
    503         return self.call_noarg('periodStart', contract_address, sender_address=sender_address)
    504 
    505 
    506     def period_duration(self, contract_address, sender_address=ZERO_ADDRESS):
    507         return self.call_noarg('periodDuration', contract_address, sender_address=sender_address)
    508 
    509 
    510     def demurrage_amount(self, contract_address, sender_address=ZERO_ADDRESS):
    511         return self.call_noarg('demurrageAmount', contract_address, sender_address=sender_address)
    512 
    513 
    514     def demurrage_timestamp(self, contract_address, sender_address=ZERO_ADDRESS):
    515         return self.call_noarg('demurrageTimestamp', contract_address, sender_address=sender_address)
    516 
    517 
    518     def max_supply(self, contract_address, sender_address=ZERO_ADDRESS):
    519         return self.call_noarg('maxSupply', contract_address, sender_address=sender_address)
    520 
    521 
    522 #    def grow_by(self, contract_address, value, period, sender_address=ZERO_ADDRESS, id_generator=None):
    523 #        j = JSONRPCRequest(id_generator)
    524 #        o = j.template()
    525 #        o['method'] = 'eth_call'
    526 #        enc = ABIContractEncoder()
    527 #        enc.method('growBy')
    528 #        enc.typ(ABIContractType.UINT256)
    529 #        enc.typ(ABIContractType.UINT256)
    530 #        enc.uint256(value)
    531 #        enc.uint256(period)
    532 #        data = add_0x(enc.get())
    533 #        tx = self.template(sender_address, contract_address)
    534 #        tx = self.set_code(tx, data)
    535 #        o['params'].append(self.normalize(tx))
    536 #        o['params'].append('latest')
    537 #        o = j.finalize(o)
    538 #        return o
    539 #
    540 
    541     def decay_by(self, contract_address, value, period, sender_address=ZERO_ADDRESS, id_generator=None):
    542         j = JSONRPCRequest(id_generator)
    543         o = j.template()
    544         o['method'] = 'eth_call'
    545         enc = ABIContractEncoder()
    546         enc.method('decayBy')
    547         enc.typ(ABIContractType.UINT256)
    548         enc.typ(ABIContractType.UINT256)
    549         enc.uint256(value)
    550         enc.uint256(period)
    551         data = add_0x(enc.get())
    552         tx = self.template(sender_address, contract_address)
    553         tx = self.set_code(tx, data)
    554         o['params'].append(self.normalize(tx))
    555         o['params'].append('latest')
    556         o = j.finalize(o)
    557         return o
    558 
    559 
    560     def get_distribution(self, contract_address, supply, demurrage_amount, sender_address=ZERO_ADDRESS, id_generator=None):
    561         j = JSONRPCRequest(id_generator)
    562         o = j.template()
    563         o['method'] = 'eth_call'
    564         enc = ABIContractEncoder()
    565         enc.method('getDistribution')
    566         enc.typ(ABIContractType.UINT256)
    567         enc.typ_literal('int128')
    568         enc.uint256(supply)
    569         enc.uint256(demurrage_amount)
    570         data = add_0x(enc.get())
    571         tx = self.template(sender_address, contract_address)
    572         tx = self.set_code(tx, data)
    573         o['params'].append(self.normalize(tx))
    574         o['params'].append('latest')
    575         o = j.finalize(o)
    576         return o
    577 
    578 
    579     def get_distribution_from_redistribution(self, contract_address, redistribution, sender_address=ZERO_ADDRESS, id_generator=None):
    580         j = JSONRPCRequest(id_generator)
    581         o = j.template()
    582         o['method'] = 'eth_call'
    583         enc = ABIContractEncoder()
    584         enc.method('getDistributionFromRedistribution')
    585         v = strip_0x(redistribution)
    586         enc.typ_literal('(uint32,uint72,uint64)')
    587         enc.bytes32(v[:64])
    588         enc.bytes32(v[64:128])
    589         enc.bytes32(v[128:192])
    590         data = add_0x(enc.get())
    591         tx = self.template(sender_address, contract_address)
    592         tx = self.set_code(tx, data)
    593         o['params'].append(self.normalize(tx))
    594         o['params'].append('latest')
    595         o = j.finalize(o)
    596         return o
    597 
    598 
    599 
    600     @classmethod
    601     def parse_actual_period(self, v):
    602         return abi_decode_single(ABIContractType.UINT256, v)
    603 
    604 
    605     @classmethod
    606     def parse_period_start(self, v):
    607         return abi_decode_single(ABIContractType.UINT256, v)
    608 
    609 
    610     @classmethod
    611     def parse_period_duration(self, v):
    612         return abi_decode_single(ABIContractType.UINT256, v)
    613 
    614 
    615     @classmethod
    616     def parse_demurrage_amount(self, v):
    617         #        return abi_decode_single(ABIContractType.UINT256, v)
    618         return from_fixed(v)
    619 
    620 
    621     @classmethod
    622     def parse_remainder(self, v):
    623         return abi_decode_single(ABIContractType.UINT256, v)
    624 
    625 
    626     @classmethod
    627     def parse_to_base_amount(self, v):
    628         return abi_decode_single(ABIContractType.UINT256, v)
    629 
    630     
    631     @classmethod
    632     def parse_redistributions(self, v):
    633         return strip_0x(v)
    634         
    635 
    636     @classmethod
    637     def parse_account_period(self, v):
    638         return abi_decode_single(ABIContractType.ADDRESS, v)
    639 
    640 
    641     @classmethod
    642     def parse_to_redistribution_period(self, v):
    643         return abi_decode_single(ABIContractType.UINT256, v)
    644 
    645 
    646     @classmethod
    647     def parse_to_redistribution_item(self, v):
    648         return abi_decode_single(ABIContractType.UINT256, v)
    649 
    650 
    651     @classmethod
    652     def parse_supply_cap(self, v):
    653         return abi_decode_single(ABIContractType.UINT256, v)
    654 
    655 
    656     @classmethod
    657     def parse_grow_by(self, v):
    658         return abi_decode_single(ABIContractType.UINT256, v)
    659 
    660 
    661     @classmethod
    662     def parse_decay_by(self, v):
    663         return abi_decode_single(ABIContractType.UINT256, v)
    664 
    665 
    666     @classmethod
    667     def parse_get_distribution(self, v):
    668         return abi_decode_single(ABIContractType.UINT256, v)
    669 
    670 
    671     @classmethod
    672     def parse_decay_level(self, v):
    673         return abi_decode_single(ABIContractType.UINT256, v)
    674 
    675 
    676     @classmethod
    677     def parse_resolution_factor(self, v):
    678         return abi_decode_single(ABIContractType.UINT256, v)
    679 
    680 
    681     @classmethod
    682     def parse_total_burned(self, v):
    683         return abi_decode_single(ABIContractType.UINT256, v)
    684 
    685 
    686 def bytecode(**kwargs):
    687     return DemurrageToken.bytecode(version=kwargs.get('version'))
    688 
    689 
    690 def create(**kwargs):
    691     return DemurrageToken.cargs(
    692             kwargs['name'],
    693             kwargs['symbol'],
    694             kwargs['decimals'],
    695             kwargs['demurragelevel'],
    696             kwargs['redistributionperiod'],
    697             kwargs['sinkaddress'],
    698             version=kwargs.get('version'))
    699 
    700 
    701 def args(v):
    702     if v == 'create':
    703         return (['name', 'symbol', 'decimals', 'demurragelevel', 'redistributionperiod', 'sinkaddress'], ['version'],)
    704     elif v == 'default' or v == 'bytecode':
    705         return ([], ['version'],)
    706     raise ValueError('unknown command: ' + v)