Add redistribution single minute demurrage test
This commit is contained in:
parent
399e24764a
commit
e47720fa04
@ -148,10 +148,10 @@ class DemurrageTokenSimulation:
|
|||||||
def get_period(self):
|
def get_period(self):
|
||||||
return self.period
|
return self.period
|
||||||
|
|
||||||
def get_demurrage_modifier(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)
|
||||||
return float(self.caller_contract.parse_demurrage_amount(r) / (10 ** 38))
|
return float(self.caller_contract.parse_demurrage_amount(r) / (10 ** 40))
|
||||||
|
|
||||||
|
|
||||||
def from_units(self, v):
|
def from_units(self, v):
|
||||||
|
@ -16,7 +16,7 @@ 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**40))
|
settings.demurrage_level = int(decay_per_minute*(10**40))
|
||||||
settings.period_minutes = 10800 # 1 week in minutes
|
settings.period_minutes = 1 # 1 week in minutes
|
||||||
chain = 'evm:foochain:42'
|
chain = 'evm:foochain:42'
|
||||||
cap = (10 ** 6) * (10 ** 12)
|
cap = (10 ** 6) * (10 ** 12)
|
||||||
|
|
||||||
@ -55,15 +55,15 @@ 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))
|
||||||
|
|
||||||
|
|
||||||
contract_demurrage = 1 - sim.get_demurrage_modifier() # demurrage in percent (float)
|
contract_demurrage = 1 - sim.get_demurrage() # demurrage in percent (float)
|
||||||
frontend_demurrage = ((1 - decay_per_minute) ** minutes / 100) # corresponding demurrage modifier (float)
|
frontend_demurrage = 1.0 - ((1 - decay_per_minute) ** minutes) # corresponding demurrage modifier (float)
|
||||||
demurrage_delta = contract_demurrage - frontend_demurrage # difference between demurrage in contract and demurrage calculated in frontend
|
demurrage_delta = contract_demurrage - frontend_demurrage # difference between demurrage in contract and demurrage calculated in frontend
|
||||||
|
|
||||||
alice_checksum = 50000000 - (50000000 * frontend_demurrage) + (200000000 * frontend_demurrage) # alice's balance calculated with frontend demurrage
|
alice_checksum = 50000000 - (50000000 * frontend_demurrage) + (200000000 * frontend_demurrage) # alice's balance calculated with frontend demurrage
|
||||||
print("""alice frontend balance {}
|
print("""alice frontend balance {}
|
||||||
alice contract balance {}
|
alice contract balance {}
|
||||||
frontend demurrage {}
|
frontend demurrage {:f}
|
||||||
contract demurrage {}
|
contract demurrage {:f}
|
||||||
demurrage delta {}""".format(
|
demurrage delta {}""".format(
|
||||||
alice_checksum,
|
alice_checksum,
|
||||||
sim.balance(alice),
|
sim.balance(alice),
|
||||||
|
@ -163,3 +163,56 @@ class TestDemurrageCap(TestDemurrage):
|
|||||||
self.deploy(c, self.mode)
|
self.deploy(c, self.mode)
|
||||||
|
|
||||||
logg.info('deployed with mode {}'.format(self.mode))
|
logg.info('deployed with mode {}'.format(self.mode))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class TestDemurrageUnit(TestDemurrage):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(TestDemurrage, self).setUp()
|
||||||
|
|
||||||
|
self.tax_level = 50
|
||||||
|
self.period_seconds = 60
|
||||||
|
|
||||||
|
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 = self.tax_level * (10 ** 32)
|
||||||
|
self.settings.period_minutes = int(self.period_seconds/60)
|
||||||
|
self.settings.sink_address = self.accounts[9]
|
||||||
|
self.sink_address = self.settings.sink_address
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.start_time = int(r['timestamp'], 16)
|
||||||
|
except TypeError:
|
||||||
|
self.start_time = int(r['timestamp'])
|
||||||
|
|
||||||
|
self.default_supply = 1000000000000
|
||||||
|
self.default_supply_cap = int(self.default_supply * 10)
|
||||||
|
|
||||||
|
nonce_oracle = RPCNonceOracle(self.accounts[0], self.rpc)
|
||||||
|
c = DemurrageToken(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
|
||||||
|
|
||||||
|
self.mode = os.environ.get('ERC20_DEMURRAGE_TOKEN_TEST_MODE')
|
||||||
|
unit_valid_modes = [
|
||||||
|
'SingleNocap',
|
||||||
|
'SingleCap',
|
||||||
|
]
|
||||||
|
if self.mode != None:
|
||||||
|
if self.mode not in unit_valid_modes:
|
||||||
|
raise ValueError('Invalid mode "{}" for "unit" contract tests, valid are {}'.format(self.mode, unit_valid_modes))
|
||||||
|
else:
|
||||||
|
self.mode = 'SingleNocap'
|
||||||
|
logg.debug('executing test setup unit mode {}'.format(self.mode))
|
||||||
|
|
||||||
|
self.deploy(c, self.mode)
|
||||||
|
|
||||||
|
logg.info('deployed with mode {}'.format(self.mode))
|
||||||
|
138
python/tests/test_redistribution_unit.py
Normal file
138
python/tests/test_redistribution_unit.py
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
import os
|
||||||
|
import unittest
|
||||||
|
import json
|
||||||
|
import logging
|
||||||
|
|
||||||
|
# external imports
|
||||||
|
from chainlib.eth.constant import ZERO_ADDRESS
|
||||||
|
from chainlib.eth.nonce import RPCNonceOracle
|
||||||
|
from chainlib.eth.tx import receipt
|
||||||
|
from chainlib.eth.block import (
|
||||||
|
block_latest,
|
||||||
|
block_by_number,
|
||||||
|
)
|
||||||
|
from chainlib.eth.address import to_checksum_address
|
||||||
|
from hexathon import (
|
||||||
|
strip_0x,
|
||||||
|
add_0x,
|
||||||
|
)
|
||||||
|
|
||||||
|
# local imports
|
||||||
|
from erc20_demurrage_token import DemurrageToken
|
||||||
|
|
||||||
|
# test imports
|
||||||
|
from tests.base import TestDemurrageUnit
|
||||||
|
|
||||||
|
logging.basicConfig(level=logging.DEBUG)
|
||||||
|
logg = logging.getLogger()
|
||||||
|
|
||||||
|
testdir = os.path.dirname(__file__)
|
||||||
|
|
||||||
|
|
||||||
|
class TestRedistribution(TestDemurrageUnit):
|
||||||
|
|
||||||
|
def test_single_step(self):
|
||||||
|
nonce_oracle = RPCNonceOracle(self.accounts[0], self.rpc)
|
||||||
|
c = DemurrageToken(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
|
||||||
|
|
||||||
|
mint_amount = 100000000
|
||||||
|
|
||||||
|
(tx_hash, o) = c.mint_to(self.address, self.accounts[0], self.accounts[1], mint_amount)
|
||||||
|
self.rpc.do(o)
|
||||||
|
|
||||||
|
self.backend.time_travel(self.start_time + self.period_seconds)
|
||||||
|
|
||||||
|
(tx_hash, o) = c.change_period(self.address, self.accounts[0])
|
||||||
|
self.rpc.do(o)
|
||||||
|
|
||||||
|
expected_balance = int(mint_amount - ((self.tax_level / 1000000) * mint_amount))
|
||||||
|
|
||||||
|
o = c.balance_of(self.address, self.accounts[1], sender_address=self.accounts[0])
|
||||||
|
r = self.rpc.do(o)
|
||||||
|
balance = c.parse_balance_of(r)
|
||||||
|
|
||||||
|
self.assertEqual(balance, expected_balance)
|
||||||
|
|
||||||
|
|
||||||
|
def test_single_step_multi(self):
|
||||||
|
nonce_oracle = RPCNonceOracle(self.accounts[0], self.rpc)
|
||||||
|
c = DemurrageToken(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
|
||||||
|
|
||||||
|
mint_amount = 100000000
|
||||||
|
|
||||||
|
for i in range(3):
|
||||||
|
(tx_hash, o) = c.mint_to(self.address, self.accounts[0], self.accounts[i+1], mint_amount)
|
||||||
|
self.rpc.do(o)
|
||||||
|
|
||||||
|
self.backend.time_travel(self.start_time + self.period_seconds)
|
||||||
|
|
||||||
|
(tx_hash, o) = c.change_period(self.address, self.accounts[0])
|
||||||
|
self.rpc.do(o)
|
||||||
|
|
||||||
|
expected_balance = int(mint_amount - ((self.tax_level / 1000000) * mint_amount))
|
||||||
|
|
||||||
|
for i in range(3):
|
||||||
|
o = c.balance_of(self.address, self.accounts[i+1], sender_address=self.accounts[0])
|
||||||
|
r = self.rpc.do(o)
|
||||||
|
balance = c.parse_balance_of(r)
|
||||||
|
self.assertEqual(balance, expected_balance)
|
||||||
|
|
||||||
|
|
||||||
|
def test_single_step_transfer(self):
|
||||||
|
nonce_oracle = RPCNonceOracle(self.accounts[0], self.rpc)
|
||||||
|
c = DemurrageToken(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
|
||||||
|
|
||||||
|
mint_amount = 100000000
|
||||||
|
half_mint_amount = int(mint_amount / 2)
|
||||||
|
|
||||||
|
(tx_hash, o) = c.mint_to(self.address, self.accounts[0], self.accounts[1], mint_amount)
|
||||||
|
self.rpc.do(o)
|
||||||
|
|
||||||
|
(tx_hash, o) = c.mint_to(self.address, self.accounts[0], self.accounts[2], mint_amount)
|
||||||
|
self.rpc.do(o)
|
||||||
|
|
||||||
|
nonce_oracle = RPCNonceOracle(self.accounts[1], self.rpc)
|
||||||
|
c = DemurrageToken(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
|
||||||
|
(tx_hash, o) = c.transfer(self.address, self.accounts[1], self.accounts[3], half_mint_amount)
|
||||||
|
self.rpc.do(o)
|
||||||
|
|
||||||
|
self.backend.time_travel(self.start_time + self.period_seconds)
|
||||||
|
|
||||||
|
(tx_hash, o) = c.change_period(self.address, self.accounts[1])
|
||||||
|
self.rpc.do(o)
|
||||||
|
|
||||||
|
demurrage_amount = int((self.tax_level / 1000000) * mint_amount)
|
||||||
|
|
||||||
|
expected_balance = mint_amount - demurrage_amount
|
||||||
|
o = c.balance_of(self.address, self.accounts[2], sender_address=self.accounts[0])
|
||||||
|
r = self.rpc.do(o)
|
||||||
|
balance = c.parse_balance_of(r)
|
||||||
|
self.assertEqual(balance, expected_balance)
|
||||||
|
|
||||||
|
half_demurrage_amount = int((self.tax_level / 1000000) * half_mint_amount)
|
||||||
|
|
||||||
|
expected_balance = half_mint_amount - half_demurrage_amount
|
||||||
|
o = c.balance_of(self.address, self.accounts[1], sender_address=self.accounts[0])
|
||||||
|
r = self.rpc.do(o)
|
||||||
|
balance = c.parse_balance_of(r)
|
||||||
|
self.assertEqual(balance, expected_balance)
|
||||||
|
|
||||||
|
o = c.balance_of(self.address, self.accounts[3], sender_address=self.accounts[0])
|
||||||
|
r = self.rpc.do(o)
|
||||||
|
balance = c.parse_balance_of(r)
|
||||||
|
self.assertEqual(balance, expected_balance)
|
||||||
|
|
||||||
|
o = c.total_supply(self.address, sender_address=self.accounts[0])
|
||||||
|
r = self.rpc.do(o)
|
||||||
|
supply = c.parse_total_supply(r)
|
||||||
|
|
||||||
|
expected_balance = int(supply * (self.tax_level / 1000000))
|
||||||
|
|
||||||
|
o = c.balance_of(self.address, self.sink_address, sender_address=self.accounts[0])
|
||||||
|
r = self.rpc.do(o)
|
||||||
|
balance = c.parse_balance_of(r)
|
||||||
|
self.assertEqual(balance, expected_balance)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
Reference in New Issue
Block a user