Define expiry in terms of period

This commit is contained in:
lash 2023-02-10 14:30:25 +00:00
parent 09b825808f
commit 1f0dc0aa5f
Signed by: lash
GPG Key ID: 21D2E7BB88C2A746
5 changed files with 37 additions and 11 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -6,13 +6,16 @@ from chainlib.eth.tx import (
from chainlib.eth.contract import ( from chainlib.eth.contract import (
ABIContractEncoder, ABIContractEncoder,
ABIContractType, ABIContractType,
abi_decode_single,
) )
from chainlib.eth.constant import ZERO_ADDRESS
class ExpiryContract(TxFactory): class ExpiryContract(TxFactory):
def set_expires(self, contract_address, sender_address, expire_timestamp, tx_format=TxFormat.JSONRPC): def set_expires_period(self, contract_address, sender_address, expire_timestamp, tx_format=TxFormat.JSONRPC):
enc = ABIContractEncoder() enc = ABIContractEncoder()
enc.method('setExpires') enc.method('setExpirePeriod')
enc.typ(ABIContractType.UINT256) enc.typ(ABIContractType.UINT256)
enc.uint256(expire_timestamp) enc.uint256(expire_timestamp)
data = enc.get() data = enc.get()
@ -20,3 +23,14 @@ class ExpiryContract(TxFactory):
tx = self.set_code(tx, data) tx = self.set_code(tx, data)
tx = self.finalize(tx, tx_format) tx = self.finalize(tx, tx_format)
return tx return tx
def expires(self, contract_address, sender_address=ZERO_ADDRESS):
return self.call_noarg('expires', contract_address, sender_address=sender_address)
@classmethod
def parse_expires(self, v):
return abi_decode_single(ABIContractType.UINT256, v)

View File

@ -37,19 +37,22 @@ class TestExpire(TestDemurrageDefault):
(tx_hash, o) = c.mint_to(self.address, self.accounts[0], self.accounts[i+1], mint_amount) (tx_hash, o) = c.mint_to(self.address, self.accounts[0], self.accounts[i+1], mint_amount)
r = self.rpc.do(o) r = self.rpc.do(o)
targetish_time = self.start_time + (self.period_seconds * 2) (tx_hash, o) = c.set_expires_period(self.address, self.accounts[0], 2)
(tx_hash, o) = c.set_expires(self.address, self.accounts[0], targetish_time)
r = self.rpc.do(o) r = 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)
self.backend.time_travel(targetish_time + 60) o = c.expires(self.address, sender_address=self.accounts[0])
r = self.rpc.do(o)
expiry_time = c.parse_expires(r)
self.backend.time_travel(expiry_time + 60)
o = block_latest() o = block_latest()
r = self.rpc.do(o) r = self.rpc.do(o)
o = block_by_number(r) o = block_by_number(r)
r = self.rpc.do(o) r = self.rpc.do(o)
self.assertGreaterEqual(r['timestamp'], targetish_time) self.assertGreaterEqual(r['timestamp'], expiry_time)
nonce_oracle = RPCNonceOracle(self.sink_address, self.rpc) nonce_oracle = RPCNonceOracle(self.sink_address, 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)
@ -59,6 +62,12 @@ class TestExpire(TestDemurrageDefault):
r = self.rpc.do(o) r = self.rpc.do(o)
self.assertEqual(r['status'], 1) self.assertEqual(r['status'], 1)
(tx_hash, o) = c.transfer(self.address, self.sink_address, self.accounts[2], 1)
r = self.rpc.do(o)
o = receipt(tx_hash)
r = self.rpc.do(o)
self.assertEqual(r['status'], 0)
o = c.balance_of(self.address, self.accounts[1], sender_address=self.accounts[0]) o = c.balance_of(self.address, self.accounts[1], sender_address=self.accounts[0])
r = self.rpc.do(o) r = self.rpc.do(o)
balance = c.parse_balance(r) balance = c.parse_balance(r)
@ -78,7 +87,7 @@ class TestExpire(TestDemurrageDefault):
r = self.rpc.do(o) r = self.rpc.do(o)
balance = c.parse_balance(r) balance = c.parse_balance(r)
o = c.decay_by(self.address, supply, int((targetish_time - self.start_time) / 60), sender_address=self.sink_address) o = c.decay_by(self.address, supply, int((expiry_time - self.start_time) / 60), sender_address=self.sink_address)
r = self.rpc.do(o) r = self.rpc.do(o)
target_balance = c.parse_balance(r) target_balance = c.parse_balance(r)

View File

@ -170,11 +170,11 @@ contract DemurrageTokenSingleCap {
return _state & sealState == _state; return _state & sealState == _state;
} }
function setExpires(uint256 _expires) public { function setExpirePeriod(uint256 _expirePeriod) public {
require(!isSealed(EXPIRY_STATE)); require(!isSealed(EXPIRY_STATE));
require(!expired); require(!expired);
require(msg.sender == owner); require(msg.sender == owner);
expires = _expires; expires = periodStart + (_expirePeriod * periodDuration);
} }
@ -185,6 +185,9 @@ contract DemurrageTokenSingleCap {
sinkAddress = _sinkAddress; sinkAddress = _sinkAddress;
} }
// Expire the contract if expire is set and we have gone over the threshold.
// Finalizes demurrage up to the timestamp of the expiry.
// The first approve, transfer or transferFrom call that hits the ex == 2 will get the tx mined. but without the actual effect. Otherwise we would have to wait until an external egent called applyExpiry to get the correct final balance.
function applyExpiry() public returns(uint8) { function applyExpiry() public returns(uint8) {
if (expired) { if (expired) {
return 1; return 1;