commit 6929b16d8c38d90a57000538f836d8d8731de04d
parent e585c158428f69679d86262ab6eafa36a23e2b12
Author: nolash <dev@holbrook.no>
Date: Sat, 12 Dec 2020 10:49:42 +0100
Add python package
Diffstat:
6 files changed, 220 insertions(+), 34 deletions(-)
diff --git a/python/CHANGELOG b/python/CHANGELOG
@@ -1,3 +1,5 @@
+- 0.0.3
+ * Add python interface
- 0.0.2
* Rename contracts-dir flag to abi-dir
* Use package data dir as abi dir
diff --git a/python/erc20_single_shot_faucet/faucet.py b/python/erc20_single_shot_faucet/faucet.py
@@ -0,0 +1,66 @@
+# Author: Louis Holbrook <dev@holbrook.no> 0826EDA1702D1E87C6E2875121D2E7BB88C2A746
+# SPDX-License-Identifier: GPL-3.0-or-later
+# File-version: 1
+# Description: Python interface to abi and bin files for faucet contracts
+
+# standard imports
+import logging
+import json
+import os
+
+logging.basicConfig(level=logging.DEBUG)
+logg = logging.getLogger()
+
+moddir = os.path.dirname(__file__)
+datadir = os.path.join(moddir, 'data')
+
+
+class Faucet:
+
+ __abi = None
+ __bytecode = None
+
+ def __init__(self, w3, address, signer_address=None):
+ abi = Faucet.abi()
+ Faucet.bytecode()
+ self.contract = w3.eth.contract(abi=abi, address=address)
+ self.w3 = w3
+ if signer_address != None:
+ self.signer_address = signer_address
+ else:
+ if type(self.w3.eth.defaultAccount).__name__ == 'Empty':
+ self.w3.eth.defaultAccount = self.w3.eth.accounts[0]
+ self.signer_address = self.w3.eth.defaultAccount
+
+
+ @staticmethod
+ def abi():
+ if Faucet.__abi == None:
+ f = open(os.path.join(datadir, 'ERC20SingleShotFaucet.abi.json'), 'r')
+ Faucet.__abi = json.load(f)
+ f.close()
+ return Faucet.__abi
+
+
+ @staticmethod
+ def bytecode(part=None):
+ if Faucet.__bytecode == None:
+ f = open(os.path.join(datadir, 'ERC20SingleShotFaucet.bin'))
+ Faucet.__bytecode = f.read()
+ f.close()
+ if part == 'storage':
+ f = open(os.path.join(datadir, 'ERC20SingleShotFaucetStorage.bin'))
+ bytecode = f.read()
+ f.close()
+ return bytecode
+ elif part != None:
+ raise ValueError('unknown bytecode identifier "{}"'.format(part))
+
+ return Faucet.__bytecode
+
+
+ def give_to(self, address):
+ tx_hash = self.contract.functions.giveTo(address).transact({
+ 'from': self.signer_address,
+ })
+ return tx_hash
diff --git a/python/setup.cfg b/python/setup.cfg
@@ -1,6 +1,6 @@
[metadata]
name = erc20-single-shot-faucet
-version = 0.0.2
+version = 0.0.3
description = ERC20 token faucet that can be used once per account
author = Louis Holbrook
author_email = dev@holbrook.no
diff --git a/python/tests/test_app.py b/python/tests/test_app.py
@@ -7,6 +7,8 @@ import web3
import eth_tester
import eth_abi
+from erc20_single_shot_faucet import Faucet
+
logging.basicConfig(level=logging.DEBUG)
logg = logging.getLogger()
@@ -56,15 +58,15 @@ class Test(unittest.TestCase):
self.abi_token = json.load(f)
f.close()
- t = self.w3.eth.contract(abi=self.abi_token, bytecode=bytecode)
- tx_hash = t.constructor('Foo Token', 'FOO', 18).transact({'from': self.w3.eth.accounts[0]})
+ self.token = self.w3.eth.contract(abi=self.abi_token, bytecode=bytecode)
+ tx_hash = self.token.constructor('Foo Token', 'FOO', 18).transact({'from': self.w3.eth.accounts[0]})
r = self.w3.eth.getTransactionReceipt(tx_hash)
self.address_token = r.contractAddress
- t = self.w3.eth.contract(abi=self.abi_token, address=self.address_token)
+ self.token = self.w3.eth.contract(abi=self.abi_token, address=self.address_token)
- tx_hash = t.functions.mint(1000).transact({'from': self.w3.eth.accounts[0]})
+ tx_hash = self.token.functions.mint(1000).transact({'from': self.w3.eth.accounts[0]})
# create faucet
@@ -94,42 +96,23 @@ class Test(unittest.TestCase):
self.address_faucet = r.contractAddress
c = self.w3.eth.contract(abi=self.abi_faucet, address=self.address_faucet)
- tx_hash = t.functions.transfer(self.address_faucet, 100).transact({'from': self.w3.eth.accounts[0]})
+ tx_hash = self.token.functions.transfer(self.address_faucet, 100).transact({'from': self.w3.eth.accounts[0]})
+
+ c.functions.setAmount(10).transact({'from': self.w3.eth.accounts[2]})
def tearDown(self):
pass
- def test_basic(self):
- c = self.w3.eth.contract(abi=self.abi_faucet, address=self.address_faucet)
- self.assertTrue(c.functions.setAmount(10).transact({'from': self.w3.eth.accounts[0]}))
- self.assertTrue(c.functions.setAmount(20).transact({'from': self.w3.eth.accounts[1]}))
- with self.assertRaises(Exception):
- c.functions.setAmount(30).transact({'from': self.w3.eth.accounts[3]})
-
-
- def test_giveto(self):
- c = self.w3.eth.contract(abi=self.abi_faucet, address=self.address_faucet)
- c.functions.setAmount(10).transact({'from': self.w3.eth.accounts[2]})
- c.functions.giveTo(self.w3.eth.accounts[3]).transact({'from': self.w3.eth.accounts[1]})
-
- t = self.w3.eth.contract(abi=self.abi_token, address=self.address_token)
- self.assertEqual(t.functions.balanceOf(self.w3.eth.accounts[3]).call(), 10);
- self.assertEqual(t.functions.balanceOf(self.address_faucet).call(), 90);
-
- with self.assertRaises(Exception):
- c.functions.giveTo(self.w3.eth.accounts[3]).transact({'from': self.w3.eth.accounts[1]})
+ def test_sanity(self):
+ faucet = Faucet(self.w3, self.address_faucet)
- c.functions.setAmount(50).transact({'from': self.w3.eth.accounts[1]})
- c.functions.giveTo(self.w3.eth.accounts[4]).transact({'from': self.w3.eth.accounts[1]})
- self.assertEqual(t.functions.balanceOf(self.w3.eth.accounts[4]).call(), 50);
- self.assertEqual(t.functions.balanceOf(self.address_faucet).call(), 40);
- with self.assertRaises(Exception):
- c.functions.giveTo(self.w3.eth.accounts[5]).transact({'from': self.w3.eth.accounts[1]})
- self.assertEqual(t.functions.balanceOf(self.w3.eth.accounts[5]).call(), 0);
- self.assertEqual(t.functions.balanceOf(self.address_faucet).call(), 40);
+ def test_give(self):
+ faucet = Faucet(self.w3, self.address_faucet)
+ faucet.give_to(self.w3.eth.accounts[3])
+ self.assertEqual(self.token.functions.balanceOf(self.w3.eth.accounts[3]).call(), 10);
if __name__ == '__main__':
unittest.main()
diff --git a/python/tests/test_contract.py b/python/tests/test_contract.py
@@ -0,0 +1,135 @@
+import os
+import unittest
+import json
+import logging
+
+import web3
+import eth_tester
+import eth_abi
+
+logging.basicConfig(level=logging.DEBUG)
+logg = logging.getLogger()
+
+logging.getLogger('web3').setLevel(logging.WARNING)
+logging.getLogger('eth.vm').setLevel(logging.WARNING)
+
+testdir = os.path.dirname(__file__)
+
+
+class Test(unittest.TestCase):
+
+ contract = None
+
+ def setUp(self):
+ eth_params = eth_tester.backends.pyevm.main.get_default_genesis_params({
+ 'gas_limit': 9000000,
+ })
+
+ # create store of used accounts
+ f = open(os.path.join(testdir, '../erc20_single_shot_faucet/data/ERC20SingleShotFaucetStorage.bin'), 'r')
+ bytecode = f.read()
+ f.close()
+
+ f = open(os.path.join(testdir, '../erc20_single_shot_faucet/data/ERC20SingleShotFaucetStorage.abi.json'), 'r')
+ self.abi_storage = json.load(f)
+ f.close()
+
+
+ backend = eth_tester.PyEVMBackend(eth_params)
+ self.eth_tester = eth_tester.EthereumTester(backend)
+ provider = web3.Web3.EthereumTesterProvider(self.eth_tester)
+ self.w3 = web3.Web3(provider)
+ c = self.w3.eth.contract(abi=self.abi_storage, bytecode=bytecode)
+ tx_hash = c.constructor().transact({'from': self.w3.eth.accounts[0]})
+
+ r = self.w3.eth.getTransactionReceipt(tx_hash)
+
+ self.address_storage = r.contractAddress
+
+
+ # create token
+ f = open(os.path.join(testdir, '../erc20_single_shot_faucet/data/GiftableToken.bin'), 'r')
+ bytecode = f.read()
+ f.close()
+
+ f = open(os.path.join(testdir, '../erc20_single_shot_faucet/data/GiftableToken.abi.json'), 'r')
+ self.abi_token = json.load(f)
+ f.close()
+
+ t = self.w3.eth.contract(abi=self.abi_token, bytecode=bytecode)
+ tx_hash = t.constructor('Foo Token', 'FOO', 18).transact({'from': self.w3.eth.accounts[0]})
+
+ r = self.w3.eth.getTransactionReceipt(tx_hash)
+
+ self.address_token = r.contractAddress
+ t = self.w3.eth.contract(abi=self.abi_token, address=self.address_token)
+
+ tx_hash = t.functions.mint(1000).transact({'from': self.w3.eth.accounts[0]})
+
+
+ # create faucet
+ f = open(os.path.join(testdir, '../erc20_single_shot_faucet/data/ERC20SingleShotFaucet.bin'), 'r')
+ bytecode = f.read()
+ f.close()
+
+ f = open(os.path.join(testdir, '../erc20_single_shot_faucet/data/ERC20SingleShotFaucet.abi.json'), 'r')
+ self.abi_faucet = json.load(f)
+ f.close()
+
+# f = open(os.path.join(testdir, '../erc20_single_shot_faucet/data/ERC20SingleShotFaucet.abi.json'), 'r')
+# abi_storage_interface = json.load(f)
+# f.close()
+
+ c = self.w3.eth.contract(abi=self.abi_faucet, bytecode=bytecode)
+ tx_hash = c.constructor([
+ self.w3.eth.accounts[1],
+ self.w3.eth.accounts[2],
+ ],
+ self.address_token,
+ self.address_storage,
+ ).transact({'from': self.w3.eth.accounts[0]})
+
+ r = self.w3.eth.getTransactionReceipt(tx_hash)
+
+ self.address_faucet = r.contractAddress
+ c = self.w3.eth.contract(abi=self.abi_faucet, address=self.address_faucet)
+
+ tx_hash = t.functions.transfer(self.address_faucet, 100).transact({'from': self.w3.eth.accounts[0]})
+
+
+ def tearDown(self):
+ pass
+
+
+ def test_basic(self):
+ c = self.w3.eth.contract(abi=self.abi_faucet, address=self.address_faucet)
+ self.assertTrue(c.functions.setAmount(10).transact({'from': self.w3.eth.accounts[0]}))
+ self.assertTrue(c.functions.setAmount(20).transact({'from': self.w3.eth.accounts[1]}))
+ with self.assertRaises(Exception):
+ c.functions.setAmount(30).transact({'from': self.w3.eth.accounts[3]})
+
+
+ def test_giveto(self):
+ c = self.w3.eth.contract(abi=self.abi_faucet, address=self.address_faucet)
+ c.functions.setAmount(10).transact({'from': self.w3.eth.accounts[2]})
+ c.functions.giveTo(self.w3.eth.accounts[3]).transact({'from': self.w3.eth.accounts[1]})
+
+ t = self.w3.eth.contract(abi=self.abi_token, address=self.address_token)
+ self.assertEqual(t.functions.balanceOf(self.w3.eth.accounts[3]).call(), 10);
+ self.assertEqual(t.functions.balanceOf(self.address_faucet).call(), 90);
+
+ with self.assertRaises(Exception):
+ c.functions.giveTo(self.w3.eth.accounts[3]).transact({'from': self.w3.eth.accounts[1]})
+
+ c.functions.setAmount(50).transact({'from': self.w3.eth.accounts[1]})
+ c.functions.giveTo(self.w3.eth.accounts[4]).transact({'from': self.w3.eth.accounts[1]})
+ self.assertEqual(t.functions.balanceOf(self.w3.eth.accounts[4]).call(), 50);
+ self.assertEqual(t.functions.balanceOf(self.address_faucet).call(), 40);
+
+ with self.assertRaises(Exception):
+ c.functions.giveTo(self.w3.eth.accounts[5]).transact({'from': self.w3.eth.accounts[1]})
+ self.assertEqual(t.functions.balanceOf(self.w3.eth.accounts[5]).call(), 0);
+ self.assertEqual(t.functions.balanceOf(self.address_faucet).call(), 40);
+
+
+
diff --git a/solidity/ERC20SingleShotFaucetStorage.sol b/solidity/ERC20SingleShotFaucetStorage.sol
@@ -18,7 +18,7 @@ contract SingleShotFaucetStorage {
return true;
}
- function completeOwnership() external returns (bool) {
+ function acceptOwnership() external returns (bool) {
require(msg.sender == new_owner);
owner = msg.sender;
return true;