eth-interface

EIP-165 interface and tools for chainlib-eth
git clone git://holbrook.no/eth-interface.git
Log | Files | Refs

commit c3985236a2aa1f3047b7560a7c200f020e8bcce1
Author: nolash <dev@holbrook.no>
Date:   Sun,  2 May 2021 16:30:21 +0200

Initial commit

Diffstat:
A.gitignore | 5+++++
Apython/eth_interface/__init__.py | 1+
Apython/eth_interface/eip165.py | 36++++++++++++++++++++++++++++++++++++
Apython/requirements.txt | 1+
Apython/setup.cfg | 31+++++++++++++++++++++++++++++++
Apython/setup.py | 31+++++++++++++++++++++++++++++++
Apython/test_requirements.txt | 4++++
Apython/tests/test_eip165.py | 61+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Apython/tests/testdata/Supports.bin | 2++
Apython/tests/testdata/Supports.sol | 10++++++++++
10 files changed, 182 insertions(+), 0 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -0,0 +1,5 @@ +__pycache__ +build/ +dist/ +*.pyc +gmon.out diff --git a/python/eth_interface/__init__.py b/python/eth_interface/__init__.py @@ -0,0 +1 @@ +from .eip165 import EIP165 diff --git a/python/eth_interface/eip165.py b/python/eth_interface/eip165.py @@ -0,0 +1,36 @@ +# external imports +from chainlib.eth.constant import ZERO_ADDRESS +from chainlib.jsonrpc import ( + jsonrpc_template, + ) +from hexathon import ( + add_0x, + ) +from chainlib.eth.contract import ( + ABIContractEncoder, + ABIContractDecoder, + ABIContractType, + abi_decode_single, + ) +from chainlib.eth.tx import TxFactory + + +class EIP165(TxFactory): + + def supports_interface(self, contract_address, interface_sum, sender_address=ZERO_ADDRESS): + o = jsonrpc_template() + o['method'] = 'eth_call' + enc = ABIContractEncoder() + enc.method('supportsInterface') + enc.typ(ABIContractType.BYTES4) + enc.bytes4(interface_sum) + 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_supports_interface(self, v): + return abi_decode_single(ABIContractType.BOOLEAN, v) diff --git a/python/requirements.txt b/python/requirements.txt @@ -0,0 +1 @@ +chainlib~=0.0.3a1 diff --git a/python/setup.cfg b/python/setup.cfg @@ -0,0 +1,31 @@ +[metadata] +name = eth-interface +version = 0.0.1a1 +description = EIP165 interface +author = Louis Holbrook +author_email = dev@holbrook.no +url = https://gitlab.com/nolash/eth-interface +keywords = + ethereum +classifiers = + Programming Language :: Python :: 3 + Operating System :: OS Independent + Development Status :: 3 - Alpha + Environment :: No Input/Output (Daemon) + Intended Audience :: Developers + License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+) + Topic :: Internet + #Topic :: Blockchain :: EVM +license = GPL3 +licence_files = + LICENSE + +[options] +include_package_data = True +python_requires = >= 3.6 +packages = + eth-interface + +[options.package_data] +* = + data/EIP165.json diff --git a/python/setup.py b/python/setup.py @@ -0,0 +1,31 @@ +from setuptools import setup + +requirements = [] +f = open('requirements.txt', 'r') +while True: + l = f.readline() + if l == '': + break + requirements.append(l.rstrip()) +f.close() + +test_requirements = [] +f = open('test_requirements.txt', 'r') +while True: + l = f.readline() + if l == '': + break + test_requirements.append(l.rstrip()) +f.close() + + +setup( + package_data={ + '': [ + 'data/EIP165.json', + ], + }, + include_package_data=True, + install_requires=requirements, + tests_require=test_requirements, + ) diff --git a/python/test_requirements.txt b/python/test_requirements.txt @@ -0,0 +1,4 @@ +eth_tester==0.5.0b3 +py-evm==0.3.0a20 +rlp==2.0.1 +pytest==6.0.1 diff --git a/python/tests/test_eip165.py b/python/tests/test_eip165.py @@ -0,0 +1,61 @@ +# standard imports +import unittest +import os +import logging + +# local imports +from chainlib.eth.unittest.ethtester import EthTesterCase +from chainlib.eth.nonce import RPCNonceOracle +from chainlib.eth.gas import OverrideGasOracle +from chainlib.connection import RPCConnection +from chainlib.eth.tx import ( + TxFactory, + receipt, + ) +from chainlib.eth.eip165 import EIP165 + +logging.basicConfig(level=logging.DEBUG) +logg = logging.getLogger() + +script_dir = os.path.realpath(os.path.dirname(__file__)) + + +class TestSupports(EthTesterCase): + + def setUp(self): + super(TestSupports, self).setUp() + self.conn = RPCConnection.connect(self.chain_spec, 'default') + nonce_oracle = RPCNonceOracle(self.accounts[0], self.conn) + + f = open(os.path.join(script_dir, 'testdata', 'Supports.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) + + r = self.conn.do(o) + logg.debug('deployed with hash {}'.format(r)) + + o = receipt(tx_hash_hex) + r = self.conn.do(o) + self.address = r['contract_address'] + + + def test_supports(self): + gas_oracle = OverrideGasOracle(limit=100000, conn=self.conn) + c = EIP165(self.chain_spec, gas_oracle=gas_oracle) + o = c.supports_interface(self.address, '0xdeadbeef', sender_address=self.accounts[0]) + r = self.conn.do(o) + v = c.parse_supports_interface(r) + self.assertEqual(v, 1) + + o = c.supports_interface(self.address, '0xbeeffeed', sender_address=self.accounts[0]) + r = self.conn.do(o) + v = c.parse_supports_interface(r) + self.assertEqual(v, 0) + +if __name__ == '__main__': + unittest.main() diff --git a/python/tests/testdata/Supports.bin b/python/tests/testdata/Supports.bin @@ -0,0 +1 @@ +608060405234801561001057600080fd5b506101c9806100206000396000f3fe608060405234801561001057600080fd5b5060043610610048576000357c01000000000000000000000000000000000000000000000000000000009004806301ffc9a71461004d575b600080fd5b610067600480360381019061006291906100f1565b61007d565b6040516100749190610129565b60405180910390f35b600063deadbeef7c010000000000000000000000000000000000000000000000000000000002827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614156100d257600190506100d7565b600090505b919050565b6000813590506100eb8161017c565b92915050565b60006020828403121561010357600080fd5b6000610111848285016100dc565b91505092915050565b61012381610144565b82525050565b600060208201905061013e600083018461011a565b92915050565b60008115159050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b61018581610150565b811461019057600080fd5b5056fea264697066735822122073144ec34d71a86680325f1aee9a3b9041e22c422e7b1b82d409b303d52192de64736f6c63430008030033 +\ No newline at end of file diff --git a/python/tests/testdata/Supports.sol b/python/tests/testdata/Supports.sol @@ -0,0 +1,10 @@ +pragma solidity ^0.8.0; + +contract Supports { + function supportsInterface(bytes4 _sum) public pure returns (bool) { + if (_sum == 0xdeadbeef) { + return true; + } + return false; + } +}