Compare commits
6 Commits
c10d2c46f1
...
6f44c8304f
Author | SHA1 | Date | |
---|---|---|---|
|
6f44c8304f | ||
|
993d52ecab | ||
|
02aa54f653 | ||
|
360a288d77 | ||
|
ef3ee7caf0 | ||
|
220b8afbeb |
5
Makefile
5
Makefile
@ -6,7 +6,7 @@ INPUTS = $(wildcard solidity/*.sol)
|
||||
OUTPUTS_JSON = $(patsubst %.sol, %.json, $(INPUTS))
|
||||
OUTPUTS_INTERFACE = $(patsubst %.sol, %.interface, $(INPUTS))
|
||||
OUTPUTS = $(OUTPUTS_JSON) $(OUTPUTS_INTERFACE)
|
||||
PREFIX = /usr/local/share/cic/solidity/abi
|
||||
PREFIX = $(DESTDIR)/usr/local/share/cic/solidity/abi
|
||||
|
||||
#%.abi.json: $(wildcard *.sol)
|
||||
# install -vDm0644 $@ $(PREFIX)/$@
|
||||
@ -44,4 +44,7 @@ readme:
|
||||
make -C doc/texinfo readme
|
||||
pandoc -f docbook -t gfm doc/texinfo/build/docbook.xml > README.md
|
||||
|
||||
python:
|
||||
make -C python
|
||||
|
||||
.PHONY: clean install
|
||||
|
@ -1 +1 @@
|
||||
include *requirements.txt
|
||||
include *requirements.txt solidity/* LICENSE README*
|
||||
|
17
python/Makefile
Normal file
17
python/Makefile
Normal file
@ -0,0 +1,17 @@
|
||||
INPUTS = $(wildcard solidity/*.sol)
|
||||
OUTPUTS = $(patsubst %.sol, %.bin, $(INPUTS))
|
||||
|
||||
all: outs package
|
||||
|
||||
.SUFFIXES: .sol .bin
|
||||
|
||||
solidity:
|
||||
|
||||
.sol.bin:
|
||||
solc $(basename $@).sol --evm-version=byzantium --bin | awk 'NR>3' > $@
|
||||
truncate -s -1 $@
|
||||
|
||||
outs: $(OUTPUTS)
|
||||
|
||||
package:
|
||||
python setup.py sdist
|
1
python/eth_burner/__init__.py
Normal file
1
python/eth_burner/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
from .burn import EthBurner
|
33
python/eth_burner/burn.py
Normal file
33
python/eth_burner/burn.py
Normal file
@ -0,0 +1,33 @@
|
||||
# external imports
|
||||
from chainlib.eth.tx import TxFormat
|
||||
from chainlib.eth.tx import TxFactory
|
||||
from chainlib.jsonrpc import JSONRPCRequest
|
||||
from chainlib.eth.constant import ZERO_ADDRESS
|
||||
from chainlib.eth.contract import ABIContractEncoder
|
||||
from chainlib.eth.contract import ABIContractType
|
||||
from chainlib.eth.contract import abi_decode_single
|
||||
from hexathon import add_0x
|
||||
|
||||
|
||||
class EthBurner(TxFactory):
|
||||
|
||||
def burn(self, contract_address, sender_address, value, tx_format=TxFormat.JSONRPC):
|
||||
enc = ABIContractEncoder()
|
||||
enc.method('burn')
|
||||
enc.typ(ABIContractType.UINT256)
|
||||
enc.uint256(value)
|
||||
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 burn_all(self, contract_address, sender_address, tx_format=TxFormat.JSONRPC):
|
||||
enc = ABIContractEncoder()
|
||||
enc.method('burn')
|
||||
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
|
1
python/eth_burner/unittest/__init__.py
Normal file
1
python/eth_burner/unittest/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
from .interface import TestEthBurnerInterface
|
53
python/eth_burner/unittest/base.py
Normal file
53
python/eth_burner/unittest/base.py
Normal file
@ -0,0 +1,53 @@
|
||||
# standard imports
|
||||
import os
|
||||
import logging
|
||||
import datetime
|
||||
|
||||
# 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.tx import TxFactory
|
||||
from chainlib.eth.tx import TxFormat
|
||||
from chainlib.eth.contract import ABIContractEncoder
|
||||
from chainlib.eth.contract import ABIContractType
|
||||
|
||||
# local imports
|
||||
from eth_burner import EthBurner
|
||||
|
||||
script_dir = os.path.dirname(os.path.realpath(__file__))
|
||||
contract_dir = os.path.join(script_dir, '..', '..', 'solidity')
|
||||
|
||||
logg = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class TestEthBurner(EthTesterCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestEthBurner, self).setUp()
|
||||
|
||||
self.conn = RPCConnection.connect(self.chain_spec, 'default')
|
||||
nonce_oracle = RPCNonceOracle(self.accounts[0], self.conn)
|
||||
|
||||
f = open(os.path.join(contract_dir, 'BurnerTest.bin'))
|
||||
code = f.read()
|
||||
f.close()
|
||||
|
||||
txf = TxFactory(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
|
||||
tx = txf.template(self.accounts[0], None, use_nonce=True)
|
||||
|
||||
self.initial_supply = 1024
|
||||
enc = ABIContractEncoder()
|
||||
enc = ABIContractEncoder()
|
||||
enc.uint256(self.initial_supply)
|
||||
args = enc.get()
|
||||
|
||||
tx = txf.set_code(tx, code + args)
|
||||
(tx_hash_hex, o) = txf.build(tx)
|
||||
self.conn.do(o)
|
||||
o = receipt(tx_hash_hex)
|
||||
r = self.conn.do(o)
|
||||
self.assertEqual(r['status'], 1)
|
||||
self.address = r['contract_address']
|
||||
logg.debug('published burner test contract with hash {}'.format(r))
|
19
python/eth_burner/unittest/interface.py
Normal file
19
python/eth_burner/unittest/interface.py
Normal file
@ -0,0 +1,19 @@
|
||||
# external imports
|
||||
from chainlib.eth.tx import receipt
|
||||
from chainlib.eth.nonce import RPCNonceOracle
|
||||
|
||||
# local imports
|
||||
from eth_burner import EthBurner
|
||||
|
||||
|
||||
class TestEthBurnerInterface:
|
||||
|
||||
def test_supply(self):
|
||||
self.alice = self.accounts[1]
|
||||
nonce_oracle = RPCNonceOracle(self.accounts[0], self.rpc)
|
||||
c = EthBurner(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
|
||||
(tx_hash, o) = c.burn(self.address, self.accounts[0], int(self.initial_supply / 2))
|
||||
self.rpc.do(o)
|
||||
o = receipt(tx_hash)
|
||||
r = self.rpc.do(o)
|
||||
self.assertEqual(r['status'],1)
|
1
python/eth_capped/__init__.py
Normal file
1
python/eth_capped/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
from .capped import EthCapped
|
22
python/eth_capped/capped.py
Normal file
22
python/eth_capped/capped.py
Normal file
@ -0,0 +1,22 @@
|
||||
# external imports
|
||||
from chainlib.eth.tx import TxFormat
|
||||
from chainlib.eth.tx import TxFactory
|
||||
from chainlib.jsonrpc import JSONRPCRequest
|
||||
from chainlib.eth.constant import ZERO_ADDRESS
|
||||
from chainlib.eth.contract import ABIContractEncoder
|
||||
from chainlib.eth.contract import ABIContractType
|
||||
from hexathon import add_0x
|
||||
|
||||
class EthCapped(TxFactory):
|
||||
|
||||
def max_supply(self, contract_address, sender_address=ZERO_ADDRESS, id_generator=None):
|
||||
j = JSONRPCRequest(id_generator)
|
||||
o = j.template()
|
||||
o['method'] = 'eth_call'
|
||||
enc = ABIContractEncoder()
|
||||
enc.method('maxSupply')
|
||||
data = add_0x(enc.get())
|
||||
tx = self.template(sender_address, contract_address)
|
||||
tx = self.set_code(tx, data)
|
||||
o['params'].append(self.normalize(tx))
|
||||
return o
|
1
python/eth_capped/unittest/__init__.py
Normal file
1
python/eth_capped/unittest/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
from .interface import TestEthCappedInterface
|
64
python/eth_capped/unittest/base.py
Normal file
64
python/eth_capped/unittest/base.py
Normal file
@ -0,0 +1,64 @@
|
||||
# standard imports
|
||||
import os
|
||||
import logging
|
||||
|
||||
# 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.tx import TxFactory
|
||||
from chainlib.eth.tx import TxFormat
|
||||
from chainlib.eth.contract import ABIContractEncoder
|
||||
from chainlib.eth.contract import ABIContractType
|
||||
|
||||
script_dir = os.path.dirname(os.path.realpath(__file__))
|
||||
contract_dir = os.path.join(script_dir, '..', '..', 'solidity')
|
||||
|
||||
logg = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class TestEthCapped(EthTesterCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestEthCapped, self).setUp()
|
||||
|
||||
self.set_method = None
|
||||
|
||||
self.conn = RPCConnection.connect(self.chain_spec, 'default')
|
||||
nonce_oracle = RPCNonceOracle(self.accounts[0], self.conn)
|
||||
|
||||
f = open(os.path.join(contract_dir, 'CappedTest.bin'))
|
||||
code = f.read()
|
||||
f.close()
|
||||
|
||||
txf = TxFactory(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
|
||||
tx = txf.template(self.accounts[0], None, use_nonce=True)
|
||||
|
||||
self.max_supply_value = 1024
|
||||
enc = ABIContractEncoder()
|
||||
enc.uint256(self.max_supply_value)
|
||||
args = enc.get()
|
||||
|
||||
tx = txf.set_code(tx, code + args)
|
||||
(tx_hash_hex, o) = txf.build(tx)
|
||||
self.conn.do(o)
|
||||
o = receipt(tx_hash_hex)
|
||||
r = self.conn.do(o)
|
||||
self.assertEqual(r['status'], 1)
|
||||
self.address = r['contract_address']
|
||||
logg.debug('published capped test contract with hash {}'.format(r))
|
||||
|
||||
|
||||
def set_max_supply(self, contract_address, sender_address, v, tx_format=TxFormat.JSONRPC):
|
||||
nonce_oracle = RPCNonceOracle(self.accounts[0], self.conn)
|
||||
txf = TxFactory(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
|
||||
enc = ABIContractEncoder()
|
||||
enc.method('setMaxSupply')
|
||||
enc.typ(ABIContractType.UINT256)
|
||||
enc.uint256(v)
|
||||
data = enc.get()
|
||||
tx = txf.template(sender_address, contract_address, use_nonce=True)
|
||||
tx = txf.set_code(tx, data)
|
||||
tx = txf.finalize(tx, tx_format)
|
||||
return tx
|
38
python/eth_capped/unittest/interface.py
Normal file
38
python/eth_capped/unittest/interface.py
Normal file
@ -0,0 +1,38 @@
|
||||
# external imports
|
||||
from chainlib.eth.tx import receipt
|
||||
|
||||
# local imports
|
||||
from eth_capped import EthCapped
|
||||
|
||||
|
||||
class TestEthCappedInterface:
|
||||
|
||||
def __init__(self):
|
||||
self.set_method = None
|
||||
self.max_supply_value = 0
|
||||
|
||||
|
||||
def test_supply(self):
|
||||
if self.max_supply_value == 0:
|
||||
return
|
||||
c = EthCapped(self.chain_spec)
|
||||
o = c.max_supply(self.address, sender_address=self.accounts[0])
|
||||
r = self.rpc.do(o)
|
||||
self.assertEqual(self.max_supply_value, int(r, 16))
|
||||
|
||||
|
||||
def test_supply_change(self):
|
||||
if self.set_method == None:
|
||||
return
|
||||
|
||||
self.max_supply_value = 2048
|
||||
(tx_hash_hex, o) = self.set_method(self.address, self.accounts[0], self.max_supply_value)
|
||||
self.rpc.do(o)
|
||||
o = receipt(tx_hash_hex)
|
||||
r = self.conn.do(o)
|
||||
self.assertEqual(r['status'], 1)
|
||||
|
||||
c = EthCapped(self.chain_spec)
|
||||
o = c.max_supply(self.address, sender_address=self.accounts[0])
|
||||
r = self.rpc.do(o)
|
||||
self.assertEqual(self.max_supply_value, int(r, 16))
|
1
python/eth_expire/__init__.py
Normal file
1
python/eth_expire/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
from .expire import EthExpire
|
37
python/eth_expire/expire.py
Normal file
37
python/eth_expire/expire.py
Normal file
@ -0,0 +1,37 @@
|
||||
# external imports
|
||||
from chainlib.eth.tx import TxFormat
|
||||
from chainlib.eth.tx import TxFactory
|
||||
from chainlib.jsonrpc import JSONRPCRequest
|
||||
from chainlib.eth.constant import ZERO_ADDRESS
|
||||
from chainlib.eth.contract import ABIContractEncoder
|
||||
from chainlib.eth.contract import ABIContractType
|
||||
from chainlib.eth.contract import abi_decode_single
|
||||
from hexathon import add_0x
|
||||
|
||||
class EthExpire(TxFactory):
|
||||
|
||||
def apply_expiry(self, method, contract_address, sender_address, tx_format=TxFormat.JSONRPC):
|
||||
enc = ABIContractEncoder()
|
||||
enc.method('applyExpiry')
|
||||
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 expires(self, contract_address, sender_address=ZERO_ADDRESS, id_generator=None):
|
||||
j = JSONRPCRequest(id_generator)
|
||||
o = j.template()
|
||||
o['method'] = 'eth_call'
|
||||
enc = ABIContractEncoder()
|
||||
enc.method('expires')
|
||||
data = add_0x(enc.get())
|
||||
tx = self.template(sender_address, contract_address)
|
||||
tx = self.set_code(tx, data)
|
||||
o['params'].append(self.normalize(tx))
|
||||
return o
|
||||
|
||||
|
||||
def parse_expires(self, v):
|
||||
return abi_decode_single(ABIContractType.UINT256, v)
|
1
python/eth_expire/unittest/__init__.py
Normal file
1
python/eth_expire/unittest/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
from .interface import TestEthExpireInterface
|
64
python/eth_expire/unittest/base.py
Normal file
64
python/eth_expire/unittest/base.py
Normal file
@ -0,0 +1,64 @@
|
||||
# standard imports
|
||||
import os
|
||||
import logging
|
||||
import datetime
|
||||
|
||||
# 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.tx import TxFactory
|
||||
from chainlib.eth.tx import TxFormat
|
||||
from chainlib.eth.contract import ABIContractEncoder
|
||||
from chainlib.eth.contract import ABIContractType
|
||||
|
||||
script_dir = os.path.dirname(os.path.realpath(__file__))
|
||||
contract_dir = os.path.join(script_dir, '..', '..', 'solidity')
|
||||
|
||||
logg = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class TestEthExpire(EthTesterCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestEthExpire, self).setUp()
|
||||
|
||||
self.conn = RPCConnection.connect(self.chain_spec, 'default')
|
||||
nonce_oracle = RPCNonceOracle(self.accounts[0], self.conn)
|
||||
|
||||
f = open(os.path.join(contract_dir, 'ExpireTest.bin'))
|
||||
code = f.read()
|
||||
f.close()
|
||||
|
||||
txf = TxFactory(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
|
||||
tx = txf.template(self.accounts[0], None, use_nonce=True)
|
||||
|
||||
date_expire = datetime.datetime.utcnow() + datetime.timedelta(seconds=10000)
|
||||
self.expire = int(date_expire.timestamp())
|
||||
enc = ABIContractEncoder()
|
||||
enc.uint256(self.expire)
|
||||
args = enc.get()
|
||||
|
||||
tx = txf.set_code(tx, code + args)
|
||||
(tx_hash_hex, o) = txf.build(tx)
|
||||
self.conn.do(o)
|
||||
o = receipt(tx_hash_hex)
|
||||
r = self.conn.do(o)
|
||||
self.assertEqual(r['status'], 1)
|
||||
self.address = r['contract_address']
|
||||
logg.debug('published expire test contract with hash {}'.format(r))
|
||||
|
||||
|
||||
def set_expiry(self, contract_address, sender_address, v, tx_format=TxFormat.JSONRPC):
|
||||
nonce_oracle = RPCNonceOracle(self.accounts[0], self.conn)
|
||||
txf = TxFactory(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
|
||||
enc = ABIContractEncoder()
|
||||
enc.method('setExpiry')
|
||||
enc.typ(ABIContractType.UINT256)
|
||||
enc.uint256(v)
|
||||
data = enc.get()
|
||||
tx = txf.template(sender_address, contract_address, use_nonce=True)
|
||||
tx = txf.set_code(tx, data)
|
||||
tx = txf.finalize(tx, tx_format)
|
||||
return tx
|
37
python/eth_expire/unittest/interface.py
Normal file
37
python/eth_expire/unittest/interface.py
Normal file
@ -0,0 +1,37 @@
|
||||
# external imports
|
||||
from chainlib.eth.tx import receipt
|
||||
|
||||
# local imports
|
||||
from eth_expire import EthExpire
|
||||
|
||||
|
||||
class TestEthExpireInterface:
|
||||
|
||||
def __init__(self):
|
||||
self.set_method = None
|
||||
|
||||
|
||||
def test_expire(self):
|
||||
if self.expire == 0:
|
||||
return
|
||||
c = EthExpire(self.chain_spec)
|
||||
o = c.expires(self.address, sender_address=self.accounts[0])
|
||||
r = self.rpc.do(o)
|
||||
self.assertEqual(self.expire, int(r, 16))
|
||||
|
||||
|
||||
def test_expire_change(self):
|
||||
if self.set_method == None:
|
||||
return
|
||||
|
||||
self.expire += 43200
|
||||
(tx_hash_hex, o) = self.set_method(self.address, self.accounts[0], self.expire)
|
||||
self.rpc.do(o)
|
||||
o = receipt(tx_hash_hex)
|
||||
r = self.conn.do(o)
|
||||
self.assertEqual(r['status'], 1)
|
||||
|
||||
c = EthExpire(self.chain_spec)
|
||||
o = c.expires(self.address, sender_address=self.accounts[0])
|
||||
r = self.rpc.do(o)
|
||||
self.assertEqual(self.expire, int(r, 16))
|
1
python/eth_minter/__init__.py
Normal file
1
python/eth_minter/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
from .minter import EthMinter
|
25
python/eth_minter/minter.py
Normal file
25
python/eth_minter/minter.py
Normal file
@ -0,0 +1,25 @@
|
||||
# external imports
|
||||
from chainlib.eth.tx import TxFormat
|
||||
from chainlib.eth.tx import TxFactory
|
||||
from chainlib.jsonrpc import JSONRPCRequest
|
||||
from chainlib.eth.constant import ZERO_ADDRESS
|
||||
from chainlib.eth.contract import ABIContractEncoder
|
||||
from chainlib.eth.contract import ABIContractType
|
||||
from chainlib.eth.contract import abi_decode_single
|
||||
from hexathon import add_0x
|
||||
|
||||
|
||||
class EthMinter(TxFactory):
|
||||
|
||||
def mint_to(self, contract_address, sender_address, recipient_address, value, tx_format=TxFormat.JSONRPC):
|
||||
enc = ABIContractEncoder()
|
||||
enc.method('mintTo')
|
||||
enc.typ(ABIContractType.ADDRESS)
|
||||
enc.typ(ABIContractType.UINT256)
|
||||
enc.address(recipient_address)
|
||||
enc.uint256(value)
|
||||
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
|
1
python/eth_minter/unittest/__init__.py
Normal file
1
python/eth_minter/unittest/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
from .interface import TestEthMinterInterface
|
51
python/eth_minter/unittest/base.py
Normal file
51
python/eth_minter/unittest/base.py
Normal file
@ -0,0 +1,51 @@
|
||||
# standard imports
|
||||
import os
|
||||
import logging
|
||||
import datetime
|
||||
|
||||
# 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.tx import TxFactory
|
||||
from chainlib.eth.tx import TxFormat
|
||||
from chainlib.eth.contract import ABIContractEncoder
|
||||
from chainlib.eth.contract import ABIContractType
|
||||
|
||||
# local imports
|
||||
from eth_minter import EthMinter
|
||||
|
||||
script_dir = os.path.dirname(os.path.realpath(__file__))
|
||||
contract_dir = os.path.join(script_dir, '..', '..', 'solidity')
|
||||
|
||||
logg = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class TestEthMinter(EthTesterCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestEthMinter, self).setUp()
|
||||
|
||||
self.conn = RPCConnection.connect(self.chain_spec, 'default')
|
||||
nonce_oracle = RPCNonceOracle(self.accounts[0], self.conn)
|
||||
|
||||
f = open(os.path.join(contract_dir, 'MinterTest.bin'))
|
||||
code = f.read()
|
||||
f.close()
|
||||
|
||||
txf = TxFactory(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
|
||||
tx = txf.template(self.accounts[0], None, use_nonce=True)
|
||||
|
||||
self.initial_supply = 1024
|
||||
enc = ABIContractEncoder()
|
||||
args = enc.get()
|
||||
|
||||
tx = txf.set_code(tx, code + args)
|
||||
(tx_hash_hex, o) = txf.build(tx)
|
||||
self.conn.do(o)
|
||||
o = receipt(tx_hash_hex)
|
||||
r = self.conn.do(o)
|
||||
self.assertEqual(r['status'], 1)
|
||||
self.address = r['contract_address']
|
||||
logg.debug('published minter test contract with hash {}'.format(r))
|
19
python/eth_minter/unittest/interface.py
Normal file
19
python/eth_minter/unittest/interface.py
Normal file
@ -0,0 +1,19 @@
|
||||
# external imports
|
||||
from chainlib.eth.tx import receipt
|
||||
from chainlib.eth.nonce import RPCNonceOracle
|
||||
|
||||
# local imports
|
||||
from eth_minter import EthMinter
|
||||
|
||||
|
||||
class TestEthMinterInterface:
|
||||
|
||||
def test_supply(self):
|
||||
self.alice = self.accounts[1]
|
||||
nonce_oracle = RPCNonceOracle(self.accounts[0], self.rpc)
|
||||
c = EthMinter(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
|
||||
(tx_hash, o) = c.mint_to(self.address, self.accounts[0], self.alice, self.initial_supply)
|
||||
self.rpc.do(o)
|
||||
o = receipt(tx_hash)
|
||||
r = self.rpc.do(o)
|
||||
self.assertEqual(r['status'],1)
|
1
python/eth_seal/__init__.py
Normal file
1
python/eth_seal/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
from .seal import EthSeal
|
32
python/eth_seal/seal.py
Normal file
32
python/eth_seal/seal.py
Normal file
@ -0,0 +1,32 @@
|
||||
# external imports
|
||||
from chainlib.eth.tx import TxFormat
|
||||
from chainlib.eth.tx import TxFactory
|
||||
from chainlib.jsonrpc import JSONRPCRequest
|
||||
from chainlib.eth.constant import ZERO_ADDRESS
|
||||
from chainlib.eth.contract import ABIContractEncoder
|
||||
from chainlib.eth.contract import ABIContractType
|
||||
from chainlib.eth.contract import abi_decode_single
|
||||
from hexathon import add_0x
|
||||
|
||||
|
||||
class EthSeal(TxFactory):
|
||||
|
||||
def __noarg(self, method, contract_address, sender_address=ZERO_ADDRESS, id_generator=None):
|
||||
j = JSONRPCRequest(id_generator)
|
||||
o = j.template()
|
||||
o['method'] = 'eth_call'
|
||||
enc = ABIContractEncoder()
|
||||
enc.method(method)
|
||||
data = add_0x(enc.get())
|
||||
tx = self.template(sender_address, contract_address)
|
||||
tx = self.set_code(tx, data)
|
||||
o['params'].append(self.normalize(tx))
|
||||
return o
|
||||
|
||||
|
||||
def max_seal_state(self, contract_address, sender_address=ZERO_ADDRESS, id_generator=None):
|
||||
return self.__noarg('maxSealState', contract_address, sender_address=sender_address, id_generator=id_generator)
|
||||
|
||||
|
||||
def seal_state(self, contract_address, sender_address=ZERO_ADDRESS, id_generator=None):
|
||||
return self.__noarg('sealState', contract_address, sender_address=sender_address, id_generator=id_generator)
|
1
python/eth_seal/unittest/__init__.py
Normal file
1
python/eth_seal/unittest/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
from .interface import TestEthSealInterface
|
60
python/eth_seal/unittest/base.py
Normal file
60
python/eth_seal/unittest/base.py
Normal file
@ -0,0 +1,60 @@
|
||||
# standard imports
|
||||
import os
|
||||
import logging
|
||||
|
||||
# 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.tx import TxFactory
|
||||
from chainlib.eth.tx import TxFormat
|
||||
from chainlib.eth.contract import ABIContractEncoder
|
||||
from chainlib.eth.contract import ABIContractType
|
||||
|
||||
script_dir = os.path.dirname(os.path.realpath(__file__))
|
||||
contract_dir = os.path.join(script_dir, '..', '..', 'solidity')
|
||||
|
||||
logg = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class TestEthSeal(EthTesterCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestEthSeal, self).setUp()
|
||||
|
||||
self.set_method = None
|
||||
|
||||
self.conn = RPCConnection.connect(self.chain_spec, 'default')
|
||||
nonce_oracle = RPCNonceOracle(self.accounts[0], self.conn)
|
||||
|
||||
f = open(os.path.join(contract_dir, 'SealTest.bin'))
|
||||
code = f.read()
|
||||
f.close()
|
||||
|
||||
txf = TxFactory(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
|
||||
tx = txf.template(self.accounts[0], None, use_nonce=True)
|
||||
|
||||
self.max_seal_state = 7
|
||||
tx = txf.set_code(tx, code)
|
||||
(tx_hash_hex, o) = txf.build(tx)
|
||||
self.conn.do(o)
|
||||
o = receipt(tx_hash_hex)
|
||||
r = self.conn.do(o)
|
||||
self.assertEqual(r['status'], 1)
|
||||
self.address = r['contract_address']
|
||||
logg.debug('published seal test contract with hash {}'.format(r))
|
||||
|
||||
|
||||
def seal(self, contract_address, sender_address, v, tx_format=TxFormat.JSONRPC):
|
||||
nonce_oracle = RPCNonceOracle(self.accounts[0], self.conn)
|
||||
txf = TxFactory(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
|
||||
enc = ABIContractEncoder()
|
||||
enc.method('seal')
|
||||
enc.typ(ABIContractType.UINT256)
|
||||
enc.uint256(v)
|
||||
data = enc.get()
|
||||
tx = txf.template(sender_address, contract_address, use_nonce=True)
|
||||
tx = txf.set_code(tx, data)
|
||||
tx = txf.finalize(tx, tx_format)
|
||||
return tx
|
21
python/eth_seal/unittest/interface.py
Normal file
21
python/eth_seal/unittest/interface.py
Normal file
@ -0,0 +1,21 @@
|
||||
# external imports
|
||||
from chainlib.eth.tx import receipt
|
||||
|
||||
# local imports
|
||||
from eth_seal import EthSeal
|
||||
|
||||
|
||||
class TestEthSealInterface:
|
||||
|
||||
def __init__(self):
|
||||
self.set_method = None
|
||||
self.max_seal_state = 0
|
||||
|
||||
|
||||
def test_supply(self):
|
||||
if self.max_seal_state == 0:
|
||||
return
|
||||
c = EthSeal(self.chain_spec)
|
||||
o = c.max_seal_state(self.address, sender_address=self.accounts[0])
|
||||
r = self.rpc.do(o)
|
||||
self.assertEqual(self.max_seal_state, int(r, 16))
|
1
python/eth_writer/__init__.py
Normal file
1
python/eth_writer/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
from .interface import *
|
44
python/eth_writer/interface.py
Normal file
44
python/eth_writer/interface.py
Normal file
@ -0,0 +1,44 @@
|
||||
# external imports
|
||||
from chainlib.eth.tx import TxFormat
|
||||
from chainlib.eth.tx import TxFactory
|
||||
from chainlib.jsonrpc import JSONRPCRequest
|
||||
from chainlib.eth.constant import ZERO_ADDRESS
|
||||
from chainlib.eth.contract import ABIContractEncoder
|
||||
from chainlib.eth.contract import ABIContractType
|
||||
from hexathon import add_0x
|
||||
|
||||
class EthWriter(TxFactory):
|
||||
|
||||
def __single_address_method(self, method, contract_address, sender_address, address, tx_format=TxFormat.JSONRPC):
|
||||
enc = ABIContractEncoder()
|
||||
enc.method(method)
|
||||
enc.typ(ABIContractType.ADDRESS)
|
||||
enc.address(address)
|
||||
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 add_writer(self, contract_address, sender_address, address, tx_format=TxFormat.JSONRPC):
|
||||
return self.__single_address_method('addWriter', contract_address, sender_address, address, tx_format)
|
||||
|
||||
|
||||
def delete_writer(self, contract_address, sender_address, address, tx_format=TxFormat.JSONRPC):
|
||||
return self.__single_address_method('deleteWriter', contract_address, sender_address, address, tx_format)
|
||||
|
||||
|
||||
def is_writer(self, contract_address, address, sender_address=ZERO_ADDRESS, id_generator=None):
|
||||
j = JSONRPCRequest(id_generator)
|
||||
o = j.template()
|
||||
o['method'] = 'eth_call'
|
||||
enc = ABIContractEncoder()
|
||||
enc.method('isWriter')
|
||||
enc.typ(ABIContractType.ADDRESS)
|
||||
enc.address(address)
|
||||
data = add_0x(enc.get())
|
||||
tx = self.template(sender_address, contract_address)
|
||||
tx = self.set_code(tx, data)
|
||||
o['params'].append(self.normalize(tx))
|
||||
return o
|
1
python/eth_writer/unittest/__init__.py
Normal file
1
python/eth_writer/unittest/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
from .interface import TestEthWriterInterface
|
58
python/eth_writer/unittest/base.py
Normal file
58
python/eth_writer/unittest/base.py
Normal file
@ -0,0 +1,58 @@
|
||||
# standard imports
|
||||
import os
|
||||
import logging
|
||||
|
||||
# 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.tx import TxFactory
|
||||
from chainlib.eth.tx import TxFormat
|
||||
from chainlib.eth.contract import ABIContractEncoder
|
||||
from chainlib.eth.contract import ABIContractType
|
||||
|
||||
# local imports
|
||||
from eth_writer import EthWriter
|
||||
|
||||
script_dir = os.path.dirname(os.path.realpath(__file__))
|
||||
contract_dir = os.path.join(script_dir, '..', '..', 'solidity')
|
||||
|
||||
logg = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class TestEthWriter(EthTesterCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestEthWriter, self).setUp()
|
||||
|
||||
self.set_method = None
|
||||
|
||||
self.conn = RPCConnection.connect(self.chain_spec, 'default')
|
||||
nonce_oracle = RPCNonceOracle(self.accounts[0], self.conn)
|
||||
|
||||
f = open(os.path.join(contract_dir, 'WriterTest.bin'))
|
||||
code = f.read()
|
||||
f.close()
|
||||
|
||||
txf = TxFactory(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
|
||||
tx = txf.template(self.accounts[0], None, use_nonce=True)
|
||||
tx = txf.set_code(tx, code)
|
||||
(tx_hash_hex, o) = txf.build(tx)
|
||||
self.conn.do(o)
|
||||
o = receipt(tx_hash_hex)
|
||||
r = self.conn.do(o)
|
||||
self.assertEqual(r['status'], 1)
|
||||
self.address = r['contract_address']
|
||||
self.contracts['writer'] = self.address
|
||||
self.roles['publisher'] = self.accounts[0]
|
||||
self.roles['writer'] = self.accounts[1]
|
||||
logg.debug('published writer test contract with hash {}'.format(r))
|
||||
|
||||
c = EthWriter(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
|
||||
(tx_hash, o) = c.add_writer(self.address, self.accounts[0], self.accounts[0])
|
||||
self.rpc.do(o)
|
||||
o = receipt(tx_hash)
|
||||
r = self.rpc.do(o)
|
||||
self.assertEqual(r['status'], 1)
|
||||
|
45
python/eth_writer/unittest/interface.py
Normal file
45
python/eth_writer/unittest/interface.py
Normal file
@ -0,0 +1,45 @@
|
||||
# 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
|
||||
|
||||
# local imports
|
||||
from eth_writer import EthWriter
|
||||
|
||||
|
||||
class TestEthWriterInterface:
|
||||
|
||||
def test_add_delete(self):
|
||||
writer_contract_address = self.contracts['writer']
|
||||
publisher_address = self.roles.get('publisher')
|
||||
writer_account = self.roles['writer']
|
||||
|
||||
nonce_oracle = RPCNonceOracle(self.publisher, conn=self.conn)
|
||||
c = EthWriter(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
|
||||
|
||||
o = c.is_writer(writer_contract_address, publisher_address, sender_address=publisher_address)
|
||||
r = self.rpc.do(o)
|
||||
self.assertEqual(int(r, 16), 1)
|
||||
|
||||
self.alice = self.accounts[1]
|
||||
(tx_hash, o) = c.add_writer(writer_contract_address, publisher_address, writer_account)
|
||||
self.rpc.do(o)
|
||||
o = receipt(tx_hash)
|
||||
r = self.rpc.do(o)
|
||||
self.assertEqual(r['status'], 1)
|
||||
|
||||
o = c.is_writer(writer_contract_address, writer_account, sender_address=publisher_address)
|
||||
r = self.rpc.do(o)
|
||||
self.assertEqual(int(r, 16), 1)
|
||||
|
||||
self.alice = self.accounts[1]
|
||||
(tx_hash, o) = c.delete_writer(writer_contract_address, publisher_address, writer_account)
|
||||
self.rpc.do(o)
|
||||
o = receipt(tx_hash)
|
||||
r = self.rpc.do(o)
|
||||
self.assertEqual(r['status'], 1)
|
||||
|
||||
o = c.is_writer(writer_contract_address, self.alice, sender_address=publisher_address)
|
||||
r = self.rpc.do(o)
|
||||
self.assertEqual(int(r, 16), 0)
|
@ -1 +1 @@
|
||||
chainlib-eth~=0.4.7
|
||||
chainlib-eth~=0.4.24
|
||||
|
15
python/run_tests.sh
Executable file
15
python/run_tests.sh
Executable file
@ -0,0 +1,15 @@
|
||||
#!/bin/bash
|
||||
|
||||
export PYTHONPATH=${PYTHONPATH}:.
|
||||
>&2 echo "using pythonpath $PYTHONPATH"
|
||||
|
||||
set -e
|
||||
set -x
|
||||
for f in `ls tests/*.py`; do
|
||||
python $f
|
||||
if [ $? -gt 0 ]; then
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
set +x
|
||||
set +e
|
@ -1,6 +1,6 @@
|
||||
[metadata]
|
||||
name = cic-contracts
|
||||
version = 0.2.0
|
||||
version = 0.3.0
|
||||
description = CIC network smart contract interfaces
|
||||
author = Louis Holbrook
|
||||
author_email = dev@holbrook.no
|
||||
@ -26,6 +26,8 @@ licence_files =
|
||||
|
||||
[options]
|
||||
include_package_data = True
|
||||
python_requires = >= 3.6
|
||||
python_requires = >= 3.7
|
||||
packages =
|
||||
cic_contracts
|
||||
eth_capped
|
||||
eth_expire
|
||||
|
1
python/solidity/BurnerTest.bin
Normal file
1
python/solidity/BurnerTest.bin
Normal file
@ -0,0 +1 @@
|
||||
608060405234801561001057600080fd5b5060405161070438038061070483398181016040528101906100329190610081565b8060008190555080600281905550506100ae565b600080fd5b6000819050919050565b61005e8161004b565b811461006957600080fd5b50565b60008151905061007b81610055565b92915050565b60006020828403121561009757610096610046565b5b60006100a58482850161006c565b91505092915050565b610647806100bd6000396000f3fe608060405234801561001057600080fd5b506004361061007f576000357c01000000000000000000000000000000000000000000000000000000009004806301ffc9a71461008457806342966c68146100b457806344d17187146100e457806344df8e7014610100578063a2309ff81461011e578063d89135cd1461013c575b600080fd5b61009e60048036038101906100999190610353565b61015a565b6040516100ab919061039b565b60405180910390f35b6100ce60048036038101906100c991906103ec565b61020a565b6040516100db919061039b565b60405180910390f35b6100fe60048036038101906100f991906104dc565b61021f565b005b61010861022f565b604051610115919061055f565b60405180910390f35b610126610241565b604051610133919061055f565b60405180910390f35b610144610247565b604051610151919061055f565b60405180910390f35b60006301ffc9a77c010000000000000000000000000000000000000000000000000000000002827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916036101ae5760019050610205565b63bc4babdd7c010000000000000000000000000000000000000000000000000000000002827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916036102005760019050610205565b600090505b919050565b60006102158261024d565b5060019050919050565b6102288361020a565b5050505050565b600061023c60005461024d565b905090565b60005481565b60015481565b6000808260025461025e91906105a9565b101561026957600080fd5b816001600082825461027b91906105dd565b92505081905550816002600082825461029491906105a9565b925050819055503373ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5836040516102e1919061055f565b60405180910390a2819050919050565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b610330816102fb565b811461033b57600080fd5b50565b60008135905061034d81610327565b92915050565b600060208284031215610369576103686102f1565b5b60006103778482850161033e565b91505092915050565b60008115159050919050565b61039581610380565b82525050565b60006020820190506103b0600083018461038c565b92915050565b6000819050919050565b6103c9816103b6565b81146103d457600080fd5b50565b6000813590506103e6816103c0565b92915050565b600060208284031215610402576104016102f1565b5b6000610410848285016103d7565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061044482610419565b9050919050565b61045481610439565b811461045f57600080fd5b50565b6000813590506104718161044b565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f84011261049c5761049b610477565b5b8235905067ffffffffffffffff8111156104b9576104b861047c565b5b6020830191508360018202830111156104d5576104d4610481565b5b9250929050565b600080600080606085870312156104f6576104f56102f1565b5b600061050487828801610462565b9450506020610515878288016103d7565b935050604085013567ffffffffffffffff811115610536576105356102f6565b5b61054287828801610486565b925092505092959194509250565b610559816103b6565b82525050565b60006020820190506105746000830184610550565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006105b4826103b6565b91506105bf836103b6565b92508282039050818111156105d7576105d661057a565b5b92915050565b60006105e8826103b6565b91506105f3836103b6565b925082820190508082111561060b5761060a61057a565b5b9291505056fea2646970667358221220cf04ca2f9a9ef1aee6a7109799862035ae01e772554ee9c71f0ca5243159197164736f6c63430008130033
|
50
python/solidity/BurnerTest.sol
Normal file
50
python/solidity/BurnerTest.sol
Normal file
@ -0,0 +1,50 @@
|
||||
pragma solidity >=0.6.3;
|
||||
|
||||
// Author: Louis Holbrook <dev@holbrook.no> 0826EDA1702D1E87C6E2875121D2E7BB88C2A746
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
contract MinterTest {
|
||||
uint256 public totalMinted;
|
||||
uint256 public totalBurned;
|
||||
uint256 balance;
|
||||
|
||||
event Burn(address indexed _burner, uint256 _burned);
|
||||
|
||||
constructor(uint256 _mintValue) {
|
||||
totalMinted = _mintValue;
|
||||
balance = _mintValue;
|
||||
}
|
||||
|
||||
function burn(address _from, uint256 _value, bytes calldata _data) public {
|
||||
_from;
|
||||
_data;
|
||||
burn(_value);
|
||||
}
|
||||
|
||||
function burn(uint256 _value) public returns (bool) {
|
||||
burnCore(_value);
|
||||
return true;
|
||||
}
|
||||
|
||||
function burnCore(uint256 _value) internal returns(uint256) {
|
||||
require(balance - _value >= 0);
|
||||
totalBurned += _value;
|
||||
balance -= _value;
|
||||
emit Burn(msg.sender, _value);
|
||||
return _value;
|
||||
}
|
||||
|
||||
function burn() public returns (uint256) {
|
||||
return burnCore(totalMinted);
|
||||
}
|
||||
|
||||
function supportsInterface(bytes4 _sum) public pure returns (bool) {
|
||||
if (_sum == 0x01ffc9a7) { // EIP165
|
||||
return true;
|
||||
}
|
||||
if (_sum == 0xbc4babdd) { // Burner
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
1
python/solidity/CappedTest.bin
Normal file
1
python/solidity/CappedTest.bin
Normal file
@ -0,0 +1 @@
|
||||
608060405234801561001057600080fd5b506040516104003803806104008339818101604052810190610032919061007a565b80600081905550506100a7565b600080fd5b6000819050919050565b61005781610044565b811461006257600080fd5b50565b6000815190506100748161004e565b92915050565b6000602082840312156100905761008f61003f565b5b600061009e84828501610065565b91505092915050565b61034a806100b66000396000f3fe608060405234801561001057600080fd5b506004361061005e576000357c01000000000000000000000000000000000000000000000000000000009004806301ffc9a7146100635780636f8b44b014610093578063d5abeb01146100af575b600080fd5b61007d60048036038101906100789190610224565b6100cd565b60405161008a919061026c565b60405180910390f35b6100ad60048036038101906100a891906102bd565b61017d565b005b6100b76101c1565b6040516100c491906102f9565b60405180910390f35b60006301ffc9a77c010000000000000000000000000000000000000000000000000000000002827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916036101215760019050610178565b63869f75947c010000000000000000000000000000000000000000000000000000000002827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916036101735760019050610178565b600090505b919050565b6000547f9722adea12ab7ef86fc45b88f0e0b567639e8dddaae60261e08c03d747fbbfe6826040516101af91906102f9565b60405180910390a28060008190555050565b60005481565b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b610201816101cc565b811461020c57600080fd5b50565b60008135905061021e816101f8565b92915050565b60006020828403121561023a576102396101c7565b5b60006102488482850161020f565b91505092915050565b60008115159050919050565b61026681610251565b82525050565b6000602082019050610281600083018461025d565b92915050565b6000819050919050565b61029a81610287565b81146102a557600080fd5b50565b6000813590506102b781610291565b92915050565b6000602082840312156102d3576102d26101c7565b5b60006102e1848285016102a8565b91505092915050565b6102f381610287565b82525050565b600060208201905061030e60008301846102ea565b9291505056fea2646970667358221220f6bc26e7c6827142ccee8c0cadc8cb76d33712a68eacd67b69e4f8108aa2b59064736f6c63430008130033
|
29
python/solidity/CappedTest.sol
Normal file
29
python/solidity/CappedTest.sol
Normal file
@ -0,0 +1,29 @@
|
||||
pragma solidity >=0.6.3;
|
||||
|
||||
// Author: Louis Holbrook <dev@holbrook.no> 0826EDA1702D1E87C6E2875121D2E7BB88C2A746
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
contract CappedTest {
|
||||
event Cap(uint256 indexed _oldCap, uint256 _newCap);
|
||||
|
||||
uint256 public maxSupply;
|
||||
|
||||
constructor(uint256 _supply) {
|
||||
maxSupply = _supply;
|
||||
}
|
||||
|
||||
function setMaxSupply(uint256 _supply) public {
|
||||
emit Cap(maxSupply, _supply);
|
||||
maxSupply = _supply;
|
||||
}
|
||||
|
||||
function supportsInterface(bytes4 _sum) public pure returns (bool) {
|
||||
if (_sum == 0x01ffc9a7) { // EIP165
|
||||
return true;
|
||||
}
|
||||
if (_sum == 0x869f7594) { // Capped
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
1
python/solidity/ExpireTest.bin
Normal file
1
python/solidity/ExpireTest.bin
Normal file
@ -0,0 +1 @@
|
||||
608060405234801561001057600080fd5b506040516105143803806105148339818101604052810190610032919061007a565b80600081905550506100a7565b600080fd5b6000819050919050565b61005781610044565b811461006257600080fd5b50565b6000815190506100748161004e565b92915050565b6000602082840312156100905761008f61003f565b5b600061009e84828501610065565b91505092915050565b61045e806100b66000396000f3fe608060405234801561001057600080fd5b5060043610610069576000357c01000000000000000000000000000000000000000000000000000000009004806301cceb381461006e57806301ffc9a71461008a5780635f408c04146100ba578063b1cb0db3146100d8575b600080fd5b610088600480360381019061008391906102df565b6100f6565b005b6100a4600480360381019061009f9190610364565b610162565b6040516100b191906103ac565b60405180910390f35b6100c2610212565b6040516100cf91906103e3565b60405180910390f35b6100e061029e565b6040516100ed919061040d565b60405180910390f35b600160009054906101000a900460ff161561011057600080fd5b600054811161011e57600080fd5b6000547ff5bd6cb27a0006b5ea8618058a0d84719695cb6d984f4840bc1a54ca12ae4b7c82604051610150919061040d565b60405180910390a28060008190555050565b60006301ffc9a77c010000000000000000000000000000000000000000000000000000000002827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916036101b6576001905061020d565b63841a0e947c010000000000000000000000000000000000000000000000000000000002827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191603610208576001905061020d565b600090505b919050565b6000600160009054906101000a900460ff1615610232576001905061029b565b600054421015610245576000905061029b565b60018060006101000a81548160ff0219169083151502179055507ff80dbaea4785589e52984ca36a31de106adc77759539a5c7d92883bf49692fe94260405161028e919061040d565b60405180910390a1600190505b90565b60005481565b600080fd5b6000819050919050565b6102bc816102a9565b81146102c757600080fd5b50565b6000813590506102d9816102b3565b92915050565b6000602082840312156102f5576102f46102a4565b5b6000610303848285016102ca565b91505092915050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6103418161030c565b811461034c57600080fd5b50565b60008135905061035e81610338565b92915050565b60006020828403121561037a576103796102a4565b5b60006103888482850161034f565b91505092915050565b60008115159050919050565b6103a681610391565b82525050565b60006020820190506103c1600083018461039d565b92915050565b600060ff82169050919050565b6103dd816103c7565b82525050565b60006020820190506103f860008301846103d4565b92915050565b610407816102a9565b82525050565b600060208201905061042260008301846103fe565b9291505056fea264697066735822122008d6e0c184036b44d56435108c0e081869b445ea32edbcd7035807691a26a11264736f6c63430008130033
|
47
python/solidity/ExpireTest.sol
Normal file
47
python/solidity/ExpireTest.sol
Normal file
@ -0,0 +1,47 @@
|
||||
pragma solidity >=0.6.3;
|
||||
|
||||
// Author: Louis Holbrook <dev@holbrook.no> 0826EDA1702D1E87C6E2875121D2E7BB88C2A746
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
contract ExpireTest {
|
||||
|
||||
uint256 public expires;
|
||||
bool expired;
|
||||
|
||||
event Expired(uint256 _timestamp);
|
||||
event ExpiryChange(uint256 indexed _oldTimestamp, uint256 _newTimestamp);
|
||||
|
||||
constructor(uint256 _timestamp) {
|
||||
expires = _timestamp;
|
||||
}
|
||||
|
||||
function setExpiry(uint256 _timestamp) public {
|
||||
require(!expired);
|
||||
require(_timestamp > expires);
|
||||
emit ExpiryChange(expires, _timestamp);
|
||||
expires = _timestamp;
|
||||
}
|
||||
|
||||
function applyExpiry() public returns(uint8) {
|
||||
if (expired) {
|
||||
return 1;
|
||||
}
|
||||
if (block.timestamp < expires) {
|
||||
return 0;
|
||||
}
|
||||
expired = true;
|
||||
emit Expired(block.timestamp);
|
||||
return 1;
|
||||
}
|
||||
|
||||
function supportsInterface(bytes4 _sum) public pure returns (bool) {
|
||||
if (_sum == 0x01ffc9a7) { // EIP165
|
||||
return true;
|
||||
}
|
||||
if (_sum == 0x841a0e94) { // Expire
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
1
python/solidity/MinterTest.bin
Normal file
1
python/solidity/MinterTest.bin
Normal file
@ -0,0 +1 @@
|
||||
608060405234801561001057600080fd5b50610653806100206000396000f3fe608060405234801561001057600080fd5b5060043610610074576000357c01000000000000000000000000000000000000000000000000000000009004806301ffc9a714610079578063449a52f8146100a95780638832e6e3146100d957806394d008ef146100f5578063e3d670d714610111575b600080fd5b610093600480360381019061008e9190610353565b610141565b6040516100a0919061039b565b60405180910390f35b6100c360048036038101906100be919061044a565b6101f1565b6040516100d0919061039b565b60405180910390f35b6100f360048036038101906100ee91906104ef565b6102b7565b005b61010f600480360381019061010a91906104ef565b6102c8565b005b61012b60048036038101906101269190610563565b6102d9565b604051610138919061059f565b60405180910390f35b60006301ffc9a77c010000000000000000000000000000000000000000000000000000000002827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19160361019557600190506101ec565b635878bcf47c010000000000000000000000000000000000000000000000000000000002827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916036101e757600190506101ec565b600090505b919050565b6000816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825461024191906105e9565b925050819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fab8530f87dc9b59234c4623bf917212bb2536d647574c8e7e5da92c2ede0c9f8846040516102a5919061059f565b60405180910390a36001905092915050565b6102c184846101f1565b5050505050565b6102d284846101f1565b5050505050565b60006020528060005260406000206000915090505481565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b610330816102fb565b811461033b57600080fd5b50565b60008135905061034d81610327565b92915050565b600060208284031215610369576103686102f1565b5b60006103778482850161033e565b91505092915050565b60008115159050919050565b61039581610380565b82525050565b60006020820190506103b0600083018461038c565b92915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006103e1826103b6565b9050919050565b6103f1816103d6565b81146103fc57600080fd5b50565b60008135905061040e816103e8565b92915050565b6000819050919050565b61042781610414565b811461043257600080fd5b50565b6000813590506104448161041e565b92915050565b60008060408385031215610461576104606102f1565b5b600061046f858286016103ff565b925050602061048085828601610435565b9150509250929050565b600080fd5b600080fd5b600080fd5b60008083601f8401126104af576104ae61048a565b5b8235905067ffffffffffffffff8111156104cc576104cb61048f565b5b6020830191508360018202830111156104e8576104e7610494565b5b9250929050565b60008060008060608587031215610509576105086102f1565b5b6000610517878288016103ff565b945050602061052887828801610435565b935050604085013567ffffffffffffffff811115610549576105486102f6565b5b61055587828801610499565b925092505092959194509250565b600060208284031215610579576105786102f1565b5b6000610587848285016103ff565b91505092915050565b61059981610414565b82525050565b60006020820190506105b46000830184610590565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006105f482610414565b91506105ff83610414565b9250828201905080821115610617576106166105ba565b5b9291505056fea2646970667358221220a5a810b6de36b1154b4b2d37d08d4e8a5fe442c870cd58cdba0d86a13da3dda964736f6c63430008130033
|
35
python/solidity/MinterTest.sol
Normal file
35
python/solidity/MinterTest.sol
Normal file
@ -0,0 +1,35 @@
|
||||
pragma solidity >=0.6.3;
|
||||
|
||||
// Author: Louis Holbrook <dev@holbrook.no> 0826EDA1702D1E87C6E2875121D2E7BB88C2A746
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
contract MinterTest {
|
||||
mapping (address => uint256) public balance;
|
||||
|
||||
event Mint(address indexed _minter, address indexed _beneficiary, uint256 _value);
|
||||
|
||||
function mintTo(address _beneficiary, uint256 _value) public returns (bool) {
|
||||
balance[_beneficiary] += _value;
|
||||
emit Mint(msg.sender, _beneficiary, _value);
|
||||
return true;
|
||||
}
|
||||
|
||||
function mint(address _beneficiary, uint256 _value, bytes calldata _data) public {
|
||||
_data;
|
||||
mintTo(_beneficiary, _value);
|
||||
}
|
||||
function safeMint(address _beneficiary, uint256 _value, bytes calldata _data) public {
|
||||
_data;
|
||||
mintTo(_beneficiary, _value);
|
||||
}
|
||||
|
||||
function supportsInterface(bytes4 _sum) public pure returns (bool) {
|
||||
if (_sum == 0x01ffc9a7) { // EIP165
|
||||
return true;
|
||||
}
|
||||
if (_sum == 0x5878bcf4) { // Minter
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
1
python/solidity/SealTest.bin
Normal file
1
python/solidity/SealTest.bin
Normal file
@ -0,0 +1 @@
|
||||
6080604052600760015534801561001557600080fd5b50610355806100256000396000f3fe608060405234801561001057600080fd5b5060043610610069576000357c01000000000000000000000000000000000000000000000000000000009004806301ffc9a71461006e57806318cbbcfc1461009e57806331a5995d146100bc57806386fe212d146100da575b600080fd5b6100886004803603810190610083919061022f565b6100f6565b6040516100959190610277565b60405180910390f35b6100a66101a6565b6040516100b391906102ab565b60405180910390f35b6100c46101ac565b6040516100d191906102ab565b60405180910390f35b6100f460048036038101906100ef91906102f2565b6101b2565b005b60006301ffc9a77c010000000000000000000000000000000000000000000000000000000002827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19160361014a57600190506101a1565b630d7491f87c010000000000000000000000000000000000000000000000000000000002827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19160361019c57600190506101a1565b600090505b919050565b60015481565b60005481565b60015481106101c057600080fd5b80600080828254179250508190555050565b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b61020c816101d7565b811461021757600080fd5b50565b60008135905061022981610203565b92915050565b600060208284031215610245576102446101d2565b5b60006102538482850161021a565b91505092915050565b60008115159050919050565b6102718161025c565b82525050565b600060208201905061028c6000830184610268565b92915050565b6000819050919050565b6102a581610292565b82525050565b60006020820190506102c0600083018461029c565b92915050565b6102cf81610292565b81146102da57600080fd5b50565b6000813590506102ec816102c6565b92915050565b600060208284031215610308576103076101d2565b5b6000610316848285016102dd565b9150509291505056fea26469706673582212208356fec8f4fc7719bf58ea1be5e22cf56cadb8367918f5b4e0a90cad23396bb064736f6c63430008130033
|
25
python/solidity/SealTest.sol
Normal file
25
python/solidity/SealTest.sol
Normal file
@ -0,0 +1,25 @@
|
||||
pragma solidity >=0.6.12;
|
||||
|
||||
// Author: Louis Holbrook <dev@holbrook.no> 0826EDA1702D1E87C6E2875121D2E7BB88C2A746
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
contract SealTest {
|
||||
event SealStateChange(bool indexed _final, uint256 _sealState);
|
||||
uint256 public sealState;
|
||||
uint256 public maxSealState = 7;
|
||||
|
||||
function seal(uint256 _bits) public {
|
||||
require(_bits < maxSealState);
|
||||
sealState |= _bits;
|
||||
}
|
||||
|
||||
function supportsInterface(bytes4 _sum) public pure returns (bool) {
|
||||
if (_sum == 0x01ffc9a7) { // EIP165
|
||||
return true;
|
||||
}
|
||||
if (_sum == 0x0d7491f8) { // Capped
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
1
python/solidity/WriterTest.bin
Normal file
1
python/solidity/WriterTest.bin
Normal file
@ -0,0 +1 @@
|
||||
608060405234801561001057600080fd5b506104da806100206000396000f3fe608060405234801561001057600080fd5b5060043610610069576000357c01000000000000000000000000000000000000000000000000000000009004806301ffc9a71461006e5780632b29ba231461009e5780635ae06f7e146100ce578063da2824a8146100fe575b600080fd5b6100886004803603810190610083919061038c565b61012e565b60405161009591906103d4565b60405180910390f35b6100b860048036038101906100b3919061044d565b6101de565b6040516100c591906103d4565b60405180910390f35b6100e860048036038101906100e3919061044d565b6101fe565b6040516100f591906103d4565b60405180910390f35b6101186004803603810190610113919061044d565b610296565b60405161012591906103d4565b60405180910390f35b60006301ffc9a77c010000000000000000000000000000000000000000000000000000000002827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19160361018257600190506101d9565b63abe1f1f57c010000000000000000000000000000000000000000000000000000000002827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916036101d457600190506101d9565b600090505b919050565b60006020528060005260406000206000915054906101000a900460ff1681565b6000806000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055507f9002f14780245e47491e7a2caae4712e7cea2e298e4e76c6916845145b90a51c826040516102859190610489565b60405180910390a160019050919050565b600060016000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055507f6ff3aa2ea7b53070f6d9d07a445d338d89e8edef44250ffa8be19f53910d4a2e8260405161031e9190610489565b60405180910390a160019050919050565b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b61036981610334565b811461037457600080fd5b50565b60008135905061038681610360565b92915050565b6000602082840312156103a2576103a161032f565b5b60006103b084828501610377565b91505092915050565b60008115159050919050565b6103ce816103b9565b82525050565b60006020820190506103e960008301846103c5565b92915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061041a826103ef565b9050919050565b61042a8161040f565b811461043557600080fd5b50565b60008135905061044781610421565b92915050565b6000602082840312156104635761046261032f565b5b600061047184828501610438565b91505092915050565b6104838161040f565b82525050565b600060208201905061049e600083018461047a565b9291505056fea26469706673582212206bef2d3402160122da272241da7b2729136d4bc1e4399f01ddd8c8a7d3b93cdd64736f6c63430008130033
|
33
python/solidity/WriterTest.sol
Normal file
33
python/solidity/WriterTest.sol
Normal file
@ -0,0 +1,33 @@
|
||||
pragma solidity >=0.6.3;
|
||||
|
||||
// Author: Louis Holbrook <dev@holbrook.no> 0826EDA1702D1E87C6E2875121D2E7BB88C2A746
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
contract WriterTest {
|
||||
mapping (address => bool ) public isWriter;
|
||||
|
||||
event WriterAdded(address _writer);
|
||||
event WriterDeleted(address _writer);
|
||||
|
||||
function addWriter(address _writer) public returns (bool) {
|
||||
isWriter[_writer] = true;
|
||||
emit WriterAdded(_writer);
|
||||
return true;
|
||||
}
|
||||
|
||||
function deleteWriter(address _writer) public returns (bool) {
|
||||
isWriter[_writer] = false;
|
||||
emit WriterDeleted(_writer);
|
||||
return true;
|
||||
}
|
||||
|
||||
function supportsInterface(bytes4 _sum) public pure returns (bool) {
|
||||
if (_sum == 0x01ffc9a7) { // EIP165
|
||||
return true;
|
||||
}
|
||||
if (_sum == 0xabe1f1f5) { // Writer
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
@ -1,2 +1,4 @@
|
||||
eth_tester==0.5.0b3
|
||||
py-evm==0.3.0a20
|
||||
eth-erc20~=0.7.4
|
||||
eth-interface~=0.1.2
|
||||
|
29
python/tests/test_burner.py
Normal file
29
python/tests/test_burner.py
Normal file
@ -0,0 +1,29 @@
|
||||
# standard imports
|
||||
import unittest
|
||||
import logging
|
||||
import os
|
||||
from chainlib.eth.nonce import RPCNonceOracle
|
||||
from chainlib.eth.tx import receipt
|
||||
from eth_erc20 import ERC20
|
||||
from giftable_erc20_token import GiftableToken
|
||||
from eth_interface.unittest import TestERC165
|
||||
|
||||
# local imports
|
||||
from eth_burner import EthBurner
|
||||
from eth_burner.unittest import TestEthBurnerInterface
|
||||
from eth_burner.unittest.base import TestEthBurner
|
||||
|
||||
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
logg = logging.getLogger()
|
||||
|
||||
|
||||
class TestBurnerBase(TestEthBurner, TestEthBurnerInterface, TestERC165):
|
||||
|
||||
def setUp(self):
|
||||
super(TestBurnerBase, self).setUp()
|
||||
self.add_interface_check('bc4babdd')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
30
python/tests/test_capped.py
Normal file
30
python/tests/test_capped.py
Normal file
@ -0,0 +1,30 @@
|
||||
# standard imports
|
||||
import unittest
|
||||
import logging
|
||||
import os
|
||||
from chainlib.eth.nonce import RPCNonceOracle
|
||||
from chainlib.eth.tx import receipt
|
||||
from eth_erc20 import ERC20
|
||||
from giftable_erc20_token import GiftableToken
|
||||
from eth_interface.unittest import TestERC165
|
||||
|
||||
# local imports
|
||||
from eth_capped import EthCapped
|
||||
from eth_capped.unittest import TestEthCappedInterface
|
||||
from eth_capped.unittest.base import TestEthCapped
|
||||
|
||||
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
logg = logging.getLogger()
|
||||
|
||||
|
||||
class TestCappedBase(TestEthCapped, TestEthCappedInterface, TestERC165):
|
||||
|
||||
def setUp(self):
|
||||
super(TestCappedBase, self).setUp()
|
||||
self.add_interface_check('869f7594')
|
||||
self.set_method = self.set_max_supply
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
30
python/tests/test_expire.py
Normal file
30
python/tests/test_expire.py
Normal file
@ -0,0 +1,30 @@
|
||||
# standard imports
|
||||
import unittest
|
||||
import logging
|
||||
import os
|
||||
from chainlib.eth.nonce import RPCNonceOracle
|
||||
from chainlib.eth.tx import receipt
|
||||
from eth_erc20 import ERC20
|
||||
from giftable_erc20_token import GiftableToken
|
||||
from eth_interface.unittest import TestERC165
|
||||
|
||||
# local imports
|
||||
from eth_expire import EthExpire
|
||||
from eth_expire.unittest import TestEthExpireInterface
|
||||
from eth_expire.unittest.base import TestEthExpire
|
||||
|
||||
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
logg = logging.getLogger()
|
||||
|
||||
|
||||
class TestExpireBase(TestEthExpire, TestEthExpireInterface, TestERC165):
|
||||
|
||||
def setUp(self):
|
||||
super(TestExpireBase, self).setUp()
|
||||
self.add_interface_check('841a0e94')
|
||||
self.set_method = self.set_expiry
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
29
python/tests/test_minter.py
Normal file
29
python/tests/test_minter.py
Normal file
@ -0,0 +1,29 @@
|
||||
# standard imports
|
||||
import unittest
|
||||
import logging
|
||||
import os
|
||||
from chainlib.eth.nonce import RPCNonceOracle
|
||||
from chainlib.eth.tx import receipt
|
||||
from eth_erc20 import ERC20
|
||||
from giftable_erc20_token import GiftableToken
|
||||
from eth_interface.unittest import TestERC165
|
||||
|
||||
# local imports
|
||||
from eth_minter import EthMinter
|
||||
from eth_minter.unittest import TestEthMinterInterface
|
||||
from eth_minter.unittest.base import TestEthMinter
|
||||
|
||||
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
logg = logging.getLogger()
|
||||
|
||||
|
||||
class TestMinterBase(TestEthMinter, TestEthMinterInterface, TestERC165):
|
||||
|
||||
def setUp(self):
|
||||
super(TestMinterBase, self).setUp()
|
||||
self.add_interface_check('5878bcf4')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
30
python/tests/test_seal.py
Normal file
30
python/tests/test_seal.py
Normal file
@ -0,0 +1,30 @@
|
||||
# standard imports
|
||||
import unittest
|
||||
import logging
|
||||
import os
|
||||
from chainlib.eth.nonce import RPCNonceOracle
|
||||
from chainlib.eth.tx import receipt
|
||||
from eth_erc20 import ERC20
|
||||
from giftable_erc20_token import GiftableToken
|
||||
from eth_interface.unittest import TestERC165
|
||||
|
||||
# local imports
|
||||
from eth_seal import EthSeal
|
||||
from eth_seal.unittest import TestEthSealInterface
|
||||
from eth_seal.unittest.base import TestEthSeal
|
||||
|
||||
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
logg = logging.getLogger()
|
||||
|
||||
|
||||
class TestSealBase(TestEthSeal, TestEthSealInterface, TestERC165):
|
||||
|
||||
def setUp(self):
|
||||
super(TestSealBase, self).setUp()
|
||||
self.add_interface_check('0d7491f8')
|
||||
self.set_method = self.seal
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
29
python/tests/test_writer.py
Normal file
29
python/tests/test_writer.py
Normal file
@ -0,0 +1,29 @@
|
||||
# standard imports
|
||||
import unittest
|
||||
import logging
|
||||
import os
|
||||
from chainlib.eth.nonce import RPCNonceOracle
|
||||
from chainlib.eth.tx import receipt
|
||||
from eth_erc20 import ERC20
|
||||
from giftable_erc20_token import GiftableToken
|
||||
from eth_interface.unittest import TestERC165
|
||||
|
||||
# local imports
|
||||
from eth_writer import EthWriter
|
||||
from eth_writer.unittest import TestEthWriterInterface
|
||||
from eth_writer.unittest.base import TestEthWriter
|
||||
|
||||
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
logg = logging.getLogger()
|
||||
|
||||
|
||||
class TestWriterBase(TestEthWriter, TestEthWriterInterface, TestERC165):
|
||||
|
||||
def setUp(self):
|
||||
super(TestWriterBase, self).setUp()
|
||||
self.add_interface_check('abe1f1f5')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
@ -12,10 +12,11 @@ interface IBurner {
|
||||
function burn(address _from, uint256 _amount, bytes calldata _data) external;
|
||||
|
||||
// Burn given amount of tokens held by signer.
|
||||
function burn(uint256 _burn) external returns (bool);
|
||||
function burn(uint256 _amount) external returns (bool);
|
||||
|
||||
// Burn all tokens held by signer.
|
||||
function burn() external returns (bool);
|
||||
// Returns the amount of tokens burned.
|
||||
function burn() external returns (uint256);
|
||||
|
||||
// Total amount of tokens that have been burned.
|
||||
function totalBurned() external returns (uint256);
|
||||
|
12
solidity/Capped.sol
Normal file
12
solidity/Capped.sol
Normal file
@ -0,0 +1,12 @@
|
||||
pragma solidity >=0.6.12;
|
||||
|
||||
// Author: Louis Holbrook <dev@holbrook.no> 0826EDA1702D1E87C6E2875121D2E7BB88C2A746
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
// File-version: 1
|
||||
|
||||
interface ICapped {
|
||||
// Supply limit is changed.
|
||||
event Cap(uint256 indexed _oldCap, uint256 _newCap);
|
||||
// Return the supply limit.
|
||||
function maxSupply() external returns(uint256);
|
||||
}
|
@ -18,5 +18,5 @@ interface IWriter {
|
||||
function deleteWriter(address _writer) external returns (bool);
|
||||
|
||||
// Check whether the given address is a writer.
|
||||
function isWriter(address _writer) external returns (bool);
|
||||
function isWriter(address _writer) external view returns (bool);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user