Add expire option

This commit is contained in:
lash
2023-02-21 20:28:25 +00:00
parent ea7c106fa4
commit d7fb3f232c
15 changed files with 196 additions and 46 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

@@ -15,29 +15,33 @@ from chainlib.eth.contract import (
# local imports
from giftable_erc20_token.data import data_dir
from eth_erc20 import ERC20
logg = logging.getLogger(__name__)
class GiftableToken(TxFactory):
class GiftableToken(ERC20):
__abi = None
__bytecode = None
def constructor(self, sender_address, name, symbol, decimals, tx_format=TxFormat.JSONRPC, version=None):
code = self.cargs(name, symbol, decimals)
def constructor(self, sender_address, name, symbol, decimals, expire=0, tx_format=TxFormat.JSONRPC, version=None):
code = self.cargs(name, symbol, decimals, expire=expire)
tx = self.template(sender_address, None, use_nonce=True)
tx = self.set_code(tx, code)
return self.finalize(tx, tx_format)
@staticmethod
def cargs(name, symbol, decimals, version=None):
def cargs(name, symbol, decimals, expire=0, version=None):
if expire == None:
expire = 0
code = GiftableToken.bytecode(version=version)
enc = ABIContractEncoder()
enc.string(name)
enc.string(symbol)
enc.uint256(decimals)
enc.uint256(expire)
code += enc.get()
return code
@@ -108,12 +112,12 @@ def bytecode(**kwargs):
def create(**kwargs):
return GiftableToken.cargs(kwargs['name'], kwargs['symbol'], kwargs['decimals'], version=kwargs.get('version'))
return GiftableToken.cargs(kwargs['name'], kwargs['symbol'], kwargs['decimals'], expire=kwargs.get('expire'), version=kwargs.get('version'))
def args(v):
if v == 'create':
return (['name', 'symbol', 'decimals'], ['version'],)
return (['name', 'symbol', 'decimals'], ['expire', 'version'],)
elif v == 'default' or v == 'bytecode':
return ([], ['version'],)
raise ValueError('unknown command: ' + v)

View File

@@ -45,6 +45,7 @@ def process_config_local(config, arg, args, flags):
config.add(args.token_name, '_TOKEN_NAME', False)
config.add(args.token_symbol, '_TOKEN_SYMBOL', False)
config.add(args.token_decimals, '_TOKEN_DECIMALS', False)
config.add(args.token_expire, '_TOKEN_EXPIRE', False)
return config
@@ -57,6 +58,7 @@ argparser = process_args(argparser, arg, flags)
argparser.add_argument('--name', dest='token_name', required=True, type=str, help='Token name')
argparser.add_argument('--symbol', dest='token_symbol', required=True, type=str, help='Token symbol')
argparser.add_argument('--decimals', dest='token_decimals', default=18, type=int, help='Token decimals')
argparser.add_argument('--expire', dest='token_expire', default=0, type=int, help='Token expiry timestamp (after which token cannot be traded)')
args = argparser.parse_args()
logg = process_log(args, logg)
@@ -87,6 +89,7 @@ def main():
config.get('_TOKEN_NAME'),
config.get('_TOKEN_SYMBOL'),
config.get('_TOKEN_DECIMALS'),
expire=config.get('_TOKEN_EXPIRE'),
)
if settings.get('RPC_SEND'):
conn.do(o)

View File

@@ -0,0 +1 @@
from .base import *

View File

@@ -0,0 +1,51 @@
# standard imports
import logging
import time
# external imports
from chainlib.eth.unittest.ethtester import EthTesterCase
from chainlib.connection import RPCConnection
from chainlib.eth.nonce import RPCNonceOracle
from chainlib.eth.tx import receipt
from chainlib.eth.address import to_checksum_address
# local imports
from giftable_erc20_token import GiftableToken
logg = logging.getLogger(__name__)
class TestGiftableToken(EthTesterCase):
expire = 0
def setUp(self):
super(TestGiftableToken, self).setUp()
self.conn = RPCConnection.connect(self.chain_spec, 'default')
nonce_oracle = RPCNonceOracle(self.accounts[0], conn=self.conn)
c = GiftableToken(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
self.symbol = 'FOO'
self.name = 'Foo Token'
self.decimals = 16
(tx_hash, o) = c.constructor(self.accounts[0], self.name, self.symbol, self.decimals, expire=self.expire)
self.rpc.do(o)
o = receipt(tx_hash)
r = self.rpc.do(o)
self.assertEqual(r['status'], 1)
self.address = to_checksum_address(r['contract_address'])
logg.debug('published on address {} with hash {}'.format(self.address, tx_hash))
self.initial_supply = 1 << 40
(tx_hash, o) = c.mint_to(self.address, self.accounts[0], self.accounts[0], self.initial_supply)
r = self.conn.do(o)
o = receipt(tx_hash)
r = self.conn.do(o)
self.assertEqual(r['status'], 1)
class TestGiftableExpireToken(TestGiftableToken):
expire = int(time.time()) + 100000
def setUp(self):
super(TestGiftableExpireToken, self).setUp()

View File

@@ -1,5 +1,7 @@
#!/bin/bash
export PYTHONPATH=${PYTHONPATH}:.
set -e
set -x
for f in `ls tests/*.py`; do

View File

@@ -1,6 +1,6 @@
[metadata]
name = eth-erc20
version = 0.5.6
version = 0.6.0
description = ERC20 interface and simple contract with deployment script that lets any address mint and gift itself tokens.
author = Louis Holbrook
author_email = dev@holbrook.no
@@ -30,6 +30,7 @@ python_requires = >= 3.7
packages =
giftable_erc20_token
giftable_erc20_token.runnable
giftable_erc20_token.unittest
giftable_erc20_token.data
eth_erc20
eth_erc20.data
@@ -46,9 +47,8 @@ packages =
[options.entry_points]
console_scripts =
giftable-token-deploy = giftable_erc20_token.runnable.deploy:main
giftable-token-publish = giftable_erc20_token.runnable.publish:main
giftable-token-gift = giftable_erc20_token.runnable.gift:main
giftable-token-minter = giftable_erc20_token.runnable.minter:main
erc20-transfer = eth_erc20.runnable.transfer:main
erc20-balance = eth_erc20.runnable.balance:main
erc20-info = eth_erc20.runnable.info:main

File diff suppressed because one or more lines are too long

View File

@@ -15,38 +15,14 @@ from chainlib.eth.address import to_checksum_address
from hexathon import strip_0x
# local imports
from giftable_erc20_token import GiftableToken
from giftable_erc20_token.unittest import TestGiftableToken
from eth_erc20 import ERC20
logging.basicConfig(level=logging.DEBUG)
logg = logging.getLogger(__name__)
logg = logging.getLogger()
class TestToken(EthTesterCase):
def setUp(self):
super(TestToken, self).setUp()
self.conn = RPCConnection.connect(self.chain_spec, 'default')
nonce_oracle = RPCNonceOracle(self.accounts[0], conn=self.conn)
c = GiftableToken(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
self.symbol = 'FOO'
self.name = 'Foo Token'
self.decimals = 16
(tx_hash, o) = c.constructor(self.accounts[0], self.name, self.symbol, self.decimals)
r = self.conn.do(o)
logg.debug('deployed with hash {}'.format(r))
o = receipt(r)
r = self.conn.do(o)
self.address = to_checksum_address(r['contract_address'])
self.initial_supply = 1 << 40
(tx_hash, o) = c.mint_to(self.address, self.accounts[0], self.accounts[0], self.initial_supply)
r = self.conn.do(o)
o = receipt(tx_hash)
r = self.conn.do(o)
self.assertEqual(r['status'], 1)
class TestToken(TestGiftableToken):
def test_balance(self):
c = ERC20(self.chain_spec)

View File

@@ -0,0 +1,84 @@
# standard imports
import os
import unittest
import json
import logging
import datetime
# 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,
)
# local imports
from giftable_erc20_token import GiftableToken
from giftable_erc20_token.unittest import TestGiftableExpireToken
logging.basicConfig(level=logging.DEBUG)
logg = logging.getLogger()
testdir = os.path.dirname(__file__)
class TestExpire(TestGiftableExpireToken):
def setUp(self):
super(TestExpire, self).setUp()
def test_expires(self):
mint_amount = self.initial_supply
nonce_oracle = RPCNonceOracle(self.accounts[0], self.rpc)
c = GiftableToken(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
(tx_hash, o) = c.transfer(self.address, self.accounts[0], self.accounts[1], int(mint_amount / 2))
r = self.rpc.do(o)
o = receipt(tx_hash)
r = self.rpc.do(o)
self.assertEqual(r['status'], 1)
self.backend.time_travel(self.expire + 60)
o = block_latest()
r = self.rpc.do(o)
o = block_by_number(r)
r = self.rpc.do(o)
self.assertGreaterEqual(r['timestamp'], self.expire)
nonce_oracle = RPCNonceOracle(self.accounts[0], self.rpc)
c = GiftableToken(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
(tx_hash, o) = c.transfer(self.address, self.accounts[0], self.accounts[1], 1)
r = self.rpc.do(o)
o = receipt(tx_hash)
r = self.rpc.do(o)
self.assertEqual(r['status'], 0)
nonce_oracle = RPCNonceOracle(self.accounts[1], self.rpc)
c = GiftableToken(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
(tx_hash, o) = c.transfer(self.address, self.accounts[1], self.accounts[0], 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[0], sender_address=self.accounts[0])
r = self.rpc.do(o)
balance = c.parse_balance(r)
self.assertEqual(balance, int(mint_amount / 2))
o = c.balance_of(self.address, self.accounts[1], sender_address=self.accounts[0])
r = self.rpc.do(o)
balance += c.parse_balance(r)
self.assertEqual(balance, mint_amount)
o = c.total_supply(self.address, sender_address=self.accounts[0])
r = self.rpc.do(o)
supply = c.parse_balance(r)
self.assertEqual(supply, mint_amount)
if __name__ == '__main__':
unittest.main()