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)