commit e3cee0101823dc64e0a810260a350f59bb7390b1
parent 23083fc4abf5be52ce5f7a66e7a8ce77a0f9d68a
Author: nolash <dev@holbrook.no>
Date: Fri, 30 Apr 2021 19:00:47 +0200
WIP rehabilitating tests
Diffstat:
13 files changed, 278 insertions(+), 64 deletions(-)
diff --git a/.gitignore b/.gitignore
@@ -0,0 +1,6 @@
+__pycache__
+gmon.out
+*.pyc
+*.egg-info
+build/
+dist/
diff --git a/python/erc20_single_shot_faucet/__init__.py b/python/erc20_single_shot_faucet/__init__.py
@@ -3,4 +3,4 @@
# File-version: 1
# Description: Python interface to abi and bin files for faucet contracts
-from .faucet import SingleShotFaucet
+from .interface import Faucet
diff --git a/python/erc20_single_shot_faucet/data/ERC20SingleShotFaucetStorage.bin b/python/erc20_single_shot_faucet/data/ERC20SingleShotFaucetStorage.bin
@@ -0,0 +1 @@
+608060405234801561001057600080fd5b50336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600360009080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000600260008073ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610915806101096000396000f3fe608060405234801561001057600080fd5b50600436106100a5576000357c01000000000000000000000000000000000000000000000000000000009004806379ba50971161007857806379ba50971461016a5780638da5cb5b14610188578063e2095c07146101a6578063f2fde38b146101d6576100a5565b806301ffc9a7146100aa5780630a3b0a4f146100da5780633ef250131461010a578063764b07e71461013a575b600080fd5b6100c460048036038101906100bf9190610756565b6101f2565b6040516100d191906107f0565b60405180910390f35b6100f460048036038101906100ef919061072d565b61034a565b60405161010191906107f0565b60405180910390f35b610124600480360381019061011f919061072d565b61044a565b60405161013191906107f0565b60405180910390f35b610154600480360381019061014f919061072d565b610495565b604051610161919061080b565b60405180910390f35b6101726104ad565b60405161017f91906107f0565b60405180910390f35b6101906105ef565b60405161019d91906107d5565b60405180910390f35b6101c060048036038101906101bb919061077f565b610613565b6040516101cd91906107d5565b60405180910390f35b6101f060048036038101906101eb919061072d565b610652565b005b600063cbdb05c77c010000000000000000000000000000000000000000000000000000000002827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614156102475760019050610345565b6301ffc9a77c010000000000000000000000000000000000000000000000000000000002827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916141561029a5760019050610345565b639493f8b27c010000000000000000000000000000000000000000000000000000000002827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614156102ed5760019050610345565b6337a47be47c010000000000000000000000000000000000000000000000000000000002827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614156103405760019050610345565b600090505b919050565b60008060038054905090506003839080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550808373ffffffffffffffffffffffffffffffffffffffff167f9cc987676e7d63379f176ea50df0ae8d2d9d1141d1231d4ce15b5965f73c943060405160405180910390a36001915050919050565b600080600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054119050919050565b60026020528060005260406000206000915090505481565b60008060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461052d57600080fd5b336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3600191505090565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6003818154811061062357600080fd5b906000526020600020016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146106aa57600080fd5b80600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6000813590506106fd8161089a565b92915050565b600081359050610712816108b1565b92915050565b600081359050610727816108c8565b92915050565b60006020828403121561073f57600080fd5b600061074d848285016106ee565b91505092915050565b60006020828403121561076857600080fd5b600061077684828501610703565b91505092915050565b60006020828403121561079157600080fd5b600061079f84828501610718565b91505092915050565b6107b181610826565b82525050565b6107c081610838565b82525050565b6107cf81610890565b82525050565b60006020820190506107ea60008301846107a8565b92915050565b600060208201905061080560008301846107b7565b92915050565b600060208201905061082060008301846107c6565b92915050565b600061083182610870565b9050919050565b60008115159050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b6108a381610826565b81146108ae57600080fd5b50565b6108ba81610844565b81146108c557600080fd5b50565b6108d181610890565b81146108dc57600080fd5b5056fea2646970667358221220c9946d1d5ce7247846f019cfa3051aae1e32efe8f4d6aaf6be588bf4aadeb9f264736f6c63430008030033
+\ No newline at end of file
diff --git a/python/erc20_single_shot_faucet/data/ERC20SingleShotFaucetStorage.json b/python/erc20_single_shot_faucet/data/ERC20SingleShotFaucetStorage.json
@@ -0,0 +1 @@
+[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"addedAccount","type":"address"},{"indexed":true,"internalType":"uint256","name":"accountIndex","type":"uint256"}],"name":"AddressAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[],"name":"acceptOwnership","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"add","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"entry","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"have","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"_sum","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"_newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"usedAccounts","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]
diff --git a/python/erc20_single_shot_faucet/faucet.py b/python/erc20_single_shot_faucet/faucet.py
@@ -19,13 +19,16 @@ from chainlib.eth.contract import (
from chainlib.jsonrpc import jsonrpc_template
from hexathon import add_0x
-logg = logging.getLogger()
+# local imports
+from .interface import Faucet
+
+logg = logging.getLogger().getChild(__name__)
moddir = os.path.dirname(__file__)
datadir = os.path.join(moddir, 'data')
-class SingleShotFaucet(TxFactory):
+class SingleShotFaucet(Faucet):
__abi = None
__bytecode = None
@@ -71,59 +74,17 @@ class SingleShotFaucet(TxFactory):
return self.build(tx)
- def usable_for(self, contract_address, address, sender_address=ZERO_ADDRESS):
- o = jsonrpc_template()
- o['method'] = 'eth_call'
- enc = ABIContractEncoder()
- enc.method('cooldown')
- 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
-
-
- @classmethod
- def parse_usable_for(self, v):
- r = abi_decode_single(ABIContractType.UINT256, v)
- return r == 0
-
-
- def token(self, contract_address, sender_address=ZERO_ADDRESS):
- o = jsonrpc_template()
- o['method'] = 'eth_call'
- enc = ABIContractEncoder()
- enc.method('token')
- 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
-
-
- @classmethod
- def parse_token(self, v):
- return abi_decode_single(ABIContractType.ADDRESS, v)
-
-
- def amount(self, contract_address, block_height=None, sender_address=ZERO_ADDRESS):
- o = jsonrpc_template()
- o['method'] = 'eth_call'
+ # TODO: allow multiple overriders
+ def constructor(self, sender_address, token, store, accounts_index, overrider):
+ code = SingleShotFaucet.bytecode()
enc = ABIContractEncoder()
- enc.method('amount')
- data = add_0x(enc.get())
- tx = self.template(sender_address, contract_address)
- tx = self.set_code(tx, data)
- o['params'].append(self.normalize(tx))
-
- if block_height != None:
- o['params'].append(block_height)
-
- return o
-
-
- @classmethod
- def parse_amount(self, v):
- return abi_decode_single(ABIContractType.UINT256, v)
+ enc.uint256(0x60)
+ enc.address(token)
+ enc.address(store)
+ enc.address(accounts_index)
+ enc.uint256(0x01)
+ enc.address(overrider)
+ code += enc.get()
+ tx = self.template(sender_address, None, use_nonce=True)
+ tx = self.set_code(tx, code)
+ return self.build(tx)
diff --git a/python/erc20_single_shot_faucet/interface.py b/python/erc20_single_shot_faucet/interface.py
@@ -0,0 +1,75 @@
+# standard imports
+import logging
+
+# external imports
+from chainlib.eth.tx import TxFactory
+from chainlib.eth.constant import ZERO_ADDRESS
+from chainlib.eth.contract import (
+ abi_decode_single,
+ ABIContractEncoder,
+ ABIContractType,
+ )
+from chainlib.jsonrpc import jsonrpc_template
+from hexathon import add_0x
+
+logg = logging.getLogger().getChild(__name__)
+
+
+class Faucet(TxFactory):
+
+ def usable_for(self, contract_address, address, sender_address=ZERO_ADDRESS):
+ o = jsonrpc_template()
+ o['method'] = 'eth_call'
+ enc = ABIContractEncoder()
+ enc.method('cooldown')
+ 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
+
+
+ @classmethod
+ def parse_usable_for(self, v):
+ r = abi_decode_single(ABIContractType.UINT256, v)
+ return r == 0
+
+
+ def token(self, contract_address, sender_address=ZERO_ADDRESS):
+ o = jsonrpc_template()
+ o['method'] = 'eth_call'
+ enc = ABIContractEncoder()
+ enc.method('token')
+ 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
+
+
+ @classmethod
+ def parse_token(self, v):
+ return abi_decode_single(ABIContractType.ADDRESS, v)
+
+
+ def amount(self, contract_address, block_height=None, sender_address=ZERO_ADDRESS):
+ o = jsonrpc_template()
+ o['method'] = 'eth_call'
+ enc = ABIContractEncoder()
+ enc.method('amount')
+ data = add_0x(enc.get())
+ tx = self.template(sender_address, contract_address)
+ tx = self.set_code(tx, data)
+ o['params'].append(self.normalize(tx))
+
+ if block_height != None:
+ o['params'].append(block_height)
+
+ return o
+
+
+ @classmethod
+ def parse_amount(self, v):
+ return abi_decode_single(ABIContractType.UINT256, v)
diff --git a/python/erc20_single_shot_faucet/runnable/list.py b/python/erc20_single_shot_faucet/runnable/list.py
@@ -0,0 +1,83 @@
+"""Query faucet store
+
+.. moduleauthor:: Louis Holbrook <dev@holbrook.no>
+.. pgp:: 0826EDA1702D1E87C6E2875121D2E7BB88C2A746
+
+"""
+
+# standard imports
+import sys
+import os
+import json
+import argparse
+import logging
+
+# third-party imports
+from crypto_dev_signer.eth.signer import ReferenceSigner as EIP155Signer
+from crypto_dev_signer.keystore.dict import DictKeystore
+from crypto_dev_signer.eth.helper import EthTxExecutor
+from chainlib.chain import ChainSpec
+from chainlib.eth.nonce import RPCNonceOracle
+from chainlib.eth.gas import RPCGasOracle
+from chainlib.eth.connection import EthHTTPConnection
+from chainlib.eth.tx import receipt
+from chainlib.eth.constant import ZERO_CONTENT
+from chainlib.error import JSONRPCException
+
+# local imports
+from erc20_single_shot_faucet import SingleShotFaucet
+
+logging.basicConfig(level=logging.WARNING)
+logg = logging.getLogger()
+
+script_dir = os.path.dirname(__file__)
+data_dir = os.path.join(script_dir, '..', 'data')
+
+default_format = 'terminal'
+
+argparser = argparse.ArgumentParser()
+argparser.add_argument('-p', '--provider', dest='p', default='http://localhost:8545', type=str, help='RPC provider url (http only)')
+argparser.add_argument('-i', '--chain-spec', dest='i', type=str, default='evm:ethereum:1', help='Chain specification string')
+argparser.add_argument('-a', '--contract-address', dest='a', required=True, type=str, help='Faucet store contract address')
+argparser.add_argument('-f', '--format', dest='f', type=str, default=default_format, help='Output format [human, brief]')
+argparser.add_argument('-v', action='store_true', help='Be verbose')
+argparser.add_argument('-vv', action='store_true', help='Be more verbose')
+argparser.add_argument('--env-prefix', default=os.environ.get('CONFINI_ENV_PREFIX'), dest='env_prefix', type=str, help='environment prefix for variables to overwrite configuration')
+argparser.add_argument('address', type=str, help='Address to check faucet usage for')
+args = argparser.parse_args()
+
+if args.vv:
+ logg.setLevel(logging.DEBUG)
+elif args.v:
+ logg.setLevel(logging.INFO)
+
+chain_spec = ChainSpec.from_chain_str(args.i)
+
+rpc = EthHTTPConnection(args.p)
+faucet_store_address = args.a
+address = args.address
+fmt = args.f
+
+
+def out_element(e, fmt=default_format, w=sys.stdout):
+ logg.debug('format {}'.format(fmt))
+ if fmt == 'brief':
+ w.write(str(e[1]) + '\n')
+ else:
+ w.write('{} {}\n'.format(e[0], e[1]))
+
+
+def element(ifc, address, fmt=default_format, w=sys.stdout):
+ o = ifc.usable_for(faucet_store_address, address)
+ r = rpc.do(o)
+ have = ifc.parse_usable_for(r)
+ out_element((address, have), fmt, w)
+
+
+def main():
+ c = SingleShotFaucet(chain_spec)
+ element(c, address, fmt=fmt, w=sys.stdout)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/python/requirements.txt b/python/requirements.txt
@@ -1,3 +1,3 @@
confini~=0.3.6rc3
-crypto-dev-signer~=0.4.14b2
-chainlib~=0.0.2a13
+crypto-dev-signer~=0.4.14b3
+chainlib~=0.0.2b1
diff --git a/python/test_requirements.txt b/python/test_requirements.txt
@@ -1,2 +1,4 @@
eth_tester==0.5.0b3
py-evm==0.3.0a20
+web3==5.12.2
+giftable_erc20_token==0.0.8a10
diff --git a/python/tests/test_basic.py b/python/tests/test_basic.py
@@ -0,0 +1,74 @@
+# standard imports
+import os
+import unittest
+import json
+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.address import to_checksum_address
+from chainlib.eth.tx import (
+ receipt,
+ transaction,
+ TxFormat,
+ )
+from chainlib.eth.contract import (
+ abi_decode_single,
+ ABIContractType,
+ )
+from chainlib.eth.nonce import RPCNonceOracle
+from chainlib.eth.constant import ZERO_ADDRESS
+from giftable_erc20_token import GiftableToken
+
+# local imports
+from erc20_single_shot_faucet import Faucet
+from erc20_single_shot_faucet.faucet import SingleShotFaucet
+
+logging.basicConfig(level=logging.DEBUG)
+logg = logging.getLogger()
+
+
+class TestFaucet(EthTesterCase):
+
+ def setUp(self):
+ super(TestFaucet, self).setUp()
+ self.conn = RPCConnection.connect(self.chain_spec, 'default')
+ nonce_oracle = RPCNonceOracle(self.accounts[0], self.conn)
+ c = SingleShotFaucet(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
+ (tx_hash, o) = c.store_constructor(self.accounts[0])
+ r = self.conn.do(o)
+ logg.debug('store deployed with hash {}'.format(r))
+
+ o = receipt(r)
+ r = self.conn.do(o)
+ self.store_address = to_checksum_address(r['contract_address'])
+ logg.debug('store contract {}'.format(self.store_address))
+
+ ct = GiftableToken(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
+ (tx_hash_hex, o) = ct.constructor(self.accounts[0], 'Foo Token', 'FOO', 6)
+ r = self.conn.do(o)
+ logg.debug('token deployed with hash {}'.format(r))
+
+ o = receipt(r)
+ r = self.conn.do(o)
+ self.token_address = to_checksum_address(r['contract_address'])
+ logg.debug('token contract {}'.format(self.store_address))
+
+ (tx_hash, o) = c.constructor(self.accounts[0], self.token_address, self.store_address, ZERO_ADDRESS, self.accounts[1])
+ r = self.conn.do(o)
+ logg.debug('faucet deployed with hash {}'.format(r))
+
+ o = receipt(r)
+ r = self.conn.do(o)
+ self.address = to_checksum_address(r['contract_address'])
+ logg.debug('faucet contract {}'.format(self.address))
+
+
+ def test_basic(self):
+ pass
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/solidity/ERC20SingleShotFaucetStorage.bin b/solidity/ERC20SingleShotFaucetStorage.bin
@@ -0,0 +1 @@
+608060405234801561001057600080fd5b50336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600360009080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000600260008073ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610915806101096000396000f3fe608060405234801561001057600080fd5b50600436106100a5576000357c01000000000000000000000000000000000000000000000000000000009004806379ba50971161007857806379ba50971461016a5780638da5cb5b14610188578063e2095c07146101a6578063f2fde38b146101d6576100a5565b806301ffc9a7146100aa5780630a3b0a4f146100da5780633ef250131461010a578063764b07e71461013a575b600080fd5b6100c460048036038101906100bf9190610756565b6101f2565b6040516100d191906107f0565b60405180910390f35b6100f460048036038101906100ef919061072d565b61034a565b60405161010191906107f0565b60405180910390f35b610124600480360381019061011f919061072d565b61044a565b60405161013191906107f0565b60405180910390f35b610154600480360381019061014f919061072d565b610495565b604051610161919061080b565b60405180910390f35b6101726104ad565b60405161017f91906107f0565b60405180910390f35b6101906105ef565b60405161019d91906107d5565b60405180910390f35b6101c060048036038101906101bb919061077f565b610613565b6040516101cd91906107d5565b60405180910390f35b6101f060048036038101906101eb919061072d565b610652565b005b600063cbdb05c77c010000000000000000000000000000000000000000000000000000000002827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614156102475760019050610345565b6301ffc9a77c010000000000000000000000000000000000000000000000000000000002827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916141561029a5760019050610345565b639493f8b27c010000000000000000000000000000000000000000000000000000000002827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614156102ed5760019050610345565b6337a47be47c010000000000000000000000000000000000000000000000000000000002827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614156103405760019050610345565b600090505b919050565b60008060038054905090506003839080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550808373ffffffffffffffffffffffffffffffffffffffff167f9cc987676e7d63379f176ea50df0ae8d2d9d1141d1231d4ce15b5965f73c943060405160405180910390a36001915050919050565b600080600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054119050919050565b60026020528060005260406000206000915090505481565b60008060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461052d57600080fd5b336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3600191505090565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6003818154811061062357600080fd5b906000526020600020016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146106aa57600080fd5b80600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6000813590506106fd8161089a565b92915050565b600081359050610712816108b1565b92915050565b600081359050610727816108c8565b92915050565b60006020828403121561073f57600080fd5b600061074d848285016106ee565b91505092915050565b60006020828403121561076857600080fd5b600061077684828501610703565b91505092915050565b60006020828403121561079157600080fd5b600061079f84828501610718565b91505092915050565b6107b181610826565b82525050565b6107c081610838565b82525050565b6107cf81610890565b82525050565b60006020820190506107ea60008301846107a8565b92915050565b600060208201905061080560008301846107b7565b92915050565b600060208201905061082060008301846107c6565b92915050565b600061083182610870565b9050919050565b60008115159050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b6108a381610826565b81146108ae57600080fd5b50565b6108ba81610844565b81146108c557600080fd5b50565b6108d181610890565b81146108dc57600080fd5b5056fea2646970667358221220c9946d1d5ce7247846f019cfa3051aae1e32efe8f4d6aaf6be588bf4aadeb9f264736f6c63430008030033
+\ No newline at end of file
diff --git a/solidity/ERC20SingleShotFaucetStorage.json b/solidity/ERC20SingleShotFaucetStorage.json
@@ -0,0 +1 @@
+[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"addedAccount","type":"address"},{"indexed":true,"internalType":"uint256","name":"accountIndex","type":"uint256"}],"name":"AddressAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[],"name":"acceptOwnership","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"add","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"entry","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"have","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"_sum","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"_newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"usedAccounts","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]
diff --git a/solidity/ERC20SingleShotFaucetStorage.sol b/solidity/ERC20SingleShotFaucetStorage.sol
@@ -17,6 +17,8 @@ contract SingleShotFaucetStorage {
constructor() public {
owner = msg.sender;
+ entry.push(address(0));
+ usedAccounts[address(0)] = 0;
}
// Implements EIP 173
@@ -36,18 +38,22 @@ contract SingleShotFaucetStorage {
// Implements AccountsIndex
function have(address _account) external view returns (bool) {
- return usedAccounts[_account];
+ return usedAccounts[_account] > 0;
}
// Implements AccountsIndex
function add(address _account) external returns (bool) {
- usedAccounts[_account] = true;
- emit AccountAdded(_account, );
+ uint256 l;
+
+ l = entry.length;
+ entry.push(_account);
+ usedAccounts[_account] = l;
+ emit AddressAdded(_account, l);
return true;
}
// Implements EIP165
- function supportsInterface(bytes4 _sum) {
+ function supportsInterface(bytes4 _sum) public pure returns (bool) {
if (_sum == 0xcbdb05c7) { // AccountsIndex
return true;
}
@@ -60,5 +66,6 @@ contract SingleShotFaucetStorage {
if (_sum == 0x37a47be4) { // OwnedAccepter
return true;
}
+ return false;
}
}