mirror of
git://holbrook.no/erc20-demurrage-token
synced 2024-11-25 17:26:45 +01:00
Keep cumulative sink total in state and deduct from upcoming demurrage
This commit is contained in:
parent
18ee9c5f9b
commit
31faa78346
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -454,16 +454,14 @@ class DemurrageToken(ERC20):
|
|||||||
return o
|
return o
|
||||||
|
|
||||||
|
|
||||||
def get_distribution_from_redistribution(self, contract_address, redistribution, redistribution_previous, sender_address=ZERO_ADDRESS, id_generator=None):
|
def get_distribution_from_redistribution(self, contract_address, redistribution, sender_address=ZERO_ADDRESS, id_generator=None):
|
||||||
j = JSONRPCRequest(id_generator)
|
j = JSONRPCRequest(id_generator)
|
||||||
o = j.template()
|
o = j.template()
|
||||||
o['method'] = 'eth_call'
|
o['method'] = 'eth_call'
|
||||||
enc = ABIContractEncoder()
|
enc = ABIContractEncoder()
|
||||||
enc.method('getDistributionFromRedistribution')
|
enc.method('getDistributionFromRedistribution')
|
||||||
enc.typ(ABIContractType.BYTES32)
|
enc.typ(ABIContractType.BYTES32)
|
||||||
enc.typ(ABIContractType.BYTES32)
|
|
||||||
enc.bytes32(redistribution)
|
enc.bytes32(redistribution)
|
||||||
enc.bytes32(redistribution_previous)
|
|
||||||
data = add_0x(enc.get())
|
data = add_0x(enc.get())
|
||||||
tx = self.template(sender_address, contract_address)
|
tx = self.template(sender_address, contract_address)
|
||||||
tx = self.set_code(tx, data)
|
tx = self.set_code(tx, data)
|
||||||
|
@ -32,7 +32,7 @@ testdir = os.path.dirname(__file__)
|
|||||||
class TestRedistribution(TestDemurrageDefault):
|
class TestRedistribution(TestDemurrageDefault):
|
||||||
|
|
||||||
|
|
||||||
def test_redistribution_boundaries(self):
|
def test_redistribution_periods(self):
|
||||||
nonce_oracle = RPCNonceOracle(self.accounts[0], self.rpc)
|
nonce_oracle = RPCNonceOracle(self.accounts[0], self.rpc)
|
||||||
c = DemurrageToken(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
|
c = DemurrageToken(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
|
||||||
|
|
||||||
@ -42,48 +42,93 @@ class TestRedistribution(TestDemurrageDefault):
|
|||||||
(tx_hash, o) = c.mint_to(self.address, self.accounts[0], self.accounts[0], supply)
|
(tx_hash, o) = c.mint_to(self.address, self.accounts[0], self.accounts[0], supply)
|
||||||
self.rpc.do(o)
|
self.rpc.do(o)
|
||||||
|
|
||||||
o = c.balance_of(self.address, self.sink_address, sender_address=self.accounts[0])
|
for i in range(1, 10):
|
||||||
r = self.rpc.do(o)
|
logg.debug('execute time travel to period {}'.format(i))
|
||||||
balance = c.parse_balance(r)
|
self.backend.time_travel(self.start_time + (self.period_seconds * i))
|
||||||
logg.debug('balance before {} supply {}'.format(balance, supply))
|
|
||||||
|
|
||||||
self.backend.time_travel(self.start_time + self.period_seconds)
|
|
||||||
(tx_hash, o) = c.change_period(self.address, self.accounts[0])
|
(tx_hash, o) = c.change_period(self.address, self.accounts[0])
|
||||||
r = self.rpc.do(o)
|
self.rpc.do(o)
|
||||||
|
|
||||||
o = receipt(tx_hash)
|
o = receipt(tx_hash)
|
||||||
r = self.rpc.do(o)
|
r = self.rpc.do(o)
|
||||||
self.assertEqual(r['status'], 1)
|
self.assertEqual(r['status'], 1)
|
||||||
|
|
||||||
o = c.redistributions(self.address, 1, sender_address=self.accounts[0])
|
o = c.redistributions(self.address, i, sender_address=self.accounts[0])
|
||||||
|
redistribution = self.rpc.do(o)
|
||||||
|
|
||||||
|
o = c.to_redistribution_demurrage_modifier(self.address, redistribution, sender_address=self.accounts[0])
|
||||||
r = self.rpc.do(o)
|
r = self.rpc.do(o)
|
||||||
oo = c.to_redistribution_supply(self.address, r, sender_address=self.accounts[0])
|
demurrage = c.parse_to_redistribution_item(r)
|
||||||
rr = self.rpc.do(oo)
|
|
||||||
oo = c.to_redistribution_demurrage_modifier(self.address, r, sender_address=self.accounts[0])
|
o = c.redistributions(self.address, i-1, sender_address=self.accounts[0])
|
||||||
rr = self.rpc.do(oo)
|
redistribution = self.rpc.do(o)
|
||||||
|
|
||||||
|
o = c.to_redistribution_demurrage_modifier(self.address, redistribution, sender_address=self.accounts[0])
|
||||||
|
r = self.rpc.do(o)
|
||||||
|
demurrage_previous = c.parse_to_redistribution_item(r)
|
||||||
|
|
||||||
o = c.balance_of(self.address, self.sink_address, sender_address=self.accounts[0])
|
o = c.balance_of(self.address, self.sink_address, sender_address=self.accounts[0])
|
||||||
r = self.rpc.do(o)
|
r = self.rpc.do(o)
|
||||||
balance = c.parse_balance(r)
|
balance_sink = c.parse_balance(r)
|
||||||
|
|
||||||
self.backend.time_travel(self.start_time + self.period_seconds * 2 + 1)
|
o = c.balance_of(self.address, self.accounts[0], sender_address=self.accounts[0])
|
||||||
(tx_hash, o) = c.change_period(self.address, self.accounts[0])
|
|
||||||
r = self.rpc.do(o)
|
r = self.rpc.do(o)
|
||||||
|
balance_minter = c.parse_balance(r)
|
||||||
|
|
||||||
o = receipt(tx_hash)
|
logg.debug('testing sink {} mint {} adds up to supply {} with demurrage between {} and {}'.format(balance_sink, balance_minter, supply, demurrage_previous, demurrage))
|
||||||
r = self.rpc.do(o)
|
|
||||||
self.assertEqual(r['status'], 1)
|
|
||||||
|
|
||||||
o = c.redistributions(self.address, 2, sender_address=self.accounts[0])
|
self.assert_within_lower(balance_minter + balance_sink, supply, 0.001)
|
||||||
r = self.rpc.do(o)
|
|
||||||
oo = c.to_redistribution_supply(self.address, r, sender_address=self.accounts[0])
|
|
||||||
rr = self.rpc.do(oo)
|
|
||||||
oo = c.to_redistribution_demurrage_modifier(self.address, r, sender_address=self.accounts[0])
|
|
||||||
rr = self.rpc.do(oo)
|
|
||||||
|
|
||||||
o = c.balance_of(self.address, self.sink_address, sender_address=self.accounts[0])
|
# def test_redistribution_boundaries(self):
|
||||||
r = self.rpc.do(o)
|
# nonce_oracle = RPCNonceOracle(self.accounts[0], self.rpc)
|
||||||
balance = c.parse_balance(r)
|
# c = DemurrageToken(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
|
||||||
|
#
|
||||||
|
# demurrage = (1 - (self.tax_level / 1000000)) * (10**28)
|
||||||
|
# supply = self.default_supply
|
||||||
|
#
|
||||||
|
# (tx_hash, o) = c.mint_to(self.address, self.accounts[0], self.accounts[0], supply)
|
||||||
|
# self.rpc.do(o)
|
||||||
|
#
|
||||||
|
# o = c.balance_of(self.address, self.sink_address, sender_address=self.accounts[0])
|
||||||
|
# r = self.rpc.do(o)
|
||||||
|
# balance = c.parse_balance(r)
|
||||||
|
# logg.debug('balance before {} supply {}'.format(balance, supply))
|
||||||
|
#
|
||||||
|
# self.backend.time_travel(self.start_time + self.period_seconds)
|
||||||
|
# (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.redistributions(self.address, 1, sender_address=self.accounts[0])
|
||||||
|
# r = self.rpc.do(o)
|
||||||
|
# oo = c.to_redistribution_supply(self.address, r, sender_address=self.accounts[0])
|
||||||
|
# rr = self.rpc.do(oo)
|
||||||
|
# oo = c.to_redistribution_demurrage_modifier(self.address, r, sender_address=self.accounts[0])
|
||||||
|
# rr = self.rpc.do(oo)
|
||||||
|
#
|
||||||
|
# o = c.balance_of(self.address, self.sink_address, sender_address=self.accounts[0])
|
||||||
|
# r = self.rpc.do(o)
|
||||||
|
# balance = c.parse_balance(r)
|
||||||
|
#
|
||||||
|
# self.backend.time_travel(self.start_time + self.period_seconds * 2 + 1)
|
||||||
|
# (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.redistributions(self.address, 2, sender_address=self.accounts[0])
|
||||||
|
# r = self.rpc.do(o)
|
||||||
|
# oo = c.to_redistribution_supply(self.address, r, sender_address=self.accounts[0])
|
||||||
|
# rr = self.rpc.do(oo)
|
||||||
|
# oo = c.to_redistribution_demurrage_modifier(self.address, r, sender_address=self.accounts[0])
|
||||||
|
# rr = self.rpc.do(oo)
|
||||||
|
#
|
||||||
|
# o = c.balance_of(self.address, self.sink_address, sender_address=self.accounts[0])
|
||||||
|
# r = self.rpc.do(o)
|
||||||
|
# balance = c.parse_balance(r)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
@ -51,22 +51,19 @@ class TestRedistribution(TestDemurrageUnit):
|
|||||||
nonce_oracle = RPCNonceOracle(self.accounts[0], self.rpc)
|
nonce_oracle = RPCNonceOracle(self.accounts[0], self.rpc)
|
||||||
c = DemurrageToken(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
|
c = DemurrageToken(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
|
||||||
|
|
||||||
demurrage_previous = (1 - (self.tax_level / 100000)) * (10**28)
|
demurrage = (1 - (self.tax_level / 100000)) * (10**28)
|
||||||
demurrage = (1 - ((self.tax_level * 1.33) / 100000)) * (10**28)
|
|
||||||
|
|
||||||
logg.debug('demurrage then {} now {}'.format(demurrage_previous, demurrage))
|
logg.debug('demurrage {}'.format(demurrage))
|
||||||
supply = self.default_supply
|
supply = self.default_supply
|
||||||
|
|
||||||
o = c.to_redistribution(self.address, 0, demurrage_previous, supply, 1, sender_address=self.accounts[0])
|
|
||||||
redistribution_previous = self.rpc.do(o)
|
|
||||||
|
|
||||||
o = c.to_redistribution(self.address, 0, demurrage, supply, 2, sender_address=self.accounts[0])
|
o = c.to_redistribution(self.address, 0, demurrage, supply, 2, sender_address=self.accounts[0])
|
||||||
redistribution = self.rpc.do(o)
|
redistribution = self.rpc.do(o)
|
||||||
|
|
||||||
o = c.get_distribution_from_redistribution(self.address, redistribution, redistribution_previous, self.accounts[0])
|
o = c.get_distribution_from_redistribution(self.address, redistribution, self.accounts[0])
|
||||||
r = self.rpc.do(o)
|
r = self.rpc.do(o)
|
||||||
distribution = c.parse_get_distribution(r)
|
distribution = c.parse_get_distribution(r)
|
||||||
expected_distribution = self.default_supply * (((self.tax_level * 1.33) - self.tax_level) / 100000)
|
#expected_distribution = self.default_supply * (((self.tax_level * 1.33) - self.tax_level) / 100000)
|
||||||
|
expected_distribution = (self.default_supply * self.tax_level) / 100000
|
||||||
logg.debug('distribution {} supply {}'.format(distribution, self.default_supply))
|
logg.debug('distribution {} supply {}'.format(distribution, self.default_supply))
|
||||||
self.assert_within_lower(distribution, expected_distribution, 1000)
|
self.assert_within_lower(distribution, expected_distribution, 1000)
|
||||||
|
|
||||||
|
@ -22,8 +22,6 @@ contract DemurrageTokenSingleCap {
|
|||||||
|
|
||||||
uint256 public demurrageStart;
|
uint256 public demurrageStart;
|
||||||
|
|
||||||
// Cached demurrage period; the period for which demurrageAmount was calculated
|
|
||||||
//uint128 public demurragePeriod;
|
|
||||||
// Cached demurrage timestamp; the timestamp for which demurrageAmount was last calculated
|
// Cached demurrage timestamp; the timestamp for which demurrageAmount was last calculated
|
||||||
uint256 public demurrageTimestamp;
|
uint256 public demurrageTimestamp;
|
||||||
|
|
||||||
@ -47,8 +45,8 @@ contract DemurrageTokenSingleCap {
|
|||||||
// Last executed period
|
// Last executed period
|
||||||
uint256 public lastPeriod;
|
uint256 public lastPeriod;
|
||||||
|
|
||||||
// Minimum amount of (demurraged) tokens an account must spend to participate in redistribution for a particular period
|
// Last sink redistribution amount
|
||||||
//uint256 public minimumParticipantSpend;
|
uint256 public totalSink;
|
||||||
|
|
||||||
// 128 bit resolution of the demurrage divisor
|
// 128 bit resolution of the demurrage divisor
|
||||||
// (this constant x 1000000 is contained within 128 bits)
|
// (this constant x 1000000 is contained within 128 bits)
|
||||||
@ -116,19 +114,14 @@ contract DemurrageTokenSingleCap {
|
|||||||
demurrageTimestamp = block.timestamp;
|
demurrageTimestamp = block.timestamp;
|
||||||
periodStart = demurrageTimestamp;
|
periodStart = demurrageTimestamp;
|
||||||
periodDuration = _periodMinutes * 60;
|
periodDuration = _periodMinutes * 60;
|
||||||
//demurrageAmount = 100000000000000000000000000000000000000 - _taxLevelMinute; // Represents 38 decimal places, same as resolutionFactor
|
|
||||||
//demurrageAmount = 100000000000000000000000000000000000000;
|
|
||||||
//demurrageAmount = 10000000000000000000000000000;
|
|
||||||
demurrageAmount = uint128(nanoDivider) * 100;
|
demurrageAmount = uint128(nanoDivider) * 100;
|
||||||
demurrageStart = demurrageAmount;
|
demurrageStart = demurrageAmount;
|
||||||
//demurragePeriod = 1;
|
|
||||||
taxLevel = _taxLevelMinute; // Represents 38 decimal places
|
taxLevel = _taxLevelMinute; // Represents 38 decimal places
|
||||||
bytes32 initialRedistribution = toRedistribution(0, demurrageAmount, 0, 1);
|
bytes32 initialRedistribution = toRedistribution(0, demurrageAmount, 0, 1);
|
||||||
redistributions.push(initialRedistribution);
|
redistributions.push(initialRedistribution);
|
||||||
|
|
||||||
// Misc settings
|
// Misc settings
|
||||||
sinkAddress = _defaultSinkAddress;
|
sinkAddress = _defaultSinkAddress;
|
||||||
//minimumParticipantSpend = 10 ** uint256(_decimals);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -160,10 +153,8 @@ contract DemurrageTokenSingleCap {
|
|||||||
|
|
||||||
baseBalance = baseBalanceOf(_account);
|
baseBalance = baseBalanceOf(_account);
|
||||||
|
|
||||||
//periodCount = actualPeriod() - demurragePeriod;
|
|
||||||
periodCount = getMinutesDelta(demurrageTimestamp);
|
periodCount = getMinutesDelta(demurrageTimestamp);
|
||||||
|
|
||||||
//currentDemurragedAmount = uint128(decayBy(demurrageAmount, periodCount));
|
|
||||||
currentDemurragedAmount = uint128(decayBy(demurrageAmount * 10000000000, periodCount));
|
currentDemurragedAmount = uint128(decayBy(demurrageAmount * 10000000000, periodCount));
|
||||||
|
|
||||||
return (baseBalance * currentDemurragedAmount) / (nanoDivider * 1000000000000);
|
return (baseBalance * currentDemurragedAmount) / (nanoDivider * 1000000000000);
|
||||||
@ -281,7 +272,6 @@ contract DemurrageTokenSingleCap {
|
|||||||
bytes32 lastRedistribution;
|
bytes32 lastRedistribution;
|
||||||
uint256 currentPeriod;
|
uint256 currentPeriod;
|
||||||
|
|
||||||
//lastRedistribution = redistributions[redistributions.length-1];
|
|
||||||
lastRedistribution = redistributions[lastPeriod];
|
lastRedistribution = redistributions[lastPeriod];
|
||||||
currentPeriod = this.actualPeriod();
|
currentPeriod = this.actualPeriod();
|
||||||
if (currentPeriod <= toRedistributionPeriod(lastRedistribution)) {
|
if (currentPeriod <= toRedistributionPeriod(lastRedistribution)) {
|
||||||
@ -293,30 +283,29 @@ contract DemurrageTokenSingleCap {
|
|||||||
function getDistribution(uint256 _supply, uint256 _demurrageAmount) public view returns (uint256) {
|
function getDistribution(uint256 _supply, uint256 _demurrageAmount) public view returns (uint256) {
|
||||||
uint256 difference;
|
uint256 difference;
|
||||||
|
|
||||||
//difference = _supply * (resolutionFactor - _demurrageAmount); //(nanoDivider - ((resolutionFactor - _demurrageAmount) / nanoDivider));
|
difference = _supply * (resolutionFactor - (_demurrageAmount * 10000000000));
|
||||||
difference = _supply * (resolutionFactor - (_demurrageAmount * 10000000000)); //(nanoDivider - ((resolutionFactor - _demurrageAmount) / nanoDivider));
|
|
||||||
return difference / resolutionFactor;
|
return difference / resolutionFactor;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getDistributionFromRedistribution(bytes32 _redistribution, bytes32 _redistributionPrevious) public returns (uint256) {
|
function getDistributionFromRedistribution(bytes32 _redistribution) public returns (uint256) {
|
||||||
uint256 redistributionSupply;
|
uint256 redistributionSupply;
|
||||||
uint256 redistributionDemurrage;
|
uint256 redistributionDemurrage;
|
||||||
uint256 redistributionDemurragePrevious;
|
|
||||||
|
|
||||||
redistributionSupply = toRedistributionSupply(_redistribution);
|
redistributionSupply = toRedistributionSupply(_redistribution);
|
||||||
redistributionDemurrage = toRedistributionDemurrageModifier(_redistribution);
|
redistributionDemurrage = toRedistributionDemurrageModifier(_redistribution);
|
||||||
redistributionDemurragePrevious = toRedistributionDemurrageModifier(_redistributionPrevious);
|
|
||||||
redistributionDemurrage = demurrageStart - (redistributionDemurragePrevious - redistributionDemurrage);
|
|
||||||
return getDistribution(redistributionSupply, redistributionDemurrage);
|
return getDistribution(redistributionSupply, redistributionDemurrage);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the amount sent to the sink address
|
// Returns the amount sent to the sink address
|
||||||
function applyDefaultRedistribution(bytes32 _redistribution, bytes32 _redistributionPrevious) private returns (uint256) {
|
function applyDefaultRedistribution(bytes32 _redistribution) private returns (uint256) {
|
||||||
uint256 unit;
|
uint256 unit;
|
||||||
|
uint256 baseUnit;
|
||||||
|
|
||||||
unit = getDistributionFromRedistribution(_redistribution, _redistributionPrevious);
|
unit = getDistributionFromRedistribution(_redistribution);
|
||||||
increaseBaseBalance(sinkAddress, toBaseAmount(unit));
|
baseUnit = toBaseAmount(unit) - totalSink;
|
||||||
|
increaseBaseBalance(sinkAddress, baseUnit);
|
||||||
lastPeriod += 1;
|
lastPeriod += 1;
|
||||||
|
totalSink += baseUnit;
|
||||||
return unit;
|
return unit;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -331,13 +320,9 @@ contract DemurrageTokenSingleCap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function applyDemurrageLimited(uint256 _rounds) public returns (bool) {
|
function applyDemurrageLimited(uint256 _rounds) public returns (bool) {
|
||||||
//uint128 epochPeriodCount;
|
|
||||||
uint256 periodCount;
|
uint256 periodCount;
|
||||||
uint256 lastDemurrageAmount;
|
uint256 lastDemurrageAmount;
|
||||||
|
|
||||||
//epochPeriodCount = actualPeriod();
|
|
||||||
//periodCount = epochPeriodCount - demurragePeriod;
|
|
||||||
|
|
||||||
periodCount = getMinutesDelta(demurrageTimestamp);
|
periodCount = getMinutesDelta(demurrageTimestamp);
|
||||||
if (periodCount == 0) {
|
if (periodCount == 0) {
|
||||||
return false;
|
return false;
|
||||||
@ -400,7 +385,7 @@ contract DemurrageTokenSingleCap {
|
|||||||
nextRedistribution = toRedistribution(0, nextRedistributionDemurrage, totalSupply, nextPeriod);
|
nextRedistribution = toRedistribution(0, nextRedistributionDemurrage, totalSupply, nextPeriod);
|
||||||
redistributions.push(nextRedistribution);
|
redistributions.push(nextRedistribution);
|
||||||
|
|
||||||
applyDefaultRedistribution(nextRedistribution, currentRedistribution);
|
applyDefaultRedistribution(nextRedistribution);
|
||||||
emit Period(nextPeriod);
|
emit Period(nextPeriod);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -435,7 +420,6 @@ contract DemurrageTokenSingleCap {
|
|||||||
|
|
||||||
// Inflates the given amount according to the current demurrage modifier
|
// Inflates the given amount according to the current demurrage modifier
|
||||||
function toBaseAmount(uint256 _value) public view returns (uint256) {
|
function toBaseAmount(uint256 _value) public view returns (uint256) {
|
||||||
//return (_value * resolutionFactor) / demurrageAmount;
|
|
||||||
return (_value * resolutionFactor) / (demurrageAmount * 10000000000);
|
return (_value * resolutionFactor) / (demurrageAmount * 10000000000);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -486,7 +470,6 @@ contract DemurrageTokenSingleCap {
|
|||||||
decreaseBaseBalance(_from, _value);
|
decreaseBaseBalance(_from, _value);
|
||||||
increaseBaseBalance(_to, _value);
|
increaseBaseBalance(_to, _value);
|
||||||
|
|
||||||
//period = actualPeriod();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user