bug: Wrong redistribution amount + limited demurrage apply

This commit is contained in:
Louis Holbrook
2022-03-02 09:01:50 +00:00
parent d0c02eadbf
commit db56e0d33f
14 changed files with 185 additions and 17 deletions

View File

@@ -1,4 +1,7 @@
- 0.0.2-pending
- 0.0.9
* Fix wrong redistribution calculation in single nocap
[...]
- 0.0.2
* Move to chainlib-eth
- 0.0.1-unreleased
* Interface for redistributed and non-redistributed, with or without cap

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -325,8 +325,19 @@ class DemurrageToken(ERC20):
return o
def apply_demurrage(self, contract_address, sender_address):
return self.transact_noarg('applyDemurrage', contract_address, sender_address)
def apply_demurrage(self, contract_address, sender_address, limit=0, tx_format=TxFormat.JSONRPC):
if limit == 0:
return self.transact_noarg('applyDemurrage', contract_address, sender_address)
enc = ABIContractEncoder()
enc.method('applyDemurrageLimited')
enc.typ(ABIContractType.UINT256)
enc.uint256(limit)
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 change_period(self, contract_address, sender_address):

View File

@@ -1,3 +1,3 @@
chainlib-eth~=0.0.15
eth-erc20~=0.1.5
funga-eth~=0.5.1
chainlib-eth~=0.0.27
eth-erc20~=0.1.10
funga-eth~=0.5.6

View File

@@ -1,6 +1,6 @@
[metadata]
name = erc20-demurrage-token
version = 0.0.8
version = 0.0.10
description = ERC20 token with redistributed continual demurrage
author = Louis Holbrook
author_email = dev@holbrook.no

View File

@@ -54,6 +54,32 @@ class TestBasic(TestDemurrageDefault):
self.assertEqual(balance, 1024)
def test_apply_demurrage_limited(self):
modifier = (10 ** 28)
nonce_oracle = RPCNonceOracle(self.accounts[0], self.rpc)
c = DemurrageToken(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
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.backend.time_travel(self.start_time + 120)
(tx_hash, o) = c.apply_demurrage(self.address, sender_address=self.accounts[0], limit=1)
r = self.rpc.do(o)
o = receipt(tx_hash)
r = self.rpc.do(o)
self.assertEqual(r['status'], 1)
o = c.demurrage_amount(self.address, sender_address=self.accounts[0])
r = self.rpc.do(o)
demurrage_amount = c.parse_demurrage_amount(r)
modifier_base = 1000000 - self.tax_level
modifier = int(modifier_base * (10 ** 22)) # 38 decimal places minus 6 (1000000)
self.assertEqual(modifier, demurrage_amount)
def test_apply_demurrage(self):
modifier = (10 ** 28)
@@ -93,7 +119,6 @@ class TestBasic(TestDemurrageDefault):
r = self.rpc.do(o)
demurrage_amount = c.parse_demurrage_amount(r)
modifier_base = 1000000 - self.tax_level
logg.debug('modifier base {}'.format(modifier_base))
modifier = int(modifier_base * (10 ** 22)) # 38 decimal places minus 6 (1000000)
self.assertEqual(modifier, demurrage_amount)
@@ -107,10 +132,11 @@ class TestBasic(TestDemurrageDefault):
r = self.rpc.do(o)
demurrage_amount = c.parse_demurrage_amount(r)
modifier_base = ((1000000 - self.tax_level) / 1000000) ** 10
logg.warning('mod base {}'.format(modifier_base))
modifier = int(modifier_base * (10 ** 12))
rounding_tolerance_nano = 4000000 # 0.000004% precision
demurrage_amount_truncate = int(demurrage_amount / (10 ** 26)) # equals 12 decimal places
demurrage_amount_truncate = int(demurrage_amount / (10 ** 16)) # equals 38 decimal places - 14 for the modifier magniture - 2 for percent int calc + 6 for token decimals <- TODO verify this calc
self.assertGreaterEqual(modifier, demurrage_amount_truncate - rounding_tolerance_nano)
self.assertLessEqual(modifier, demurrage_amount_truncate)

View File

@@ -7,7 +7,15 @@ 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.tx import (
receipt,
TxFactory,
TxFormat,
)
from chainlib.eth.contract import (
ABIContractEncoder,
ABIContractType,
)
# local imports
from erc20_demurrage_token import DemurrageToken
@@ -103,5 +111,90 @@ class TestPeriod(TestDemurrageDefault):
self.assertEqual(modifier, period)
def test_change_sink(self):
nonce_oracle = RPCNonceOracle(self.accounts[0], self.rpc)
c = DemurrageToken(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
o = c.balance_of(self.address, ZERO_ADDRESS, sender_address=self.accounts[0])
r = self.rpc.do(o)
balance = c.parse_balance_of(r)
self.assertEqual(balance, 0)
(tx_hash, o) = c.mint_to(self.address, self.accounts[0], self.accounts[1], 102400000000)
r = self.rpc.do(o)
o = receipt(tx_hash)
r = self.rpc.do(o)
self.assertEqual(r['status'], 1)
self.backend.time_travel(self.start_time + self.period_seconds + 1)
c = DemurrageToken(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
(tx_hash, o) = c.change_period(self.address, self.accounts[0])
r = self.rpc.do(o)
o = receipt(tx_hash)
r = self.rpc.do(o)
self.assertEqual(r['status'], 1)
o = c.balance_of(self.address, ZERO_ADDRESS, sender_address=self.accounts[0])
r = self.rpc.do(o)
balance = c.parse_balance_of(r)
self.assertGreater(balance, 0)
old_sink_balance = 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, 0)
nonce_oracle = RPCNonceOracle(self.accounts[5], self.rpc)
c = TxFactory(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
enc = ABIContractEncoder()
enc.method('setSinkAddress')
enc.typ(ABIContractType.ADDRESS)
enc.address(self.accounts[3])
data = enc.get()
o = c.template(self.accounts[5], self.address, use_nonce=True)
o = c.set_code(o, data)
(tx_hash, o) = c.finalize(o, TxFormat.JSONRPC)
r = self.rpc.do(o)
o = receipt(tx_hash)
r = self.rpc.do(o)
self.assertEqual(r['status'], 0)
nonce_oracle = RPCNonceOracle(self.accounts[0], self.rpc)
c = TxFactory(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
enc = ABIContractEncoder()
enc.method('setSinkAddress')
enc.typ(ABIContractType.ADDRESS)
enc.address(self.accounts[3])
data = enc.get()
o = c.template(self.accounts[0], self.address, use_nonce=True)
o = c.set_code(o, data)
(tx_hash, o) = c.finalize(o, TxFormat.JSONRPC)
r = self.rpc.do(o)
o = receipt(tx_hash)
r = self.rpc.do(o)
self.assertEqual(r['status'], 1)
self.backend.time_travel(self.start_time + (self.period_seconds * 2) + 1)
c = DemurrageToken(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
(tx_hash, o) = c.change_period(self.address, self.accounts[0])
r = self.rpc.do(o)
o = receipt(tx_hash)
r = self.rpc.do(o)
self.assertEqual(r['status'], 1)
o = c.balance_of(self.address, ZERO_ADDRESS, sender_address=self.accounts[0])
r = self.rpc.do(o)
balance = c.parse_balance_of(r)
self.assertLess(balance, old_sink_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.assertGreater(balance, 0)
if __name__ == '__main__':
unittest.main()