Rename module, add test base and two basic tests to chainlib

This commit is contained in:
nolash 2021-06-04 09:05:08 +02:00
parent b4dfb5a381
commit 9f27f9e26a
Signed by: lash
GPG Key ID: 21D2E7BB88C2A746
16 changed files with 380 additions and 425 deletions

View File

@ -0,0 +1,4 @@
from .token import (
DemurrageToken,
DemurrageTokenSettings,
)

View File

@ -29,7 +29,7 @@ from chainlib.eth.tx import receipt
from chainlib.eth.constant import ZERO_ADDRESS from chainlib.eth.constant import ZERO_ADDRESS
# local imports # local imports
from sarafu_token import RedistributedDemurrageToken from erc20_demurrage_token import DemurrageToken
logging.basicConfig(level=logging.WARNING) logging.basicConfig(level=logging.WARNING)
logg = logging.getLogger() logg = logging.getLogger()
@ -92,9 +92,9 @@ else:
gas_oracle = None gas_oracle = None
if args.gas_price !=None: if args.gas_price !=None:
gas_oracle = OverrideGasOracle(price=args.gas_price, conn=rpc, code_callback=RedistributedDemurrageToken.gas) gas_oracle = OverrideGasOracle(price=args.gas_price, conn=rpc, code_callback=DemurrageToken.gas)
else: else:
gas_oracle = RPCGasOracle(rpc, code_callback=RedistributedDemurrageToken.gas) gas_oracle = RPCGasOracle(rpc, code_callback=DemurrageToken.gas)
dummy = args.d dummy = args.d
@ -103,7 +103,7 @@ if token_name == None:
token_name = args.symbol token_name = args.symbol
def main(): def main():
c = RedistributedDemurrageToken(chain_spec, signer=signer, gas_oracle=gas_oracle, nonce_oracle=nonce_oracle) c = DemurrageToken(chain_spec, signer=signer, gas_oracle=gas_oracle, nonce_oracle=nonce_oracle)
(tx_hash_hex, o) = c.constructor( (tx_hash_hex, o) = c.constructor(
signer_address, signer_address,
token_name, token_name,

View File

@ -0,0 +1,128 @@
# standard imports
import os
import logging
# external imports
from chainlib.eth.tx import (
TxFactory,
TxFormat,
)
from chainlib.hash import keccak256_string_to_hex
from chainlib.eth.contract import (
ABIContractEncoder,
ABIContractType,
abi_decode_single,
)
from chainlib.eth.constant import ZERO_ADDRESS
from chainlib.jsonrpc import jsonrpc_template
from eth_erc20 import ERC20
from hexathon import (
add_0x,
strip_0x,
)
# local imports
from erc20_demurrage_token.data import data_dir
logg = logging.getLogger(__name__)
class DemurrageTokenSettings:
def __init__(self):
self.name = None
self.symbol = None
self.decimals = None
self.demurrage_level = None
self.period_minutes = None
self.sink_address = None
class DemurrageToken(ERC20):
__abi = None
__bytecode = None
def constructor(self, sender_address, settings, redistribute=True, cap=0, tx_format=TxFormat.JSONRPC):
if not redistribute or cap:
raise NotImplementedError('token cap and sink only redistribution not yet implemented')
code = DemurrageToken.bytecode()
enc = ABIContractEncoder()
enc.string(settings.name)
enc.string(settings.symbol)
enc.uint256(settings.decimals)
enc.uint256(settings.demurrage_level)
enc.uint256(settings.period_minutes)
enc.address(settings.sink_address)
code += enc.get()
tx = self.template(sender_address, None, use_nonce=True)
tx = self.set_code(tx, code)
return self.finalize(tx, tx_format)
@staticmethod
def gas(code=None):
return 3500000
@staticmethod
def abi():
if DemurrageToken.__abi == None:
f = open(os.path.join(data_dir, 'DemurrageTokenMultiNocap.json'), 'r')
DemurrageToken.__abi = json.load(f)
f.close()
return DemurrageToken.__abi
@staticmethod
def bytecode():
if DemurrageToken.__bytecode == None:
f = open(os.path.join(data_dir, 'DemurrageTokenMultiNocap.bin'), 'r')
DemurrageToken.__bytecode = f.read()
f.close()
return DemurrageToken.__bytecode
def add_minter(self, contract_address, sender_address, address, tx_format=TxFormat.JSONRPC):
enc = ABIContractEncoder()
enc.method('addMinter')
enc.typ(ABIContractType.ADDRESS)
enc.address(address)
data = enc.get()
tx = self.template(sender_address, contract_address, use_nonce=True)
tx = self.set_code(tx, data)
tx = self.finalize(tx, tx_format)
return tx
def mint_to(self, contract_address, sender_address, address, value, tx_format=TxFormat.JSONRPC):
enc = ABIContractEncoder()
enc.method('mintTo')
enc.typ(ABIContractType.ADDRESS)
enc.typ(ABIContractType.UINT256)
enc.address(address)
enc.uint256(value)
data = enc.get()
tx = self.template(sender_address, contract_address, use_nonce=True)
tx = self.set_code(tx, data)
tx = self.finalize(tx, tx_format)
return tx
def apply_demurrage(self, contract_address, sender_address):
return self.transact_noarg('applyDemurrage', contract_address, sender_address)
def actual_period(self, contract_address, sender_address=ZERO_ADDRESS):
return self.call_noarg('actualPeriod', contract_address, sender_address=sender_address)
def demurrage_amount(self, contract_address, sender_address=ZERO_ADDRESS):
return self.call_noarg('demurrageAmount', contract_address, sender_address=sender_address)
def parse_actual_period(self, v):
return abi_decode_single(ABIContractType.UINT256, v)
def parse_demurrage_amount(self, v):
return abi_decode_single(ABIContractType.UINT256, v)

View File

@ -1,3 +1,3 @@
chainlib~=0.0.3a1 chainlib~=0.0.3rc2
eth-erc20~=0.0.9a1 eth-erc20~=0.0.9a3
crypto-dev-signer~=0.4.14b3 crypto-dev-signer~=0.4.14b3

View File

@ -1 +0,0 @@
from .token import RedistributedDemurrageToken

View File

@ -1,133 +0,0 @@
"""Deploys Sarafu token
.. moduleauthor:: Louis Holbrook <dev@holbrook.no>
.. pgp:: 0826EDA1702D1E87C6E2875121D2E7BB88C2A746
"""
# SPDX-License-Identifier: GPL-3.0-or-later
# standard imports
import sys
import os
import json
import argparse
import logging
import time
from enum import Enum
# third-party imports
import web3
from crypto_dev_signer.eth.signer import ReferenceSigner as EIP155Signer
from crypto_dev_signer.keystore import DictKeystore
from crypto_dev_signer.eth.helper import EthTxExecutor
logging.basicConfig(level=logging.WARNING)
logg = logging.getLogger()
logging.getLogger('web3').setLevel(logging.WARNING)
logging.getLogger('urllib3').setLevel(logging.WARNING)
script_dir = os.path.dirname(__file__)
data_dir = os.path.join(script_dir, '..', '..', 'data')
argparser = argparse.ArgumentParser()
argparser.add_argument('-p', '--provider', dest='p', default='http://localhost:8545', type=str, help='Web3 provider url (http only)')
argparser.add_argument('-w', action='store_true', help='Wait for the last transaction to be confirmed')
argparser.add_argument('-ww', action='store_true', help='Wait for every transaction to be confirmed')
argparser.add_argument('-e', action='store_true', help='Treat all transactions as essential')
argparser.add_argument('-i', '--chain-spec', dest='i', type=str, default='Ethereum:1', help='Chain specification string')
argparser.add_argument('-y', '--key-file', dest='y', type=str, help='Ethereum keystore file to use for signing')
argparser.add_argument('--name', dest='n', default='Giftable Token', type=str, help='Token name')
argparser.add_argument('--symbol', dest='s', default='GFT', type=str, help='Token symbol')
argparser.add_argument('--decimals', dest='d', default=18, type=int, help='Token decimals')
argparser.add_argument('--minter', action='append', type=str, help='Minter to add')
argparser.add_argument('--sink-address', type=str, help='Sink address (if not set, signer address is used)')
argparser.add_argument('--abi-dir', dest='abi_dir', type=str, default=data_dir, help='Directory containing bytecode and abi (default: {})'.format(data_dir))
argparser.add_argument('-v', action='store_true', help='Be verbose')
argparser.add_argument('taxlevel_minute', type=int, help='Tax level per minute in ppm')
argparser.add_argument('period_minutes', type=int, help='Redistribution period, in minutes')
args = argparser.parse_args()
if args.v:
logg.setLevel(logging.DEBUG)
block_last = args.w
block_all = args.ww
w3 = web3.Web3(web3.Web3.HTTPProvider(args.p))
signer_address = None
keystore = DictKeystore()
if args.y != None:
logg.debug('loading keystore file {}'.format(args.y))
signer_address = keystore.import_keystore_file(args.y)
logg.debug('now have key for signer address {}'.format(signer_address))
signer = EIP155Signer(keystore)
chain_pair = args.i.split(':')
chain_id = int(chain_pair[1])
helper = EthTxExecutor(
w3,
signer_address,
signer,
chain_id,
block=args.ww,
)
#g = ERC20TxFactory(signer=signer, gas_oracle=gas_oracle, nonce_oracle=nonce_oracle, chain_id=chain_id)
def main():
f = open(os.path.join(args.abi_dir, 'RedistributedDemurrageToken.json'), 'r')
abi = json.load(f)
f.close()
f = open(os.path.join(args.abi_dir, 'RedistributedDemurrageToken.bin'), 'r')
bytecode = f.read()
f.close()
sink_address = args.sink_address
if sink_address == None:
sink_address = signer_address
c = w3.eth.contract(abi=abi, bytecode=bytecode)
(tx_hash, rcpt) = helper.sign_and_send(
[
c.constructor(args.n, args.s, args.d, args.taxlevel_minute, args.period_minutes, sink_address).buildTransaction
],
force_wait=True,
)
logg.debug('tx hash {} rcpt {}'.format(tx_hash, rcpt))
address = rcpt.contractAddress
logg.debug('token contract mined {} {} {} {}'.format(address, args.n, args.s, args.d, args.taxlevel_minute, args.period_minutes, sink_address))
c = w3.eth.contract(abi=abi, address=address)
balance = c.functions.balanceOf(signer_address).call()
logg.info('balance {}: {} {}'.format(signer_address, balance, tx_hash))
if args.minter != None:
for a in args.minter:
if a == signer_address:
continue
(tx_hash, rcpt) = helper.sign_and_send(
[
c.functions.addMinter(a).buildTransaction,
],
)
logg.debug('minter add {} {}'.format(a, tx_hash))
if block_last:
helper.wait_for()
print(address)
sys.exit(0)
if __name__ == '__main__':
main()

View File

@ -1,87 +0,0 @@
# standard imports
import os
import logging
# external imports
from chainlib.eth.tx import (
TxFactory,
TxFormat,
)
from chainlib.hash import keccak256_string_to_hex
from chainlib.eth.contract import (
ABIContractEncoder,
ABIContractType,
)
# local imports
from sarafu_token.data import data_dir
logg = logging.getLogger(__name__)
class RedistributedDemurrageToken(TxFactory):
__abi = None
__bytecode = None
def constructor(self, sender_address, name, symbol, decimals, demurrage_level, period_minutes, sink_address, tx_format=TxFormat.JSONRPC):
code = RedistributedDemurrageToken.bytecode()
enc = ABIContractEncoder()
enc.string(name)
enc.string(symbol)
enc.uint256(decimals)
enc.uint256(demurrage_level)
enc.uint256(period_minutes)
enc.address(sink_address)
code += enc.get()
tx = self.template(sender_address, None, use_nonce=True)
tx = self.set_code(tx, code)
return self.finalize(tx, tx_format)
@staticmethod
def gas(code=None):
return 3500000
@staticmethod
def abi():
if RedistributedDemurrageToken.__abi == None:
f = open(os.path.join(data_dir, 'RedistributedDemurrageToken.json'), 'r')
RedistributedDemurrageToken.__abi = json.load(f)
f.close()
return RedistributedDemurrageToken.__abi
@staticmethod
def bytecode():
if RedistributedDemurrageToken.__bytecode == None:
f = open(os.path.join(data_dir, 'RedistributedDemurrageToken.bin'), 'r')
RedistributedDemurrageToken.__bytecode = f.read()
f.close()
return RedistributedDemurrageToken.__bytecode
def add_minter(self, contract_address, sender_address, address, tx_format=TxFormat.JSONRPC):
enc = ABIContractEncoder()
enc.method('addMinter')
enc.typ(ABIContractType.ADDRESS)
enc.address(address)
data = enc.get()
tx = self.template(sender_address, contract_address, use_nonce=True)
tx = self.set_code(tx, data)
tx = self.finalize(tx, tx_format)
return tx
def mint_to(self, contract_address, sender_address, address, value, tx_format=TxFormat.JSONRPC):
enc = ABIContractEncoder()
enc.method('mintTo')
enc.typ(ABIContractType.ADDRESS)
enc.typ(ABIContractType.UINT256)
enc.address(address)
enc.uint256(value)
data = enc.get()
tx = self.template(sender_address, contract_address, use_nonce=True)
tx = self.set_code(tx, data)
tx = self.finalize(tx, tx_format)
return tx

View File

@ -1,12 +1,15 @@
[metadata] [metadata]
name = sarafu-token name = erc20-demurrage-token
version = 0.0.1a8 version = 0.0.1b1
description = ERC20 token with redistributed continual demurrage description = ERC20 token with redistributed continual demurrage
author = Louis Holbrook author = Louis Holbrook
author_email = dev@holbrook.no author_email = dev@holbrook.no
url = https://gitlab.com/grassrootseconomics/sarafu-token url = https://gitlab.com/grassrootseconomics/sarafu-token
keywords = keywords =
ethereum ethereum
blockchain
cryptocurrency
erc20
classifiers = classifiers =
Programming Language :: Python :: 3 Programming Language :: Python :: 3
Operating System :: OS Independent Operating System :: OS Independent
@ -24,18 +27,14 @@ licence_files =
include_package_data = True include_package_data = True
python_requires = >= 3.6 python_requires = >= 3.6
packages = packages =
sarafu_token erc20_demurrage_token
sarafu_token.runnable erc20_demurrage_token.runnable
install_requires =
chainlib~=0.0.3a1
crypto-dev-signer~=0.4.14b3
[options.package_data] [options.package_data]
* = * =
data/RedistributedDemurrageToken.bin data/DemurrageToken*.bin
data/RedistributedDemurrageToken.json data/DemurrageToken*.json
[options.entry_points] [options.entry_points]
console_scripts = console_scripts =
sarafu-token-deploy = sarafu_token.runnable.deploy:main erc20-demurrage-token-deploy = erc20_demurrage_token.runnable.deploy:main

View File

@ -1,3 +1,3 @@
web3==5.12.2 #web3==5.12.2
eth_tester==0.5.0b3 eth_tester==0.5.0b3
py-evm==0.3.0a20 py-evm==0.3.0a20

78
python/tests/base.py Normal file
View File

@ -0,0 +1,78 @@
# standard imports
import logging
# external imports
from chainlib.eth.unittest.ethtester import EthTesterCase
from chainlib.eth.tx import (
receipt,
)
from chainlib.eth.block import (
block_latest,
block_by_number,
)
from chainlib.eth.nonce import RPCNonceOracle
# local imports
from erc20_demurrage_token import (
DemurrageTokenSettings,
DemurrageToken,
)
logg = logging.getLogger()
#BLOCKTIME = 5 # seconds
TAX_LEVEL = int(10000 * 2) # 2%
# calc "1-(0.98)^(1/518400)" <- 518400 = 30 days of blocks
# 0.00000003897127107225
#PERIOD = int(60/BLOCKTIME) * 60 * 24 * 30 # month
PERIOD = 1
class TestDemurrage(EthTesterCase):
def setUp(self):
super(TestDemurrage, self).setUp()
nonce_oracle = RPCNonceOracle(self.accounts[0], self.rpc)
self.settings = DemurrageTokenSettings()
self.settings.name = 'Foo Token'
self.settings.symbol = 'FOO'
self.settings.decimals = 6
self.settings.demurrage_level = TAX_LEVEL * (10 ** 32)
self.settings.period_minutes = PERIOD
self.settings.sink_address = self.accounts[1]
o = block_latest()
self.start_block = self.rpc.do(o)
o = block_by_number(self.start_block, include_tx=False)
r = self.rpc.do(o)
logg.debug('r {}'.format(r))
try:
self.start_time = int(r['timestamp'], 16)
except TypeError:
self.start_time = int(r['timestamp'])
def tearDown(self):
pass
class TestDemurrageDefault(TestDemurrage):
def setUp(self):
super(TestDemurrageDefault, self).setUp()
nonce_oracle = RPCNonceOracle(self.accounts[0], self.rpc)
c = DemurrageToken(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
(tx_hash, o) = c.constructor(self.accounts[0], self.settings)
r = self.rpc.do(o)
o = receipt(tx_hash)
r = self.rpc.do(o)
self.assertEqual(r['status'], 1)
self.address = r['contract_address']

View File

@ -5,206 +5,173 @@ import json
import logging import logging
import datetime import datetime
# third-party imports # external imports
import web3 from chainlib.eth.constant import ZERO_ADDRESS
import eth_tester from chainlib.eth.nonce import RPCNonceOracle
import eth_abi
# local imports
from erc20_demurrage_token import DemurrageToken
# test imports
from tests.base import TestDemurrageDefault
logging.basicConfig(level=logging.DEBUG) logging.basicConfig(level=logging.DEBUG)
logg = logging.getLogger() logg = logging.getLogger()
logging.getLogger('web3').setLevel(logging.WARNING)
logging.getLogger('eth.vm').setLevel(logging.WARNING)
testdir = os.path.dirname(__file__) testdir = os.path.dirname(__file__)
#BLOCKTIME = 5 # seconds
TAX_LEVEL = int(10000 * 2) # 2%
# calc "1-(0.98)^(1/518400)" <- 518400 = 30 days of blocks
# 0.00000003897127107225
#PERIOD = int(60/BLOCKTIME) * 60 * 24 * 30 # month
PERIOD = 1
class Test(unittest.TestCase):
contract = None
def setUp(self):
eth_params = eth_tester.backends.pyevm.main.get_default_genesis_params({
'gas_limit': 9000000,
})
f = open(os.path.join(testdir, '../../solidity/RedistributedDemurrageToken.bin'), 'r')
self.bytecode = f.read()
f.close()
f = open(os.path.join(testdir, '../../solidity/RedistributedDemurrageToken.json'), 'r')
self.abi = json.load(f)
f.close()
backend = eth_tester.PyEVMBackend(eth_params)
self.eth_tester = eth_tester.EthereumTester(backend)
provider = web3.Web3.EthereumTesterProvider(self.eth_tester)
self.w3 = web3.Web3(provider)
self.sink_address = self.w3.eth.accounts[9]
c = self.w3.eth.contract(abi=self.abi, bytecode=self.bytecode)
tx_hash = c.constructor('Foo Token', 'FOO', 6, TAX_LEVEL * (10 ** 32), PERIOD, self.sink_address).transact({'from': self.w3.eth.accounts[0]})
r = self.w3.eth.getTransactionReceipt(tx_hash)
self.contract = self.w3.eth.contract(abi=self.abi, address=r.contractAddress)
self.start_block = self.w3.eth.blockNumber
b = self.w3.eth.getBlock(self.start_block)
self.start_time = b['timestamp']
def tearDown(self):
pass
class TestBasic(TestDemurrageDefault):
@unittest.skip('foo')
def test_hello(self): def test_hello(self):
self.assertEqual(self.contract.functions.actualPeriod().call(), 1)
self.eth_tester.time_travel(self.start_time + 61) nonce_oracle = RPCNonceOracle(self.accounts[0], self.rpc)
self.assertEqual(self.contract.functions.actualPeriod().call(), 2) c = DemurrageToken(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
o = c.actual_period(self.address, sender_address=self.accounts[0])
r = self.rpc.do(o)
self.backend.time_travel(self.start_time + 61)
o = c.actual_period(self.address, sender_address=self.accounts[0])
r = self.rpc.do(o)
def test_apply_demurrage(self): def test_apply_demurrage(self):
modifier = 10 * (10 ** 37) modifier = 10 * (10 ** 37)
#demurrage_modifier = self.contract.functions.demurrageModifier().call()
#demurrage_modifier &= (1 << 128) - 1 nonce_oracle = RPCNonceOracle(self.accounts[0], self.rpc)
demurrage_amount = self.contract.functions.demurrageAmount().call() c = DemurrageToken(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
#self.assertEqual(modifier, demurrage_modifier)
o = c.demurrage_amount(self.address, sender_address=self.accounts[0])
r = self.rpc.do(o)
demurrage_amount = c.parse_demurrage_amount(r)
self.assertEqual(modifier, demurrage_amount) self.assertEqual(modifier, demurrage_amount)
self.eth_tester.time_travel(self.start_time + 59) self.backend.time_travel(self.start_time + 59)
#demurrage_modifier = self.contract.functions.demurrageModifier().call() o = c.demurrage_amount(self.address, sender_address=self.accounts[0])
demurrage_amount = self.contract.functions.demurrageAmount().call() r = self.rpc.do(o)
#demurrage_modifier &= (1 << 128) - 1 demurrage_amount = c.parse_demurrage_amount(r)
#self.assertEqual(modifier, demurrage_modifier)
self.assertEqual(modifier, demurrage_amount) self.assertEqual(modifier, demurrage_amount)
self.eth_tester.time_travel(self.start_time + 61) self.backend.time_travel(self.start_time + 61)
tx_hash = self.contract.functions.applyDemurrage().transact() (tx_hash, o) = c.apply_demurrage(self.address, sender_address=self.accounts[0])
r = self.w3.eth.getTransactionReceipt(tx_hash) r = self.rpc.do(o)
o = c.demurrage_amount(self.address, sender_address=self.accounts[0])
#demurrage_modifier = self.contract.functions.demurrageModifier().call() r = self.rpc.do(o)
demurrage_amount = self.contract.functions.demurrageAmount().call() demurrage_amount = c.parse_demurrage_amount(r)
#demurrage_modifier &= (1 << 128) - 1 modifier = int(98 * (10 ** 36))
#self.assertEqual(int(98 * (10 ** 36)), demurrage_modifier) self.assertEqual(modifier, demurrage_amount)
self.assertEqual(int(98 * (10 ** 36)), demurrage_amount)
def test_mint(self): # def test_mint(self):
tx_hash = self.contract.functions.mintTo(self.w3.eth.accounts[1], 1024).transact() # tx_hash = self.contract.functions.mintTo(self.w3.eth.accounts[1], 1024).transact()
r = self.w3.eth.getTransactionReceipt(tx_hash) # r = self.w3.eth.getTransactionReceipt(tx_hash)
self.assertEqual(r.status, 1) # self.assertEqual(r.status, 1)
#
balance = self.contract.functions.balanceOf(self.w3.eth.accounts[1]).call() # balance = self.contract.functions.balanceOf(self.w3.eth.accounts[1]).call()
self.assertEqual(balance, 1024) # self.assertEqual(balance, 1024)
#
tx_hash = self.contract.functions.mintTo(self.w3.eth.accounts[1], 976).transact() # tx_hash = self.contract.functions.mintTo(self.w3.eth.accounts[1], 976).transact()
r = self.w3.eth.getTransactionReceipt(tx_hash) # r = self.w3.eth.getTransactionReceipt(tx_hash)
self.assertEqual(r.status, 1) # self.assertEqual(r.status, 1)
#
balance = self.contract.functions.balanceOf(self.w3.eth.accounts[1]).call() # balance = self.contract.functions.balanceOf(self.w3.eth.accounts[1]).call()
self.assertEqual(balance, 2000) # self.assertEqual(balance, 2000)
#
self.eth_tester.time_travel(self.start_time + 61) # self.eth_tester.time_travel(self.start_time + 61)
balance = self.contract.functions.balanceOf(self.w3.eth.accounts[1]).call() # balance = self.contract.functions.balanceOf(self.w3.eth.accounts[1]).call()
self.assertEqual(balance, int(2000 * 0.98)) # self.assertEqual(balance, int(2000 * 0.98))
#
#
def test_minter_control(self): # def test_minter_control(self):
with self.assertRaises(eth_tester.exceptions.TransactionFailed): # with self.assertRaises(eth_tester.exceptions.TransactionFailed):
tx_hash = self.contract.functions.mintTo(self.w3.eth.accounts[2], 1024).transact({'from': self.w3.eth.accounts[1]}) # tx_hash = self.contract.functions.mintTo(self.w3.eth.accounts[2], 1024).transact({'from': self.w3.eth.accounts[1]})
#
with self.assertRaises(eth_tester.exceptions.TransactionFailed): # with self.assertRaises(eth_tester.exceptions.TransactionFailed):
tx_hash = self.contract.functions.addMinter(self.w3.eth.accounts[1]).transact({'from': self.w3.eth.accounts[1]}) # tx_hash = self.contract.functions.addMinter(self.w3.eth.accounts[1]).transact({'from': self.w3.eth.accounts[1]})
#
tx_hash = self.contract.functions.addMinter(self.w3.eth.accounts[1]).transact({'from': self.w3.eth.accounts[0]}) # tx_hash = self.contract.functions.addMinter(self.w3.eth.accounts[1]).transact({'from': self.w3.eth.accounts[0]})
r = self.w3.eth.getTransactionReceipt(tx_hash) # r = self.w3.eth.getTransactionReceipt(tx_hash)
self.assertEqual(r.status, 1) # self.assertEqual(r.status, 1)
#
with self.assertRaises(eth_tester.exceptions.TransactionFailed): # with self.assertRaises(eth_tester.exceptions.TransactionFailed):
tx_hash = self.contract.functions.addMinter(self.w3.eth.accounts[2]).transact({'from': self.w3.eth.accounts[1]}) # tx_hash = self.contract.functions.addMinter(self.w3.eth.accounts[2]).transact({'from': self.w3.eth.accounts[1]})
#
tx_hash = self.contract.functions.mintTo(self.w3.eth.accounts[2], 1024).transact({'from': self.w3.eth.accounts[1]}) # tx_hash = self.contract.functions.mintTo(self.w3.eth.accounts[2], 1024).transact({'from': self.w3.eth.accounts[1]})
#
with self.assertRaises(eth_tester.exceptions.TransactionFailed): # with self.assertRaises(eth_tester.exceptions.TransactionFailed):
tx_hash = self.contract.functions.addMinter(self.w3.eth.accounts[1]).transact({'from': self.w3.eth.accounts[2]}) # tx_hash = self.contract.functions.addMinter(self.w3.eth.accounts[1]).transact({'from': self.w3.eth.accounts[2]})
#
tx_hash = self.contract.functions.removeMinter(self.w3.eth.accounts[1]).transact({'from': self.w3.eth.accounts[1]}) # tx_hash = self.contract.functions.removeMinter(self.w3.eth.accounts[1]).transact({'from': self.w3.eth.accounts[1]})
r = self.w3.eth.getTransactionReceipt(tx_hash) # r = self.w3.eth.getTransactionReceipt(tx_hash)
self.assertEqual(r.status, 1) # self.assertEqual(r.status, 1)
#
with self.assertRaises(eth_tester.exceptions.TransactionFailed): # with self.assertRaises(eth_tester.exceptions.TransactionFailed):
tx_hash = self.contract.functions.mintTo(self.w3.eth.accounts[2], 1024).transact({'from': self.w3.eth.accounts[1]}) # tx_hash = self.contract.functions.mintTo(self.w3.eth.accounts[2], 1024).transact({'from': self.w3.eth.accounts[1]})
#
#
def test_base_amount(self): # def test_base_amount(self):
tx_hash = self.contract.functions.mintTo(self.w3.eth.accounts[1], 1000).transact() # tx_hash = self.contract.functions.mintTo(self.w3.eth.accounts[1], 1000).transact()
r = self.w3.eth.getTransactionReceipt(tx_hash) # r = self.w3.eth.getTransactionReceipt(tx_hash)
self.assertEqual(r.status, 1) # self.assertEqual(r.status, 1)
#
self.eth_tester.time_travel(self.start_time + 61) # self.eth_tester.time_travel(self.start_time + 61)
#
self.contract.functions.applyDemurrage().transact() # self.contract.functions.applyDemurrage().transact()
#demurrage_modifier = self.contract.functions.demurrageModifier().call() # #demurrage_modifier = self.contract.functions.demurrageModifier().call()
#demurrage_amount = self.contract.functions.toDemurrageAmount(demurrage_modifier).call() # #demurrage_amount = self.contract.functions.toDemurrageAmount(demurrage_modifier).call()
demurrage_amount = self.contract.functions.demurrageAmount().call() # demurrage_amount = self.contract.functions.demurrageAmount().call()
#
a = self.contract.functions.toBaseAmount(1000).call(); # a = self.contract.functions.toBaseAmount(1000).call();
self.assertEqual(a, 1020) # self.assertEqual(a, 1020)
#
#
def test_transfer(self): # def test_transfer(self):
tx_hash = self.contract.functions.mintTo(self.w3.eth.accounts[1], 1024).transact() # tx_hash = self.contract.functions.mintTo(self.w3.eth.accounts[1], 1024).transact()
r = self.w3.eth.getTransactionReceipt(tx_hash) # r = self.w3.eth.getTransactionReceipt(tx_hash)
self.assertEqual(r.status, 1) # self.assertEqual(r.status, 1)
#
tx_hash = self.contract.functions.transfer(self.w3.eth.accounts[2], 500).transact({'from': self.w3.eth.accounts[1]}) # tx_hash = self.contract.functions.transfer(self.w3.eth.accounts[2], 500).transact({'from': self.w3.eth.accounts[1]})
r = self.w3.eth.getTransactionReceipt(tx_hash) # r = self.w3.eth.getTransactionReceipt(tx_hash)
self.assertEqual(r.status, 1) # self.assertEqual(r.status, 1)
logg.debug('tx {}'.format(r)) # logg.debug('tx {}'.format(r))
#
balance_alice = self.contract.functions.balanceOf(self.w3.eth.accounts[1]).call() # balance_alice = self.contract.functions.balanceOf(self.w3.eth.accounts[1]).call()
self.assertEqual(balance_alice, 524) # self.assertEqual(balance_alice, 524)
#
balance_bob = self.contract.functions.balanceOf(self.w3.eth.accounts[2]).call() # balance_bob = self.contract.functions.balanceOf(self.w3.eth.accounts[2]).call()
self.assertEqual(balance_bob, 500) # self.assertEqual(balance_bob, 500)
#
tx_hash = self.contract.functions.transfer(self.w3.eth.accounts[2], 500).transact({'from': self.w3.eth.accounts[1]}) # tx_hash = self.contract.functions.transfer(self.w3.eth.accounts[2], 500).transact({'from': self.w3.eth.accounts[1]})
r = self.w3.eth.getTransactionReceipt(tx_hash) # r = self.w3.eth.getTransactionReceipt(tx_hash)
self.assertEqual(r.status, 1) # self.assertEqual(r.status, 1)
logg.debug('tx {}'.format(r)) # logg.debug('tx {}'.format(r))
#
#
def test_transfer_from(self): # def test_transfer_from(self):
tx_hash = self.contract.functions.mintTo(self.w3.eth.accounts[1], 1024).transact() # tx_hash = self.contract.functions.mintTo(self.w3.eth.accounts[1], 1024).transact()
r = self.w3.eth.getTransactionReceipt(tx_hash) # r = self.w3.eth.getTransactionReceipt(tx_hash)
self.assertEqual(r.status, 1) # self.assertEqual(r.status, 1)
#
tx_hash = self.contract.functions.approve(self.w3.eth.accounts[2], 500).transact({'from': self.w3.eth.accounts[1]}) # tx_hash = self.contract.functions.approve(self.w3.eth.accounts[2], 500).transact({'from': self.w3.eth.accounts[1]})
r = self.w3.eth.getTransactionReceipt(tx_hash) # r = self.w3.eth.getTransactionReceipt(tx_hash)
self.assertEqual(r.status, 1) # self.assertEqual(r.status, 1)
logg.debug('tx {}'.format(r)) # logg.debug('tx {}'.format(r))
#
balance_alice = self.contract.functions.balanceOf(self.w3.eth.accounts[1]).call() # balance_alice = self.contract.functions.balanceOf(self.w3.eth.accounts[1]).call()
self.assertEqual(balance_alice, 1024) # self.assertEqual(balance_alice, 1024)
#
tx_hash = self.contract.functions.transferFrom(self.w3.eth.accounts[1], self.w3.eth.accounts[3], 500).transact({'from': self.w3.eth.accounts[2]}) # tx_hash = self.contract.functions.transferFrom(self.w3.eth.accounts[1], self.w3.eth.accounts[3], 500).transact({'from': self.w3.eth.accounts[2]})
r = self.w3.eth.getTransactionReceipt(tx_hash) # r = self.w3.eth.getTransactionReceipt(tx_hash)
self.assertEqual(r.status, 1) # self.assertEqual(r.status, 1)
logg.debug('tx {}'.format(r)) # logg.debug('tx {}'.format(r))
#
balance_alice = self.contract.functions.balanceOf(self.w3.eth.accounts[1]).call() # balance_alice = self.contract.functions.balanceOf(self.w3.eth.accounts[1]).call()
self.assertEqual(balance_alice, 524) # self.assertEqual(balance_alice, 524)
#
balance_alice = self.contract.functions.balanceOf(self.w3.eth.accounts[3]).call() # balance_alice = self.contract.functions.balanceOf(self.w3.eth.accounts[3]).call()
self.assertEqual(balance_alice, 500) # self.assertEqual(balance_alice, 500)
if __name__ == '__main__': if __name__ == '__main__':

View File

@ -1,9 +1,9 @@
SOLC = /usr/bin/solc SOLC = /usr/bin/solc
all: all:
$(SOLC) RedistributedDemurrageToken.sol --abi --evm-version byzantium | awk 'NR>3' > RedistributedDemurrageToken.json $(SOLC) DemurrageTokenMultiNocap.sol --abi --evm-version byzantium | awk 'NR>3' > DemurrageTokenMultiNocap.json
$(SOLC) RedistributedDemurrageToken.sol --bin --evm-version byzantium | awk 'NR>3' > RedistributedDemurrageToken.bin $(SOLC) DemurrageTokenMultiNocap.sol --bin --evm-version byzantium | awk 'NR>3' > DemurrageTokenMultiNocap.bin
truncate -s -1 RedistributedDemurrageToken.bin truncate -s -1 DemurrageTokenMultiNocap.bin
test: all test: all
python ../python/tests/test_basic.py python ../python/tests/test_basic.py
@ -11,6 +11,6 @@ test: all
python ../python/tests/test_redistribution.py python ../python/tests/test_redistribution.py
install: all install: all
cp -v RedistributedDemurrageToken.{json,bin} ../python/sarafu_token/data/ cp -v DemurrageTokenMultiNocap.{json,bin} ../python/sarafu_token/data/
.PHONY: test install .PHONY: test install