From ead80991099256c7239fe3d6af2c5304ce0fb8eb Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Tue, 23 Jul 2019 12:58:18 -0400 Subject: [PATCH] Auto-gen Python Exchange wrapper (#1919) * Rename existing wrapper, to match contract name * base contract: make member var public * json_schemas.py: stop storing copies of schemas! * .gitignore generated erc20_token.py wrapper * json schemas: allow uppercase digits in address * existing exchange wrapper: re-order methods to match method order in Solidity contract, to reduce noise in upcoming diffs of newly generated code vs. old manually-written code. * existing exchange wrapper: rename method params To match contract method param names * existing exchange wrapper: remove redundant member * existing exchange wrapper: make signatures bytes Not strings. * abi-gen/test-cli: show context on diff failure * abi-gen-templates/Py: fix broken event interface Previous changes had removed the `token_address` parameter from all generated methods, but this instance was missed because there weren't tests/examples using events for the first contract for which wrappers were generated (ERC20Token). * abi-gen: remove unused method parameters * abi-gen: convert Py method params to snake case * abi-gen: rewrite Python tuple handling * python-generated-wrappers: include Exchange * abi-gen-templates/Py: easy linter fixes * abi-gen-templates/Py: satisfy docstring linters * abi-gen-templates/Py: normalize bytes before use * contract_wrappers.py: replace Exchange w/generated * contract_wrappers.py: rm manually written Exchange * contract_wrappers.py/doctest: rename variables * abi-gen: fix misspelling in docstring Co-Authored-By: Fabio B * Py docs: error on warning, and test build in CI * abi-gen: doc Py bytes params as requiring UTF-8 * abi-gen: git mv diff.sh test-cli/ * abi-gen: put Py wrapper in module folder, not file This leaves space for user-defined additions to the same module, such as for custom types, as shown herein. * abi-gen: customizable param validation for Python * contract_wrappers.py: JSON schema Order validation * CircleCI Build Artifacts For abi-gen command-line test output, for generated Python contract wrappers as output by abi-gen, for generated Python contract wrappers as reformatted and included in the Python package area, and for the "build" output folder in each Python package, which includes the generated documentation. * CHANGELOG updates for all components * abi-gen: grammar in comments Co-Authored-By: Fabio B * abi-gen: CHANGELOG spelling correction Co-Authored-By: Fabio B * order_utils.py: reverse (chronological) CHANGELOG * abi-gen-templates: reset CHANGELOG patch version * CHANGELOGs: use multiple entries where appropriate * abi-gen: enable devdoc solc output in test-cli * abi-gen-templates/Py: consolidate return type * abi-gen/test-cli: non-pure fixture contract method Added a method to the "dummy" test fixture contract that isn't pure. All of the other prior method cases were pure. * abi-gen/Py: fix const methods missing return type * abi-gen/Py: fix wrong return types on some methods Specifically, wrapper methods wrapping contract methods that modify contract state and return no return value. There was no test case for this. Now there is. * contract_wrappers.py: rm generated code in `clean` * Parallelize Py monorepo scripts (test, lint, etc) --- .circleci/config.yml | 25 +- .gitignore | 5 + .prettierignore | 3 + packages/0x.js/CHANGELOG.json | 9 + packages/0x.js/src/index.ts | 1 + packages/abi-gen-templates/CHANGELOG.json | 21 + .../Python/contract.handlebars | 62 +- .../Python/partials/call.handlebars | 37 +- .../Python/partials/event.handlebars | 7 +- .../Python/partials/params.handlebars | 2 +- .../Python/partials/return_type.handlebars | 15 +- .../Python/partials/typed_params.handlebars | 2 +- packages/abi-gen/CHANGELOG.json | 33 + packages/abi-gen/compiler.json | 3 +- packages/abi-gen/package.json | 2 +- packages/abi-gen/src/index.ts | 126 +++- packages/abi-gen/src/utils.ts | 190 ++++- packages/abi-gen/{ => test-cli}/diff.sh | 4 +- .../expected-output/python/abi_gen_dummy.py | 243 ------ .../python/abi_gen_dummy/__init__.py | 619 ++++++++++++++++ .../expected-output/python/lib_dummy.py | 51 -- .../python/lib_dummy/__init__.py | 109 +++ .../__init__.py} | 80 +- .../typescript/abi_gen_dummy.ts | 697 ++++++++++++++++++ .../fixtures/artifacts/AbiGenDummy.json | 644 ++++++++++------ .../test-cli/fixtures/artifacts/LibDummy.json | 122 +-- .../fixtures/artifacts/TestLibDummy.json | 208 +++--- .../fixtures/contracts/AbiGenDummy.sol | 34 + packages/contract-wrappers/CHANGELOG.json | 9 + packages/contract-wrappers/src/index.ts | 1 + packages/ethereum-types/CHANGELOG.json | 9 + packages/ethereum-types/src/index.ts | 4 + packages/json-schemas/CHANGELOG.json | 8 + .../json-schemas/schemas/address_schema.json | 2 +- packages/json-schemas/test/schema_test.ts | 12 +- .../python-contract-wrappers/CHANGELOG.json | 4 + .../python-contract-wrappers/package.json | 2 +- packages/sol-compiler/CHANGELOG.json | 9 + packages/sol-compiler/src/index.ts | 1 + packages/web3-wrapper/CHANGELOG.json | 9 + packages/web3-wrapper/src/index.ts | 1 + python-packages/build_docs | 3 + python-packages/contract_addresses/setup.py | 1 + python-packages/contract_artifacts/setup.py | 10 +- python-packages/contract_wrappers/.pylintrc | 5 +- .../contract_wrappers/CHANGELOG.md | 4 + python-packages/contract_wrappers/setup.py | 38 +- .../contract_wrappers/src/index.rst | 32 + .../src/zero_ex/contract_wrappers/__init__.py | 50 +- .../_base_contract_wrapper.py | 6 +- .../contract_wrappers/erc20_token/.gitkeep | 0 .../contract_wrappers/exchange/.gitkeep | 0 .../contract_wrappers/exchange/types.py | 200 +++++ .../contract_wrappers/exchange/validator.py | 47 ++ .../contract_wrappers/exchange_wrapper.py | 327 -------- .../test/test_exchange_wrapper.py | 43 +- python-packages/install_editable | 14 +- python-packages/json_schemas/setup.py | 33 +- .../src/zero_ex/json_schemas/__init__.py | 5 +- .../json_schemas/schemas/address_schema.json | 5 - .../asset_pairs_request_opts_schema.json | 8 - .../schemas/block_param_schema.json | 11 - .../schemas/block_range_schema.json | 8 - .../schemas/call_data_schema.json | 27 - .../ec_signature_parameter_schema.json | 5 - .../schemas/ec_signature_schema.json | 14 - .../schemas/eip712_typed_data_schema.json | 28 - .../json_schemas/schemas/hex_schema.json | 5 - .../schemas/index_filter_values_schema.json | 7 - .../schemas/js_number_schema.json | 5 - .../json_schemas/schemas/number_schema.json | 5 - .../schemas/order_cancel_schema.json | 12 - .../schemas/order_config_request_schema.json | 24 - .../order_fill_or_kill_requests_schema.json | 12 - .../schemas/order_fill_requests_schema.json | 12 - .../schemas/order_hash_schema.json | 5 - .../json_schemas/schemas/order_schema.json | 34 - ...der_watcher_web_socket_request_schema.json | 52 -- ...atcher_web_socket_utf8_message_schema.json | 10 - .../schemas/orderbook_request_schema.json | 9 - .../schemas/orders_request_opts_schema.json | 19 - .../json_schemas/schemas/orders_schema.json | 5 - .../schemas/paged_request_opts_schema.json | 8 - .../schemas/paginated_collection_schema.json | 10 - ..._api_asset_data_pairs_response_schema.json | 13 - .../relayer_api_asset_data_pairs_schema.json | 12 - ...ayer_api_asset_data_trade_info_schema.json | 11 - .../relayer_api_error_response_schema.json | 21 - ...er_api_fee_recipients_response_schema.json | 16 - ...layer_api_order_config_payload_schema.json | 24 - ...ayer_api_order_config_response_schema.json | 11 - .../schemas/relayer_api_order_schema.json | 9 - ...relayer_api_orderbook_response_schema.json | 9 - ...ders_channel_subscribe_payload_schema.json | 14 - ...r_api_orders_channel_subscribe_schema.json | 11 - ...orders_channel_update_response_schema.json | 11 - .../relayer_api_orders_response_schema.json | 13 - .../schemas/relayer_api_orders_schema.json | 5 - .../schemas/request_opts_schema.json | 7 - .../schemas/signed_order_schema.json | 12 - .../schemas/signed_orders_schema.json | 5 - .../json_schemas/schemas/token_schema.json | 11 - .../json_schemas/schemas/tx_data_schema.json | 26 - .../schemas/whole_number_schema.json | 12 - .../schemas/zero_ex_transaction_schema.json | 11 - .../json_schemas/test/test_json_schemas.py | 3 +- python-packages/lint | 14 +- python-packages/middlewares/setup.py | 1 + .../test/test_local_message_signer.py | 16 +- python-packages/order_utils/CHANGELOG.md | 8 +- python-packages/order_utils/setup.py | 1 + python-packages/order_utils/src/index.rst | 4 - .../src/zero_ex/order_utils/__init__.py | 345 +-------- .../test/test_generate_order_hash_hex.py | 20 +- .../order_utils/test/test_signature_utils.py | 16 +- python-packages/parallel | 44 ++ python-packages/pre_install | 18 +- python-packages/sra_client/setup.py | 1 + .../src/zero_ex/sra_client/__init__.py | 9 +- python-packages/test | 14 +- 120 files changed, 3245 insertions(+), 2116 deletions(-) rename packages/abi-gen/{ => test-cli}/diff.sh (59%) delete mode 100644 packages/abi-gen/test-cli/expected-output/python/abi_gen_dummy.py create mode 100644 packages/abi-gen/test-cli/expected-output/python/abi_gen_dummy/__init__.py delete mode 100644 packages/abi-gen/test-cli/expected-output/python/lib_dummy.py create mode 100644 packages/abi-gen/test-cli/expected-output/python/lib_dummy/__init__.py rename packages/abi-gen/test-cli/expected-output/python/{test_lib_dummy.py => test_lib_dummy/__init__.py} (57%) create mode 100755 python-packages/build_docs create mode 100644 python-packages/contract_wrappers/src/zero_ex/contract_wrappers/erc20_token/.gitkeep create mode 100644 python-packages/contract_wrappers/src/zero_ex/contract_wrappers/exchange/.gitkeep create mode 100644 python-packages/contract_wrappers/src/zero_ex/contract_wrappers/exchange/types.py create mode 100644 python-packages/contract_wrappers/src/zero_ex/contract_wrappers/exchange/validator.py delete mode 100644 python-packages/contract_wrappers/src/zero_ex/contract_wrappers/exchange_wrapper.py delete mode 100644 python-packages/json_schemas/src/zero_ex/json_schemas/schemas/address_schema.json delete mode 100644 python-packages/json_schemas/src/zero_ex/json_schemas/schemas/asset_pairs_request_opts_schema.json delete mode 100644 python-packages/json_schemas/src/zero_ex/json_schemas/schemas/block_param_schema.json delete mode 100644 python-packages/json_schemas/src/zero_ex/json_schemas/schemas/block_range_schema.json delete mode 100644 python-packages/json_schemas/src/zero_ex/json_schemas/schemas/call_data_schema.json delete mode 100644 python-packages/json_schemas/src/zero_ex/json_schemas/schemas/ec_signature_parameter_schema.json delete mode 100644 python-packages/json_schemas/src/zero_ex/json_schemas/schemas/ec_signature_schema.json delete mode 100644 python-packages/json_schemas/src/zero_ex/json_schemas/schemas/eip712_typed_data_schema.json delete mode 100644 python-packages/json_schemas/src/zero_ex/json_schemas/schemas/hex_schema.json delete mode 100644 python-packages/json_schemas/src/zero_ex/json_schemas/schemas/index_filter_values_schema.json delete mode 100644 python-packages/json_schemas/src/zero_ex/json_schemas/schemas/js_number_schema.json delete mode 100644 python-packages/json_schemas/src/zero_ex/json_schemas/schemas/number_schema.json delete mode 100644 python-packages/json_schemas/src/zero_ex/json_schemas/schemas/order_cancel_schema.json delete mode 100644 python-packages/json_schemas/src/zero_ex/json_schemas/schemas/order_config_request_schema.json delete mode 100644 python-packages/json_schemas/src/zero_ex/json_schemas/schemas/order_fill_or_kill_requests_schema.json delete mode 100644 python-packages/json_schemas/src/zero_ex/json_schemas/schemas/order_fill_requests_schema.json delete mode 100644 python-packages/json_schemas/src/zero_ex/json_schemas/schemas/order_hash_schema.json delete mode 100644 python-packages/json_schemas/src/zero_ex/json_schemas/schemas/order_schema.json delete mode 100644 python-packages/json_schemas/src/zero_ex/json_schemas/schemas/order_watcher_web_socket_request_schema.json delete mode 100644 python-packages/json_schemas/src/zero_ex/json_schemas/schemas/order_watcher_web_socket_utf8_message_schema.json delete mode 100644 python-packages/json_schemas/src/zero_ex/json_schemas/schemas/orderbook_request_schema.json delete mode 100644 python-packages/json_schemas/src/zero_ex/json_schemas/schemas/orders_request_opts_schema.json delete mode 100644 python-packages/json_schemas/src/zero_ex/json_schemas/schemas/orders_schema.json delete mode 100644 python-packages/json_schemas/src/zero_ex/json_schemas/schemas/paged_request_opts_schema.json delete mode 100644 python-packages/json_schemas/src/zero_ex/json_schemas/schemas/paginated_collection_schema.json delete mode 100644 python-packages/json_schemas/src/zero_ex/json_schemas/schemas/relayer_api_asset_data_pairs_response_schema.json delete mode 100644 python-packages/json_schemas/src/zero_ex/json_schemas/schemas/relayer_api_asset_data_pairs_schema.json delete mode 100644 python-packages/json_schemas/src/zero_ex/json_schemas/schemas/relayer_api_asset_data_trade_info_schema.json delete mode 100644 python-packages/json_schemas/src/zero_ex/json_schemas/schemas/relayer_api_error_response_schema.json delete mode 100644 python-packages/json_schemas/src/zero_ex/json_schemas/schemas/relayer_api_fee_recipients_response_schema.json delete mode 100644 python-packages/json_schemas/src/zero_ex/json_schemas/schemas/relayer_api_order_config_payload_schema.json delete mode 100644 python-packages/json_schemas/src/zero_ex/json_schemas/schemas/relayer_api_order_config_response_schema.json delete mode 100644 python-packages/json_schemas/src/zero_ex/json_schemas/schemas/relayer_api_order_schema.json delete mode 100644 python-packages/json_schemas/src/zero_ex/json_schemas/schemas/relayer_api_orderbook_response_schema.json delete mode 100644 python-packages/json_schemas/src/zero_ex/json_schemas/schemas/relayer_api_orders_channel_subscribe_payload_schema.json delete mode 100644 python-packages/json_schemas/src/zero_ex/json_schemas/schemas/relayer_api_orders_channel_subscribe_schema.json delete mode 100644 python-packages/json_schemas/src/zero_ex/json_schemas/schemas/relayer_api_orders_channel_update_response_schema.json delete mode 100644 python-packages/json_schemas/src/zero_ex/json_schemas/schemas/relayer_api_orders_response_schema.json delete mode 100644 python-packages/json_schemas/src/zero_ex/json_schemas/schemas/relayer_api_orders_schema.json delete mode 100644 python-packages/json_schemas/src/zero_ex/json_schemas/schemas/request_opts_schema.json delete mode 100644 python-packages/json_schemas/src/zero_ex/json_schemas/schemas/signed_order_schema.json delete mode 100644 python-packages/json_schemas/src/zero_ex/json_schemas/schemas/signed_orders_schema.json delete mode 100644 python-packages/json_schemas/src/zero_ex/json_schemas/schemas/token_schema.json delete mode 100644 python-packages/json_schemas/src/zero_ex/json_schemas/schemas/tx_data_schema.json delete mode 100644 python-packages/json_schemas/src/zero_ex/json_schemas/schemas/whole_number_schema.json delete mode 100644 python-packages/json_schemas/src/zero_ex/json_schemas/schemas/zero_ex_transaction_schema.json create mode 100755 python-packages/parallel diff --git a/.circleci/config.yml b/.circleci/config.yml index 496f16cff4..742cdebc8d 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -33,6 +33,10 @@ jobs: key: python-contract-wrappers-{{ .Environment.CIRCLE_SHA1 }} paths: - ~/repo/packages/python-contract-wrappers/generated + - store_artifacts: + path: ~/repo/packages/python-contract-wrappers/generated + - store_artifacts: + path: ~/repo/packages/abi-gen/test-cli/output build-website: resource_class: medium+ docker: @@ -204,7 +208,8 @@ jobs: - run: command: | cd python-packages - ./cmd_pkgs_in_dep_order.py coverage run setup.py test + ./parallel coverage run setup.py test + ./build_docs - save_cache: key: coverage-python-contract-addresses-{{ .Environment.CIRCLE_SHA1 }} paths: @@ -229,6 +234,24 @@ jobs: key: coverage-python-sra-client-{{ .Environment.CIRCLE_SHA1 }} paths: - ~/repo/python-packages/sra_client/.coverage + - store_artifacts: + path: ~/repo/python-packages/contract_wrappers/src/zero_ex/contract_wrappers/erc20_token/__init__.py + - store_artifacts: + path: ~/repo/python-packages/contract_wrappers/src/zero_ex/contract_wrappers/exchange/__init__.py + - store_artifacts: + path: ~/repo/python-packages/contract_addresses/build + - store_artifacts: + path: ~/repo/python-packages/contract_artifacts/build + - store_artifacts: + path: ~/repo/python-packages/contract_wrappers/build + - store_artifacts: + path: ~/repo/python-packages/json_schemas/build + - store_artifacts: + path: ~/repo/python-packages/middlewares/build + - store_artifacts: + path: ~/repo/python-packages/order_utils/build + - store_artifacts: + path: ~/repo/python-packages/sra_client/build test-rest-python: working_directory: ~/repo docker: diff --git a/.gitignore b/.gitignore index 257065e0bf..9fde6b4c0f 100644 --- a/.gitignore +++ b/.gitignore @@ -113,6 +113,8 @@ contracts/erc1155/generated-wrappers/ contracts/extensions/generated-wrappers/ contracts/exchange-forwarder/generated-wrappers/ contracts/dev-utils/generated-wrappers/ +python-packages/contract_wrappers/src/zero_ex/contract_wrappers/erc20_token/__init__.py +python-packages/contract_wrappers/src/zero_ex/contract_wrappers/exchange/__init__.py # cli test output packages/abi-gen/test-cli/output @@ -132,3 +134,6 @@ python-packages/*/dist __pycache__ python-packages/*/src/*.egg-info python-packages/*/.coverage + +# python keeps package-local copies of json schemas +python-packages/json_schemas/src/zero_ex/json_schemas/schemas diff --git a/.prettierignore b/.prettierignore index 14cf6a013f..f4d158c3ae 100644 --- a/.prettierignore +++ b/.prettierignore @@ -35,3 +35,6 @@ packages/sol-coverage/test/fixtures/artifacts .pytest_cache .mypy_cache .tox +packages/abi-gen/test-cli/fixtures/artifacts/AbiGenDummy.json +packages/abi-gen/test-cli/fixtures/artifacts/LibDummy.json +packages/abi-gen/test-cli/fixtures/artifacts/TestLibDummy.json diff --git a/packages/0x.js/CHANGELOG.json b/packages/0x.js/CHANGELOG.json index a1323f2522..abfe801643 100644 --- a/packages/0x.js/CHANGELOG.json +++ b/packages/0x.js/CHANGELOG.json @@ -1,4 +1,13 @@ [ + { + "version": "6.0.13", + "changes": [ + { + "note": "re-export new ethereum-types type, TupleDataItem", + "pr": 1919 + } + ] + }, { "timestamp": 1563193019, "version": "6.0.12", diff --git a/packages/0x.js/src/index.ts b/packages/0x.js/src/index.ts index 6951f36b48..ddd7100661 100644 --- a/packages/0x.js/src/index.ts +++ b/packages/0x.js/src/index.ts @@ -131,6 +131,7 @@ export { ConstructorAbi, FallbackAbi, DataItem, + TupleDataItem, ConstructorStateMutability, StateMutability, Web3JsProvider, diff --git a/packages/abi-gen-templates/CHANGELOG.json b/packages/abi-gen-templates/CHANGELOG.json index 94f5bd1422..b9b463acbe 100644 --- a/packages/abi-gen-templates/CHANGELOG.json +++ b/packages/abi-gen-templates/CHANGELOG.json @@ -1,4 +1,25 @@ [ + { + "version": "2.3.0", + "changes": [ + { + "note": "Python: fix broken event handling", + "pr": 1919 + }, + { + "note": "Python: custom validator class support", + "pr": 1919 + }, + { + "note": "Python: linter fixes", + "pr": 1919 + }, + { + "note": "Python: normalize bytes parameters in wrapper methods", + "pr": 1919 + } + ] + }, { "timestamp": 1563006338, "version": "2.2.1", diff --git a/packages/abi-gen-templates/Python/contract.handlebars b/packages/abi-gen-templates/Python/contract.handlebars index 4e5646bcaa..25eaa2980b 100644 --- a/packages/abi-gen-templates/Python/contract.handlebars +++ b/packages/abi-gen-templates/Python/contract.handlebars @@ -1,8 +1,17 @@ """Generated wrapper for {{contractName}} Solidity contract.""" +# pylint: disable=too-many-arguments + import json -from typing import Optional, Tuple, Union +from typing import ( # pylint: disable=unused-import + Any, + List, + Optional, + Tuple, + Union, +) +from mypy_extensions import TypedDict # pylint: disable=unused-import from hexbytes import HexBytes from web3.datastructures import AttributeDict from web3.providers.base import BaseProvider @@ -11,13 +20,55 @@ from zero_ex.contract_wrappers._base_contract_wrapper import BaseContractWrapper from zero_ex.contract_wrappers.tx_params import TxParams +class {{contractName}}ValidatorBase: + """Base class for validating inputs to {{contractName}} methods.""" + def __init__( + self, + provider: BaseProvider, + contract_address: str, + private_key: str = None, + ): + """Initialize the instance.""" + + def assert_valid( + self, method_name: str, parameter_name: str, argument_value: Any + ): + """Raise an exception if method input is not valid. + + :param method_name: Name of the method whose input is to be validated. + :param parameter_name: Name of the parameter whose input is to be + validated. + :param argument_value: Value of argument to parameter to be validated. + """ + + +# Try to import a custom validator class definition; if there isn't one, +# declare one that we can instantiate for the default argument to the +# constructor for {{contractName}} below. +try: + # both mypy and pylint complain about what we're doing here, but this + # works just fine, so their messages have been disabled here. + from . import ( # type: ignore # pylint: disable=import-self + {{contractName}}Validator, + ) +except ImportError: + + class {{contractName}}Validator({{contractName}}ValidatorBase): # type: ignore + """No-op input validator.""" + + +{{tupleDefinitions ABIString}} + + +# pylint: disable=too-many-public-methods class {{contractName}}(BaseContractWrapper): - """Wrapper class for {{contractName}} Solidity contract.""" + """Wrapper class for {{contractName}} Solidity contract.{{docBytesIfNecessary ABIString}}""" def __init__( self, provider: BaseProvider, contract_address: str, + validator: {{contractName}}Validator = None, private_key: str = None, ): """Get an instance of wrapper for smart contract. @@ -34,6 +85,11 @@ class {{contractName}}(BaseContractWrapper): private_key=private_key, ) + if not validator: + validator = {{contractName}}Validator(provider, contract_address, private_key) + + self.validator = validator + def _get_contract_instance(self, token_address): """Get an instance of the smart contract at a specific address. @@ -55,3 +111,5 @@ class {{contractName}}(BaseContractWrapper): return json.loads( '{{{ABIString}}}' # noqa: E501 (line-too-long) ) + +# pylint: disable=too-many-lines diff --git a/packages/abi-gen-templates/Python/partials/call.handlebars b/packages/abi-gen-templates/Python/partials/call.handlebars index 334b1d21ac..f0756937df 100644 --- a/packages/abi-gen-templates/Python/partials/call.handlebars +++ b/packages/abi-gen-templates/Python/partials/call.handlebars @@ -6,31 +6,44 @@ {{^this.constant}} view_only: bool = False, {{/this.constant}} - ) ->{{#if outputs}}{{~> return_type outputs=outputs~}}{{else}} None{{/if}}: + ) -> {{> return_type outputs=outputs~}}: """Execute underlying, same-named contract method. -{{sanitizeDevdocDetails this.name this.devdoc.details 8}} - {{#each this.devdoc.params}} - :param {{@key}}: {{this}} - {{/each}} - {{#if this.constant}} - {{#if this.devdoc.return}}:returns: {{this.devdoc.return}}{{/if}} - {{else}} +{{sanitizeDevdocDetails this.name this.devdoc.details 8}}{{~#if this.devdoc.params~}}{{#each this.devdoc.params}} +{{makeParameterDocstringRole @key this 8}}{{/each}}{{/if}} :param tx_params: transaction parameters + {{#if this.constant~}} + {{#if this.devdoc.return}} +{{makeReturnDocstringRole this.devdoc.return 8}}{{/if}} + {{else}} :param view_only: whether to use transact() or call() - :returns: transaction hash + :returns: if param `view_only`:code: is `True`:code:, then returns the + value returned from the underlying function; else returns the + transaction hash. {{/if}} """ {{#each this.inputs}} + self.validator.assert_valid( + method_name='{{../name}}', + parameter_name='{{name}}', + argument_value={{toPythonIdentifier name}}, + ) {{#if (equal type 'address')}} - {{this.name}} = self._validate_and_checksum_address({{this.name}}) + {{toPythonIdentifier this.name}} = self._validate_and_checksum_address({{toPythonIdentifier this.name}}) {{else if (equal type 'uint256')}} # safeguard against fractional inputs - {{this.name}} = int({{this.name}}) + {{toPythonIdentifier this.name}} = int({{toPythonIdentifier this.name}}) + {{else if (equal type 'bytes')}} + {{toPythonIdentifier this.name}} = bytes.fromhex({{toPythonIdentifier this.name}}.decode("utf-8")) + {{else if (equal type 'bytes[]')}} + {{toPythonIdentifier this.name}} = [ + bytes.fromhex({{toPythonIdentifier this.name}}_element.decode("utf-8")) + for {{toPythonIdentifier this.name}}_element in {{toPythonIdentifier this.name}} + ] {{/if}} {{/each}} func = self._get_contract_instance( - self._contract_address + self.contract_address ).functions.{{this.name}}( {{> params}} ) diff --git a/packages/abi-gen-templates/Python/partials/event.handlebars b/packages/abi-gen-templates/Python/partials/event.handlebars index eb3725612e..461f38b3ec 100644 --- a/packages/abi-gen-templates/Python/partials/event.handlebars +++ b/packages/abi-gen-templates/Python/partials/event.handlebars @@ -1,14 +1,13 @@ def get_{{languageSpecificName}}_event( - self, token_address: str, tx_hash: Union[HexBytes, bytes] + self, tx_hash: Union[HexBytes, bytes] ) -> Tuple[AttributeDict]: """Get log entry for {{name}} event. - :param tx_hash: hash of transaction emitting {{name}} event. +{{makeEventParameterDocstringRole name 8}} """ tx_receipt = self._web3_eth.getTransactionReceipt(tx_hash) - token_address = self._validate_and_checksum_address(token_address) return ( - self._get_contract_instance(token_address) + self._get_contract_instance(self.contract_address) .events.{{name}}() .processReceipt(tx_receipt) ) diff --git a/packages/abi-gen-templates/Python/partials/params.handlebars b/packages/abi-gen-templates/Python/partials/params.handlebars index 2d9bb8ed96..1b2b86e6a5 100644 --- a/packages/abi-gen-templates/Python/partials/params.handlebars +++ b/packages/abi-gen-templates/Python/partials/params.handlebars @@ -1,3 +1,3 @@ {{#each inputs}} -{{name}}{{#if @last}}{{else}},{{/if}} +{{toPythonIdentifier name}}{{#if @last}}{{else}},{{/if}} {{/each}} diff --git a/packages/abi-gen-templates/Python/partials/return_type.handlebars b/packages/abi-gen-templates/Python/partials/return_type.handlebars index 7ff7b83696..54dc63ef71 100644 --- a/packages/abi-gen-templates/Python/partials/return_type.handlebars +++ b/packages/abi-gen-templates/Python/partials/return_type.handlebars @@ -1,13 +1,14 @@ -{{#if this.constant}} +{{~#if outputs~}} +{{^if this.constant}} +Union[ +{{~/if~}} {{#if outputs.length}} {{#singleReturnValue}} - {{#returnType outputs.0.type outputs.0.components}}{{~/returnType~}} +{{#returnType outputs.0.type outputs.0.components}}{{~/returnType~}} {{/singleReturnValue}} {{^singleReturnValue}} [{{#each outputs}}{{#returnType type components}}{{/returnType}}{{#unless @last}}, {{/unless}}{{/each}}] {{/singleReturnValue}} -{{/if}} -{{/if}} -{{^if this.constant}} - Union[HexBytes, bytes] -{{~/if~}} +{{else}}None +{{/if}}{{^if this.constant}}, Union[HexBytes, bytes]]{{/if~}} +{{else}}{{#if this.constant}}None{{else}}Union[None, Union[HexBytes, bytes]]{{/if}}{{/if~}} diff --git a/packages/abi-gen-templates/Python/partials/typed_params.handlebars b/packages/abi-gen-templates/Python/partials/typed_params.handlebars index bbbdef29b4..640d1188e5 100644 --- a/packages/abi-gen-templates/Python/partials/typed_params.handlebars +++ b/packages/abi-gen-templates/Python/partials/typed_params.handlebars @@ -1,3 +1,3 @@ {{#each inputs}} -{{name}}: {{#parameterType type components}}{{/parameterType}}, +{{toPythonIdentifier name}}: {{#parameterType type components}}{{/parameterType}}, {{/each}} diff --git a/packages/abi-gen/CHANGELOG.json b/packages/abi-gen/CHANGELOG.json index 5e89dc1e40..af73fccfc8 100644 --- a/packages/abi-gen/CHANGELOG.json +++ b/packages/abi-gen/CHANGELOG.json @@ -1,4 +1,37 @@ [ + { + "version": "3.1.1", + "changes": [ + { + "note": "Python method parameters are now in snake case", + "pr": 1919 + }, + { + "note": "Python wrappers now support tuples in method parameters", + "pr": 1919 + }, + { + "note": "document Python method's bytes params as requiring UTF-8", + "pr": 1919 + }, + { + "note": "generate Python output into a contract-named folder, not a file (eg exchange/__init__.py rather than exchange.py) leaving space for user-defined additions to the same module, such as for custom types, as used by the Exchange wrapper's manually-written type aliases in the contract_wrappers.exchange.types Python module", + "pr": 1919 + }, + { + "note": "support for customizable parameter validation for Python wrappers", + "pr": 1919 + }, + { + "note": "wrap Python docstrings better, for pydocstyle compliance", + "pr": 1919 + }, + { + "note": "lots of fixes to satisfy linters of generated Python code", + "pr": 1919 + } + ] + }, { "timestamp": 1563047529, "version": "2.1.1", diff --git a/packages/abi-gen/compiler.json b/packages/abi-gen/compiler.json index 546ec75729..3298f028f2 100644 --- a/packages/abi-gen/compiler.json +++ b/packages/abi-gen/compiler.json @@ -17,7 +17,8 @@ "evm.bytecode.object", "evm.bytecode.sourceMap", "evm.deployedBytecode.object", - "evm.deployedBytecode.sourceMap" + "evm.deployedBytecode.sourceMap", + "devdoc" ] } } diff --git a/packages/abi-gen/package.json b/packages/abi-gen/package.json index 6cd5b8e0e1..1d81675691 100644 --- a/packages/abi-gen/package.json +++ b/packages/abi-gen/package.json @@ -33,7 +33,7 @@ "generate_contract_wrappers": "run-p gen_typescript gen_python", "gen_typescript": "abi-gen --abis ${npm_package_config_abis} --template ../../node_modules/@0x/abi-gen-templates/contract.handlebars --partials '../../node_modules/@0x/abi-gen-templates/partials/**/*.handlebars' --output ./test-cli/output/typescript --backend ethers", "gen_python": "abi-gen --abis ${npm_package_config_abis} --template ../../node_modules/@0x/abi-gen-templates/Python/contract.handlebars --partials '../../node_modules/@0x/abi-gen-templates/Python/partials/**/*.handlebars' --output ./test-cli/output/python --language Python", - "diff_contract_wrappers": "./diff.sh ./test-cli/expected-output ./test-cli/output", + "diff_contract_wrappers": "test-cli/diff.sh ./test-cli/expected-output ./test-cli/output", "coverage:report:text": "istanbul report text", "coverage:report:html": "istanbul report html && open coverage/index.html", "profiler:report:html": "istanbul report html && open coverage/index.html", diff --git a/packages/abi-gen/src/index.ts b/packages/abi-gen/src/index.ts index 41faec0d03..a325d31c52 100644 --- a/packages/abi-gen/src/index.ts +++ b/packages/abi-gen/src/index.ts @@ -4,7 +4,16 @@ import { AbiEncoder, abiUtils, logUtils } from '@0x/utils'; import chalk from 'chalk'; import * as changeCase from 'change-case'; import * as cliFormat from 'cli-format'; -import { AbiDefinition, ConstructorAbi, ContractAbi, DevdocOutput, EventAbi, MethodAbi } from 'ethereum-types'; +import { + AbiDefinition, + ConstructorAbi, + ContractAbi, + DataItem, + DevdocOutput, + EventAbi, + MethodAbi, + TupleDataItem, +} from 'ethereum-types'; import { sync as globSync } from 'glob'; import * as Handlebars from 'handlebars'; import * as _ from 'lodash'; @@ -102,8 +111,9 @@ function registerPythonHelpers(): void { return lhs === rhs; }); Handlebars.registerHelper('safeString', (str, options) => new Handlebars.SafeString(str)); - Handlebars.registerHelper('parameterType', utils.solTypeToPyType.bind(utils, ParamKind.Input, args.backend)); - Handlebars.registerHelper('returnType', utils.solTypeToPyType.bind(utils, ParamKind.Output, args.backend)); + Handlebars.registerHelper('parameterType', utils.solTypeToPyType.bind(utils)); + Handlebars.registerHelper('returnType', utils.solTypeToPyType.bind(utils)); + Handlebars.registerHelper('toPythonIdentifier', utils.toPythonIdentifier.bind(utils)); Handlebars.registerHelper( 'sanitizeDevdocDetails', (methodName: string, devdocDetails: string, indent: number, options) => { @@ -116,12 +126,111 @@ function registerPythonHelpers(): void { return new Handlebars.SafeString( `\n${cliFormat.wrap(devdocDetails || '', { paddingLeft: ' '.repeat(indent), - width: columnsPerRow - indent, + width: columnsPerRow, ansi: false, })}\n`, ); }, ); + Handlebars.registerHelper( + 'makeParameterDocstringRole', + (name: string, description: string, indent: number, options) => { + let docstring = `:param ${name}:`; + if (description && description.length > 0) { + docstring = `${docstring} ${description}`; + } + return new Handlebars.SafeString(utils.wrapPythonDocstringRole(docstring, indent)); + }, + ); + Handlebars.registerHelper( + 'makeReturnDocstringRole', + (description: string, indent: number, options) => + new Handlebars.SafeString(utils.wrapPythonDocstringRole(`:returns: ${description}`, indent)), + ); + Handlebars.registerHelper( + 'makeEventParameterDocstringRole', + (eventName: string, indent: number, options) => + new Handlebars.SafeString( + utils.wrapPythonDocstringRole( + `:param tx_hash: hash of transaction emitting ${eventName} event`, + indent, + ), + ), + ); + Handlebars.registerHelper('tupleDefinitions', (abisJSON: string, options) => { + const abis: AbiDefinition[] = JSON.parse(abisJSON); + // build an array of objects, each of which has one key, the Python + // name of a tuple, with a string value holding the Python + // definition of that tuple. Using a key-value object conveniently + // filters duplicate references to the same tuple. + const tupleDefinitions: { [pythonTupleName: string]: string } = {}; + for (const abi of abis) { + let parameters: DataItem[] = []; + if (abi.hasOwnProperty('inputs')) { + // HACK(feuGeneA): using "as MethodAbi" below, but abi + // could just as well be ConstructorAbi, EventAbi, etc. We + // just need to tell the TypeScript compiler that it's NOT + // FallbackAbi, or else it would complain, "Property + // 'inputs' does not exist on type 'AbiDefinition'. + // Property 'inputs' does not exist on type + // 'FallbackAbi'.", despite the enclosing if statement. + // tslint:disable:no-unnecessary-type-assertion + parameters = parameters.concat((abi as MethodAbi).inputs); + } + if (abi.hasOwnProperty('outputs')) { + // HACK(feuGeneA): same as described above, except here we + // KNOW that it's a MethodAbi, given the enclosing if + // statement, because that's the only AbiDefinition subtype + // that actually has an outputs field. + parameters = parameters.concat((abi as MethodAbi).outputs); + } + for (const parameter of parameters) { + if (parameter.type === 'tuple') { + tupleDefinitions[ + utils.makePythonTupleName((parameter as TupleDataItem).components) + ] = utils.makePythonTupleClassBody((parameter as TupleDataItem).components); + } + } + } + const tupleDeclarations = []; + for (const pythonTupleName in tupleDefinitions) { + if (tupleDefinitions[pythonTupleName]) { + tupleDeclarations.push( + `class ${pythonTupleName}(TypedDict):\n """Python representation of a tuple or struct.\n\n A tuple found in an ABI may have been written in Solidity as a literal\n tuple, or it may have been written as a parameter with a Solidity\n \`struct\`:code: data type; there's no way to tell which, based solely on the\n ABI, and the name of a Solidity \`struct\`:code: is not conveyed through the\n ABI. This class represents a tuple that appeared in a method definition.\n Its name is derived from a hash of that tuple's field names, and every\n method whose ABI refers to a tuple with that same list of field names will\n have a generated wrapper method that refers to this class.\n\n Any members of type \`bytes\`:code: should be encoded as UTF-8, which can be\n accomplished via \`str.encode("utf_8")\`:code:\n """${ + tupleDefinitions[pythonTupleName] + }`, + ); + } + } + return new Handlebars.SafeString(tupleDeclarations.join('\n\n')); + }); + Handlebars.registerHelper('docBytesIfNecessary', (abisJSON: string, options) => { + const abis: AbiDefinition[] = JSON.parse(abisJSON); + // see if any ABIs accept params of type bytes, and if so then emit + // explanatory documentation string. + for (const abi of abis) { + if (abi.hasOwnProperty('inputs')) { + // HACK(feuGeneA): using "as MethodAbi" below, but abi + // could just as well be ConstructorAbi, EventAbi, etc. We + // just need to tell the TypeScript compiler that it's NOT + // FallbackAbi, or else it would complain, "Property + // 'inputs' does not exist on type 'AbiDefinition'. + // Property 'inputs' does not exist on type + // 'FallbackAbi'.", despite the enclosing if statement. + // tslint:disable:no-unnecessary-type-assertion + if ((abi as MethodAbi).inputs) { + for (const input of (abi as MethodAbi).inputs) { + if (input.type === 'bytes') { + return new Handlebars.SafeString( + '\n\n All method parameters of type `bytes`:code: should be encoded as UTF-8,\n which can be accomplished via `str.encode("utf_8")`:code:.\n ', + ); + } + } + } + } + } + return ''; + }); } if (args.language === 'TypeScript') { registerTypeScriptHelpers(); @@ -168,16 +277,17 @@ for (const abiFileName of abiFileNames) { } const outFileName = utils.makeOutputFileName(namedContent.name); - const outFileExtension = (() => { + const outFilePath = (() => { if (args.language === 'TypeScript') { - return 'ts'; + return `${args.output}/${outFileName}.ts`; } else if (args.language === 'Python') { - return 'py'; + const directory = `${args.output}/${outFileName}`; + mkdirp.sync(directory); + return `${directory}/__init__.py`; } else { throw new Error(`Unexpected language '${args.language}'`); } })(); - const outFilePath = `${args.output}/${outFileName}.${outFileExtension}`; if (utils.isOutputFileUpToDate(outFilePath, [abiFileName, args.template, ...partialTemplateFileNames])) { logUtils.log(`Already up to date: ${chalk.bold(outFilePath)}`); diff --git a/packages/abi-gen/src/utils.ts b/packages/abi-gen/src/utils.ts index dfa102f2db..83ee80eac8 100644 --- a/packages/abi-gen/src/utils.ts +++ b/packages/abi-gen/src/utils.ts @@ -1,3 +1,7 @@ +import { createHash } from 'crypto'; + +import * as changeCase from 'change-case'; +import * as cliFormat from 'cli-format'; import { AbiType, ConstructorAbi, DataItem } from 'ethereum-types'; import * as fs from 'fs'; import * as _ from 'lodash'; @@ -98,12 +102,12 @@ export const utils = { throw new Error(`Unknown Solidity type found: ${solType}`); } }, - solTypeToPyType(paramKind: ParamKind, backend: ContractsBackend, solType: string, components?: DataItem[]): string { + solTypeToPyType(solType: string, components?: DataItem[]): string { const trailingArrayRegex = /\[\d*\]$/; if (solType.match(trailingArrayRegex)) { const arrayItemSolType = solType.replace(trailingArrayRegex, ''); - const arrayItemPyType = utils.solTypeToPyType(paramKind, backend, arrayItemSolType, components); - const arrayPyType = `Array[${arrayItemPyType}]`; + const arrayItemPyType = utils.solTypeToPyType(arrayItemSolType, components); + const arrayPyType = `List[${arrayItemPyType}]`; return arrayPyType; } else { const solTypeRegexToPyType = [ @@ -121,18 +125,7 @@ export const utils = { } const TUPLE_TYPE_REGEX = '^tuple$'; if (solType.match(TUPLE_TYPE_REGEX)) { - const componentsType = _.map(components, component => { - const componentValueType = utils.solTypeToPyType( - paramKind, - backend, - component.type, - component.components, - ); - const componentType = `'${component.name}': ${componentValueType}`; - return componentType; - }); - const pyType = `TypedDict('${solType}(${components})', {${componentsType.join(',')}}`; - return pyType; + return utils.makePythonTupleName(components as DataItem[]); } throw new Error(`Unknown Solidity type found: ${solType}`); } @@ -190,4 +183,171 @@ export const utils = { } } }, + /** + * simply concatenate all of the names of the components, and convert that + * concatenation into PascalCase to conform to Python convention. + */ + makePythonTupleName(tupleComponents: DataItem[]): string { + const lengthOfHashSuffix = 8; + return `Tuple0x${createHash('MD5') + .update(_.map(tupleComponents, component => component.name).join('_')) + .digest() + .toString('hex') + .substring(0, lengthOfHashSuffix)}`; + }, + /** + * @returns a string that is a Python code snippet that's intended to be + * used as the second parameter to a TypedDict() instantiation; value + * looks like "{ 'python_dict_key': python_type, ... }". + */ + makePythonTupleClassBody(tupleComponents: DataItem[]): string { + let toReturn: string = ''; + for (const tupleComponent of tupleComponents) { + toReturn = `${toReturn}\n\n ${tupleComponent.name}: ${utils.solTypeToPyType( + tupleComponent.type, + tupleComponent.components, + )}`; + } + toReturn = `${toReturn}`; + return toReturn; + }, + /** + * used to generate Python-parseable identifier names for parameters to + * contract methods. + */ + toPythonIdentifier(input: string): string { + let snakeCased = changeCase.snake(input); + const pythonReservedWords = [ + 'False', + 'None', + 'True', + 'and', + 'as', + 'assert', + 'break', + 'class', + 'continue', + 'def', + 'del', + 'elif', + 'else', + 'except', + 'finally', + 'for', + 'from', + 'global', + 'if', + 'import', + 'in', + 'is', + 'lambda', + 'nonlocal', + 'not', + 'or', + 'pass', + 'raise', + 'return', + 'try', + 'while', + 'with', + 'yield', + ]; + const pythonBuiltins = [ + 'abs', + 'delattr', + 'hash', + 'memoryview', + 'set', + 'all', + 'dict', + 'help', + 'min', + 'setattr', + 'any', + 'dir', + 'hex', + 'next', + 'slice', + 'ascii', + 'divmod', + 'id', + 'object', + 'sorted', + 'bin', + 'enumerate', + 'input', + 'oct', + 'staticmethod', + 'bool', + 'eval', + 'int', + 'open', + 'str', + 'breakpoint', + 'exec', + 'isinstance', + 'ord', + 'sum', + 'bytearray', + 'filter', + 'issubclass', + 'pow', + 'super', + 'bytes', + 'float', + 'iter', + 'print', + 'tuple', + 'callable', + 'format', + 'len', + 'property', + 'type', + 'chr', + 'frozenset', + 'list', + 'range', + 'vars', + 'classmethod', + 'getattr', + 'locals', + 'repr', + 'zip', + 'compile', + 'globals', + 'map', + 'reversed', + '__import__', + 'complex', + 'hasattr', + 'max', + 'round', + ]; + if ( + pythonReservedWords.includes(snakeCased) || + pythonBuiltins.includes(snakeCased) || + /*changeCase strips leading underscores :(*/ input[0] === '_' + ) { + snakeCased = `_${snakeCased}`; + } + return snakeCased; + }, + /** + * Python docstrings are used to generate documentation, and that + * transformation supports annotation of parameters, return types, etc, via + * re-Structured Text "interpreted text roles". Per the pydocstyle linter, + * such annotations should be line-wrapped at 80 columns, with a hanging + * indent of 4 columns. This function simply returns an accordingly + * wrapped and hanging-indented `role` string. + */ + wrapPythonDocstringRole(docstring: string, indent: number): string { + const columnsPerIndent = 4; + const columnsPerRow = 80; + return cliFormat.wrap(docstring, { + paddingLeft: ' '.repeat(indent), + width: columnsPerRow, + ansi: false, + hangingIndent: ' '.repeat(columnsPerIndent), + }); + }, }; diff --git a/packages/abi-gen/diff.sh b/packages/abi-gen/test-cli/diff.sh similarity index 59% rename from packages/abi-gen/diff.sh rename to packages/abi-gen/test-cli/diff.sh index 6ee07669d7..d4f914f344 100755 --- a/packages/abi-gen/diff.sh +++ b/packages/abi-gen/test-cli/diff.sh @@ -1,4 +1,6 @@ -diff -r $1 $2 +diff -r -U 5 $1 $2 +# -r tells diff to compare folders recursively. +# "-U 5" tells diff to output a "unified" format, with 5 lines of context. if [ $? -ne 0 ]; then echo "ERROR: Freshly generated output does not match expected output. If you're confident that the expected output should be updated, copy it in there and commit it." exit 1 diff --git a/packages/abi-gen/test-cli/expected-output/python/abi_gen_dummy.py b/packages/abi-gen/test-cli/expected-output/python/abi_gen_dummy.py deleted file mode 100644 index 7215e31b3f..0000000000 --- a/packages/abi-gen/test-cli/expected-output/python/abi_gen_dummy.py +++ /dev/null @@ -1,243 +0,0 @@ -"""Generated wrapper for AbiGenDummy Solidity contract.""" - -import json -from typing import Optional, Tuple, Union - -from hexbytes import HexBytes -from web3.datastructures import AttributeDict -from web3.providers.base import BaseProvider - -from zero_ex.contract_wrappers._base_contract_wrapper import BaseContractWrapper -from zero_ex.contract_wrappers.tx_params import TxParams - - -class AbiGenDummy(BaseContractWrapper): - """Wrapper class for AbiGenDummy Solidity contract.""" - - def __init__( - self, - provider: BaseProvider, - contract_address: str, - private_key: str = None, - ): - """Get an instance of wrapper for smart contract. - - :param provider: instance of :class:`web3.providers.base.BaseProvider` - :param contract_address: where the contract has been deployed - :param private_key: If specified, transactions will be signed locally, - via Web3.py's `eth.account.signTransaction()`:code:, before being - sent via `eth.sendRawTransaction()`:code:. - """ - super().__init__( - provider=provider, - contract_address=contract_address, - private_key=private_key, - ) - - def _get_contract_instance(self, token_address): - """Get an instance of the smart contract at a specific address. - - :returns: contract object - """ - return self._contract_instance( - address=token_address, abi=AbiGenDummy.abi() - ) - - def simple_require( - self, - tx_params: Optional[TxParams] = None, - ) -> None: - """Execute underlying, same-named contract method. - - - """ - func = self._get_contract_instance( - self._contract_address - ).functions.simpleRequire( - ) - return self._invoke_function_call( - func=func, - tx_params=tx_params, - view_only=True - ) - - def ecrecover_fn( - self, - hash: bytes, - v: int, - r: bytes, - s: bytes, - tx_params: Optional[TxParams] = None, - ) -> str: - """Execute underlying, same-named contract method. - - - """ - func = self._get_contract_instance( - self._contract_address - ).functions.ecrecoverFn( - hash, - v, - r, - s - ) - return self._invoke_function_call( - func=func, - tx_params=tx_params, - view_only=True - ) - - def revert_with_constant( - self, - tx_params: Optional[TxParams] = None, - ) -> None: - """Execute underlying, same-named contract method. - - - """ - func = self._get_contract_instance( - self._contract_address - ).functions.revertWithConstant( - ) - return self._invoke_function_call( - func=func, - tx_params=tx_params, - view_only=True - ) - - def simple_revert( - self, - tx_params: Optional[TxParams] = None, - ) -> None: - """Execute underlying, same-named contract method. - - - """ - func = self._get_contract_instance( - self._contract_address - ).functions.simpleRevert( - ) - return self._invoke_function_call( - func=func, - tx_params=tx_params, - view_only=True - ) - - def require_with_constant( - self, - tx_params: Optional[TxParams] = None, - ) -> None: - """Execute underlying, same-named contract method. - - - """ - func = self._get_contract_instance( - self._contract_address - ).functions.requireWithConstant( - ) - return self._invoke_function_call( - func=func, - tx_params=tx_params, - view_only=True - ) - - def with_address_input( - self, - x: str, - a: int, - b: int, - y: str, - c: int, - tx_params: Optional[TxParams] = None, - ) -> str: - """Execute underlying, same-named contract method. - - - """ - x = self._validate_and_checksum_address(x) - # safeguard against fractional inputs - a = int(a) - # safeguard against fractional inputs - b = int(b) - y = self._validate_and_checksum_address(y) - # safeguard against fractional inputs - c = int(c) - func = self._get_contract_instance( - self._contract_address - ).functions.withAddressInput( - x, - a, - b, - y, - c - ) - return self._invoke_function_call( - func=func, - tx_params=tx_params, - view_only=True - ) - - def simple_pure_function_with_input( - self, - x: int, - tx_params: Optional[TxParams] = None, - ) -> int: - """Execute underlying, same-named contract method. - - - """ - # safeguard against fractional inputs - x = int(x) - func = self._get_contract_instance( - self._contract_address - ).functions.simplePureFunctionWithInput( - x - ) - return self._invoke_function_call( - func=func, - tx_params=tx_params, - view_only=True - ) - - def simple_pure_function( - self, - tx_params: Optional[TxParams] = None, - ) -> int: - """Execute underlying, same-named contract method. - - - """ - func = self._get_contract_instance( - self._contract_address - ).functions.simplePureFunction( - ) - return self._invoke_function_call( - func=func, - tx_params=tx_params, - view_only=True - ) - - def pure_function_with_constant( - self, - tx_params: Optional[TxParams] = None, - ) -> int: - """Execute underlying, same-named contract method. - - - """ - func = self._get_contract_instance( - self._contract_address - ).functions.pureFunctionWithConstant( - ) - return self._invoke_function_call( - func=func, - tx_params=tx_params, - view_only=True - ) - - @staticmethod - def abi(): - """Return the ABI to the underlying contract.""" - return json.loads( - '[{"constant":true,"inputs":[],"name":"simpleRequire","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"name":"hash","type":"bytes32"},{"name":"v","type":"uint8"},{"name":"r","type":"bytes32"},{"name":"s","type":"bytes32"}],"name":"ecrecoverFn","outputs":[{"name":"signerAddress","type":"address"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"revertWithConstant","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"simpleRevert","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"requireWithConstant","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"name":"x","type":"address"},{"name":"a","type":"uint256"},{"name":"b","type":"uint256"},{"name":"y","type":"address"},{"name":"c","type":"uint256"}],"name":"withAddressInput","outputs":[{"name":"z","type":"address"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"name":"x","type":"uint256"}],"name":"simplePureFunctionWithInput","outputs":[{"name":"sum","type":"uint256"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"simplePureFunction","outputs":[{"name":"result","type":"uint256"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"pureFunctionWithConstant","outputs":[{"name":"someConstant","type":"uint256"}],"payable":false,"stateMutability":"pure","type":"function"}]' # noqa: E501 (line-too-long) - ) diff --git a/packages/abi-gen/test-cli/expected-output/python/abi_gen_dummy/__init__.py b/packages/abi-gen/test-cli/expected-output/python/abi_gen_dummy/__init__.py new file mode 100644 index 0000000000..70ca086ae5 --- /dev/null +++ b/packages/abi-gen/test-cli/expected-output/python/abi_gen_dummy/__init__.py @@ -0,0 +1,619 @@ +"""Generated wrapper for AbiGenDummy Solidity contract.""" + +# pylint: disable=too-many-arguments + +import json +from typing import ( # pylint: disable=unused-import + Any, + List, + Optional, + Tuple, + Union, +) + +from mypy_extensions import TypedDict # pylint: disable=unused-import +from hexbytes import HexBytes +from web3.datastructures import AttributeDict +from web3.providers.base import BaseProvider + +from zero_ex.contract_wrappers._base_contract_wrapper import BaseContractWrapper +from zero_ex.contract_wrappers.tx_params import TxParams + + +class AbiGenDummyValidatorBase: + """Base class for validating inputs to AbiGenDummy methods.""" + def __init__( + self, + provider: BaseProvider, + contract_address: str, + private_key: str = None, + ): + """Initialize the instance.""" + + def assert_valid( + self, method_name: str, parameter_name: str, argument_value: Any + ): + """Raise an exception if method input is not valid. + + :param method_name: Name of the method whose input is to be validated. + :param parameter_name: Name of the parameter whose input is to be + validated. + :param argument_value: Value of argument to parameter to be validated. + """ + + +# Try to import a custom validator class definition; if there isn't one, +# declare one that we can instantiate for the default argument to the +# constructor for AbiGenDummy below. +try: + # both mypy and pylint complain about what we're doing here, but this + # works just fine, so their messages have been disabled here. + from . import ( # type: ignore # pylint: disable=import-self + AbiGenDummyValidator, + ) +except ImportError: + + class AbiGenDummyValidator(AbiGenDummyValidatorBase): # type: ignore + """No-op input validator.""" + + +class Tuple0xc9bdd2d5(TypedDict): + """Python representation of a tuple or struct. + + A tuple found in an ABI may have been written in Solidity as a literal + tuple, or it may have been written as a parameter with a Solidity + `struct`:code: data type; there's no way to tell which, based solely on the + ABI, and the name of a Solidity `struct`:code: is not conveyed through the + ABI. This class represents a tuple that appeared in a method definition. + Its name is derived from a hash of that tuple's field names, and every + method whose ABI refers to a tuple with that same list of field names will + have a generated wrapper method that refers to this class. + + Any members of type `bytes`:code: should be encoded as UTF-8, which can be + accomplished via `str.encode("utf_8")`:code: + """ + + innerStruct: Tuple0xcf8ad995 + + description: str + +class Tuple0xcf8ad995(TypedDict): + """Python representation of a tuple or struct. + + A tuple found in an ABI may have been written in Solidity as a literal + tuple, or it may have been written as a parameter with a Solidity + `struct`:code: data type; there's no way to tell which, based solely on the + ABI, and the name of a Solidity `struct`:code: is not conveyed through the + ABI. This class represents a tuple that appeared in a method definition. + Its name is derived from a hash of that tuple's field names, and every + method whose ABI refers to a tuple with that same list of field names will + have a generated wrapper method that refers to this class. + + Any members of type `bytes`:code: should be encoded as UTF-8, which can be + accomplished via `str.encode("utf_8")`:code: + """ + + someBytes: bytes + + anInteger: int + + aDynamicArrayOfBytes: List[bytes] + + aString: str + + +# pylint: disable=too-many-public-methods +class AbiGenDummy(BaseContractWrapper): + """Wrapper class for AbiGenDummy Solidity contract. + + All method parameters of type `bytes`:code: should be encoded as UTF-8, + which can be accomplished via `str.encode("utf_8")`:code:. + """ + + def __init__( + self, + provider: BaseProvider, + contract_address: str, + validator: AbiGenDummyValidator = None, + private_key: str = None, + ): + """Get an instance of wrapper for smart contract. + + :param provider: instance of :class:`web3.providers.base.BaseProvider` + :param contract_address: where the contract has been deployed + :param private_key: If specified, transactions will be signed locally, + via Web3.py's `eth.account.signTransaction()`:code:, before being + sent via `eth.sendRawTransaction()`:code:. + """ + super().__init__( + provider=provider, + contract_address=contract_address, + private_key=private_key, + ) + + if not validator: + validator = AbiGenDummyValidator(provider, contract_address, private_key) + + self.validator = validator + + def _get_contract_instance(self, token_address): + """Get an instance of the smart contract at a specific address. + + :returns: contract object + """ + return self._contract_instance( + address=token_address, abi=AbiGenDummy.abi() + ) + + def simple_require( + self, + tx_params: Optional[TxParams] = None, + ) -> None: + """Execute underlying, same-named contract method. + + :param tx_params: transaction parameters + + """ + func = self._get_contract_instance( + self.contract_address + ).functions.simpleRequire( + ) + return self._invoke_function_call( + func=func, + tx_params=tx_params, + view_only=True + ) + + def accepts_an_array_of_bytes( + self, + a: List[bytes], + tx_params: Optional[TxParams] = None, + ) -> None: + """Execute underlying, same-named contract method. + + a method that accepts an array of bytes + + :param a: the array of bytes being accepted + :param tx_params: transaction parameters + + """ + self.validator.assert_valid( + method_name='acceptsAnArrayOfBytes', + parameter_name='a', + argument_value=a, + ) + a = [ + bytes.fromhex(a_element.decode("utf-8")) + for a_element in a + ] + func = self._get_contract_instance( + self.contract_address + ).functions.acceptsAnArrayOfBytes( + a + ) + return self._invoke_function_call( + func=func, + tx_params=tx_params, + view_only=True + ) + + def ecrecover_fn( + self, + _hash: bytes, + v: int, + r: bytes, + s: bytes, + tx_params: Optional[TxParams] = None, + ) -> str: + """Execute underlying, same-named contract method. + + :param tx_params: transaction parameters + + """ + self.validator.assert_valid( + method_name='ecrecoverFn', + parameter_name='hash', + argument_value=_hash, + ) + self.validator.assert_valid( + method_name='ecrecoverFn', + parameter_name='v', + argument_value=v, + ) + self.validator.assert_valid( + method_name='ecrecoverFn', + parameter_name='r', + argument_value=r, + ) + self.validator.assert_valid( + method_name='ecrecoverFn', + parameter_name='s', + argument_value=s, + ) + func = self._get_contract_instance( + self.contract_address + ).functions.ecrecoverFn( + _hash, + v, + r, + s + ) + return self._invoke_function_call( + func=func, + tx_params=tx_params, + view_only=True + ) + + def accepts_bytes( + self, + a: bytes, + tx_params: Optional[TxParams] = None, + ) -> None: + """Execute underlying, same-named contract method. + + :param tx_params: transaction parameters + + """ + self.validator.assert_valid( + method_name='acceptsBytes', + parameter_name='a', + argument_value=a, + ) + a = bytes.fromhex(a.decode("utf-8")) + func = self._get_contract_instance( + self.contract_address + ).functions.acceptsBytes( + a + ) + return self._invoke_function_call( + func=func, + tx_params=tx_params, + view_only=True + ) + + def revert_with_constant( + self, + tx_params: Optional[TxParams] = None, + ) -> None: + """Execute underlying, same-named contract method. + + :param tx_params: transaction parameters + + """ + func = self._get_contract_instance( + self.contract_address + ).functions.revertWithConstant( + ) + return self._invoke_function_call( + func=func, + tx_params=tx_params, + view_only=True + ) + + def simple_revert( + self, + tx_params: Optional[TxParams] = None, + ) -> None: + """Execute underlying, same-named contract method. + + :param tx_params: transaction parameters + + """ + func = self._get_contract_instance( + self.contract_address + ).functions.simpleRevert( + ) + return self._invoke_function_call( + func=func, + tx_params=tx_params, + view_only=True + ) + + def nested_struct_output( + self, + tx_params: Optional[TxParams] = None, + ) -> Tuple0xc9bdd2d5: + """Execute underlying, same-named contract method. + + :param tx_params: transaction parameters + + """ + func = self._get_contract_instance( + self.contract_address + ).functions.nestedStructOutput( + ) + return self._invoke_function_call( + func=func, + tx_params=tx_params, + view_only=True + ) + + def require_with_constant( + self, + tx_params: Optional[TxParams] = None, + ) -> None: + """Execute underlying, same-named contract method. + + :param tx_params: transaction parameters + + """ + func = self._get_contract_instance( + self.contract_address + ).functions.requireWithConstant( + ) + return self._invoke_function_call( + func=func, + tx_params=tx_params, + view_only=True + ) + + def with_address_input( + self, + x: str, + a: int, + b: int, + y: str, + c: int, + tx_params: Optional[TxParams] = None, + ) -> str: + """Execute underlying, same-named contract method. + + :param tx_params: transaction parameters + + """ + self.validator.assert_valid( + method_name='withAddressInput', + parameter_name='x', + argument_value=x, + ) + x = self._validate_and_checksum_address(x) + self.validator.assert_valid( + method_name='withAddressInput', + parameter_name='a', + argument_value=a, + ) + # safeguard against fractional inputs + a = int(a) + self.validator.assert_valid( + method_name='withAddressInput', + parameter_name='b', + argument_value=b, + ) + # safeguard against fractional inputs + b = int(b) + self.validator.assert_valid( + method_name='withAddressInput', + parameter_name='y', + argument_value=y, + ) + y = self._validate_and_checksum_address(y) + self.validator.assert_valid( + method_name='withAddressInput', + parameter_name='c', + argument_value=c, + ) + # safeguard against fractional inputs + c = int(c) + func = self._get_contract_instance( + self.contract_address + ).functions.withAddressInput( + x, + a, + b, + y, + c + ) + return self._invoke_function_call( + func=func, + tx_params=tx_params, + view_only=True + ) + + def struct_input( + self, + s: Tuple0xcf8ad995, + tx_params: Optional[TxParams] = None, + ) -> None: + """Execute underlying, same-named contract method. + + :param tx_params: transaction parameters + + """ + self.validator.assert_valid( + method_name='structInput', + parameter_name='s', + argument_value=s, + ) + func = self._get_contract_instance( + self.contract_address + ).functions.structInput( + s + ) + return self._invoke_function_call( + func=func, + tx_params=tx_params, + view_only=True + ) + + def non_pure_method( + self, + tx_params: Optional[TxParams] = None, + view_only: bool = False, + ) -> Union[int, Union[HexBytes, bytes]]: + """Execute underlying, same-named contract method. + + :param tx_params: transaction parameters + :param view_only: whether to use transact() or call() + + :returns: if param `view_only`:code: is `True`:code:, then returns the + value returned from the underlying function; else returns the + transaction hash. + """ + func = self._get_contract_instance( + self.contract_address + ).functions.nonPureMethod( + ) + return self._invoke_function_call( + func=func, + tx_params=tx_params, + view_only=view_only + ) + + def simple_pure_function_with_input( + self, + x: int, + tx_params: Optional[TxParams] = None, + ) -> int: + """Execute underlying, same-named contract method. + + :param tx_params: transaction parameters + + """ + self.validator.assert_valid( + method_name='simplePureFunctionWithInput', + parameter_name='x', + argument_value=x, + ) + # safeguard against fractional inputs + x = int(x) + func = self._get_contract_instance( + self.contract_address + ).functions.simplePureFunctionWithInput( + x + ) + return self._invoke_function_call( + func=func, + tx_params=tx_params, + view_only=True + ) + + def non_pure_method_that_returns_nothing( + self, + tx_params: Optional[TxParams] = None, + view_only: bool = False, + ) -> Union[None, Union[HexBytes, bytes]]: + """Execute underlying, same-named contract method. + + :param tx_params: transaction parameters + :param view_only: whether to use transact() or call() + + :returns: if param `view_only`:code: is `True`:code:, then returns the + value returned from the underlying function; else returns the + transaction hash. + """ + func = self._get_contract_instance( + self.contract_address + ).functions.nonPureMethodThatReturnsNothing( + ) + return self._invoke_function_call( + func=func, + tx_params=tx_params, + view_only=view_only + ) + + def simple_pure_function( + self, + tx_params: Optional[TxParams] = None, + ) -> int: + """Execute underlying, same-named contract method. + + :param tx_params: transaction parameters + + """ + func = self._get_contract_instance( + self.contract_address + ).functions.simplePureFunction( + ) + return self._invoke_function_call( + func=func, + tx_params=tx_params, + view_only=True + ) + + def nested_struct_input( + self, + n: Tuple0xc9bdd2d5, + tx_params: Optional[TxParams] = None, + ) -> None: + """Execute underlying, same-named contract method. + + :param tx_params: transaction parameters + + """ + self.validator.assert_valid( + method_name='nestedStructInput', + parameter_name='n', + argument_value=n, + ) + func = self._get_contract_instance( + self.contract_address + ).functions.nestedStructInput( + n + ) + return self._invoke_function_call( + func=func, + tx_params=tx_params, + view_only=True + ) + + def struct_output( + self, + tx_params: Optional[TxParams] = None, + ) -> Tuple0xcf8ad995: + """Execute underlying, same-named contract method. + + a method that returns a struct + + :param tx_params: transaction parameters + :returns: a Struct struct + """ + func = self._get_contract_instance( + self.contract_address + ).functions.structOutput( + ) + return self._invoke_function_call( + func=func, + tx_params=tx_params, + view_only=True + ) + + def pure_function_with_constant( + self, + tx_params: Optional[TxParams] = None, + ) -> int: + """Execute underlying, same-named contract method. + + :param tx_params: transaction parameters + + """ + func = self._get_contract_instance( + self.contract_address + ).functions.pureFunctionWithConstant( + ) + return self._invoke_function_call( + func=func, + tx_params=tx_params, + view_only=True + ) + def get_an_event_event( + self, tx_hash: Union[HexBytes, bytes] + ) -> Tuple[AttributeDict]: + """Get log entry for AnEvent event. + + :param tx_hash: hash of transaction emitting AnEvent event + """ + tx_receipt = self._web3_eth.getTransactionReceipt(tx_hash) + return ( + self._get_contract_instance(self.contract_address) + .events.AnEvent() + .processReceipt(tx_receipt) + ) + + @staticmethod + def abi(): + """Return the ABI to the underlying contract.""" + return json.loads( + '[{"constant":true,"inputs":[],"name":"simpleRequire","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"name":"a","type":"bytes[]"}],"name":"acceptsAnArrayOfBytes","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"name":"hash","type":"bytes32"},{"name":"v","type":"uint8"},{"name":"r","type":"bytes32"},{"name":"s","type":"bytes32"}],"name":"ecrecoverFn","outputs":[{"name":"signerAddress","type":"address"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"name":"a","type":"bytes"}],"name":"acceptsBytes","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"revertWithConstant","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"simpleRevert","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"nestedStructOutput","outputs":[{"components":[{"components":[{"name":"someBytes","type":"bytes"},{"name":"anInteger","type":"uint32"},{"name":"aDynamicArrayOfBytes","type":"bytes[]"},{"name":"aString","type":"string"}],"name":"innerStruct","type":"tuple"},{"name":"description","type":"string"}],"name":"","type":"tuple"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"requireWithConstant","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"name":"x","type":"address"},{"name":"a","type":"uint256"},{"name":"b","type":"uint256"},{"name":"y","type":"address"},{"name":"c","type":"uint256"}],"name":"withAddressInput","outputs":[{"name":"z","type":"address"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"components":[{"name":"someBytes","type":"bytes"},{"name":"anInteger","type":"uint32"},{"name":"aDynamicArrayOfBytes","type":"bytes[]"},{"name":"aString","type":"string"}],"name":"s","type":"tuple"}],"name":"structInput","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":false,"inputs":[],"name":"nonPureMethod","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"x","type":"uint256"}],"name":"simplePureFunctionWithInput","outputs":[{"name":"sum","type":"uint256"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":false,"inputs":[],"name":"nonPureMethodThatReturnsNothing","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"simplePureFunction","outputs":[{"name":"result","type":"uint256"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"components":[{"components":[{"name":"someBytes","type":"bytes"},{"name":"anInteger","type":"uint32"},{"name":"aDynamicArrayOfBytes","type":"bytes[]"},{"name":"aString","type":"string"}],"name":"innerStruct","type":"tuple"},{"name":"description","type":"string"}],"name":"n","type":"tuple"}],"name":"nestedStructInput","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"structOutput","outputs":[{"components":[{"name":"someBytes","type":"bytes"},{"name":"anInteger","type":"uint32"},{"name":"aDynamicArrayOfBytes","type":"bytes[]"},{"name":"aString","type":"string"}],"name":"s","type":"tuple"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"pureFunctionWithConstant","outputs":[{"name":"someConstant","type":"uint256"}],"payable":false,"stateMutability":"pure","type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"name":"param","type":"uint8"}],"name":"AnEvent","type":"event"}]' # noqa: E501 (line-too-long) + ) + +# pylint: disable=too-many-lines diff --git a/packages/abi-gen/test-cli/expected-output/python/lib_dummy.py b/packages/abi-gen/test-cli/expected-output/python/lib_dummy.py deleted file mode 100644 index cd9a9103df..0000000000 --- a/packages/abi-gen/test-cli/expected-output/python/lib_dummy.py +++ /dev/null @@ -1,51 +0,0 @@ -"""Generated wrapper for LibDummy Solidity contract.""" - -import json -from typing import Optional, Tuple, Union - -from hexbytes import HexBytes -from web3.datastructures import AttributeDict -from web3.providers.base import BaseProvider - -from zero_ex.contract_wrappers._base_contract_wrapper import BaseContractWrapper -from zero_ex.contract_wrappers.tx_params import TxParams - - -class LibDummy(BaseContractWrapper): - """Wrapper class for LibDummy Solidity contract.""" - - def __init__( - self, - provider: BaseProvider, - contract_address: str, - private_key: str = None, - ): - """Get an instance of wrapper for smart contract. - - :param provider: instance of :class:`web3.providers.base.BaseProvider` - :param contract_address: where the contract has been deployed - :param private_key: If specified, transactions will be signed locally, - via Web3.py's `eth.account.signTransaction()`:code:, before being - sent via `eth.sendRawTransaction()`:code:. - """ - super().__init__( - provider=provider, - contract_address=contract_address, - private_key=private_key, - ) - - def _get_contract_instance(self, token_address): - """Get an instance of the smart contract at a specific address. - - :returns: contract object - """ - return self._contract_instance( - address=token_address, abi=LibDummy.abi() - ) - - @staticmethod - def abi(): - """Return the ABI to the underlying contract.""" - return json.loads( - '[]' # noqa: E501 (line-too-long) - ) diff --git a/packages/abi-gen/test-cli/expected-output/python/lib_dummy/__init__.py b/packages/abi-gen/test-cli/expected-output/python/lib_dummy/__init__.py new file mode 100644 index 0000000000..66bb91e528 --- /dev/null +++ b/packages/abi-gen/test-cli/expected-output/python/lib_dummy/__init__.py @@ -0,0 +1,109 @@ +"""Generated wrapper for LibDummy Solidity contract.""" + +# pylint: disable=too-many-arguments + +import json +from typing import ( # pylint: disable=unused-import + Any, + List, + Optional, + Tuple, + Union, +) + +from mypy_extensions import TypedDict # pylint: disable=unused-import +from hexbytes import HexBytes +from web3.datastructures import AttributeDict +from web3.providers.base import BaseProvider + +from zero_ex.contract_wrappers._base_contract_wrapper import BaseContractWrapper +from zero_ex.contract_wrappers.tx_params import TxParams + + +class LibDummyValidatorBase: + """Base class for validating inputs to LibDummy methods.""" + def __init__( + self, + provider: BaseProvider, + contract_address: str, + private_key: str = None, + ): + """Initialize the instance.""" + + def assert_valid( + self, method_name: str, parameter_name: str, argument_value: Any + ): + """Raise an exception if method input is not valid. + + :param method_name: Name of the method whose input is to be validated. + :param parameter_name: Name of the parameter whose input is to be + validated. + :param argument_value: Value of argument to parameter to be validated. + """ + + +# Try to import a custom validator class definition; if there isn't one, +# declare one that we can instantiate for the default argument to the +# constructor for LibDummy below. +try: + # both mypy and pylint complain about what we're doing here, but this + # works just fine, so their messages have been disabled here. + from . import ( # type: ignore # pylint: disable=import-self + LibDummyValidator, + ) +except ImportError: + + class LibDummyValidator(LibDummyValidatorBase): # type: ignore + """No-op input validator.""" + + + + + +# pylint: disable=too-many-public-methods +class LibDummy(BaseContractWrapper): + """Wrapper class for LibDummy Solidity contract.""" + + def __init__( + self, + provider: BaseProvider, + contract_address: str, + validator: LibDummyValidator = None, + private_key: str = None, + ): + """Get an instance of wrapper for smart contract. + + :param provider: instance of :class:`web3.providers.base.BaseProvider` + :param contract_address: where the contract has been deployed + :param private_key: If specified, transactions will be signed locally, + via Web3.py's `eth.account.signTransaction()`:code:, before being + sent via `eth.sendRawTransaction()`:code:. + """ + super().__init__( + provider=provider, + contract_address=contract_address, + private_key=private_key, + ) + + if not validator: + validator = LibDummyValidator(provider, contract_address, private_key) + + self.validator = validator + + def _get_contract_instance(self, token_address): + """Get an instance of the smart contract at a specific address. + + :returns: contract object + """ + return self._contract_instance( + address=token_address, abi=LibDummy.abi() + ) + + @staticmethod + def abi(): + """Return the ABI to the underlying contract.""" + return json.loads( + '[]' # noqa: E501 (line-too-long) + ) + +# pylint: disable=too-many-lines diff --git a/packages/abi-gen/test-cli/expected-output/python/test_lib_dummy.py b/packages/abi-gen/test-cli/expected-output/python/test_lib_dummy/__init__.py similarity index 57% rename from packages/abi-gen/test-cli/expected-output/python/test_lib_dummy.py rename to packages/abi-gen/test-cli/expected-output/python/test_lib_dummy/__init__.py index 98b33bd621..5c4cab81d8 100644 --- a/packages/abi-gen/test-cli/expected-output/python/test_lib_dummy.py +++ b/packages/abi-gen/test-cli/expected-output/python/test_lib_dummy/__init__.py @@ -1,8 +1,17 @@ """Generated wrapper for TestLibDummy Solidity contract.""" +# pylint: disable=too-many-arguments + import json -from typing import Optional, Tuple, Union +from typing import ( # pylint: disable=unused-import + Any, + List, + Optional, + Tuple, + Union, +) +from mypy_extensions import TypedDict # pylint: disable=unused-import from hexbytes import HexBytes from web3.datastructures import AttributeDict from web3.providers.base import BaseProvider @@ -11,6 +20,47 @@ from zero_ex.contract_wrappers.tx_params import TxParams +class TestLibDummyValidatorBase: + """Base class for validating inputs to TestLibDummy methods.""" + def __init__( + self, + provider: BaseProvider, + contract_address: str, + private_key: str = None, + ): + """Initialize the instance.""" + + def assert_valid( + self, method_name: str, parameter_name: str, argument_value: Any + ): + """Raise an exception if method input is not valid. + + :param method_name: Name of the method whose input is to be validated. + :param parameter_name: Name of the parameter whose input is to be + validated. + :param argument_value: Value of argument to parameter to be validated. + """ + + +# Try to import a custom validator class definition; if there isn't one, +# declare one that we can instantiate for the default argument to the +# constructor for TestLibDummy below. +try: + # both mypy and pylint complain about what we're doing here, but this + # works just fine, so their messages have been disabled here. + from . import ( # type: ignore # pylint: disable=import-self + TestLibDummyValidator, + ) +except ImportError: + + class TestLibDummyValidator(TestLibDummyValidatorBase): # type: ignore + """No-op input validator.""" + + + + + +# pylint: disable=too-many-public-methods class TestLibDummy(BaseContractWrapper): """Wrapper class for TestLibDummy Solidity contract.""" @@ -18,6 +68,7 @@ def __init__( self, provider: BaseProvider, contract_address: str, + validator: TestLibDummyValidator = None, private_key: str = None, ): """Get an instance of wrapper for smart contract. @@ -34,6 +85,11 @@ def __init__( private_key=private_key, ) + if not validator: + validator = TestLibDummyValidator(provider, contract_address, private_key) + + self.validator = validator + def _get_contract_instance(self, token_address): """Get an instance of the smart contract at a specific address. @@ -50,12 +106,18 @@ def public_add_constant( ) -> int: """Execute underlying, same-named contract method. - + :param tx_params: transaction parameters + """ + self.validator.assert_valid( + method_name='publicAddConstant', + parameter_name='x', + argument_value=x, + ) # safeguard against fractional inputs x = int(x) func = self._get_contract_instance( - self._contract_address + self.contract_address ).functions.publicAddConstant( x ) @@ -72,12 +134,18 @@ def public_add_one( ) -> int: """Execute underlying, same-named contract method. - + :param tx_params: transaction parameters + """ + self.validator.assert_valid( + method_name='publicAddOne', + parameter_name='x', + argument_value=x, + ) # safeguard against fractional inputs x = int(x) func = self._get_contract_instance( - self._contract_address + self.contract_address ).functions.publicAddOne( x ) @@ -93,3 +161,5 @@ def abi(): return json.loads( '[{"constant":true,"inputs":[{"name":"x","type":"uint256"}],"name":"publicAddConstant","outputs":[{"name":"result","type":"uint256"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"name":"x","type":"uint256"}],"name":"publicAddOne","outputs":[{"name":"result","type":"uint256"}],"payable":false,"stateMutability":"pure","type":"function"}]' # noqa: E501 (line-too-long) ) + +# pylint: disable=too-many-lines diff --git a/packages/abi-gen/test-cli/expected-output/typescript/abi_gen_dummy.ts b/packages/abi-gen/test-cli/expected-output/typescript/abi_gen_dummy.ts index 57293155d6..67ca4b9534 100644 --- a/packages/abi-gen/test-cli/expected-output/typescript/abi_gen_dummy.ts +++ b/packages/abi-gen/test-cli/expected-output/typescript/abi_gen_dummy.ts @@ -23,6 +23,16 @@ import { assert } from '@0x/assert'; import * as ethers from 'ethers'; // tslint:enable:no-unused-variable +export type AbiGenDummyEventArgs = AbiGenDummyAnEventEventArgs; + +export enum AbiGenDummyEvents { + AnEvent = 'AnEvent', +} + +export interface AbiGenDummyAnEventEventArgs extends DecodedLogArgs { + param: number; +} + /* istanbul ignore next */ // tslint:disable:no-parameter-reassignment // tslint:disable-next-line:class-name @@ -65,6 +75,46 @@ export class AbiGenDummyContract extends BaseContract { return abiEncodedTransactionData; }, }; + public acceptsAnArrayOfBytes = { + async callAsync(a: string[], callData: Partial = {}, defaultBlock?: BlockParam): Promise { + assert.isArray('a', a); + assert.doesConformToSchema('callData', callData, schemas.callDataSchema, [ + schemas.addressSchema, + schemas.numberSchema, + schemas.jsNumber, + ]); + if (defaultBlock !== undefined) { + assert.isBlockParam('defaultBlock', defaultBlock); + } + const self = (this as any) as AbiGenDummyContract; + const encodedData = self._strictEncodeArguments('acceptsAnArrayOfBytes(bytes[])', [a]); + const callDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync( + { + to: self.address, + ...callData, + data: encodedData, + }, + self._web3Wrapper.getContractDefaults(), + ); + callDataWithDefaults.from = callDataWithDefaults.from + ? callDataWithDefaults.from.toLowerCase() + : callDataWithDefaults.from; + + const rawCallResult = await self._web3Wrapper.callAsync(callDataWithDefaults, defaultBlock); + BaseContract._throwIfRevertWithReasonCallResult(rawCallResult); + const abiEncoder = self._lookupAbiEncoder('acceptsAnArrayOfBytes(bytes[])'); + // tslint:disable boolean-naming + const result = abiEncoder.strictDecodeReturnValue(rawCallResult); + // tslint:enable boolean-naming + return result; + }, + getABIEncodedTransactionData(a: string[]): string { + assert.isArray('a', a); + const self = (this as any) as AbiGenDummyContract; + const abiEncodedTransactionData = self._strictEncodeArguments('acceptsAnArrayOfBytes(bytes[])', [a]); + return abiEncodedTransactionData; + }, + }; public ecrecoverFn = { async callAsync( hash: string, @@ -126,6 +176,46 @@ export class AbiGenDummyContract extends BaseContract { return abiEncodedTransactionData; }, }; + public acceptsBytes = { + async callAsync(a: string, callData: Partial = {}, defaultBlock?: BlockParam): Promise { + assert.isString('a', a); + assert.doesConformToSchema('callData', callData, schemas.callDataSchema, [ + schemas.addressSchema, + schemas.numberSchema, + schemas.jsNumber, + ]); + if (defaultBlock !== undefined) { + assert.isBlockParam('defaultBlock', defaultBlock); + } + const self = (this as any) as AbiGenDummyContract; + const encodedData = self._strictEncodeArguments('acceptsBytes(bytes)', [a]); + const callDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync( + { + to: self.address, + ...callData, + data: encodedData, + }, + self._web3Wrapper.getContractDefaults(), + ); + callDataWithDefaults.from = callDataWithDefaults.from + ? callDataWithDefaults.from.toLowerCase() + : callDataWithDefaults.from; + + const rawCallResult = await self._web3Wrapper.callAsync(callDataWithDefaults, defaultBlock); + BaseContract._throwIfRevertWithReasonCallResult(rawCallResult); + const abiEncoder = self._lookupAbiEncoder('acceptsBytes(bytes)'); + // tslint:disable boolean-naming + const result = abiEncoder.strictDecodeReturnValue(rawCallResult); + // tslint:enable boolean-naming + return result; + }, + getABIEncodedTransactionData(a: string): string { + assert.isString('a', a); + const self = (this as any) as AbiGenDummyContract; + const abiEncodedTransactionData = self._strictEncodeArguments('acceptsBytes(bytes)', [a]); + return abiEncodedTransactionData; + }, + }; public revertWithConstant = { async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { assert.doesConformToSchema('callData', callData, schemas.callDataSchema, [ @@ -202,6 +292,53 @@ export class AbiGenDummyContract extends BaseContract { return abiEncodedTransactionData; }, }; + public nestedStructOutput = { + async callAsync( + callData: Partial = {}, + defaultBlock?: BlockParam, + ): Promise<{ + innerStruct: { someBytes: string; anInteger: number; aDynamicArrayOfBytes: string[]; aString: string }; + description: string; + }> { + assert.doesConformToSchema('callData', callData, schemas.callDataSchema, [ + schemas.addressSchema, + schemas.numberSchema, + schemas.jsNumber, + ]); + if (defaultBlock !== undefined) { + assert.isBlockParam('defaultBlock', defaultBlock); + } + const self = (this as any) as AbiGenDummyContract; + const encodedData = self._strictEncodeArguments('nestedStructOutput()', []); + const callDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync( + { + to: self.address, + ...callData, + data: encodedData, + }, + self._web3Wrapper.getContractDefaults(), + ); + callDataWithDefaults.from = callDataWithDefaults.from + ? callDataWithDefaults.from.toLowerCase() + : callDataWithDefaults.from; + + const rawCallResult = await self._web3Wrapper.callAsync(callDataWithDefaults, defaultBlock); + BaseContract._throwIfRevertWithReasonCallResult(rawCallResult); + const abiEncoder = self._lookupAbiEncoder('nestedStructOutput()'); + // tslint:disable boolean-naming + const result = abiEncoder.strictDecodeReturnValue<{ + innerStruct: { someBytes: string; anInteger: number; aDynamicArrayOfBytes: string[]; aString: string }; + description: string; + }>(rawCallResult); + // tslint:enable boolean-naming + return result; + }, + getABIEncodedTransactionData(): string { + const self = (this as any) as AbiGenDummyContract; + const abiEncodedTransactionData = self._strictEncodeArguments('nestedStructOutput()', []); + return abiEncodedTransactionData; + }, + }; public requireWithConstant = { async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { assert.doesConformToSchema('callData', callData, schemas.callDataSchema, [ @@ -302,6 +439,150 @@ export class AbiGenDummyContract extends BaseContract { return abiEncodedTransactionData; }, }; + public structInput = { + async callAsync( + s: { someBytes: string; anInteger: number | BigNumber; aDynamicArrayOfBytes: string[]; aString: string }, + callData: Partial = {}, + defaultBlock?: BlockParam, + ): Promise { + assert.doesConformToSchema('callData', callData, schemas.callDataSchema, [ + schemas.addressSchema, + schemas.numberSchema, + schemas.jsNumber, + ]); + if (defaultBlock !== undefined) { + assert.isBlockParam('defaultBlock', defaultBlock); + } + const self = (this as any) as AbiGenDummyContract; + const encodedData = self._strictEncodeArguments('structInput((bytes,uint32,bytes[],string))', [s]); + const callDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync( + { + to: self.address, + ...callData, + data: encodedData, + }, + self._web3Wrapper.getContractDefaults(), + ); + callDataWithDefaults.from = callDataWithDefaults.from + ? callDataWithDefaults.from.toLowerCase() + : callDataWithDefaults.from; + + const rawCallResult = await self._web3Wrapper.callAsync(callDataWithDefaults, defaultBlock); + BaseContract._throwIfRevertWithReasonCallResult(rawCallResult); + const abiEncoder = self._lookupAbiEncoder('structInput((bytes,uint32,bytes[],string))'); + // tslint:disable boolean-naming + const result = abiEncoder.strictDecodeReturnValue(rawCallResult); + // tslint:enable boolean-naming + return result; + }, + getABIEncodedTransactionData(s: { + someBytes: string; + anInteger: number | BigNumber; + aDynamicArrayOfBytes: string[]; + aString: string; + }): string { + const self = (this as any) as AbiGenDummyContract; + const abiEncodedTransactionData = self._strictEncodeArguments( + 'structInput((bytes,uint32,bytes[],string))', + [s], + ); + return abiEncodedTransactionData; + }, + }; + public nonPureMethod = { + async sendTransactionAsync(txData?: Partial | undefined): Promise { + const self = (this as any) as AbiGenDummyContract; + const encodedData = self._strictEncodeArguments('nonPureMethod()', []); + const txDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync( + { + to: self.address, + ...txData, + data: encodedData, + }, + self._web3Wrapper.getContractDefaults(), + self.nonPureMethod.estimateGasAsync.bind(self), + ); + if (txDataWithDefaults.from !== undefined) { + txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); + } + + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); + return txHash; + }, + awaitTransactionSuccessAsync( + txData?: Partial, + pollingIntervalMs?: number, + timeoutMs?: number, + ): PromiseWithTransactionHash { + const self = (this as any) as AbiGenDummyContract; + const txHashPromise = self.nonPureMethod.sendTransactionAsync(txData); + return new PromiseWithTransactionHash( + txHashPromise, + (async (): Promise => { + // When the transaction hash resolves, wait for it to be mined. + return self._web3Wrapper.awaitTransactionSuccessAsync( + await txHashPromise, + pollingIntervalMs, + timeoutMs, + ); + })(), + ); + }, + async estimateGasAsync(txData?: Partial | undefined): Promise { + const self = (this as any) as AbiGenDummyContract; + const encodedData = self._strictEncodeArguments('nonPureMethod()', []); + const txDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync( + { + to: self.address, + ...txData, + data: encodedData, + }, + self._web3Wrapper.getContractDefaults(), + ); + if (txDataWithDefaults.from !== undefined) { + txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); + } + + const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); + return gas; + }, + async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { + assert.doesConformToSchema('callData', callData, schemas.callDataSchema, [ + schemas.addressSchema, + schemas.numberSchema, + schemas.jsNumber, + ]); + if (defaultBlock !== undefined) { + assert.isBlockParam('defaultBlock', defaultBlock); + } + const self = (this as any) as AbiGenDummyContract; + const encodedData = self._strictEncodeArguments('nonPureMethod()', []); + const callDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync( + { + to: self.address, + ...callData, + data: encodedData, + }, + self._web3Wrapper.getContractDefaults(), + ); + callDataWithDefaults.from = callDataWithDefaults.from + ? callDataWithDefaults.from.toLowerCase() + : callDataWithDefaults.from; + + const rawCallResult = await self._web3Wrapper.callAsync(callDataWithDefaults, defaultBlock); + BaseContract._throwIfRevertWithReasonCallResult(rawCallResult); + const abiEncoder = self._lookupAbiEncoder('nonPureMethod()'); + // tslint:disable boolean-naming + const result = abiEncoder.strictDecodeReturnValue(rawCallResult); + // tslint:enable boolean-naming + return result; + }, + getABIEncodedTransactionData(): string { + const self = (this as any) as AbiGenDummyContract; + const abiEncodedTransactionData = self._strictEncodeArguments('nonPureMethod()', []); + return abiEncodedTransactionData; + }, + }; public simplePureFunctionWithInput = { async callAsync(x: BigNumber, callData: Partial = {}, defaultBlock?: BlockParam): Promise { assert.isBigNumber('x', x); @@ -342,6 +623,100 @@ export class AbiGenDummyContract extends BaseContract { return abiEncodedTransactionData; }, }; + public nonPureMethodThatReturnsNothing = { + async sendTransactionAsync(txData?: Partial | undefined): Promise { + const self = (this as any) as AbiGenDummyContract; + const encodedData = self._strictEncodeArguments('nonPureMethodThatReturnsNothing()', []); + const txDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync( + { + to: self.address, + ...txData, + data: encodedData, + }, + self._web3Wrapper.getContractDefaults(), + self.nonPureMethodThatReturnsNothing.estimateGasAsync.bind(self), + ); + if (txDataWithDefaults.from !== undefined) { + txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); + } + + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); + return txHash; + }, + awaitTransactionSuccessAsync( + txData?: Partial, + pollingIntervalMs?: number, + timeoutMs?: number, + ): PromiseWithTransactionHash { + const self = (this as any) as AbiGenDummyContract; + const txHashPromise = self.nonPureMethodThatReturnsNothing.sendTransactionAsync(txData); + return new PromiseWithTransactionHash( + txHashPromise, + (async (): Promise => { + // When the transaction hash resolves, wait for it to be mined. + return self._web3Wrapper.awaitTransactionSuccessAsync( + await txHashPromise, + pollingIntervalMs, + timeoutMs, + ); + })(), + ); + }, + async estimateGasAsync(txData?: Partial | undefined): Promise { + const self = (this as any) as AbiGenDummyContract; + const encodedData = self._strictEncodeArguments('nonPureMethodThatReturnsNothing()', []); + const txDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync( + { + to: self.address, + ...txData, + data: encodedData, + }, + self._web3Wrapper.getContractDefaults(), + ); + if (txDataWithDefaults.from !== undefined) { + txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); + } + + const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); + return gas; + }, + async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { + assert.doesConformToSchema('callData', callData, schemas.callDataSchema, [ + schemas.addressSchema, + schemas.numberSchema, + schemas.jsNumber, + ]); + if (defaultBlock !== undefined) { + assert.isBlockParam('defaultBlock', defaultBlock); + } + const self = (this as any) as AbiGenDummyContract; + const encodedData = self._strictEncodeArguments('nonPureMethodThatReturnsNothing()', []); + const callDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync( + { + to: self.address, + ...callData, + data: encodedData, + }, + self._web3Wrapper.getContractDefaults(), + ); + callDataWithDefaults.from = callDataWithDefaults.from + ? callDataWithDefaults.from.toLowerCase() + : callDataWithDefaults.from; + + const rawCallResult = await self._web3Wrapper.callAsync(callDataWithDefaults, defaultBlock); + BaseContract._throwIfRevertWithReasonCallResult(rawCallResult); + const abiEncoder = self._lookupAbiEncoder('nonPureMethodThatReturnsNothing()'); + // tslint:disable boolean-naming + const result = abiEncoder.strictDecodeReturnValue(rawCallResult); + // tslint:enable boolean-naming + return result; + }, + getABIEncodedTransactionData(): string { + const self = (this as any) as AbiGenDummyContract; + const abiEncodedTransactionData = self._strictEncodeArguments('nonPureMethodThatReturnsNothing()', []); + return abiEncodedTransactionData; + }, + }; public simplePureFunction = { async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { assert.doesConformToSchema('callData', callData, schemas.callDataSchema, [ @@ -380,6 +755,116 @@ export class AbiGenDummyContract extends BaseContract { return abiEncodedTransactionData; }, }; + public nestedStructInput = { + async callAsync( + n: { + innerStruct: { + someBytes: string; + anInteger: number | BigNumber; + aDynamicArrayOfBytes: string[]; + aString: string; + }; + description: string; + }, + callData: Partial = {}, + defaultBlock?: BlockParam, + ): Promise { + assert.doesConformToSchema('callData', callData, schemas.callDataSchema, [ + schemas.addressSchema, + schemas.numberSchema, + schemas.jsNumber, + ]); + if (defaultBlock !== undefined) { + assert.isBlockParam('defaultBlock', defaultBlock); + } + const self = (this as any) as AbiGenDummyContract; + const encodedData = self._strictEncodeArguments( + 'nestedStructInput(((bytes,uint32,bytes[],string),string))', + [n], + ); + const callDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync( + { + to: self.address, + ...callData, + data: encodedData, + }, + self._web3Wrapper.getContractDefaults(), + ); + callDataWithDefaults.from = callDataWithDefaults.from + ? callDataWithDefaults.from.toLowerCase() + : callDataWithDefaults.from; + + const rawCallResult = await self._web3Wrapper.callAsync(callDataWithDefaults, defaultBlock); + BaseContract._throwIfRevertWithReasonCallResult(rawCallResult); + const abiEncoder = self._lookupAbiEncoder('nestedStructInput(((bytes,uint32,bytes[],string),string))'); + // tslint:disable boolean-naming + const result = abiEncoder.strictDecodeReturnValue(rawCallResult); + // tslint:enable boolean-naming + return result; + }, + getABIEncodedTransactionData(n: { + innerStruct: { + someBytes: string; + anInteger: number | BigNumber; + aDynamicArrayOfBytes: string[]; + aString: string; + }; + description: string; + }): string { + const self = (this as any) as AbiGenDummyContract; + const abiEncodedTransactionData = self._strictEncodeArguments( + 'nestedStructInput(((bytes,uint32,bytes[],string),string))', + [n], + ); + return abiEncodedTransactionData; + }, + }; + public structOutput = { + async callAsync( + callData: Partial = {}, + defaultBlock?: BlockParam, + ): Promise<{ someBytes: string; anInteger: number; aDynamicArrayOfBytes: string[]; aString: string }> { + assert.doesConformToSchema('callData', callData, schemas.callDataSchema, [ + schemas.addressSchema, + schemas.numberSchema, + schemas.jsNumber, + ]); + if (defaultBlock !== undefined) { + assert.isBlockParam('defaultBlock', defaultBlock); + } + const self = (this as any) as AbiGenDummyContract; + const encodedData = self._strictEncodeArguments('structOutput()', []); + const callDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync( + { + to: self.address, + ...callData, + data: encodedData, + }, + self._web3Wrapper.getContractDefaults(), + ); + callDataWithDefaults.from = callDataWithDefaults.from + ? callDataWithDefaults.from.toLowerCase() + : callDataWithDefaults.from; + + const rawCallResult = await self._web3Wrapper.callAsync(callDataWithDefaults, defaultBlock); + BaseContract._throwIfRevertWithReasonCallResult(rawCallResult); + const abiEncoder = self._lookupAbiEncoder('structOutput()'); + // tslint:disable boolean-naming + const result = abiEncoder.strictDecodeReturnValue<{ + someBytes: string; + anInteger: number; + aDynamicArrayOfBytes: string[]; + aString: string; + }>(rawCallResult); + // tslint:enable boolean-naming + return result; + }, + getABIEncodedTransactionData(): string { + const self = (this as any) as AbiGenDummyContract; + const abiEncodedTransactionData = self._strictEncodeArguments('structOutput()', []); + return abiEncodedTransactionData; + }, + }; public pureFunctionWithConstant = { async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { assert.doesConformToSchema('callData', callData, schemas.callDataSchema, [ @@ -483,6 +968,20 @@ export class AbiGenDummyContract extends BaseContract { stateMutability: 'pure', type: 'function', }, + { + constant: true, + inputs: [ + { + name: 'a', + type: 'bytes[]', + }, + ], + name: 'acceptsAnArrayOfBytes', + outputs: [], + payable: false, + stateMutability: 'pure', + type: 'function', + }, { constant: true, inputs: [ @@ -514,6 +1013,20 @@ export class AbiGenDummyContract extends BaseContract { stateMutability: 'pure', type: 'function', }, + { + constant: true, + inputs: [ + { + name: 'a', + type: 'bytes', + }, + ], + name: 'acceptsBytes', + outputs: [], + payable: false, + stateMutability: 'pure', + type: 'function', + }, { constant: true, inputs: [], @@ -532,6 +1045,48 @@ export class AbiGenDummyContract extends BaseContract { stateMutability: 'pure', type: 'function', }, + { + constant: true, + inputs: [], + name: 'nestedStructOutput', + outputs: [ + { + name: '', + type: 'tuple', + components: [ + { + name: 'innerStruct', + type: 'tuple', + components: [ + { + name: 'someBytes', + type: 'bytes', + }, + { + name: 'anInteger', + type: 'uint32', + }, + { + name: 'aDynamicArrayOfBytes', + type: 'bytes[]', + }, + { + name: 'aString', + type: 'string', + }, + ], + }, + { + name: 'description', + type: 'string', + }, + ], + }, + ], + payable: false, + stateMutability: 'pure', + type: 'function', + }, { constant: true, inputs: [], @@ -576,6 +1131,52 @@ export class AbiGenDummyContract extends BaseContract { stateMutability: 'pure', type: 'function', }, + { + constant: true, + inputs: [ + { + name: 's', + type: 'tuple', + components: [ + { + name: 'someBytes', + type: 'bytes', + }, + { + name: 'anInteger', + type: 'uint32', + }, + { + name: 'aDynamicArrayOfBytes', + type: 'bytes[]', + }, + { + name: 'aString', + type: 'string', + }, + ], + }, + ], + name: 'structInput', + outputs: [], + payable: false, + stateMutability: 'pure', + type: 'function', + }, + { + constant: false, + inputs: [], + name: 'nonPureMethod', + outputs: [ + { + name: '', + type: 'uint256', + }, + ], + payable: false, + stateMutability: 'nonpayable', + type: 'function', + }, { constant: true, inputs: [ @@ -595,6 +1196,15 @@ export class AbiGenDummyContract extends BaseContract { stateMutability: 'pure', type: 'function', }, + { + constant: false, + inputs: [], + name: 'nonPureMethodThatReturnsNothing', + outputs: [], + payable: false, + stateMutability: 'nonpayable', + type: 'function', + }, { constant: true, inputs: [], @@ -609,6 +1219,80 @@ export class AbiGenDummyContract extends BaseContract { stateMutability: 'pure', type: 'function', }, + { + constant: true, + inputs: [ + { + name: 'n', + type: 'tuple', + components: [ + { + name: 'innerStruct', + type: 'tuple', + components: [ + { + name: 'someBytes', + type: 'bytes', + }, + { + name: 'anInteger', + type: 'uint32', + }, + { + name: 'aDynamicArrayOfBytes', + type: 'bytes[]', + }, + { + name: 'aString', + type: 'string', + }, + ], + }, + { + name: 'description', + type: 'string', + }, + ], + }, + ], + name: 'nestedStructInput', + outputs: [], + payable: false, + stateMutability: 'pure', + type: 'function', + }, + { + constant: true, + inputs: [], + name: 'structOutput', + outputs: [ + { + name: 's', + type: 'tuple', + components: [ + { + name: 'someBytes', + type: 'bytes', + }, + { + name: 'anInteger', + type: 'uint32', + }, + { + name: 'aDynamicArrayOfBytes', + type: 'bytes[]', + }, + { + name: 'aString', + type: 'string', + }, + ], + }, + ], + payable: false, + stateMutability: 'pure', + type: 'function', + }, { constant: true, inputs: [], @@ -623,6 +1307,19 @@ export class AbiGenDummyContract extends BaseContract { stateMutability: 'pure', type: 'function', }, + { + anonymous: false, + inputs: [ + { + name: 'param', + type: 'uint8', + indexed: false, + }, + ], + name: 'AnEvent', + outputs: [], + type: 'event', + }, ] as ContractAbi; return abi; } diff --git a/packages/abi-gen/test-cli/fixtures/artifacts/AbiGenDummy.json b/packages/abi-gen/test-cli/fixtures/artifacts/AbiGenDummy.json index 09009b62bb..0d6cf52860 100644 --- a/packages/abi-gen/test-cli/fixtures/artifacts/AbiGenDummy.json +++ b/packages/abi-gen/test-cli/fixtures/artifacts/AbiGenDummy.json @@ -1,210 +1,436 @@ { - "schemaVersion": "2.0.0", - "contractName": "AbiGenDummy", - "compilerOutput": { - "abi": [ - { - "constant": true, - "inputs": [], - "name": "simpleRequire", - "outputs": [], - "payable": false, - "stateMutability": "pure", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "hash", - "type": "bytes32" - }, - { - "name": "v", - "type": "uint8" - }, - { - "name": "r", - "type": "bytes32" - }, - { - "name": "s", - "type": "bytes32" - } - ], - "name": "ecrecoverFn", - "outputs": [ - { - "name": "signerAddress", - "type": "address" - } - ], - "payable": false, - "stateMutability": "pure", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "revertWithConstant", - "outputs": [], - "payable": false, - "stateMutability": "pure", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "simpleRevert", - "outputs": [], - "payable": false, - "stateMutability": "pure", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "requireWithConstant", - "outputs": [], - "payable": false, - "stateMutability": "pure", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "x", - "type": "address" - }, - { - "name": "a", - "type": "uint256" - }, - { - "name": "b", - "type": "uint256" - }, - { - "name": "y", - "type": "address" - }, - { - "name": "c", - "type": "uint256" - } - ], - "name": "withAddressInput", - "outputs": [ - { - "name": "z", - "type": "address" - } - ], - "payable": false, - "stateMutability": "pure", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "x", - "type": "uint256" - } - ], - "name": "simplePureFunctionWithInput", - "outputs": [ - { - "name": "sum", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "pure", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "simplePureFunction", - "outputs": [ - { - "name": "result", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "pure", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "pureFunctionWithConstant", - "outputs": [ - { - "name": "someConstant", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "pure", - "type": "function" - } - ], - "evm": { - "bytecode": { - "linkReferences": {}, - "object": "0x608060405234801561001057600080fd5b506105c3806100206000396000f3fe608060405234801561001057600080fd5b50600436106100a25760003560e01c80635ba3c7c0116100765780638ee52b4e1161005b5780638ee52b4e14610173578063a3c2f6b6146101a2578063d88be12f146101aa576100a2565b80635ba3c7c01461011c57806363d69c8814610124576100a2565b806209e437146100a757806336b32396146100b15780634582eab21461010c57806345fdbdb714610114575b600080fd5b6100af6101b2565b005b6100e3600480360360808110156100c757600080fd5b5080359060ff6020820135169060408101359060600135610219565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b6100af6103a7565b6100af61047b565b6100af6104e2565b6100e3600480360360a081101561013a57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160208101359160408201359160608101359091169060800135610574565b6101906004803603602081101561018957600080fd5b503561057d565b60408051918252519081900360200190f35b610190610583565b610190610588565b604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f53494d504c455f52455155495245000000000000000000000000000000000000604482015290519081900360640190fd5b600060606040518060400160405280601c81526020017f19457468657265756d205369676e6564204d6573736167653a0a3332000000008152509050600081876040516020018083805190602001908083835b602083106102a957805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909201916020918201910161026c565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0180199092169116179052920193845250604080518085038152848301808352815191840191909120600090915281850180835281905260ff8c166060860152608085018b905260a085018a905290519095506001945060c0808501949293507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08201928290030190855afa158015610373573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015198975050505050505050565b6040518060400160405280601481526020017f5245564552545f574954485f434f4e5354414e540000000000000000000000008152506040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610440578181015183820152602001610428565b50505050905090810190601f16801561046d5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f53494d504c455f52455645525400000000000000000000000000000000000000604482015290519081900360640190fd5b604080518082018252601581527f524551554952455f574954485f434f4e5354414e540000000000000000000000602080830191825292517f08c379a00000000000000000000000000000000000000000000000000000000081526004810193845282516024820152825192939283926044909201919080838360008315610440578181015183820152602001610428565b50929392505050565b60010190565b600190565b6104d29056fea265627a7a72305820fe29f2a571cfcbf82abb5eaa5b4e17b2bea39d36b386e88463d23d21b83c5a2364736f6c634300050a0032", - "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x5C3 DUP1 PUSH2 0x20 PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN INVALID PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x4 CALLDATASIZE LT PUSH2 0xA2 JUMPI PUSH1 0x0 CALLDATALOAD PUSH1 0xE0 SHR DUP1 PUSH4 0x5BA3C7C0 GT PUSH2 0x76 JUMPI DUP1 PUSH4 0x8EE52B4E GT PUSH2 0x5B JUMPI DUP1 PUSH4 0x8EE52B4E EQ PUSH2 0x173 JUMPI DUP1 PUSH4 0xA3C2F6B6 EQ PUSH2 0x1A2 JUMPI DUP1 PUSH4 0xD88BE12F EQ PUSH2 0x1AA JUMPI PUSH2 0xA2 JUMP JUMPDEST DUP1 PUSH4 0x5BA3C7C0 EQ PUSH2 0x11C JUMPI DUP1 PUSH4 0x63D69C88 EQ PUSH2 0x124 JUMPI PUSH2 0xA2 JUMP JUMPDEST DUP1 PUSH3 0x9E437 EQ PUSH2 0xA7 JUMPI DUP1 PUSH4 0x36B32396 EQ PUSH2 0xB1 JUMPI DUP1 PUSH4 0x4582EAB2 EQ PUSH2 0x10C JUMPI DUP1 PUSH4 0x45FDBDB7 EQ PUSH2 0x114 JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0xAF PUSH2 0x1B2 JUMP JUMPDEST STOP JUMPDEST PUSH2 0xE3 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x80 DUP2 LT ISZERO PUSH2 0xC7 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP DUP1 CALLDATALOAD SWAP1 PUSH1 0xFF PUSH1 0x20 DUP3 ADD CALLDATALOAD AND SWAP1 PUSH1 0x40 DUP2 ADD CALLDATALOAD SWAP1 PUSH1 0x60 ADD CALLDATALOAD PUSH2 0x219 JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF SWAP1 SWAP3 AND DUP3 MSTORE MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x20 ADD SWAP1 RETURN JUMPDEST PUSH2 0xAF PUSH2 0x3A7 JUMP JUMPDEST PUSH2 0xAF PUSH2 0x47B JUMP JUMPDEST PUSH2 0xAF PUSH2 0x4E2 JUMP JUMPDEST PUSH2 0xE3 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0xA0 DUP2 LT ISZERO PUSH2 0x13A JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP2 CALLDATALOAD DUP2 AND SWAP2 PUSH1 0x20 DUP2 ADD CALLDATALOAD SWAP2 PUSH1 0x40 DUP3 ADD CALLDATALOAD SWAP2 PUSH1 0x60 DUP2 ADD CALLDATALOAD SWAP1 SWAP2 AND SWAP1 PUSH1 0x80 ADD CALLDATALOAD PUSH2 0x574 JUMP JUMPDEST PUSH2 0x190 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x20 DUP2 LT ISZERO PUSH2 0x189 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP CALLDATALOAD PUSH2 0x57D JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD SWAP2 DUP3 MSTORE MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x20 ADD SWAP1 RETURN JUMPDEST PUSH2 0x190 PUSH2 0x583 JUMP JUMPDEST PUSH2 0x190 PUSH2 0x588 JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x20 PUSH1 0x4 DUP3 ADD MSTORE PUSH1 0xE PUSH1 0x24 DUP3 ADD MSTORE PUSH32 0x53494D504C455F52455155495245000000000000000000000000000000000000 PUSH1 0x44 DUP3 ADD MSTORE SWAP1 MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x64 ADD SWAP1 REVERT JUMPDEST PUSH1 0x0 PUSH1 0x60 PUSH1 0x40 MLOAD DUP1 PUSH1 0x40 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x1C DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x19457468657265756D205369676E6564204D6573736167653A0A333200000000 DUP2 MSTORE POP SWAP1 POP PUSH1 0x0 DUP2 DUP8 PUSH1 0x40 MLOAD PUSH1 0x20 ADD DUP1 DUP4 DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 JUMPDEST PUSH1 0x20 DUP4 LT PUSH2 0x2A9 JUMPI DUP1 MLOAD DUP3 MSTORE PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0 SWAP1 SWAP3 ADD SWAP2 PUSH1 0x20 SWAP2 DUP3 ADD SWAP2 ADD PUSH2 0x26C JUMP JUMPDEST MLOAD DUP2 MLOAD PUSH1 0x20 SWAP4 DUP5 SUB PUSH2 0x100 EXP PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ADD DUP1 NOT SWAP1 SWAP3 AND SWAP2 AND OR SWAP1 MSTORE SWAP3 ADD SWAP4 DUP5 MSTORE POP PUSH1 0x40 DUP1 MLOAD DUP1 DUP6 SUB DUP2 MSTORE DUP5 DUP4 ADD DUP1 DUP4 MSTORE DUP2 MLOAD SWAP2 DUP5 ADD SWAP2 SWAP1 SWAP2 KECCAK256 PUSH1 0x0 SWAP1 SWAP2 MSTORE DUP2 DUP6 ADD DUP1 DUP4 MSTORE DUP2 SWAP1 MSTORE PUSH1 0xFF DUP13 AND PUSH1 0x60 DUP7 ADD MSTORE PUSH1 0x80 DUP6 ADD DUP12 SWAP1 MSTORE PUSH1 0xA0 DUP6 ADD DUP11 SWAP1 MSTORE SWAP1 MLOAD SWAP1 SWAP6 POP PUSH1 0x1 SWAP5 POP PUSH1 0xC0 DUP1 DUP6 ADD SWAP5 SWAP3 SWAP4 POP PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0 DUP3 ADD SWAP3 DUP3 SWAP1 SUB ADD SWAP1 DUP6 GAS STATICCALL ISZERO DUP1 ISZERO PUSH2 0x373 JUMPI RETURNDATASIZE PUSH1 0x0 DUP1 RETURNDATACOPY RETURNDATASIZE PUSH1 0x0 REVERT JUMPDEST POP POP PUSH1 0x40 MLOAD PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0 ADD MLOAD SWAP9 SWAP8 POP POP POP POP POP POP POP POP JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 PUSH1 0x40 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x14 DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x5245564552545F574954485F434F4E5354414E54000000000000000000000000 DUP2 MSTORE POP PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0x440 JUMPI DUP2 DUP2 ADD MLOAD DUP4 DUP3 ADD MSTORE PUSH1 0x20 ADD PUSH2 0x428 JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0x46D JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH1 0x40 DUP1 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x20 PUSH1 0x4 DUP3 ADD MSTORE PUSH1 0xD PUSH1 0x24 DUP3 ADD MSTORE PUSH32 0x53494D504C455F52455645525400000000000000000000000000000000000000 PUSH1 0x44 DUP3 ADD MSTORE SWAP1 MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x64 ADD SWAP1 REVERT JUMPDEST PUSH1 0x40 DUP1 MLOAD DUP1 DUP3 ADD DUP3 MSTORE PUSH1 0x15 DUP2 MSTORE PUSH32 0x524551554952455F574954485F434F4E5354414E540000000000000000000000 PUSH1 0x20 DUP1 DUP4 ADD SWAP2 DUP3 MSTORE SWAP3 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 DUP2 ADD SWAP4 DUP5 MSTORE DUP3 MLOAD PUSH1 0x24 DUP3 ADD MSTORE DUP3 MLOAD SWAP3 SWAP4 SWAP3 DUP4 SWAP3 PUSH1 0x44 SWAP1 SWAP3 ADD SWAP2 SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 DUP4 ISZERO PUSH2 0x440 JUMPI DUP2 DUP2 ADD MLOAD DUP4 DUP3 ADD MSTORE PUSH1 0x20 ADD PUSH2 0x428 JUMP JUMPDEST POP SWAP3 SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x1 ADD SWAP1 JUMP JUMPDEST PUSH1 0x1 SWAP1 JUMP JUMPDEST PUSH2 0x4D2 SWAP1 JUMP INVALID LOG2 PUSH6 0x627A7A723058 KECCAK256 INVALID 0x29 CALLCODE 0xa5 PUSH18 0xCFCBF82ABB5EAA5B4E17B2BEA39D36B386E8 DUP5 PUSH4 0xD23D21B8 EXTCODECOPY GAS 0x23 PUSH5 0x736F6C6343 STOP SDIV EXP STOP ORIGIN ", - "sourceMap": "606:1667:0:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;606:1667:0;;;;;;;" - }, - "deployedBytecode": { - "linkReferences": {}, - "object": "0x608060405234801561001057600080fd5b50600436106100a25760003560e01c80635ba3c7c0116100765780638ee52b4e1161005b5780638ee52b4e14610173578063a3c2f6b6146101a2578063d88be12f146101aa576100a2565b80635ba3c7c01461011c57806363d69c8814610124576100a2565b806209e437146100a757806336b32396146100b15780634582eab21461010c57806345fdbdb714610114575b600080fd5b6100af6101b2565b005b6100e3600480360360808110156100c757600080fd5b5080359060ff6020820135169060408101359060600135610219565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b6100af6103a7565b6100af61047b565b6100af6104e2565b6100e3600480360360a081101561013a57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160208101359160408201359160608101359091169060800135610574565b6101906004803603602081101561018957600080fd5b503561057d565b60408051918252519081900360200190f35b610190610583565b610190610588565b604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f53494d504c455f52455155495245000000000000000000000000000000000000604482015290519081900360640190fd5b600060606040518060400160405280601c81526020017f19457468657265756d205369676e6564204d6573736167653a0a3332000000008152509050600081876040516020018083805190602001908083835b602083106102a957805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909201916020918201910161026c565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0180199092169116179052920193845250604080518085038152848301808352815191840191909120600090915281850180835281905260ff8c166060860152608085018b905260a085018a905290519095506001945060c0808501949293507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08201928290030190855afa158015610373573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015198975050505050505050565b6040518060400160405280601481526020017f5245564552545f574954485f434f4e5354414e540000000000000000000000008152506040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610440578181015183820152602001610428565b50505050905090810190601f16801561046d5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f53494d504c455f52455645525400000000000000000000000000000000000000604482015290519081900360640190fd5b604080518082018252601581527f524551554952455f574954485f434f4e5354414e540000000000000000000000602080830191825292517f08c379a00000000000000000000000000000000000000000000000000000000081526004810193845282516024820152825192939283926044909201919080838360008315610440578181015183820152602001610428565b50929392505050565b60010190565b600190565b6104d29056fea265627a7a72305820fe29f2a571cfcbf82abb5eaa5b4e17b2bea39d36b386e88463d23d21b83c5a2364736f6c634300050a0032", - "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x4 CALLDATASIZE LT PUSH2 0xA2 JUMPI PUSH1 0x0 CALLDATALOAD PUSH1 0xE0 SHR DUP1 PUSH4 0x5BA3C7C0 GT PUSH2 0x76 JUMPI DUP1 PUSH4 0x8EE52B4E GT PUSH2 0x5B JUMPI DUP1 PUSH4 0x8EE52B4E EQ PUSH2 0x173 JUMPI DUP1 PUSH4 0xA3C2F6B6 EQ PUSH2 0x1A2 JUMPI DUP1 PUSH4 0xD88BE12F EQ PUSH2 0x1AA JUMPI PUSH2 0xA2 JUMP JUMPDEST DUP1 PUSH4 0x5BA3C7C0 EQ PUSH2 0x11C JUMPI DUP1 PUSH4 0x63D69C88 EQ PUSH2 0x124 JUMPI PUSH2 0xA2 JUMP JUMPDEST DUP1 PUSH3 0x9E437 EQ PUSH2 0xA7 JUMPI DUP1 PUSH4 0x36B32396 EQ PUSH2 0xB1 JUMPI DUP1 PUSH4 0x4582EAB2 EQ PUSH2 0x10C JUMPI DUP1 PUSH4 0x45FDBDB7 EQ PUSH2 0x114 JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0xAF PUSH2 0x1B2 JUMP JUMPDEST STOP JUMPDEST PUSH2 0xE3 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x80 DUP2 LT ISZERO PUSH2 0xC7 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP DUP1 CALLDATALOAD SWAP1 PUSH1 0xFF PUSH1 0x20 DUP3 ADD CALLDATALOAD AND SWAP1 PUSH1 0x40 DUP2 ADD CALLDATALOAD SWAP1 PUSH1 0x60 ADD CALLDATALOAD PUSH2 0x219 JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF SWAP1 SWAP3 AND DUP3 MSTORE MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x20 ADD SWAP1 RETURN JUMPDEST PUSH2 0xAF PUSH2 0x3A7 JUMP JUMPDEST PUSH2 0xAF PUSH2 0x47B JUMP JUMPDEST PUSH2 0xAF PUSH2 0x4E2 JUMP JUMPDEST PUSH2 0xE3 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0xA0 DUP2 LT ISZERO PUSH2 0x13A JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP2 CALLDATALOAD DUP2 AND SWAP2 PUSH1 0x20 DUP2 ADD CALLDATALOAD SWAP2 PUSH1 0x40 DUP3 ADD CALLDATALOAD SWAP2 PUSH1 0x60 DUP2 ADD CALLDATALOAD SWAP1 SWAP2 AND SWAP1 PUSH1 0x80 ADD CALLDATALOAD PUSH2 0x574 JUMP JUMPDEST PUSH2 0x190 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x20 DUP2 LT ISZERO PUSH2 0x189 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP CALLDATALOAD PUSH2 0x57D JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD SWAP2 DUP3 MSTORE MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x20 ADD SWAP1 RETURN JUMPDEST PUSH2 0x190 PUSH2 0x583 JUMP JUMPDEST PUSH2 0x190 PUSH2 0x588 JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x20 PUSH1 0x4 DUP3 ADD MSTORE PUSH1 0xE PUSH1 0x24 DUP3 ADD MSTORE PUSH32 0x53494D504C455F52455155495245000000000000000000000000000000000000 PUSH1 0x44 DUP3 ADD MSTORE SWAP1 MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x64 ADD SWAP1 REVERT JUMPDEST PUSH1 0x0 PUSH1 0x60 PUSH1 0x40 MLOAD DUP1 PUSH1 0x40 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x1C DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x19457468657265756D205369676E6564204D6573736167653A0A333200000000 DUP2 MSTORE POP SWAP1 POP PUSH1 0x0 DUP2 DUP8 PUSH1 0x40 MLOAD PUSH1 0x20 ADD DUP1 DUP4 DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 JUMPDEST PUSH1 0x20 DUP4 LT PUSH2 0x2A9 JUMPI DUP1 MLOAD DUP3 MSTORE PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0 SWAP1 SWAP3 ADD SWAP2 PUSH1 0x20 SWAP2 DUP3 ADD SWAP2 ADD PUSH2 0x26C JUMP JUMPDEST MLOAD DUP2 MLOAD PUSH1 0x20 SWAP4 DUP5 SUB PUSH2 0x100 EXP PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ADD DUP1 NOT SWAP1 SWAP3 AND SWAP2 AND OR SWAP1 MSTORE SWAP3 ADD SWAP4 DUP5 MSTORE POP PUSH1 0x40 DUP1 MLOAD DUP1 DUP6 SUB DUP2 MSTORE DUP5 DUP4 ADD DUP1 DUP4 MSTORE DUP2 MLOAD SWAP2 DUP5 ADD SWAP2 SWAP1 SWAP2 KECCAK256 PUSH1 0x0 SWAP1 SWAP2 MSTORE DUP2 DUP6 ADD DUP1 DUP4 MSTORE DUP2 SWAP1 MSTORE PUSH1 0xFF DUP13 AND PUSH1 0x60 DUP7 ADD MSTORE PUSH1 0x80 DUP6 ADD DUP12 SWAP1 MSTORE PUSH1 0xA0 DUP6 ADD DUP11 SWAP1 MSTORE SWAP1 MLOAD SWAP1 SWAP6 POP PUSH1 0x1 SWAP5 POP PUSH1 0xC0 DUP1 DUP6 ADD SWAP5 SWAP3 SWAP4 POP PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0 DUP3 ADD SWAP3 DUP3 SWAP1 SUB ADD SWAP1 DUP6 GAS STATICCALL ISZERO DUP1 ISZERO PUSH2 0x373 JUMPI RETURNDATASIZE PUSH1 0x0 DUP1 RETURNDATACOPY RETURNDATASIZE PUSH1 0x0 REVERT JUMPDEST POP POP PUSH1 0x40 MLOAD PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0 ADD MLOAD SWAP9 SWAP8 POP POP POP POP POP POP POP POP JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 PUSH1 0x40 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x14 DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x5245564552545F574954485F434F4E5354414E54000000000000000000000000 DUP2 MSTORE POP PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0x440 JUMPI DUP2 DUP2 ADD MLOAD DUP4 DUP3 ADD MSTORE PUSH1 0x20 ADD PUSH2 0x428 JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0x46D JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH1 0x40 DUP1 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x20 PUSH1 0x4 DUP3 ADD MSTORE PUSH1 0xD PUSH1 0x24 DUP3 ADD MSTORE PUSH32 0x53494D504C455F52455645525400000000000000000000000000000000000000 PUSH1 0x44 DUP3 ADD MSTORE SWAP1 MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x64 ADD SWAP1 REVERT JUMPDEST PUSH1 0x40 DUP1 MLOAD DUP1 DUP3 ADD DUP3 MSTORE PUSH1 0x15 DUP2 MSTORE PUSH32 0x524551554952455F574954485F434F4E5354414E540000000000000000000000 PUSH1 0x20 DUP1 DUP4 ADD SWAP2 DUP3 MSTORE SWAP3 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 DUP2 ADD SWAP4 DUP5 MSTORE DUP3 MLOAD PUSH1 0x24 DUP3 ADD MSTORE DUP3 MLOAD SWAP3 SWAP4 SWAP3 DUP4 SWAP3 PUSH1 0x44 SWAP1 SWAP3 ADD SWAP2 SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 DUP4 ISZERO PUSH2 0x440 JUMPI DUP2 DUP2 ADD MLOAD DUP4 DUP3 ADD MSTORE PUSH1 0x20 ADD PUSH2 0x428 JUMP JUMPDEST POP SWAP3 SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x1 ADD SWAP1 JUMP JUMPDEST PUSH1 0x1 SWAP1 JUMP JUMPDEST PUSH2 0x4D2 SWAP1 JUMP INVALID LOG2 PUSH6 0x627A7A723058 KECCAK256 INVALID 0x29 CALLCODE 0xa5 PUSH18 0xCFCBF82ABB5EAA5B4E17B2BEA39D36B386E8 DUP5 PUSH4 0xD23D21B8 EXTCODECOPY GAS 0x23 PUSH5 0x736F6C6343 STOP SDIV EXP STOP ORIGIN ", - "sourceMap": "606:1667:0:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;606:1667:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1461:107;;;:::i;:::-;;1691:334;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;-1:-1;1691:334:0;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;1354:101;;;:::i;1251:97::-;;;:::i;1574:111::-;;;:::i;2104:166::-;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;-1:-1;2104:166:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;954:140::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;954:140:0;;:::i;:::-;;;;;;;;;;;;;;;;827:121;;;:::i;1100:145::-;;;:::i;1461:107::-;1529:32;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1691:334;1802:21;1839:19;:56;;;;;;;;;;;;;;;;;;;1905:20;1955:6;1963:4;1938:30;;;;;;;;;;;;;;;36:153:-1;66:2;61:3;58:11;36:153;;176:10;;164:23;;139:12;;;;;98:2;89:12;;;;114;36:153;;;299:10;344;;263:2;259:12;;;254:3;250:22;246:30;;311:9;;295:26;;;340:21;;377:20;365:33;;1938:30:0;;;;;-1:-1:-1;1938:30:0;;;26:21:-1;;;6:49;;1938:30:0;;;;;;1928:41;;;;;;;;;-1:-1:-1;1986:32:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1928:41;;-1:-1:-1;274:1;;-1:-1;1986:32:0;;;;;263:2:-1;;-1:-1;;1986:32:0;;;;;;;;274:1:-1;1986:32:0;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;1986:32:0;;;;;;1691:334;-1:-1:-1;;;;;;;;1691:334:0:o;1354:101::-;1434:13;;;;;;;;;;;;;;;;;1427:21;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;1427:21:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1251:97;1318:23;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1574:111;1663:14;;;;;;;;;;;;;;;;;;;1648:30;;;;;;;;;;;;;;;;;;;1663:14;;1648:30;;;;;;;;1663:14;1648:30;;1663:14;-1:-1:-1;27:10;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;2104:166:0;-1:-1:-1;2262:1:0;;2104:166;-1:-1:-1;;;2104:166:0:o;954:140::-;1082:1;:5;;954:140::o;827:121::-;940:1;827:121;:::o;1100:145::-;676:4;1100:145;:::o" - } - } - }, - "sources": { - "AbiGenDummy.sol": { - "id": 0 - } - }, - "sourceCodes": { - "AbiGenDummy.sol": "/*\n\n Copyright 2018 ZeroEx Intl.\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n*/\n\npragma solidity ^0.5.5;\n\n\ncontract AbiGenDummy\n{\n\n uint256 constant internal SOME_CONSTANT = 1234;\n string constant internal REVERT_REASON = \"REVERT_WITH_CONSTANT\";\n string constant internal REQUIRE_REASON = \"REQUIRE_WITH_CONSTANT\";\n\n function simplePureFunction ()\n public\n pure\n returns (uint256 result)\n {\n return 1;\n }\n\n function simplePureFunctionWithInput (uint256 x)\n public\n pure\n returns (uint256 sum)\n {\n return 1 + x;\n }\n\n function pureFunctionWithConstant ()\n public\n pure\n returns (uint256 someConstant)\n {\n return SOME_CONSTANT;\n }\n\n function simpleRevert ()\n public\n pure\n {\n revert(\"SIMPLE_REVERT\");\n }\n\n function revertWithConstant ()\n public\n pure\n {\n revert(REVERT_REASON);\n }\n\n function simpleRequire ()\n public\n pure\n {\n require(0 > 1, \"SIMPLE_REQUIRE\");\n }\n\n function requireWithConstant ()\n public\n pure\n {\n require(0 > 1, REQUIRE_REASON);\n }\n\n function ecrecoverFn(bytes32 hash, uint8 v, bytes32 r, bytes32 s)\n public\n pure\n returns (address signerAddress)\n {\n bytes memory prefix = \"\\x19Ethereum Signed Message:\\n32\";\n bytes32 prefixedHash = keccak256(abi.encodePacked(prefix, hash));\n return ecrecover(prefixedHash, v, r, s);\n }\n\n // test: generated code should normalize address inputs to lowercase\n function withAddressInput(address x, uint256 a, uint256 b, address y, uint256 c)\n public\n pure\n returns (address z)\n {\n return x;\n }\n\n}\n" - }, - "sourceTreeHashHex": "0x0b6cc8d8d854c5af8d62214c19140c45ab98691b4d3074cd164e32158a1185b7", - "compiler": { - "name": "solc", - "version": "soljson-v0.5.10+commit.5a6ea5b1.js", - "settings": { - "optimizer": { - "enabled": true, - "runs": 1000000, - "details": { - "yul": true, - "deduplicate": true, - "cse": true, - "constantOptimizer": true - } - }, - "outputSelection": { - "*": { - "*": [ - "abi", - "evm.bytecode.object", - "evm.bytecode.sourceMap", - "evm.deployedBytecode.object", - "evm.deployedBytecode.sourceMap" - ] - } - }, - "evmVersion": "constantinople", - "remappings": [] - } - }, - "networks": {} -} + "schemaVersion": "2.0.0", + "contractName": "AbiGenDummy", + "compilerOutput": { + "abi": [ + { + "constant": true, + "inputs": [], + "name": "simpleRequire", + "outputs": [], + "payable": false, + "stateMutability": "pure", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "a", + "type": "bytes[]" + } + ], + "name": "acceptsAnArrayOfBytes", + "outputs": [], + "payable": false, + "stateMutability": "pure", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "hash", + "type": "bytes32" + }, + { + "name": "v", + "type": "uint8" + }, + { + "name": "r", + "type": "bytes32" + }, + { + "name": "s", + "type": "bytes32" + } + ], + "name": "ecrecoverFn", + "outputs": [ + { + "name": "signerAddress", + "type": "address" + } + ], + "payable": false, + "stateMutability": "pure", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "a", + "type": "bytes" + } + ], + "name": "acceptsBytes", + "outputs": [], + "payable": false, + "stateMutability": "pure", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "revertWithConstant", + "outputs": [], + "payable": false, + "stateMutability": "pure", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "simpleRevert", + "outputs": [], + "payable": false, + "stateMutability": "pure", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "nestedStructOutput", + "outputs": [ + { + "components": [ + { + "components": [ + { + "name": "someBytes", + "type": "bytes" + }, + { + "name": "anInteger", + "type": "uint32" + }, + { + "name": "aDynamicArrayOfBytes", + "type": "bytes[]" + }, + { + "name": "aString", + "type": "string" + } + ], + "name": "innerStruct", + "type": "tuple" + }, + { + "name": "description", + "type": "string" + } + ], + "name": "", + "type": "tuple" + } + ], + "payable": false, + "stateMutability": "pure", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "requireWithConstant", + "outputs": [], + "payable": false, + "stateMutability": "pure", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "x", + "type": "address" + }, + { + "name": "a", + "type": "uint256" + }, + { + "name": "b", + "type": "uint256" + }, + { + "name": "y", + "type": "address" + }, + { + "name": "c", + "type": "uint256" + } + ], + "name": "withAddressInput", + "outputs": [ + { + "name": "z", + "type": "address" + } + ], + "payable": false, + "stateMutability": "pure", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "components": [ + { + "name": "someBytes", + "type": "bytes" + }, + { + "name": "anInteger", + "type": "uint32" + }, + { + "name": "aDynamicArrayOfBytes", + "type": "bytes[]" + }, + { + "name": "aString", + "type": "string" + } + ], + "name": "s", + "type": "tuple" + } + ], + "name": "structInput", + "outputs": [], + "payable": false, + "stateMutability": "pure", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "nonPureMethod", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "x", + "type": "uint256" + } + ], + "name": "simplePureFunctionWithInput", + "outputs": [ + { + "name": "sum", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "pure", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "nonPureMethodThatReturnsNothing", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "simplePureFunction", + "outputs": [ + { + "name": "result", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "pure", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "components": [ + { + "components": [ + { + "name": "someBytes", + "type": "bytes" + }, + { + "name": "anInteger", + "type": "uint32" + }, + { + "name": "aDynamicArrayOfBytes", + "type": "bytes[]" + }, + { + "name": "aString", + "type": "string" + } + ], + "name": "innerStruct", + "type": "tuple" + }, + { + "name": "description", + "type": "string" + } + ], + "name": "n", + "type": "tuple" + } + ], + "name": "nestedStructInput", + "outputs": [], + "payable": false, + "stateMutability": "pure", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "structOutput", + "outputs": [ + { + "components": [ + { + "name": "someBytes", + "type": "bytes" + }, + { + "name": "anInteger", + "type": "uint32" + }, + { + "name": "aDynamicArrayOfBytes", + "type": "bytes[]" + }, + { + "name": "aString", + "type": "string" + } + ], + "name": "s", + "type": "tuple" + } + ], + "payable": false, + "stateMutability": "pure", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pureFunctionWithConstant", + "outputs": [ + { + "name": "someConstant", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "pure", + "type": "function" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "param", + "type": "uint8" + } + ], + "name": "AnEvent", + "type": "event" + } + ], + "devdoc": { + "methods": { + "acceptsAnArrayOfBytes(bytes[])": { + "details": "a method that accepts an array of bytes", + "params": { + "a": "the array of bytes being accepted" + } + }, + "structOutput()": { + "details": "a method that returns a struct", + "return": "a Struct struct" + } + } + }, + "evm": { + "bytecode": { + "linkReferences": {}, + "object": "0x608060405234801561001057600080fd5b50610b98806100206000396000f3fe608060405234801561001057600080fd5b506004361061011a5760003560e01c806363d69c88116100b25780639a3b618511610081578063ae2dae1711610066578063ae2dae17146101f9578063d6d7618c14610207578063d88be12f1461021c5761011a565b80639a3b6185146101e9578063a3c2f6b6146101f15761011a565b806363d69c88146101a0578063647341eb146101b357806376f15d5b146101c15780638ee52b4e146101d65761011a565b80634582eab2116100ee5780634582eab21461017357806345fdbdb71461017b57806359c28add146101835780635ba3c7c0146101985761011a565b806209e4371461011f5780630527c28f1461012957806336b323961461013c5780633e9ef66a14610165575b600080fd5b610127610224565b005b6101276101373660046106d7565b61025f565b61014f61014a366004610714565b610262565b60405161015c9190610999565b60405180910390f35b610127610137366004610757565b610127610344565b6101276103a9565b61018b6103db565b60405161015c9190610a60565b6101276103e6565b61014f6101ae366004610685565b61044b565b61012761013736600461081c565b6101c9610454565b60405161015c9190610ad3565b6101c96101e4366004610851565b610462565b610127610468565b6101c9610473565b61012761013736600461078c565b61020f610478565b60405161015c9190610ac0565b6101c9610480565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161025690610a29565b60405180910390fd5b50565b600060606040518060400160405280601c81526020017f19457468657265756d205369676e6564204d6573736167653a0a3332000000008152509050600081876040516020016102b3929190610977565b604051602081830303815290604052805190602001209050600181878787604051600081526020016040526040516102ee94939291906109ba565b6020604051602081039080840390855afa158015610310573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015198975050505050505050565b604080518082018252601481527f5245564552545f574954485f434f4e5354414e54000000000000000000000000602082015290517f08c379a000000000000000000000000000000000000000000000000000000000815261025691906004016109d8565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610256906109f2565b6103e3610486565b90565b604080518082018252601581527f524551554952455f574954485f434f4e5354414e540000000000000000000000602082015290517f08c379a000000000000000000000000000000000000000000000000000000000815261025691906004016109d8565b50929392505050565b600080546001019081905590565b60010190565b600080546001019055565b600190565b6103e36104a6565b6104d290565b6040518060a001604052806104996104a6565b8152602001606081525090565b604051806080016040528060608152602001600063ffffffff16815260200160608152602001606081525090565b600082601f8301126104e4578081fd5b813567ffffffffffffffff8111156104fa578182fd5b60206105098182840201610adc565b828152925080830184820160005b848110156105405761052e888584358a010161054b565b83529183019190830190600101610517565b505050505092915050565b600082601f83011261055b578081fd5b813567ffffffffffffffff811115610571578182fd5b6105a260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601610adc565b91508082528360208285010111156105b957600080fd5b8060208401602084013760009082016020015292915050565b6000608082840312156105e3578081fd5b6105ed6080610adc565b90506000823567ffffffffffffffff80821115610608578283fd5b6106148683870161054b565b84526020850135915063ffffffff8216821461062e578283fd5b8160208501526040850135915080821115610647578283fd5b610653868387016104d4565b6040850152606085013591508082111561066b578283fd5b506106788582860161054b565b6060840152505092915050565b600080600080600060a0868803121561069d57600080fd5b85356106a881610b33565b9450602086013593506040860135925060608601356106c681610b33565b949793965091946080013592915050565b6000602082840312156106e957600080fd5b813567ffffffffffffffff81111561070057600080fd5b61070c848285016104d4565b949350505050565b6000806000806080858703121561072a57600080fd5b84359350602085013560ff8116811461074257600080fd5b93969395505050506040820135916060013590565b60006020828403121561076957600080fd5b813567ffffffffffffffff81111561078057600080fd5b61070c8482850161054b565b60006020828403121561079d578081fd5b813567ffffffffffffffff808211156107b4578283fd5b818401604081870312156107c6578384fd5b6107d06040610adc565b92508035828111156107e0578485fd5b6107ec878284016105d2565b845250602081013582811115610800578485fd5b61080c8782840161054b565b6020850152509195945050505050565b60006020828403121561082e57600080fd5b813567ffffffffffffffff81111561084557600080fd5b61070c848285016105d2565b60006020828403121561086357600080fd5b5035919050565b60008151808452610882816020860160208601610b03565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60008151608084526108c9608085018261086a565b6020915063ffffffff82850151168286015260408401518582036040870152818151808452848401915084858202850101858401600094505b82851015610950577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe086830301845261093c82825161086a565b600195909501949387019391508601610902565b506060880151955088810360608a015261096a818761086a565b9998505050505050505050565b60008351610989818460208801610b03565b9190910191825250602001919050565b73ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b93845260ff9290921660208401526040830152606082015260800190565b6000602082526109eb602083018461086a565b9392505050565b6020808252600d908201527f53494d504c455f52455645525400000000000000000000000000000000000000604082015260600190565b6020808252600e908201527f53494d504c455f52455155495245000000000000000000000000000000000000604082015260600190565b600060208252825160406020840152610a7c60608401826108b4565b602085015191507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848203016040850152610ab7818361086a565b95945050505050565b6000602082526109eb60208301846108b4565b90815260200190565b60405181810167ffffffffffffffff81118282101715610afb57600080fd5b604052919050565b60005b83811015610b1e578181015183820152602001610b06565b83811115610b2d576000848401525b50505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461025f57600080fdfea365627a7a72305820888f51db8be2b65eeba07b18b43cdc6dad5d8e6807eb4aa7f11e06f111742aef6c6578706572696d656e74616cf564736f6c634300050a0040", + "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0xB98 DUP1 PUSH2 0x20 PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN INVALID PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x4 CALLDATASIZE LT PUSH2 0x11A JUMPI PUSH1 0x0 CALLDATALOAD PUSH1 0xE0 SHR DUP1 PUSH4 0x63D69C88 GT PUSH2 0xB2 JUMPI DUP1 PUSH4 0x9A3B6185 GT PUSH2 0x81 JUMPI DUP1 PUSH4 0xAE2DAE17 GT PUSH2 0x66 JUMPI DUP1 PUSH4 0xAE2DAE17 EQ PUSH2 0x1F9 JUMPI DUP1 PUSH4 0xD6D7618C EQ PUSH2 0x207 JUMPI DUP1 PUSH4 0xD88BE12F EQ PUSH2 0x21C JUMPI PUSH2 0x11A JUMP JUMPDEST DUP1 PUSH4 0x9A3B6185 EQ PUSH2 0x1E9 JUMPI DUP1 PUSH4 0xA3C2F6B6 EQ PUSH2 0x1F1 JUMPI PUSH2 0x11A JUMP JUMPDEST DUP1 PUSH4 0x63D69C88 EQ PUSH2 0x1A0 JUMPI DUP1 PUSH4 0x647341EB EQ PUSH2 0x1B3 JUMPI DUP1 PUSH4 0x76F15D5B EQ PUSH2 0x1C1 JUMPI DUP1 PUSH4 0x8EE52B4E EQ PUSH2 0x1D6 JUMPI PUSH2 0x11A JUMP JUMPDEST DUP1 PUSH4 0x4582EAB2 GT PUSH2 0xEE JUMPI DUP1 PUSH4 0x4582EAB2 EQ PUSH2 0x173 JUMPI DUP1 PUSH4 0x45FDBDB7 EQ PUSH2 0x17B JUMPI DUP1 PUSH4 0x59C28ADD EQ PUSH2 0x183 JUMPI DUP1 PUSH4 0x5BA3C7C0 EQ PUSH2 0x198 JUMPI PUSH2 0x11A JUMP JUMPDEST DUP1 PUSH3 0x9E437 EQ PUSH2 0x11F JUMPI DUP1 PUSH4 0x527C28F EQ PUSH2 0x129 JUMPI DUP1 PUSH4 0x36B32396 EQ PUSH2 0x13C JUMPI DUP1 PUSH4 0x3E9EF66A EQ PUSH2 0x165 JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0x127 PUSH2 0x224 JUMP JUMPDEST STOP JUMPDEST PUSH2 0x127 PUSH2 0x137 CALLDATASIZE PUSH1 0x4 PUSH2 0x6D7 JUMP JUMPDEST PUSH2 0x25F JUMP JUMPDEST PUSH2 0x14F PUSH2 0x14A CALLDATASIZE PUSH1 0x4 PUSH2 0x714 JUMP JUMPDEST PUSH2 0x262 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x15C SWAP2 SWAP1 PUSH2 0x999 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x127 PUSH2 0x137 CALLDATASIZE PUSH1 0x4 PUSH2 0x757 JUMP JUMPDEST PUSH2 0x127 PUSH2 0x344 JUMP JUMPDEST PUSH2 0x127 PUSH2 0x3A9 JUMP JUMPDEST PUSH2 0x18B PUSH2 0x3DB JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x15C SWAP2 SWAP1 PUSH2 0xA60 JUMP JUMPDEST PUSH2 0x127 PUSH2 0x3E6 JUMP JUMPDEST PUSH2 0x14F PUSH2 0x1AE CALLDATASIZE PUSH1 0x4 PUSH2 0x685 JUMP JUMPDEST PUSH2 0x44B JUMP JUMPDEST PUSH2 0x127 PUSH2 0x137 CALLDATASIZE PUSH1 0x4 PUSH2 0x81C JUMP JUMPDEST PUSH2 0x1C9 PUSH2 0x454 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x15C SWAP2 SWAP1 PUSH2 0xAD3 JUMP JUMPDEST PUSH2 0x1C9 PUSH2 0x1E4 CALLDATASIZE PUSH1 0x4 PUSH2 0x851 JUMP JUMPDEST PUSH2 0x462 JUMP JUMPDEST PUSH2 0x127 PUSH2 0x468 JUMP JUMPDEST PUSH2 0x1C9 PUSH2 0x473 JUMP JUMPDEST PUSH2 0x127 PUSH2 0x137 CALLDATASIZE PUSH1 0x4 PUSH2 0x78C JUMP JUMPDEST PUSH2 0x20F PUSH2 0x478 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x15C SWAP2 SWAP1 PUSH2 0xAC0 JUMP JUMPDEST PUSH2 0x1C9 PUSH2 0x480 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x256 SWAP1 PUSH2 0xA29 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x60 PUSH1 0x40 MLOAD DUP1 PUSH1 0x40 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x1C DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x19457468657265756D205369676E6564204D6573736167653A0A333200000000 DUP2 MSTORE POP SWAP1 POP PUSH1 0x0 DUP2 DUP8 PUSH1 0x40 MLOAD PUSH1 0x20 ADD PUSH2 0x2B3 SWAP3 SWAP2 SWAP1 PUSH2 0x977 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH1 0x20 DUP2 DUP4 SUB SUB DUP2 MSTORE SWAP1 PUSH1 0x40 MSTORE DUP1 MLOAD SWAP1 PUSH1 0x20 ADD KECCAK256 SWAP1 POP PUSH1 0x1 DUP2 DUP8 DUP8 DUP8 PUSH1 0x40 MLOAD PUSH1 0x0 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x40 MSTORE PUSH1 0x40 MLOAD PUSH2 0x2EE SWAP5 SWAP4 SWAP3 SWAP2 SWAP1 PUSH2 0x9BA JUMP JUMPDEST PUSH1 0x20 PUSH1 0x40 MLOAD PUSH1 0x20 DUP2 SUB SWAP1 DUP1 DUP5 SUB SWAP1 DUP6 GAS STATICCALL ISZERO DUP1 ISZERO PUSH2 0x310 JUMPI RETURNDATASIZE PUSH1 0x0 DUP1 RETURNDATACOPY RETURNDATASIZE PUSH1 0x0 REVERT JUMPDEST POP POP PUSH1 0x40 MLOAD PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0 ADD MLOAD SWAP9 SWAP8 POP POP POP POP POP POP POP POP JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD DUP1 DUP3 ADD DUP3 MSTORE PUSH1 0x14 DUP2 MSTORE PUSH32 0x5245564552545F574954485F434F4E5354414E54000000000000000000000000 PUSH1 0x20 DUP3 ADD MSTORE SWAP1 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH2 0x256 SWAP2 SWAP1 PUSH1 0x4 ADD PUSH2 0x9D8 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x256 SWAP1 PUSH2 0x9F2 JUMP JUMPDEST PUSH2 0x3E3 PUSH2 0x486 JUMP JUMPDEST SWAP1 JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD DUP1 DUP3 ADD DUP3 MSTORE PUSH1 0x15 DUP2 MSTORE PUSH32 0x524551554952455F574954485F434F4E5354414E540000000000000000000000 PUSH1 0x20 DUP3 ADD MSTORE SWAP1 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH2 0x256 SWAP2 SWAP1 PUSH1 0x4 ADD PUSH2 0x9D8 JUMP JUMPDEST POP SWAP3 SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 SLOAD PUSH1 0x1 ADD SWAP1 DUP2 SWAP1 SSTORE SWAP1 JUMP JUMPDEST PUSH1 0x1 ADD SWAP1 JUMP JUMPDEST PUSH1 0x0 DUP1 SLOAD PUSH1 0x1 ADD SWAP1 SSTORE JUMP JUMPDEST PUSH1 0x1 SWAP1 JUMP JUMPDEST PUSH2 0x3E3 PUSH2 0x4A6 JUMP JUMPDEST PUSH2 0x4D2 SWAP1 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 PUSH1 0xA0 ADD PUSH1 0x40 MSTORE DUP1 PUSH2 0x499 PUSH2 0x4A6 JUMP JUMPDEST DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x60 DUP2 MSTORE POP SWAP1 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 PUSH1 0x80 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x60 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 PUSH4 0xFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x60 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x60 DUP2 MSTORE POP SWAP1 JUMP JUMPDEST PUSH1 0x0 DUP3 PUSH1 0x1F DUP4 ADD SLT PUSH2 0x4E4 JUMPI DUP1 DUP2 REVERT JUMPDEST DUP2 CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0x4FA JUMPI DUP2 DUP3 REVERT JUMPDEST PUSH1 0x20 PUSH2 0x509 DUP2 DUP3 DUP5 MUL ADD PUSH2 0xADC JUMP JUMPDEST DUP3 DUP2 MSTORE SWAP3 POP DUP1 DUP4 ADD DUP5 DUP3 ADD PUSH1 0x0 JUMPDEST DUP5 DUP2 LT ISZERO PUSH2 0x540 JUMPI PUSH2 0x52E DUP9 DUP6 DUP5 CALLDATALOAD DUP11 ADD ADD PUSH2 0x54B JUMP JUMPDEST DUP4 MSTORE SWAP2 DUP4 ADD SWAP2 SWAP1 DUP4 ADD SWAP1 PUSH1 0x1 ADD PUSH2 0x517 JUMP JUMPDEST POP POP POP POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP3 PUSH1 0x1F DUP4 ADD SLT PUSH2 0x55B JUMPI DUP1 DUP2 REVERT JUMPDEST DUP2 CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0x571 JUMPI DUP2 DUP3 REVERT JUMPDEST PUSH2 0x5A2 PUSH1 0x20 PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0 PUSH1 0x1F DUP5 ADD AND ADD PUSH2 0xADC JUMP JUMPDEST SWAP2 POP DUP1 DUP3 MSTORE DUP4 PUSH1 0x20 DUP3 DUP6 ADD ADD GT ISZERO PUSH2 0x5B9 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP1 PUSH1 0x20 DUP5 ADD PUSH1 0x20 DUP5 ADD CALLDATACOPY PUSH1 0x0 SWAP1 DUP3 ADD PUSH1 0x20 ADD MSTORE SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x80 DUP3 DUP5 SUB SLT ISZERO PUSH2 0x5E3 JUMPI DUP1 DUP2 REVERT JUMPDEST PUSH2 0x5ED PUSH1 0x80 PUSH2 0xADC JUMP JUMPDEST SWAP1 POP PUSH1 0x0 DUP3 CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP1 DUP3 GT ISZERO PUSH2 0x608 JUMPI DUP3 DUP4 REVERT JUMPDEST PUSH2 0x614 DUP7 DUP4 DUP8 ADD PUSH2 0x54B JUMP JUMPDEST DUP5 MSTORE PUSH1 0x20 DUP6 ADD CALLDATALOAD SWAP2 POP PUSH4 0xFFFFFFFF DUP3 AND DUP3 EQ PUSH2 0x62E JUMPI DUP3 DUP4 REVERT JUMPDEST DUP2 PUSH1 0x20 DUP6 ADD MSTORE PUSH1 0x40 DUP6 ADD CALLDATALOAD SWAP2 POP DUP1 DUP3 GT ISZERO PUSH2 0x647 JUMPI DUP3 DUP4 REVERT JUMPDEST PUSH2 0x653 DUP7 DUP4 DUP8 ADD PUSH2 0x4D4 JUMP JUMPDEST PUSH1 0x40 DUP6 ADD MSTORE PUSH1 0x60 DUP6 ADD CALLDATALOAD SWAP2 POP DUP1 DUP3 GT ISZERO PUSH2 0x66B JUMPI DUP3 DUP4 REVERT JUMPDEST POP PUSH2 0x678 DUP6 DUP3 DUP7 ADD PUSH2 0x54B JUMP JUMPDEST PUSH1 0x60 DUP5 ADD MSTORE POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x0 DUP1 PUSH1 0x0 PUSH1 0xA0 DUP7 DUP9 SUB SLT ISZERO PUSH2 0x69D JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP6 CALLDATALOAD PUSH2 0x6A8 DUP2 PUSH2 0xB33 JUMP JUMPDEST SWAP5 POP PUSH1 0x20 DUP7 ADD CALLDATALOAD SWAP4 POP PUSH1 0x40 DUP7 ADD CALLDATALOAD SWAP3 POP PUSH1 0x60 DUP7 ADD CALLDATALOAD PUSH2 0x6C6 DUP2 PUSH2 0xB33 JUMP JUMPDEST SWAP5 SWAP8 SWAP4 SWAP7 POP SWAP2 SWAP5 PUSH1 0x80 ADD CALLDATALOAD SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 DUP5 SUB SLT ISZERO PUSH2 0x6E9 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0x700 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0x70C DUP5 DUP3 DUP6 ADD PUSH2 0x4D4 JUMP JUMPDEST SWAP5 SWAP4 POP POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x0 DUP1 PUSH1 0x80 DUP6 DUP8 SUB SLT ISZERO PUSH2 0x72A JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP5 CALLDATALOAD SWAP4 POP PUSH1 0x20 DUP6 ADD CALLDATALOAD PUSH1 0xFF DUP2 AND DUP2 EQ PUSH2 0x742 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST SWAP4 SWAP7 SWAP4 SWAP6 POP POP POP POP PUSH1 0x40 DUP3 ADD CALLDATALOAD SWAP2 PUSH1 0x60 ADD CALLDATALOAD SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 DUP5 SUB SLT ISZERO PUSH2 0x769 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0x780 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0x70C DUP5 DUP3 DUP6 ADD PUSH2 0x54B JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 DUP5 SUB SLT ISZERO PUSH2 0x79D JUMPI DUP1 DUP2 REVERT JUMPDEST DUP2 CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP1 DUP3 GT ISZERO PUSH2 0x7B4 JUMPI DUP3 DUP4 REVERT JUMPDEST DUP2 DUP5 ADD PUSH1 0x40 DUP2 DUP8 SUB SLT ISZERO PUSH2 0x7C6 JUMPI DUP4 DUP5 REVERT JUMPDEST PUSH2 0x7D0 PUSH1 0x40 PUSH2 0xADC JUMP JUMPDEST SWAP3 POP DUP1 CALLDATALOAD DUP3 DUP2 GT ISZERO PUSH2 0x7E0 JUMPI DUP5 DUP6 REVERT JUMPDEST PUSH2 0x7EC DUP8 DUP3 DUP5 ADD PUSH2 0x5D2 JUMP JUMPDEST DUP5 MSTORE POP PUSH1 0x20 DUP2 ADD CALLDATALOAD DUP3 DUP2 GT ISZERO PUSH2 0x800 JUMPI DUP5 DUP6 REVERT JUMPDEST PUSH2 0x80C DUP8 DUP3 DUP5 ADD PUSH2 0x54B JUMP JUMPDEST PUSH1 0x20 DUP6 ADD MSTORE POP SWAP2 SWAP6 SWAP5 POP POP POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 DUP5 SUB SLT ISZERO PUSH2 0x82E JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0x845 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0x70C DUP5 DUP3 DUP6 ADD PUSH2 0x5D2 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 DUP5 SUB SLT ISZERO PUSH2 0x863 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP CALLDATALOAD SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 DUP2 MLOAD DUP1 DUP5 MSTORE PUSH2 0x882 DUP2 PUSH1 0x20 DUP7 ADD PUSH1 0x20 DUP7 ADD PUSH2 0xB03 JUMP JUMPDEST PUSH1 0x1F ADD PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0 AND SWAP3 SWAP1 SWAP3 ADD PUSH1 0x20 ADD SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP2 MLOAD PUSH1 0x80 DUP5 MSTORE PUSH2 0x8C9 PUSH1 0x80 DUP6 ADD DUP3 PUSH2 0x86A JUMP JUMPDEST PUSH1 0x20 SWAP2 POP PUSH4 0xFFFFFFFF DUP3 DUP6 ADD MLOAD AND DUP3 DUP7 ADD MSTORE PUSH1 0x40 DUP5 ADD MLOAD DUP6 DUP3 SUB PUSH1 0x40 DUP8 ADD MSTORE DUP2 DUP2 MLOAD DUP1 DUP5 MSTORE DUP5 DUP5 ADD SWAP2 POP DUP5 DUP6 DUP3 MUL DUP6 ADD ADD DUP6 DUP5 ADD PUSH1 0x0 SWAP5 POP JUMPDEST DUP3 DUP6 LT ISZERO PUSH2 0x950 JUMPI PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0 DUP7 DUP4 SUB ADD DUP5 MSTORE PUSH2 0x93C DUP3 DUP3 MLOAD PUSH2 0x86A JUMP JUMPDEST PUSH1 0x1 SWAP6 SWAP1 SWAP6 ADD SWAP5 SWAP4 DUP8 ADD SWAP4 SWAP2 POP DUP7 ADD PUSH2 0x902 JUMP JUMPDEST POP PUSH1 0x60 DUP9 ADD MLOAD SWAP6 POP DUP9 DUP2 SUB PUSH1 0x60 DUP11 ADD MSTORE PUSH2 0x96A DUP2 DUP8 PUSH2 0x86A JUMP JUMPDEST SWAP10 SWAP9 POP POP POP POP POP POP POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP4 MLOAD PUSH2 0x989 DUP2 DUP5 PUSH1 0x20 DUP9 ADD PUSH2 0xB03 JUMP JUMPDEST SWAP2 SWAP1 SWAP2 ADD SWAP2 DUP3 MSTORE POP PUSH1 0x20 ADD SWAP2 SWAP1 POP JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF SWAP2 SWAP1 SWAP2 AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 JUMP JUMPDEST SWAP4 DUP5 MSTORE PUSH1 0xFF SWAP3 SWAP1 SWAP3 AND PUSH1 0x20 DUP5 ADD MSTORE PUSH1 0x40 DUP4 ADD MSTORE PUSH1 0x60 DUP3 ADD MSTORE PUSH1 0x80 ADD SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 MSTORE PUSH2 0x9EB PUSH1 0x20 DUP4 ADD DUP5 PUSH2 0x86A JUMP JUMPDEST SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x20 DUP1 DUP3 MSTORE PUSH1 0xD SWAP1 DUP3 ADD MSTORE PUSH32 0x53494D504C455F52455645525400000000000000000000000000000000000000 PUSH1 0x40 DUP3 ADD MSTORE PUSH1 0x60 ADD SWAP1 JUMP JUMPDEST PUSH1 0x20 DUP1 DUP3 MSTORE PUSH1 0xE SWAP1 DUP3 ADD MSTORE PUSH32 0x53494D504C455F52455155495245000000000000000000000000000000000000 PUSH1 0x40 DUP3 ADD MSTORE PUSH1 0x60 ADD SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 MSTORE DUP3 MLOAD PUSH1 0x40 PUSH1 0x20 DUP5 ADD MSTORE PUSH2 0xA7C PUSH1 0x60 DUP5 ADD DUP3 PUSH2 0x8B4 JUMP JUMPDEST PUSH1 0x20 DUP6 ADD MLOAD SWAP2 POP PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0 DUP5 DUP3 SUB ADD PUSH1 0x40 DUP6 ADD MSTORE PUSH2 0xAB7 DUP2 DUP4 PUSH2 0x86A JUMP JUMPDEST SWAP6 SWAP5 POP POP POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 MSTORE PUSH2 0x9EB PUSH1 0x20 DUP4 ADD DUP5 PUSH2 0x8B4 JUMP JUMPDEST SWAP1 DUP2 MSTORE PUSH1 0x20 ADD SWAP1 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP2 DUP2 ADD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT DUP3 DUP3 LT OR ISZERO PUSH2 0xAFB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x40 MSTORE SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xB1E JUMPI DUP2 DUP2 ADD MLOAD DUP4 DUP3 ADD MSTORE PUSH1 0x20 ADD PUSH2 0xB06 JUMP JUMPDEST DUP4 DUP2 GT ISZERO PUSH2 0xB2D JUMPI PUSH1 0x0 DUP5 DUP5 ADD MSTORE JUMPDEST POP POP POP POP JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP2 AND DUP2 EQ PUSH2 0x25F JUMPI PUSH1 0x0 DUP1 REVERT INVALID LOG3 PUSH6 0x627A7A723058 KECCAK256 DUP9 DUP16 MLOAD 0xdb DUP12 0xe2 0xb6 0x5e 0xeb LOG0 PUSH28 0x18B43CDC6DAD5D8E6807EB4AA7F11E06F111742AEF6C657870657269 PUSH14 0x656E74616CF564736F6C63430005 EXP STOP BLOCKHASH ", + "sourceMap": "641:2757:0:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;641:2757:0;;;;;;;" + }, + "deployedBytecode": { + "linkReferences": {}, + "object": "0x608060405234801561001057600080fd5b506004361061011a5760003560e01c806363d69c88116100b25780639a3b618511610081578063ae2dae1711610066578063ae2dae17146101f9578063d6d7618c14610207578063d88be12f1461021c5761011a565b80639a3b6185146101e9578063a3c2f6b6146101f15761011a565b806363d69c88146101a0578063647341eb146101b357806376f15d5b146101c15780638ee52b4e146101d65761011a565b80634582eab2116100ee5780634582eab21461017357806345fdbdb71461017b57806359c28add146101835780635ba3c7c0146101985761011a565b806209e4371461011f5780630527c28f1461012957806336b323961461013c5780633e9ef66a14610165575b600080fd5b610127610224565b005b6101276101373660046106d7565b61025f565b61014f61014a366004610714565b610262565b60405161015c9190610999565b60405180910390f35b610127610137366004610757565b610127610344565b6101276103a9565b61018b6103db565b60405161015c9190610a60565b6101276103e6565b61014f6101ae366004610685565b61044b565b61012761013736600461081c565b6101c9610454565b60405161015c9190610ad3565b6101c96101e4366004610851565b610462565b610127610468565b6101c9610473565b61012761013736600461078c565b61020f610478565b60405161015c9190610ac0565b6101c9610480565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161025690610a29565b60405180910390fd5b50565b600060606040518060400160405280601c81526020017f19457468657265756d205369676e6564204d6573736167653a0a3332000000008152509050600081876040516020016102b3929190610977565b604051602081830303815290604052805190602001209050600181878787604051600081526020016040526040516102ee94939291906109ba565b6020604051602081039080840390855afa158015610310573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015198975050505050505050565b604080518082018252601481527f5245564552545f574954485f434f4e5354414e54000000000000000000000000602082015290517f08c379a000000000000000000000000000000000000000000000000000000000815261025691906004016109d8565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610256906109f2565b6103e3610486565b90565b604080518082018252601581527f524551554952455f574954485f434f4e5354414e540000000000000000000000602082015290517f08c379a000000000000000000000000000000000000000000000000000000000815261025691906004016109d8565b50929392505050565b600080546001019081905590565b60010190565b600080546001019055565b600190565b6103e36104a6565b6104d290565b6040518060a001604052806104996104a6565b8152602001606081525090565b604051806080016040528060608152602001600063ffffffff16815260200160608152602001606081525090565b600082601f8301126104e4578081fd5b813567ffffffffffffffff8111156104fa578182fd5b60206105098182840201610adc565b828152925080830184820160005b848110156105405761052e888584358a010161054b565b83529183019190830190600101610517565b505050505092915050565b600082601f83011261055b578081fd5b813567ffffffffffffffff811115610571578182fd5b6105a260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601610adc565b91508082528360208285010111156105b957600080fd5b8060208401602084013760009082016020015292915050565b6000608082840312156105e3578081fd5b6105ed6080610adc565b90506000823567ffffffffffffffff80821115610608578283fd5b6106148683870161054b565b84526020850135915063ffffffff8216821461062e578283fd5b8160208501526040850135915080821115610647578283fd5b610653868387016104d4565b6040850152606085013591508082111561066b578283fd5b506106788582860161054b565b6060840152505092915050565b600080600080600060a0868803121561069d57600080fd5b85356106a881610b33565b9450602086013593506040860135925060608601356106c681610b33565b949793965091946080013592915050565b6000602082840312156106e957600080fd5b813567ffffffffffffffff81111561070057600080fd5b61070c848285016104d4565b949350505050565b6000806000806080858703121561072a57600080fd5b84359350602085013560ff8116811461074257600080fd5b93969395505050506040820135916060013590565b60006020828403121561076957600080fd5b813567ffffffffffffffff81111561078057600080fd5b61070c8482850161054b565b60006020828403121561079d578081fd5b813567ffffffffffffffff808211156107b4578283fd5b818401604081870312156107c6578384fd5b6107d06040610adc565b92508035828111156107e0578485fd5b6107ec878284016105d2565b845250602081013582811115610800578485fd5b61080c8782840161054b565b6020850152509195945050505050565b60006020828403121561082e57600080fd5b813567ffffffffffffffff81111561084557600080fd5b61070c848285016105d2565b60006020828403121561086357600080fd5b5035919050565b60008151808452610882816020860160208601610b03565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60008151608084526108c9608085018261086a565b6020915063ffffffff82850151168286015260408401518582036040870152818151808452848401915084858202850101858401600094505b82851015610950577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe086830301845261093c82825161086a565b600195909501949387019391508601610902565b506060880151955088810360608a015261096a818761086a565b9998505050505050505050565b60008351610989818460208801610b03565b9190910191825250602001919050565b73ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b93845260ff9290921660208401526040830152606082015260800190565b6000602082526109eb602083018461086a565b9392505050565b6020808252600d908201527f53494d504c455f52455645525400000000000000000000000000000000000000604082015260600190565b6020808252600e908201527f53494d504c455f52455155495245000000000000000000000000000000000000604082015260600190565b600060208252825160406020840152610a7c60608401826108b4565b602085015191507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848203016040850152610ab7818361086a565b95945050505050565b6000602082526109eb60208301846108b4565b90815260200190565b60405181810167ffffffffffffffff81118282101715610afb57600080fd5b604052919050565b60005b83811015610b1e578181015183820152602001610b06565b83811115610b2d576000848401525b50505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461025f57600080fdfea365627a7a72305820888f51db8be2b65eeba07b18b43cdc6dad5d8e6807eb4aa7f11e06f111742aef6c6578706572696d656e74616cf564736f6c634300050a0040", + "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x4 CALLDATASIZE LT PUSH2 0x11A JUMPI PUSH1 0x0 CALLDATALOAD PUSH1 0xE0 SHR DUP1 PUSH4 0x63D69C88 GT PUSH2 0xB2 JUMPI DUP1 PUSH4 0x9A3B6185 GT PUSH2 0x81 JUMPI DUP1 PUSH4 0xAE2DAE17 GT PUSH2 0x66 JUMPI DUP1 PUSH4 0xAE2DAE17 EQ PUSH2 0x1F9 JUMPI DUP1 PUSH4 0xD6D7618C EQ PUSH2 0x207 JUMPI DUP1 PUSH4 0xD88BE12F EQ PUSH2 0x21C JUMPI PUSH2 0x11A JUMP JUMPDEST DUP1 PUSH4 0x9A3B6185 EQ PUSH2 0x1E9 JUMPI DUP1 PUSH4 0xA3C2F6B6 EQ PUSH2 0x1F1 JUMPI PUSH2 0x11A JUMP JUMPDEST DUP1 PUSH4 0x63D69C88 EQ PUSH2 0x1A0 JUMPI DUP1 PUSH4 0x647341EB EQ PUSH2 0x1B3 JUMPI DUP1 PUSH4 0x76F15D5B EQ PUSH2 0x1C1 JUMPI DUP1 PUSH4 0x8EE52B4E EQ PUSH2 0x1D6 JUMPI PUSH2 0x11A JUMP JUMPDEST DUP1 PUSH4 0x4582EAB2 GT PUSH2 0xEE JUMPI DUP1 PUSH4 0x4582EAB2 EQ PUSH2 0x173 JUMPI DUP1 PUSH4 0x45FDBDB7 EQ PUSH2 0x17B JUMPI DUP1 PUSH4 0x59C28ADD EQ PUSH2 0x183 JUMPI DUP1 PUSH4 0x5BA3C7C0 EQ PUSH2 0x198 JUMPI PUSH2 0x11A JUMP JUMPDEST DUP1 PUSH3 0x9E437 EQ PUSH2 0x11F JUMPI DUP1 PUSH4 0x527C28F EQ PUSH2 0x129 JUMPI DUP1 PUSH4 0x36B32396 EQ PUSH2 0x13C JUMPI DUP1 PUSH4 0x3E9EF66A EQ PUSH2 0x165 JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0x127 PUSH2 0x224 JUMP JUMPDEST STOP JUMPDEST PUSH2 0x127 PUSH2 0x137 CALLDATASIZE PUSH1 0x4 PUSH2 0x6D7 JUMP JUMPDEST PUSH2 0x25F JUMP JUMPDEST PUSH2 0x14F PUSH2 0x14A CALLDATASIZE PUSH1 0x4 PUSH2 0x714 JUMP JUMPDEST PUSH2 0x262 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x15C SWAP2 SWAP1 PUSH2 0x999 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x127 PUSH2 0x137 CALLDATASIZE PUSH1 0x4 PUSH2 0x757 JUMP JUMPDEST PUSH2 0x127 PUSH2 0x344 JUMP JUMPDEST PUSH2 0x127 PUSH2 0x3A9 JUMP JUMPDEST PUSH2 0x18B PUSH2 0x3DB JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x15C SWAP2 SWAP1 PUSH2 0xA60 JUMP JUMPDEST PUSH2 0x127 PUSH2 0x3E6 JUMP JUMPDEST PUSH2 0x14F PUSH2 0x1AE CALLDATASIZE PUSH1 0x4 PUSH2 0x685 JUMP JUMPDEST PUSH2 0x44B JUMP JUMPDEST PUSH2 0x127 PUSH2 0x137 CALLDATASIZE PUSH1 0x4 PUSH2 0x81C JUMP JUMPDEST PUSH2 0x1C9 PUSH2 0x454 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x15C SWAP2 SWAP1 PUSH2 0xAD3 JUMP JUMPDEST PUSH2 0x1C9 PUSH2 0x1E4 CALLDATASIZE PUSH1 0x4 PUSH2 0x851 JUMP JUMPDEST PUSH2 0x462 JUMP JUMPDEST PUSH2 0x127 PUSH2 0x468 JUMP JUMPDEST PUSH2 0x1C9 PUSH2 0x473 JUMP JUMPDEST PUSH2 0x127 PUSH2 0x137 CALLDATASIZE PUSH1 0x4 PUSH2 0x78C JUMP JUMPDEST PUSH2 0x20F PUSH2 0x478 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x15C SWAP2 SWAP1 PUSH2 0xAC0 JUMP JUMPDEST PUSH2 0x1C9 PUSH2 0x480 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x256 SWAP1 PUSH2 0xA29 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x60 PUSH1 0x40 MLOAD DUP1 PUSH1 0x40 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x1C DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x19457468657265756D205369676E6564204D6573736167653A0A333200000000 DUP2 MSTORE POP SWAP1 POP PUSH1 0x0 DUP2 DUP8 PUSH1 0x40 MLOAD PUSH1 0x20 ADD PUSH2 0x2B3 SWAP3 SWAP2 SWAP1 PUSH2 0x977 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH1 0x20 DUP2 DUP4 SUB SUB DUP2 MSTORE SWAP1 PUSH1 0x40 MSTORE DUP1 MLOAD SWAP1 PUSH1 0x20 ADD KECCAK256 SWAP1 POP PUSH1 0x1 DUP2 DUP8 DUP8 DUP8 PUSH1 0x40 MLOAD PUSH1 0x0 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x40 MSTORE PUSH1 0x40 MLOAD PUSH2 0x2EE SWAP5 SWAP4 SWAP3 SWAP2 SWAP1 PUSH2 0x9BA JUMP JUMPDEST PUSH1 0x20 PUSH1 0x40 MLOAD PUSH1 0x20 DUP2 SUB SWAP1 DUP1 DUP5 SUB SWAP1 DUP6 GAS STATICCALL ISZERO DUP1 ISZERO PUSH2 0x310 JUMPI RETURNDATASIZE PUSH1 0x0 DUP1 RETURNDATACOPY RETURNDATASIZE PUSH1 0x0 REVERT JUMPDEST POP POP PUSH1 0x40 MLOAD PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0 ADD MLOAD SWAP9 SWAP8 POP POP POP POP POP POP POP POP JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD DUP1 DUP3 ADD DUP3 MSTORE PUSH1 0x14 DUP2 MSTORE PUSH32 0x5245564552545F574954485F434F4E5354414E54000000000000000000000000 PUSH1 0x20 DUP3 ADD MSTORE SWAP1 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH2 0x256 SWAP2 SWAP1 PUSH1 0x4 ADD PUSH2 0x9D8 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x256 SWAP1 PUSH2 0x9F2 JUMP JUMPDEST PUSH2 0x3E3 PUSH2 0x486 JUMP JUMPDEST SWAP1 JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD DUP1 DUP3 ADD DUP3 MSTORE PUSH1 0x15 DUP2 MSTORE PUSH32 0x524551554952455F574954485F434F4E5354414E540000000000000000000000 PUSH1 0x20 DUP3 ADD MSTORE SWAP1 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH2 0x256 SWAP2 SWAP1 PUSH1 0x4 ADD PUSH2 0x9D8 JUMP JUMPDEST POP SWAP3 SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 SLOAD PUSH1 0x1 ADD SWAP1 DUP2 SWAP1 SSTORE SWAP1 JUMP JUMPDEST PUSH1 0x1 ADD SWAP1 JUMP JUMPDEST PUSH1 0x0 DUP1 SLOAD PUSH1 0x1 ADD SWAP1 SSTORE JUMP JUMPDEST PUSH1 0x1 SWAP1 JUMP JUMPDEST PUSH2 0x3E3 PUSH2 0x4A6 JUMP JUMPDEST PUSH2 0x4D2 SWAP1 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 PUSH1 0xA0 ADD PUSH1 0x40 MSTORE DUP1 PUSH2 0x499 PUSH2 0x4A6 JUMP JUMPDEST DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x60 DUP2 MSTORE POP SWAP1 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 PUSH1 0x80 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x60 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 PUSH4 0xFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x60 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x60 DUP2 MSTORE POP SWAP1 JUMP JUMPDEST PUSH1 0x0 DUP3 PUSH1 0x1F DUP4 ADD SLT PUSH2 0x4E4 JUMPI DUP1 DUP2 REVERT JUMPDEST DUP2 CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0x4FA JUMPI DUP2 DUP3 REVERT JUMPDEST PUSH1 0x20 PUSH2 0x509 DUP2 DUP3 DUP5 MUL ADD PUSH2 0xADC JUMP JUMPDEST DUP3 DUP2 MSTORE SWAP3 POP DUP1 DUP4 ADD DUP5 DUP3 ADD PUSH1 0x0 JUMPDEST DUP5 DUP2 LT ISZERO PUSH2 0x540 JUMPI PUSH2 0x52E DUP9 DUP6 DUP5 CALLDATALOAD DUP11 ADD ADD PUSH2 0x54B JUMP JUMPDEST DUP4 MSTORE SWAP2 DUP4 ADD SWAP2 SWAP1 DUP4 ADD SWAP1 PUSH1 0x1 ADD PUSH2 0x517 JUMP JUMPDEST POP POP POP POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP3 PUSH1 0x1F DUP4 ADD SLT PUSH2 0x55B JUMPI DUP1 DUP2 REVERT JUMPDEST DUP2 CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0x571 JUMPI DUP2 DUP3 REVERT JUMPDEST PUSH2 0x5A2 PUSH1 0x20 PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0 PUSH1 0x1F DUP5 ADD AND ADD PUSH2 0xADC JUMP JUMPDEST SWAP2 POP DUP1 DUP3 MSTORE DUP4 PUSH1 0x20 DUP3 DUP6 ADD ADD GT ISZERO PUSH2 0x5B9 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP1 PUSH1 0x20 DUP5 ADD PUSH1 0x20 DUP5 ADD CALLDATACOPY PUSH1 0x0 SWAP1 DUP3 ADD PUSH1 0x20 ADD MSTORE SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x80 DUP3 DUP5 SUB SLT ISZERO PUSH2 0x5E3 JUMPI DUP1 DUP2 REVERT JUMPDEST PUSH2 0x5ED PUSH1 0x80 PUSH2 0xADC JUMP JUMPDEST SWAP1 POP PUSH1 0x0 DUP3 CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP1 DUP3 GT ISZERO PUSH2 0x608 JUMPI DUP3 DUP4 REVERT JUMPDEST PUSH2 0x614 DUP7 DUP4 DUP8 ADD PUSH2 0x54B JUMP JUMPDEST DUP5 MSTORE PUSH1 0x20 DUP6 ADD CALLDATALOAD SWAP2 POP PUSH4 0xFFFFFFFF DUP3 AND DUP3 EQ PUSH2 0x62E JUMPI DUP3 DUP4 REVERT JUMPDEST DUP2 PUSH1 0x20 DUP6 ADD MSTORE PUSH1 0x40 DUP6 ADD CALLDATALOAD SWAP2 POP DUP1 DUP3 GT ISZERO PUSH2 0x647 JUMPI DUP3 DUP4 REVERT JUMPDEST PUSH2 0x653 DUP7 DUP4 DUP8 ADD PUSH2 0x4D4 JUMP JUMPDEST PUSH1 0x40 DUP6 ADD MSTORE PUSH1 0x60 DUP6 ADD CALLDATALOAD SWAP2 POP DUP1 DUP3 GT ISZERO PUSH2 0x66B JUMPI DUP3 DUP4 REVERT JUMPDEST POP PUSH2 0x678 DUP6 DUP3 DUP7 ADD PUSH2 0x54B JUMP JUMPDEST PUSH1 0x60 DUP5 ADD MSTORE POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x0 DUP1 PUSH1 0x0 PUSH1 0xA0 DUP7 DUP9 SUB SLT ISZERO PUSH2 0x69D JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP6 CALLDATALOAD PUSH2 0x6A8 DUP2 PUSH2 0xB33 JUMP JUMPDEST SWAP5 POP PUSH1 0x20 DUP7 ADD CALLDATALOAD SWAP4 POP PUSH1 0x40 DUP7 ADD CALLDATALOAD SWAP3 POP PUSH1 0x60 DUP7 ADD CALLDATALOAD PUSH2 0x6C6 DUP2 PUSH2 0xB33 JUMP JUMPDEST SWAP5 SWAP8 SWAP4 SWAP7 POP SWAP2 SWAP5 PUSH1 0x80 ADD CALLDATALOAD SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 DUP5 SUB SLT ISZERO PUSH2 0x6E9 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0x700 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0x70C DUP5 DUP3 DUP6 ADD PUSH2 0x4D4 JUMP JUMPDEST SWAP5 SWAP4 POP POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x0 DUP1 PUSH1 0x80 DUP6 DUP8 SUB SLT ISZERO PUSH2 0x72A JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP5 CALLDATALOAD SWAP4 POP PUSH1 0x20 DUP6 ADD CALLDATALOAD PUSH1 0xFF DUP2 AND DUP2 EQ PUSH2 0x742 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST SWAP4 SWAP7 SWAP4 SWAP6 POP POP POP POP PUSH1 0x40 DUP3 ADD CALLDATALOAD SWAP2 PUSH1 0x60 ADD CALLDATALOAD SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 DUP5 SUB SLT ISZERO PUSH2 0x769 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0x780 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0x70C DUP5 DUP3 DUP6 ADD PUSH2 0x54B JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 DUP5 SUB SLT ISZERO PUSH2 0x79D JUMPI DUP1 DUP2 REVERT JUMPDEST DUP2 CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP1 DUP3 GT ISZERO PUSH2 0x7B4 JUMPI DUP3 DUP4 REVERT JUMPDEST DUP2 DUP5 ADD PUSH1 0x40 DUP2 DUP8 SUB SLT ISZERO PUSH2 0x7C6 JUMPI DUP4 DUP5 REVERT JUMPDEST PUSH2 0x7D0 PUSH1 0x40 PUSH2 0xADC JUMP JUMPDEST SWAP3 POP DUP1 CALLDATALOAD DUP3 DUP2 GT ISZERO PUSH2 0x7E0 JUMPI DUP5 DUP6 REVERT JUMPDEST PUSH2 0x7EC DUP8 DUP3 DUP5 ADD PUSH2 0x5D2 JUMP JUMPDEST DUP5 MSTORE POP PUSH1 0x20 DUP2 ADD CALLDATALOAD DUP3 DUP2 GT ISZERO PUSH2 0x800 JUMPI DUP5 DUP6 REVERT JUMPDEST PUSH2 0x80C DUP8 DUP3 DUP5 ADD PUSH2 0x54B JUMP JUMPDEST PUSH1 0x20 DUP6 ADD MSTORE POP SWAP2 SWAP6 SWAP5 POP POP POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 DUP5 SUB SLT ISZERO PUSH2 0x82E JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0x845 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0x70C DUP5 DUP3 DUP6 ADD PUSH2 0x5D2 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 DUP5 SUB SLT ISZERO PUSH2 0x863 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP CALLDATALOAD SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 DUP2 MLOAD DUP1 DUP5 MSTORE PUSH2 0x882 DUP2 PUSH1 0x20 DUP7 ADD PUSH1 0x20 DUP7 ADD PUSH2 0xB03 JUMP JUMPDEST PUSH1 0x1F ADD PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0 AND SWAP3 SWAP1 SWAP3 ADD PUSH1 0x20 ADD SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP2 MLOAD PUSH1 0x80 DUP5 MSTORE PUSH2 0x8C9 PUSH1 0x80 DUP6 ADD DUP3 PUSH2 0x86A JUMP JUMPDEST PUSH1 0x20 SWAP2 POP PUSH4 0xFFFFFFFF DUP3 DUP6 ADD MLOAD AND DUP3 DUP7 ADD MSTORE PUSH1 0x40 DUP5 ADD MLOAD DUP6 DUP3 SUB PUSH1 0x40 DUP8 ADD MSTORE DUP2 DUP2 MLOAD DUP1 DUP5 MSTORE DUP5 DUP5 ADD SWAP2 POP DUP5 DUP6 DUP3 MUL DUP6 ADD ADD DUP6 DUP5 ADD PUSH1 0x0 SWAP5 POP JUMPDEST DUP3 DUP6 LT ISZERO PUSH2 0x950 JUMPI PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0 DUP7 DUP4 SUB ADD DUP5 MSTORE PUSH2 0x93C DUP3 DUP3 MLOAD PUSH2 0x86A JUMP JUMPDEST PUSH1 0x1 SWAP6 SWAP1 SWAP6 ADD SWAP5 SWAP4 DUP8 ADD SWAP4 SWAP2 POP DUP7 ADD PUSH2 0x902 JUMP JUMPDEST POP PUSH1 0x60 DUP9 ADD MLOAD SWAP6 POP DUP9 DUP2 SUB PUSH1 0x60 DUP11 ADD MSTORE PUSH2 0x96A DUP2 DUP8 PUSH2 0x86A JUMP JUMPDEST SWAP10 SWAP9 POP POP POP POP POP POP POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP4 MLOAD PUSH2 0x989 DUP2 DUP5 PUSH1 0x20 DUP9 ADD PUSH2 0xB03 JUMP JUMPDEST SWAP2 SWAP1 SWAP2 ADD SWAP2 DUP3 MSTORE POP PUSH1 0x20 ADD SWAP2 SWAP1 POP JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF SWAP2 SWAP1 SWAP2 AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 JUMP JUMPDEST SWAP4 DUP5 MSTORE PUSH1 0xFF SWAP3 SWAP1 SWAP3 AND PUSH1 0x20 DUP5 ADD MSTORE PUSH1 0x40 DUP4 ADD MSTORE PUSH1 0x60 DUP3 ADD MSTORE PUSH1 0x80 ADD SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 MSTORE PUSH2 0x9EB PUSH1 0x20 DUP4 ADD DUP5 PUSH2 0x86A JUMP JUMPDEST SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x20 DUP1 DUP3 MSTORE PUSH1 0xD SWAP1 DUP3 ADD MSTORE PUSH32 0x53494D504C455F52455645525400000000000000000000000000000000000000 PUSH1 0x40 DUP3 ADD MSTORE PUSH1 0x60 ADD SWAP1 JUMP JUMPDEST PUSH1 0x20 DUP1 DUP3 MSTORE PUSH1 0xE SWAP1 DUP3 ADD MSTORE PUSH32 0x53494D504C455F52455155495245000000000000000000000000000000000000 PUSH1 0x40 DUP3 ADD MSTORE PUSH1 0x60 ADD SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 MSTORE DUP3 MLOAD PUSH1 0x40 PUSH1 0x20 DUP5 ADD MSTORE PUSH2 0xA7C PUSH1 0x60 DUP5 ADD DUP3 PUSH2 0x8B4 JUMP JUMPDEST PUSH1 0x20 DUP6 ADD MLOAD SWAP2 POP PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0 DUP5 DUP3 SUB ADD PUSH1 0x40 DUP6 ADD MSTORE PUSH2 0xAB7 DUP2 DUP4 PUSH2 0x86A JUMP JUMPDEST SWAP6 SWAP5 POP POP POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 MSTORE PUSH2 0x9EB PUSH1 0x20 DUP4 ADD DUP5 PUSH2 0x8B4 JUMP JUMPDEST SWAP1 DUP2 MSTORE PUSH1 0x20 ADD SWAP1 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP2 DUP2 ADD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT DUP3 DUP3 LT OR ISZERO PUSH2 0xAFB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x40 MSTORE SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xB1E JUMPI DUP2 DUP2 ADD MLOAD DUP4 DUP3 ADD MSTORE PUSH1 0x20 ADD PUSH2 0xB06 JUMP JUMPDEST DUP4 DUP2 GT ISZERO PUSH2 0xB2D JUMPI PUSH1 0x0 DUP5 DUP5 ADD MSTORE JUMPDEST POP POP POP POP JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP2 AND DUP2 EQ PUSH2 0x25F JUMPI PUSH1 0x0 DUP1 REVERT INVALID LOG3 PUSH6 0x627A7A723058 KECCAK256 DUP9 DUP16 MLOAD 0xdb DUP12 0xe2 0xb6 0x5e 0xeb LOG0 PUSH28 0x18B43CDC6DAD5D8E6807EB4AA7F11E06F111742AEF6C657870657269 PUSH14 0x656E74616CF564736F6C63430005 EXP STOP BLOCKHASH ", + "sourceMap": "641:2757:0:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;641:2757:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1496:107;;;:::i;:::-;;2581:63;;;;;;;;;:::i;1726:334::-;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;2419:52;;;;;;;1389:101;;;:::i;1286:97::-;;;:::i;3151:73::-;;;:::i;:::-;;;;;;;;1609:111;;;:::i;2214:166::-;;;;;;;;;:::i;2790:52::-;;;;;;;3250:72;;;:::i;:::-;;;;;;;;989:140;;;;;;;;;:::i;3327:69::-;;;:::i;862:121::-;;;:::i;3082:64::-;;;;;;;2924:63;;;:::i;:::-;;;;;;;;1135:145;;;:::i;1496:107::-;1564:32;;;;;;;;;;;;;;;;;;;2581:63;;:::o;1726:334::-;1837:21;1874:19;:56;;;;;;;;;;;;;;;;;;;1940:20;1990:6;1998:4;1973:30;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;1973:30:0;;;1963:41;;;;;;1940:64;;2021:32;2031:12;2045:1;2048;2051;2021:32;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;2021:32:0;;;;;;1726:334;-1:-1:-1;;;;;;;;1726:334:0:o;1389:101::-;1469:13;;;;;;;;;;;;;;;;1462:21;;;;;;;1469:13;1462:21;;;;1286:97;1353:23;;;;;;;;;;;3151:73;3201:19;;:::i;:::-;3151:73;:::o;1609:111::-;1698:14;;;;;;;;;;;;;;;;1683:30;;;;;;;1698:14;1683:30;;;;2214:166;-1:-1:-1;2372:1:0;;2214:166;-1:-1:-1;;;2214:166:0:o;3250:72::-;3290:4;3305:14;;3318:1;3305:14;;;;;3250:72;:::o;989:140::-;1117:1;:5;;989:140::o;3327:69::-;3379:9;:14;;3392:1;3379:14;;;3327:69::o;862:121::-;975:1;862:121;:::o;2924:63::-;2968:15;;:::i;1135:145::-;711:4;1135:145;:::o;641:2757::-;;;;;;;;;;;:::i;:::-;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;158:685:-1:-;;276:3;269:4;261:6;257:17;253:27;243:2;;-1:-1;;284:12;243:2;331:6;318:20;20177:18;20169:6;20166:30;20163:2;;;-1:-1;;20199:12;20163:2;20244:4;353:81;20307:4;20244;20236:6;20232:17;20297:15;353:81;;;462:21;;;344:90;-1:-1;519:14;;;494:17;;;614:1;599:238;624:6;621:1;618:13;599:238;;;731:42;769:3;506:4;707:3;694:17;498:6;682:30;;731:42;;;719:55;;788:14;;;;816;;;;646:1;639:9;599:238;;;603:14;;;;;236:607;;;;;1706:432;;1803:3;1796:4;1788:6;1784:17;1780:27;1770:2;;-1:-1;;1811:12;1770:2;1858:6;1845:20;20784:18;20776:6;20773:30;20770:2;;;-1:-1;;20806:12;20770:2;1880:60;20947:4;20879:9;1796:4;20864:6;20860:17;20856:33;20937:15;1880:60;;;1871:69;;1960:6;1953:5;1946:21;2064:3;20947:4;2055:6;1988;2046:16;;2043:25;2040:2;;;2081:1;;2071:12;2040:2;23898:6;20947:4;1988:6;1984:17;20947:4;2022:5;2018:16;23875:30;23954:1;23936:16;;;20947:4;23936:16;23929:27;2022:5;1763:375;-1:-1;;1763:375;3796:1071;;3904:4;3892:9;3887:3;3883:19;3879:30;3876:2;;;-1:-1;;3912:12;3876:2;3940:20;3904:4;3940:20;;;3931:29;;4043:1;4028:17;4015:31;4066:18;;4058:6;4055:30;4052:2;;;4098:1;4095;4088:12;4052:2;4132:54;4182:3;4173:6;4162:9;4158:22;4132:54;;;4115:15;4108:79;4253:2;4310:9;4306:22;6191:20;6182:29;;23705:10;24890:5;23694:22;24866:5;24863:34;24853:2;;24911:1;24908;24901:12;24853:2;4286:48;4253:2;4272:5;4268:16;4261:74;4440:2;4429:9;4425:18;4412:32;4398:46;;4464:18;4456:6;4453:30;4450:2;;;4496:1;4493;4486:12;4450:2;4531:75;4602:3;4593:6;4582:9;4578:22;4531:75;;;4440:2;4517:5;4513:16;4506:101;4699:2;4688:9;4684:18;4671:32;4657:46;;4723:18;4715:6;4712:30;4709:2;;;4755:1;4752;4745:12;4709:2;;4790:55;4841:3;4832:6;4821:9;4817:22;4790:55;;;4699:2;4776:5;4772:16;4765:81;;;3870:997;;;;;6393:743;;;;;;6565:3;6553:9;6544:7;6540:23;6536:33;6533:2;;;-1:-1;;6572:12;6533:2;85:6;72:20;97:33;124:5;97:33;;;6624:63;-1:-1;6724:2;6763:22;;6055:20;;-1:-1;6832:2;6871:22;;6055:20;;-1:-1;6940:2;6979:22;;72:20;97:33;72:20;97:33;;;6527:609;;;;-1:-1;6527:609;;7048:3;7088:22;6055:20;;6527:609;-1:-1;;6527:609;7143:387;;7277:2;7265:9;7256:7;7252:23;7248:32;7245:2;;;-1:-1;;7283:12;7245:2;7341:17;7328:31;7379:18;7371:6;7368:30;7365:2;;;-1:-1;;7401:12;7365:2;7431:83;7506:7;7497:6;7486:9;7482:22;7431:83;;;7421:93;7239:291;-1:-1;;;;7239:291;7537:613;;;;;7690:3;7678:9;7669:7;7665:23;7661:33;7658:2;;;-1:-1;;7697:12;7658:2;1648:6;1635:20;7749:63;;7849:2;7890:9;7886:22;6325:20;23799:4;25010:5;23788:16;24987:5;24984:33;24974:2;;-1:-1;;25021:12;24974:2;7652:498;;7857:61;;-1:-1;;;;7955:2;7994:22;;1635:20;;8063:2;8102:22;1635:20;;7652:498;8157:345;;8270:2;8258:9;8249:7;8245:23;8241:32;8238:2;;;-1:-1;;8276:12;8238:2;8334:17;8321:31;8372:18;8364:6;8361:30;8358:2;;;-1:-1;;8394:12;8358:2;8424:62;8478:7;8469:6;8458:9;8454:22;8424:62;;8509:385;;8642:2;8630:9;8621:7;8617:23;8613:32;8610:2;;;8658:1;8655;8648:12;8610:2;8706:17;8693:31;8744:18;;8736:6;8733:30;8730:2;;;8776:1;8773;8766:12;8730:2;8861:6;8850:9;8846:22;3194:4;3182:9;3177:3;3173:19;3169:30;3166:2;;;3212:1;3209;3202:12;3166:2;3230:20;3194:4;3230:20;;;3221:29;;3320:17;3307:31;3358:18;3350:6;3347:30;3344:2;;;3390:1;3387;3380:12;3344:2;3424:68;3488:3;3479:6;3468:9;3464:22;3424:68;;;3407:15;3400:93;;8642:2;3578:9;3574:18;3561:32;3613:18;3605:6;3602:30;3599:2;;;3645:1;3642;3635:12;3599:2;3680:55;3731:3;3722:6;3711:9;3707:22;3680:55;;;8642:2;3662:16;;3655:81;-1:-1;3666:5;;8604:290;-1:-1;;;;;8604:290;8901:373;;9028:2;9016:9;9007:7;9003:23;8999:32;8996:2;;;-1:-1;;9034:12;8996:2;9092:17;9079:31;9130:18;9122:6;9119:30;9116:2;;;-1:-1;;9152:12;9116:2;9182:76;9250:7;9241:6;9230:9;9226:22;9182:76;;9281:241;;9385:2;9373:9;9364:7;9360:23;9356:32;9353:2;;;-1:-1;;9391:12;9353:2;-1:-1;6055:20;;9347:175;-1:-1;9347:175;11364:315;;11488:5;21885:12;22545:6;22540:3;22533:19;11571:52;11616:6;22582:4;22577:3;22573:14;22582:4;11597:5;11593:16;11571:52;;;24416:2;24396:14;24412:7;24392:28;11635:39;;;;22582:4;11635:39;;11440:239;-1:-1;;11440:239;13930:1078;;14154:15;14148:22;14077:4;14190:13;14183:37;14235:67;14077:4;14072:3;14068:14;14283:12;14235:67;;;14392:4;;;23705:10;14392:4;14385:5;14381:16;14375:23;23694:22;14459:4;14454:3;14450:14;16326:36;14560:4;14553:5;14549:16;14543:23;14612:3;14606:4;14602:14;14560:4;14590:3;14586:14;14579:38;14632:109;10052:5;21885:12;22545:6;22540:3;22533:19;22582:4;22577:3;22573:14;10064:88;;14392:4;10217;10209:6;10205:17;22577:3;10196:27;;21747:4;10295:5;21738:14;-1:-1;10340:10;;10334:341;10359:6;10356:1;10353:13;10334:341;;;10411:20;22577:3;10415:4;10411:20;;10406:3;10399:33;9641:60;9697:3;10466:6;10460:13;9641:60;;;10381:1;10374:9;;;;;10654:14;;;;10480:82;-1:-1;22393:14;;10334:341;;;10338:14;14829:4;14822:5;14818:16;14812:23;14792:43;;14881:3;14875:4;14871:14;14829:4;14859:3;14855:14;14848:38;14901:69;14965:4;14951:12;14901:69;;;14992:11;14050:958;-1:-1;;;;;;;;;14050:958;16488:401;;11161:5;21885:12;11272:52;11317:6;11312:3;11305:4;11298:5;11294:16;11272:52;;;11336:16;;;;10793:37;;;-1:-1;11305:4;16852:12;;16641:248;-1:-1;16641:248;16896:213;23499:42;23488:54;;;;9786:37;;17014:2;16999:18;;16985:124;17116:539;10793:37;;;23799:4;23788:16;;;;17475:2;17460:18;;16441:35;17558:2;17543:18;;10793:37;17641:2;17626:18;;10793:37;17314:3;17299:19;;17285:370;17662:293;;17796:2;17817:17;17810:47;17871:74;17796:2;17785:9;17781:18;17931:6;17871:74;;;17863:82;17767:188;-1:-1;;;17767:188;17962:407;18153:2;18167:47;;;12583:2;18138:18;;;22533:19;12619:66;22573:14;;;12599:87;12705:12;;;18124:245;18376:407;18567:2;18581:47;;;12956:2;18552:18;;;22533:19;12992:66;22573:14;;;12972:87;13078:12;;;18538:245;18790:377;;18966:2;18987:17;18980:47;13415:15;13409:22;13336:4;18966:2;18955:9;18951:18;13444:37;13496:95;13327:14;18955:9;13327:14;13572:12;13496:95;;;18966:2;13676:5;13672:16;13666:23;13646:43;;13725:14;18955:9;13729:4;13725:14;;13336:4;18955:9;13709:14;13702:38;13755:69;13819:4;13805:12;13755:69;;;19033:124;18937:230;-1:-1;;;;;18937:230;19174:353;;19338:2;19359:17;19352:47;19413:104;19338:2;19327:9;19323:18;19503:6;19413:104;;19534:213;10793:37;;;19652:2;19637:18;;19623:124;19754:256;19816:2;19810:9;19842:17;;;19917:18;19902:34;;19938:22;;;19899:62;19896:2;;;19974:1;;19964:12;19896:2;19816;19983:22;19794:216;;-1:-1;19794:216;23971:268;24036:1;24043:101;24057:6;24054:1;24051:13;24043:101;;;24124:11;;;24118:18;24105:11;;;24098:39;24079:2;24072:10;24043:101;;;24159:6;24156:1;24153:13;24150:2;;;24036:1;24215:6;24210:3;24206:16;24199:27;24150:2;;24020:219;;;;24433:117;23499:42;24520:5;23488:54;24495:5;24492:35;24482:2;;24541:1;;24531:12" + } + } + }, + "sources": { + "AbiGenDummy.sol": { + "id": 0 + } + }, + "sourceCodes": { + "AbiGenDummy.sol": "/*\n\n Copyright 2018 ZeroEx Intl.\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n*/\n\npragma experimental ABIEncoderV2;\n\npragma solidity ^0.5.5;\n\n\ncontract AbiGenDummy\n{\n\n uint256 constant internal SOME_CONSTANT = 1234;\n string constant internal REVERT_REASON = \"REVERT_WITH_CONSTANT\";\n string constant internal REQUIRE_REASON = \"REQUIRE_WITH_CONSTANT\";\n\n function simplePureFunction ()\n public\n pure\n returns (uint256 result)\n {\n return 1;\n }\n\n function simplePureFunctionWithInput (uint256 x)\n public\n pure\n returns (uint256 sum)\n {\n return 1 + x;\n }\n\n function pureFunctionWithConstant ()\n public\n pure\n returns (uint256 someConstant)\n {\n return SOME_CONSTANT;\n }\n\n function simpleRevert ()\n public\n pure\n {\n revert(\"SIMPLE_REVERT\");\n }\n\n function revertWithConstant ()\n public\n pure\n {\n revert(REVERT_REASON);\n }\n\n function simpleRequire ()\n public\n pure\n {\n require(0 > 1, \"SIMPLE_REQUIRE\");\n }\n\n function requireWithConstant ()\n public\n pure\n {\n require(0 > 1, REQUIRE_REASON);\n }\n\n function ecrecoverFn(bytes32 hash, uint8 v, bytes32 r, bytes32 s)\n public\n pure\n returns (address signerAddress)\n {\n bytes memory prefix = \"\\x19Ethereum Signed Message:\\n32\";\n bytes32 prefixedHash = keccak256(abi.encodePacked(prefix, hash));\n return ecrecover(prefixedHash, v, r, s);\n }\n\n // test: generated code should normalize address inputs to lowercase\n // add extra inputs to make sure it works with address in any position\n function withAddressInput(address x, uint256 a, uint256 b, address y, uint256 c)\n public\n pure\n returns (address z)\n {\n return x;\n }\n\n event AnEvent(uint8 param);\n\n function acceptsBytes(bytes memory a) public pure {}\n\n /// @dev a method that accepts an array of bytes\n /// @param a the array of bytes being accepted\n function acceptsAnArrayOfBytes(bytes[] memory a) public pure {}\n\n struct Struct {\n bytes someBytes;\n uint32 anInteger;\n bytes[] aDynamicArrayOfBytes;\n string aString;\n }\n\n function structInput(Struct memory s) public pure {}\n\n /// @dev a method that returns a struct\n /// @return a Struct struct\n function structOutput() public pure returns(Struct memory s) {}\n\n struct NestedStruct {\n Struct innerStruct;\n string description;\n }\n\n function nestedStructInput(NestedStruct memory n) public pure {}\n function nestedStructOutput() public pure returns(NestedStruct memory) {}\n\n uint someState;\n function nonPureMethod() public returns(uint) { return someState += 1; }\n function nonPureMethodThatReturnsNothing() public { someState += 1; }\n}\n" + }, + "sourceTreeHashHex": "0xafbcbb2a469a1062791f49abdf3076b97d06d1994fbaf9f07f46a4fe95e07880", + "compiler": { + "name": "solc", + "version": "soljson-v0.5.10+commit.5a6ea5b1.js", + "settings": { + "optimizer": { + "enabled": true, + "runs": 1000000, + "details": { + "yul": true, + "deduplicate": true, + "cse": true, + "constantOptimizer": true + } + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode.object", + "evm.bytecode.sourceMap", + "evm.deployedBytecode.object", + "evm.deployedBytecode.sourceMap", + "devdoc" + ] + } + }, + "evmVersion": "constantinople", + "remappings": [] + } + }, + "networks": {} +} \ No newline at end of file diff --git a/packages/abi-gen/test-cli/fixtures/artifacts/LibDummy.json b/packages/abi-gen/test-cli/fixtures/artifacts/LibDummy.json index 172ac7deb0..0c12f88e2d 100644 --- a/packages/abi-gen/test-cli/fixtures/artifacts/LibDummy.json +++ b/packages/abi-gen/test-cli/fixtures/artifacts/LibDummy.json @@ -1,60 +1,64 @@ { - "schemaVersion": "2.0.0", - "contractName": "LibDummy", - "compilerOutput": { - "abi": [], - "evm": { - "bytecode": { - "linkReferences": {}, - "object": "0x60556023600b82828239805160001a607314601657fe5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea265627a7a72305820a278ce8d53a26107b2f2ba78687fa040ee9ab2ecf0e44ebff0f9410c586e0c6d64736f6c634300050a0032", - "opcodes": "PUSH1 0x55 PUSH1 0x23 PUSH1 0xB DUP3 DUP3 DUP3 CODECOPY DUP1 MLOAD PUSH1 0x0 BYTE PUSH1 0x73 EQ PUSH1 0x16 JUMPI INVALID JUMPDEST ADDRESS PUSH1 0x0 MSTORE PUSH1 0x73 DUP2 MSTORE8 DUP3 DUP2 RETURN INVALID PUSH20 0x0 ADDRESS EQ PUSH1 0x80 PUSH1 0x40 MSTORE PUSH1 0x0 DUP1 REVERT INVALID LOG2 PUSH6 0x627A7A723058 KECCAK256 LOG2 PUSH25 0xCE8D53A26107B2F2BA78687FA040EE9AB2ECF0E44EBFF0F941 0xc PC PUSH15 0xC6D64736F6C634300050A00320000 ", - "sourceMap": "606:385:1:-;;132:2:-1;166:7;155:9;146:7;137:37;255:7;249:14;246:1;241:23;235:4;232:33;222:2;;269:9;222:2;293:9;290:1;283:20;323:4;314:7;306:22;347:7;338;331:24" - }, - "deployedBytecode": { - "linkReferences": {}, - "object": "0x73000000000000000000000000000000000000000030146080604052600080fdfea265627a7a72305820a278ce8d53a26107b2f2ba78687fa040ee9ab2ecf0e44ebff0f9410c586e0c6d64736f6c634300050a0032", - "opcodes": "PUSH20 0x0 ADDRESS EQ PUSH1 0x80 PUSH1 0x40 MSTORE PUSH1 0x0 DUP1 REVERT INVALID LOG2 PUSH6 0x627A7A723058 KECCAK256 LOG2 PUSH25 0xCE8D53A26107B2F2BA78687FA040EE9AB2ECF0E44EBFF0F941 0xc PC PUSH15 0xC6D64736F6C634300050A00320000 ", - "sourceMap": "606:385:1:-;;;;;;;;" - } - } - }, - "sources": { - "LibDummy.sol": { - "id": 1 - } - }, - "sourceCodes": { - "LibDummy.sol": "/*\n\n Copyright 2018 ZeroEx Intl.\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n*/\n\npragma solidity ^0.5.5;\n\n\nlibrary LibDummy {\n\n using LibDummy for uint256;\n uint256 constant internal SOME_CONSTANT = 1234;\n\n function addOne (uint256 x)\n internal\n pure\n returns (uint256 sum)\n {\n return x + 1;\n }\n\n function addConstant (uint256 x)\n internal\n pure\n returns (uint256 someConstant)\n {\n return x + SOME_CONSTANT;\n }\n}\n" - }, - "sourceTreeHashHex": "0xe9654f3d694bd3513dddbcc0ccd7a75739bf63dc92b974e163f191122416fdb6", - "compiler": { - "name": "solc", - "version": "soljson-v0.5.10+commit.5a6ea5b1.js", - "settings": { - "optimizer": { - "enabled": true, - "runs": 1000000, - "details": { - "yul": true, - "deduplicate": true, - "cse": true, - "constantOptimizer": true - } - }, - "outputSelection": { - "*": { - "*": [ - "abi", - "evm.bytecode.object", - "evm.bytecode.sourceMap", - "evm.deployedBytecode.object", - "evm.deployedBytecode.sourceMap" - ] - } - }, - "evmVersion": "constantinople", - "remappings": [] - } - }, - "networks": {} -} + "schemaVersion": "2.0.0", + "contractName": "LibDummy", + "compilerOutput": { + "abi": [], + "devdoc": { + "methods": {} + }, + "evm": { + "bytecode": { + "linkReferences": {}, + "object": "0x60556023600b82828239805160001a607314601657fe5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea265627a7a72305820b14322cd05aa1dcae66812e472d3ab85cced78118ea7f9a5098d073b2accc45964736f6c634300050a0032", + "opcodes": "PUSH1 0x55 PUSH1 0x23 PUSH1 0xB DUP3 DUP3 DUP3 CODECOPY DUP1 MLOAD PUSH1 0x0 BYTE PUSH1 0x73 EQ PUSH1 0x16 JUMPI INVALID JUMPDEST ADDRESS PUSH1 0x0 MSTORE PUSH1 0x73 DUP2 MSTORE8 DUP3 DUP2 RETURN INVALID PUSH20 0x0 ADDRESS EQ PUSH1 0x80 PUSH1 0x40 MSTORE PUSH1 0x0 DUP1 REVERT INVALID LOG2 PUSH6 0x627A7A723058 KECCAK256 0xb1 NUMBER 0x22 0xcd SDIV 0xaa SAR 0xca 0xe6 PUSH9 0x12E472D3AB85CCED78 GT DUP15 0xa7 0xf9 0xa5 MULMOD DUP14 SMOD EXTCODESIZE 0x2a 0xcc 0xc4 MSIZE PUSH5 0x736F6C6343 STOP SDIV EXP STOP ORIGIN ", + "sourceMap": "606:385:1:-;;132:2:-1;166:7;155:9;146:7;137:37;255:7;249:14;246:1;241:23;235:4;232:33;222:2;;269:9;222:2;293:9;290:1;283:20;323:4;314:7;306:22;347:7;338;331:24" + }, + "deployedBytecode": { + "linkReferences": {}, + "object": "0x73000000000000000000000000000000000000000030146080604052600080fdfea265627a7a72305820b14322cd05aa1dcae66812e472d3ab85cced78118ea7f9a5098d073b2accc45964736f6c634300050a0032", + "opcodes": "PUSH20 0x0 ADDRESS EQ PUSH1 0x80 PUSH1 0x40 MSTORE PUSH1 0x0 DUP1 REVERT INVALID LOG2 PUSH6 0x627A7A723058 KECCAK256 0xb1 NUMBER 0x22 0xcd SDIV 0xaa SAR 0xca 0xe6 PUSH9 0x12E472D3AB85CCED78 GT DUP15 0xa7 0xf9 0xa5 MULMOD DUP14 SMOD EXTCODESIZE 0x2a 0xcc 0xc4 MSIZE PUSH5 0x736F6C6343 STOP SDIV EXP STOP ORIGIN ", + "sourceMap": "606:385:1:-;;;;;;;;" + } + } + }, + "sources": { + "LibDummy.sol": { + "id": 1 + } + }, + "sourceCodes": { + "LibDummy.sol": "/*\n\n Copyright 2018 ZeroEx Intl.\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n*/\n\npragma solidity ^0.5.5;\n\n\nlibrary LibDummy {\n\n using LibDummy for uint256;\n uint256 constant internal SOME_CONSTANT = 1234;\n\n function addOne (uint256 x)\n internal\n pure\n returns (uint256 sum)\n {\n return x + 1;\n }\n\n function addConstant (uint256 x)\n internal\n pure\n returns (uint256 someConstant)\n {\n return x + SOME_CONSTANT;\n }\n}\n" + }, + "sourceTreeHashHex": "0xe9654f3d694bd3513dddbcc0ccd7a75739bf63dc92b974e163f191122416fdb6", + "compiler": { + "name": "solc", + "version": "soljson-v0.5.10+commit.5a6ea5b1.js", + "settings": { + "optimizer": { + "enabled": true, + "runs": 1000000, + "details": { + "yul": true, + "deduplicate": true, + "cse": true, + "constantOptimizer": true + } + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode.object", + "evm.bytecode.sourceMap", + "evm.deployedBytecode.object", + "evm.deployedBytecode.sourceMap", + "devdoc" + ] + } + }, + "evmVersion": "constantinople", + "remappings": [] + } + }, + "networks": {} +} \ No newline at end of file diff --git a/packages/abi-gen/test-cli/fixtures/artifacts/TestLibDummy.json b/packages/abi-gen/test-cli/fixtures/artifacts/TestLibDummy.json index f397efabb7..a91c32998a 100644 --- a/packages/abi-gen/test-cli/fixtures/artifacts/TestLibDummy.json +++ b/packages/abi-gen/test-cli/fixtures/artifacts/TestLibDummy.json @@ -1,103 +1,107 @@ { - "schemaVersion": "2.0.0", - "contractName": "TestLibDummy", - "compilerOutput": { - "abi": [ - { - "constant": true, - "inputs": [ - { - "name": "x", - "type": "uint256" - } - ], - "name": "publicAddConstant", - "outputs": [ - { - "name": "result", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "pure", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "x", - "type": "uint256" - } - ], - "name": "publicAddOne", - "outputs": [ - { - "name": "result", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "pure", - "type": "function" - } - ], - "evm": { - "bytecode": { - "linkReferences": {}, - "object": "0x608060405234801561001057600080fd5b5060d78061001f6000396000f3fe6080604052348015600f57600080fd5b506004361060325760003560e01c806322935e921460375780632b82fdf0146063575b600080fd5b605160048036036020811015604b57600080fd5b5035607d565b60408051918252519081900360200190f35b605160048036036020811015607757600080fd5b5035608c565b60006086826095565b92915050565b6000608682609c565b6104d20190565b6001019056fea265627a7a72305820c97345939b2d163165dee7bdfbbd7ca281c5bdaea7b03de53b0ceb32b097cdf864736f6c634300050a0032", - "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0xD7 DUP1 PUSH2 0x1F PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN INVALID PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH1 0xF JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x4 CALLDATASIZE LT PUSH1 0x32 JUMPI PUSH1 0x0 CALLDATALOAD PUSH1 0xE0 SHR DUP1 PUSH4 0x22935E92 EQ PUSH1 0x37 JUMPI DUP1 PUSH4 0x2B82FDF0 EQ PUSH1 0x63 JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x51 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x20 DUP2 LT ISZERO PUSH1 0x4B JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP CALLDATALOAD PUSH1 0x7D JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD SWAP2 DUP3 MSTORE MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x20 ADD SWAP1 RETURN JUMPDEST PUSH1 0x51 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x20 DUP2 LT ISZERO PUSH1 0x77 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP CALLDATALOAD PUSH1 0x8C JUMP JUMPDEST PUSH1 0x0 PUSH1 0x86 DUP3 PUSH1 0x95 JUMP JUMPDEST SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x86 DUP3 PUSH1 0x9C JUMP JUMPDEST PUSH2 0x4D2 ADD SWAP1 JUMP JUMPDEST PUSH1 0x1 ADD SWAP1 JUMP INVALID LOG2 PUSH6 0x627A7A723058 KECCAK256 0xc9 PUSH20 0x45939B2D163165DEE7BDFBBD7CA281C5BDAEA7B0 RETURNDATASIZE 0xe5 EXTCODESIZE 0xc 0xeb ORIGIN 0xb0 SWAP8 0xcd 0xf8 PUSH5 0x736F6C6343 STOP SDIV EXP STOP ORIGIN ", - "sourceMap": "632:346:2:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;632:346:2;;;;;;;" - }, - "deployedBytecode": { - "linkReferences": {}, - "object": "0x6080604052348015600f57600080fd5b506004361060325760003560e01c806322935e921460375780632b82fdf0146063575b600080fd5b605160048036036020811015604b57600080fd5b5035607d565b60408051918252519081900360200190f35b605160048036036020811015607757600080fd5b5035608c565b60006086826095565b92915050565b6000608682609c565b6104d20190565b6001019056fea265627a7a72305820c97345939b2d163165dee7bdfbbd7ca281c5bdaea7b03de53b0ceb32b097cdf864736f6c634300050a0032", - "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH1 0xF JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x4 CALLDATASIZE LT PUSH1 0x32 JUMPI PUSH1 0x0 CALLDATALOAD PUSH1 0xE0 SHR DUP1 PUSH4 0x22935E92 EQ PUSH1 0x37 JUMPI DUP1 PUSH4 0x2B82FDF0 EQ PUSH1 0x63 JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x51 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x20 DUP2 LT ISZERO PUSH1 0x4B JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP CALLDATALOAD PUSH1 0x7D JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD SWAP2 DUP3 MSTORE MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x20 ADD SWAP1 RETURN JUMPDEST PUSH1 0x51 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x20 DUP2 LT ISZERO PUSH1 0x77 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP CALLDATALOAD PUSH1 0x8C JUMP JUMPDEST PUSH1 0x0 PUSH1 0x86 DUP3 PUSH1 0x95 JUMP JUMPDEST SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x86 DUP3 PUSH1 0x9C JUMP JUMPDEST PUSH2 0x4D2 ADD SWAP1 JUMP JUMPDEST PUSH1 0x1 ADD SWAP1 JUMP INVALID LOG2 PUSH6 0x627A7A723058 KECCAK256 0xc9 PUSH20 0x45939B2D163165DEE7BDFBBD7CA281C5BDAEA7B0 RETURNDATASIZE 0xe5 EXTCODESIZE 0xc 0xeb ORIGIN 0xb0 SWAP8 0xcd 0xf8 PUSH5 0x736F6C6343 STOP SDIV EXP STOP ORIGIN ", - "sourceMap": "632:346:2:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;632:346:2;;;;;;;;;;;;;;;;;;;;;;;;833:143;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;833:143:2;;:::i;:::-;;;;;;;;;;;;;;;;694:133;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;694:133:2;;:::i;833:143::-;917:14;954:15;:1;:13;:15::i;:::-;947:22;833:143;-1:-1:-1;;833:143:2:o;694:133::-;773:14;810:10;:1;:8;:10::i;842:147:1:-;704:4;965:17;;842:147::o;715:121::-;828:1;824:5;;715:121::o" - } - } - }, - "sources": { - "TestLibDummy.sol": { - "id": 2 - }, - "LibDummy.sol": { - "id": 1 - } - }, - "sourceCodes": { - "TestLibDummy.sol": "/*\n\n Copyright 2018 ZeroEx Intl.\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n*/\n\npragma solidity ^0.5.5;\n\nimport \"./LibDummy.sol\";\n\n\ncontract TestLibDummy {\n\n using LibDummy for uint256;\n\n function publicAddOne (uint256 x)\n public\n pure\n returns (uint256 result)\n {\n return x.addOne();\n }\n\n function publicAddConstant (uint256 x)\n public\n pure\n returns (uint256 result)\n {\n return x.addConstant();\n }\n}\n", - "LibDummy.sol": "/*\n\n Copyright 2018 ZeroEx Intl.\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n*/\n\npragma solidity ^0.5.5;\n\n\nlibrary LibDummy {\n\n using LibDummy for uint256;\n uint256 constant internal SOME_CONSTANT = 1234;\n\n function addOne (uint256 x)\n internal\n pure\n returns (uint256 sum)\n {\n return x + 1;\n }\n\n function addConstant (uint256 x)\n internal\n pure\n returns (uint256 someConstant)\n {\n return x + SOME_CONSTANT;\n }\n}\n" - }, - "sourceTreeHashHex": "0xca99c7d7de9db975842de61e6ec01debdada66cf91d28fc3f2983de3011560dc", - "compiler": { - "name": "solc", - "version": "soljson-v0.5.10+commit.5a6ea5b1.js", - "settings": { - "optimizer": { - "enabled": true, - "runs": 1000000, - "details": { - "yul": true, - "deduplicate": true, - "cse": true, - "constantOptimizer": true - } - }, - "outputSelection": { - "*": { - "*": [ - "abi", - "evm.bytecode.object", - "evm.bytecode.sourceMap", - "evm.deployedBytecode.object", - "evm.deployedBytecode.sourceMap" - ] - } - }, - "evmVersion": "constantinople", - "remappings": [] - } - }, - "networks": {} -} + "schemaVersion": "2.0.0", + "contractName": "TestLibDummy", + "compilerOutput": { + "abi": [ + { + "constant": true, + "inputs": [ + { + "name": "x", + "type": "uint256" + } + ], + "name": "publicAddConstant", + "outputs": [ + { + "name": "result", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "pure", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "x", + "type": "uint256" + } + ], + "name": "publicAddOne", + "outputs": [ + { + "name": "result", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "pure", + "type": "function" + } + ], + "devdoc": { + "methods": {} + }, + "evm": { + "bytecode": { + "linkReferences": {}, + "object": "0x608060405234801561001057600080fd5b5060d78061001f6000396000f3fe6080604052348015600f57600080fd5b506004361060325760003560e01c806322935e921460375780632b82fdf0146063575b600080fd5b605160048036036020811015604b57600080fd5b5035607d565b60408051918252519081900360200190f35b605160048036036020811015607757600080fd5b5035608c565b60006086826095565b92915050565b6000608682609c565b6104d20190565b6001019056fea265627a7a72305820ddb720d14b34694daaefebcbd729af6ae04fa2232481812dd8fde63d6a4c32c164736f6c634300050a0032", + "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0xD7 DUP1 PUSH2 0x1F PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN INVALID PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH1 0xF JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x4 CALLDATASIZE LT PUSH1 0x32 JUMPI PUSH1 0x0 CALLDATALOAD PUSH1 0xE0 SHR DUP1 PUSH4 0x22935E92 EQ PUSH1 0x37 JUMPI DUP1 PUSH4 0x2B82FDF0 EQ PUSH1 0x63 JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x51 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x20 DUP2 LT ISZERO PUSH1 0x4B JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP CALLDATALOAD PUSH1 0x7D JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD SWAP2 DUP3 MSTORE MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x20 ADD SWAP1 RETURN JUMPDEST PUSH1 0x51 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x20 DUP2 LT ISZERO PUSH1 0x77 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP CALLDATALOAD PUSH1 0x8C JUMP JUMPDEST PUSH1 0x0 PUSH1 0x86 DUP3 PUSH1 0x95 JUMP JUMPDEST SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x86 DUP3 PUSH1 0x9C JUMP JUMPDEST PUSH2 0x4D2 ADD SWAP1 JUMP JUMPDEST PUSH1 0x1 ADD SWAP1 JUMP INVALID LOG2 PUSH6 0x627A7A723058 KECCAK256 0xdd 0xb7 KECCAK256 0xd1 0x4b CALLVALUE PUSH10 0x4DAAEFEBCBD729AF6AE0 0x4f LOG2 0x23 0x24 DUP2 DUP2 0x2d 0xd8 REVERT 0xe6 RETURNDATASIZE PUSH11 0x4C32C164736F6C63430005 EXP STOP ORIGIN ", + "sourceMap": "632:346:2:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;632:346:2;;;;;;;" + }, + "deployedBytecode": { + "linkReferences": {}, + "object": "0x6080604052348015600f57600080fd5b506004361060325760003560e01c806322935e921460375780632b82fdf0146063575b600080fd5b605160048036036020811015604b57600080fd5b5035607d565b60408051918252519081900360200190f35b605160048036036020811015607757600080fd5b5035608c565b60006086826095565b92915050565b6000608682609c565b6104d20190565b6001019056fea265627a7a72305820ddb720d14b34694daaefebcbd729af6ae04fa2232481812dd8fde63d6a4c32c164736f6c634300050a0032", + "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH1 0xF JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x4 CALLDATASIZE LT PUSH1 0x32 JUMPI PUSH1 0x0 CALLDATALOAD PUSH1 0xE0 SHR DUP1 PUSH4 0x22935E92 EQ PUSH1 0x37 JUMPI DUP1 PUSH4 0x2B82FDF0 EQ PUSH1 0x63 JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x51 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x20 DUP2 LT ISZERO PUSH1 0x4B JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP CALLDATALOAD PUSH1 0x7D JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD SWAP2 DUP3 MSTORE MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x20 ADD SWAP1 RETURN JUMPDEST PUSH1 0x51 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x20 DUP2 LT ISZERO PUSH1 0x77 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP CALLDATALOAD PUSH1 0x8C JUMP JUMPDEST PUSH1 0x0 PUSH1 0x86 DUP3 PUSH1 0x95 JUMP JUMPDEST SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x86 DUP3 PUSH1 0x9C JUMP JUMPDEST PUSH2 0x4D2 ADD SWAP1 JUMP JUMPDEST PUSH1 0x1 ADD SWAP1 JUMP INVALID LOG2 PUSH6 0x627A7A723058 KECCAK256 0xdd 0xb7 KECCAK256 0xd1 0x4b CALLVALUE PUSH10 0x4DAAEFEBCBD729AF6AE0 0x4f LOG2 0x23 0x24 DUP2 DUP2 0x2d 0xd8 REVERT 0xe6 RETURNDATASIZE PUSH11 0x4C32C164736F6C63430005 EXP STOP ORIGIN ", + "sourceMap": "632:346:2:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;632:346:2;;;;;;;;;;;;;;;;;;;;;;;;833:143;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;833:143:2;;:::i;:::-;;;;;;;;;;;;;;;;694:133;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;694:133:2;;:::i;833:143::-;917:14;954:15;:1;:13;:15::i;:::-;947:22;833:143;-1:-1:-1;;833:143:2:o;694:133::-;773:14;810:10;:1;:8;:10::i;842:147:1:-;704:4;965:17;;842:147::o;715:121::-;828:1;824:5;;715:121::o" + } + } + }, + "sources": { + "TestLibDummy.sol": { + "id": 2 + }, + "LibDummy.sol": { + "id": 1 + } + }, + "sourceCodes": { + "TestLibDummy.sol": "/*\n\n Copyright 2018 ZeroEx Intl.\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n*/\n\npragma solidity ^0.5.5;\n\nimport \"./LibDummy.sol\";\n\n\ncontract TestLibDummy {\n\n using LibDummy for uint256;\n\n function publicAddOne (uint256 x)\n public\n pure\n returns (uint256 result)\n {\n return x.addOne();\n }\n\n function publicAddConstant (uint256 x)\n public\n pure\n returns (uint256 result)\n {\n return x.addConstant();\n }\n}\n", + "LibDummy.sol": "/*\n\n Copyright 2018 ZeroEx Intl.\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n*/\n\npragma solidity ^0.5.5;\n\n\nlibrary LibDummy {\n\n using LibDummy for uint256;\n uint256 constant internal SOME_CONSTANT = 1234;\n\n function addOne (uint256 x)\n internal\n pure\n returns (uint256 sum)\n {\n return x + 1;\n }\n\n function addConstant (uint256 x)\n internal\n pure\n returns (uint256 someConstant)\n {\n return x + SOME_CONSTANT;\n }\n}\n" + }, + "sourceTreeHashHex": "0xca99c7d7de9db975842de61e6ec01debdada66cf91d28fc3f2983de3011560dc", + "compiler": { + "name": "solc", + "version": "soljson-v0.5.10+commit.5a6ea5b1.js", + "settings": { + "optimizer": { + "enabled": true, + "runs": 1000000, + "details": { + "yul": true, + "deduplicate": true, + "cse": true, + "constantOptimizer": true + } + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode.object", + "evm.bytecode.sourceMap", + "evm.deployedBytecode.object", + "evm.deployedBytecode.sourceMap", + "devdoc" + ] + } + }, + "evmVersion": "constantinople", + "remappings": [] + } + }, + "networks": {} +} \ No newline at end of file diff --git a/packages/abi-gen/test-cli/fixtures/contracts/AbiGenDummy.sol b/packages/abi-gen/test-cli/fixtures/contracts/AbiGenDummy.sol index 1c64410845..d5fb6250b2 100644 --- a/packages/abi-gen/test-cli/fixtures/contracts/AbiGenDummy.sol +++ b/packages/abi-gen/test-cli/fixtures/contracts/AbiGenDummy.sol @@ -16,6 +16,8 @@ */ +pragma experimental ABIEncoderV2; + pragma solidity ^0.5.5; @@ -98,4 +100,36 @@ contract AbiGenDummy return x; } + event AnEvent(uint8 param); + + function acceptsBytes(bytes memory a) public pure {} + + /// @dev a method that accepts an array of bytes + /// @param a the array of bytes being accepted + function acceptsAnArrayOfBytes(bytes[] memory a) public pure {} + + struct Struct { + bytes someBytes; + uint32 anInteger; + bytes[] aDynamicArrayOfBytes; + string aString; + } + + function structInput(Struct memory s) public pure {} + + /// @dev a method that returns a struct + /// @return a Struct struct + function structOutput() public pure returns(Struct memory s) {} + + struct NestedStruct { + Struct innerStruct; + string description; + } + + function nestedStructInput(NestedStruct memory n) public pure {} + function nestedStructOutput() public pure returns(NestedStruct memory) {} + + uint someState; + function nonPureMethod() public returns(uint) { return someState += 1; } + function nonPureMethodThatReturnsNothing() public { someState += 1; } } diff --git a/packages/contract-wrappers/CHANGELOG.json b/packages/contract-wrappers/CHANGELOG.json index 09fa6f929b..23c6967531 100644 --- a/packages/contract-wrappers/CHANGELOG.json +++ b/packages/contract-wrappers/CHANGELOG.json @@ -1,4 +1,13 @@ [ + { + "version": "9.1.8", + "changes": [ + { + "note": "re-export new ethereum-types type, TupleDataItem", + "pr": 1919 + } + ] + }, { "timestamp": 1563193019, "version": "9.1.7", diff --git a/packages/contract-wrappers/src/index.ts b/packages/contract-wrappers/src/index.ts index f179df21f9..2c9f869392 100644 --- a/packages/contract-wrappers/src/index.ts +++ b/packages/contract-wrappers/src/index.ts @@ -105,6 +105,7 @@ export { ConstructorAbi, FallbackAbi, DataItem, + TupleDataItem, ConstructorStateMutability, StateMutability, Web3JsProvider, diff --git a/packages/ethereum-types/CHANGELOG.json b/packages/ethereum-types/CHANGELOG.json index 461bd38714..ebdf3668ee 100644 --- a/packages/ethereum-types/CHANGELOG.json +++ b/packages/ethereum-types/CHANGELOG.json @@ -1,4 +1,13 @@ [ + { + "version": "2.1.4", + "changes": [ + { + "note": "new interface TupleDataItem, a DataItem that definitely has a `components` field", + "pr": 1919 + } + ] + }, { "version": "2.1.3", "changes": [ diff --git a/packages/ethereum-types/src/index.ts b/packages/ethereum-types/src/index.ts index 74b1717274..e49c945dd4 100644 --- a/packages/ethereum-types/src/index.ts +++ b/packages/ethereum-types/src/index.ts @@ -131,6 +131,10 @@ export interface DataItem { components?: DataItem[]; } +export interface TupleDataItem extends DataItem { + components: DataItem[]; +} + export enum OpCode { // 0s: Stop and Arithmetic Operations Stop = 'STOP', diff --git a/packages/json-schemas/CHANGELOG.json b/packages/json-schemas/CHANGELOG.json index 827c8e9ae7..031664fdcb 100644 --- a/packages/json-schemas/CHANGELOG.json +++ b/packages/json-schemas/CHANGELOG.json @@ -1,4 +1,12 @@ [ + { + "version": "3.1.11", + "changes": [ + { + "note": "permit mixed-case addresses" + } + ] + }, { "timestamp": 1563006338, "version": "3.0.11", diff --git a/packages/json-schemas/schemas/address_schema.json b/packages/json-schemas/schemas/address_schema.json index 0dc02d3313..db49edc557 100644 --- a/packages/json-schemas/schemas/address_schema.json +++ b/packages/json-schemas/schemas/address_schema.json @@ -1,5 +1,5 @@ { "id": "/addressSchema", "type": "string", - "pattern": "^0x[0-9a-f]{40}$" + "pattern": "^0x[0-9a-fA-F]{40}$" } diff --git a/packages/json-schemas/test/schema_test.ts b/packages/json-schemas/test/schema_test.ts index bfa2c56686..dfab7f457a 100644 --- a/packages/json-schemas/test/schema_test.ts +++ b/packages/json-schemas/test/schema_test.ts @@ -91,13 +91,7 @@ describe('Schema', () => { validateAgainstSchema(testCases, addressSchema); }); it('should fail for invalid addresses', () => { - const testCases = [ - '0x', - '0', - '0x00', - '0xzzzzzzB11a196601eD2ce54B665CaFEca0347D42', - '0x8b0292B11a196601eD2ce54B665CaFEca0347D42', - ]; + const testCases = ['0x', '0', '0x00', '0xzzzzzzB11a196601eD2ce54B665CaFEca0347D42']; const shouldFail = true; validateAgainstSchema(testCases, addressSchema, shouldFail); }); @@ -730,7 +724,7 @@ describe('Schema', () => { validateAgainstSchema(testCases, relayerApiOrdersChannelSubscribeSchema); }); it('should fail for invalid orders channel websocket subscribe message', () => { - const checksummedAddress = '0xA2b31daCf30a9C50ca473337c01d8A201ae33e32'; + const bogusAddress = '0xz2b31daCf30a9C50ca473337c01d8A201ae33e32'; const testCases = [ { type: 'subscribe', @@ -743,7 +737,7 @@ describe('Schema', () => { payload: { makerAssetProxyId: '0x02571792', takerAssetProxyId: '0xf47261b0', - makerAssetAddress: checksummedAddress, + makerAssetAddress: bogusAddress, }, }, { diff --git a/packages/python-contract-wrappers/CHANGELOG.json b/packages/python-contract-wrappers/CHANGELOG.json index 0e8561487e..3d2e1168f4 100644 --- a/packages/python-contract-wrappers/CHANGELOG.json +++ b/packages/python-contract-wrappers/CHANGELOG.json @@ -5,6 +5,10 @@ { "note": "Initial commit. Functionality tested for ERC20Token wrapper", "pr": 1878 + }, + { + "note": "Include the Exchange contract in the list of generation targets", + "pr": 1919 } ] } diff --git a/packages/python-contract-wrappers/package.json b/packages/python-contract-wrappers/package.json index 629b02c3be..0aaef82252 100644 --- a/packages/python-contract-wrappers/package.json +++ b/packages/python-contract-wrappers/package.json @@ -13,7 +13,7 @@ "clean": "shx rm -rf generated" }, "config": { - "abis": "../contract-artifacts/artifacts/ERC20Token.json" + "abis": "../contract-artifacts/artifacts/{Exchange,ERC20Token}.json" }, "repository": { "type": "git", diff --git a/packages/sol-compiler/CHANGELOG.json b/packages/sol-compiler/CHANGELOG.json index b9c1c3abd7..3062927a69 100644 --- a/packages/sol-compiler/CHANGELOG.json +++ b/packages/sol-compiler/CHANGELOG.json @@ -1,4 +1,13 @@ [ + { + "version": "3.1.10", + "changes": [ + { + "note": "re-export new ethereum-types types, TupleDataItem", + "pr": 1919 + } + ] + }, { "timestamp": 1563006338, "version": "3.1.9", diff --git a/packages/sol-compiler/src/index.ts b/packages/sol-compiler/src/index.ts index d8a60666f4..db77fb86b6 100644 --- a/packages/sol-compiler/src/index.ts +++ b/packages/sol-compiler/src/index.ts @@ -4,6 +4,7 @@ export { CompilerOptions, CompilerSettings, DataItem, + TupleDataItem, DevdocOutput, ErrorSeverity, ErrorType, diff --git a/packages/web3-wrapper/CHANGELOG.json b/packages/web3-wrapper/CHANGELOG.json index 8baa47d6a5..edb4f740b3 100644 --- a/packages/web3-wrapper/CHANGELOG.json +++ b/packages/web3-wrapper/CHANGELOG.json @@ -1,4 +1,13 @@ [ + { + "version": "6.0.8", + "changes": [ + { + "note": "re-export new ethereum-types types, TupleDataItem", + "pr": 1919 + } + ] + }, { "timestamp": 1563006338, "version": "6.0.7", diff --git a/packages/web3-wrapper/src/index.ts b/packages/web3-wrapper/src/index.ts index b2407bb58c..a355f80bff 100644 --- a/packages/web3-wrapper/src/index.ts +++ b/packages/web3-wrapper/src/index.ts @@ -43,6 +43,7 @@ export { ConstructorAbi, FallbackAbi, DataItem, + TupleDataItem, ConstructorStateMutability, StateMutability, Web3JsProvider, diff --git a/python-packages/build_docs b/python-packages/build_docs new file mode 100755 index 0000000000..18271a5270 --- /dev/null +++ b/python-packages/build_docs @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +./parallel ./setup.py build_sphinx diff --git a/python-packages/contract_addresses/setup.py b/python-packages/contract_addresses/setup.py index 6bebc210ad..f197122930 100755 --- a/python-packages/contract_addresses/setup.py +++ b/python-packages/contract_addresses/setup.py @@ -186,6 +186,7 @@ def run_tests(self): "build_sphinx": { "source_dir": ("setup.py", "src"), "build_dir": ("setup.py", "build/docs"), + "warning_is_error": ("setup.py", "true"), } }, ) diff --git a/python-packages/contract_artifacts/setup.py b/python-packages/contract_artifacts/setup.py index f3a88cd483..14db18fcb3 100755 --- a/python-packages/contract_artifacts/setup.py +++ b/python-packages/contract_artifacts/setup.py @@ -60,15 +60,6 @@ def run(self): "mypy src setup.py".split(), # security issue checker: "bandit -r src ./setup.py".split(), - # HACK: ensure contract artifacts match the authoritative copies: - # this is a hack. ideally we would symlink to the authoritative - # copies, but a problem with setuptools is preventing it from - # following symlinks when gathering package_data. see - # https://github.com/pypa/setuptools/issues/415. - ( - "diff src/zero_ex/contract_artifacts/artifacts" - + " ../../packages/contract-artifacts/artifacts" - ).split(), # general linter: "pylint src setup.py".split(), # pylint takes relatively long to run, so it runs last, to enable @@ -225,6 +216,7 @@ def run_tests(self): "build_sphinx": { "source_dir": ("setup.py", "src"), "build_dir": ("setup.py", "build/docs"), + "warning_is_error": ("setup.py", "true"), } }, ) diff --git a/python-packages/contract_wrappers/.pylintrc b/python-packages/contract_wrappers/.pylintrc index 1d5842bc1c..be7c8ed341 100644 --- a/python-packages/contract_wrappers/.pylintrc +++ b/python-packages/contract_wrappers/.pylintrc @@ -1,6 +1,3 @@ [MESSAGES CONTROL] -disable=C0330,line-too-long,fixme,too-few-public-methods,too-many-ancestors +disable=C0330,line-too-long,fixme,too-few-public-methods,too-many-ancestors,duplicate-code # C0330 is "bad hanging indent". we use indents per `black`. - -[SIMILARITIES] -min-similarity-lines=12 diff --git a/python-packages/contract_wrappers/CHANGELOG.md b/python-packages/contract_wrappers/CHANGELOG.md index 1639a8f546..e2d8fc4e00 100644 --- a/python-packages/contract_wrappers/CHANGELOG.md +++ b/python-packages/contract_wrappers/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## 2.0.0 - TBD + +- Completely new implementation of the Exchange wrapper, virtually all auto-generated from the Solidity contract. Breaking changes include method parameter name changes and accepting of signatures as bytes. + ## 1.0.0 - 2019-04-30 - Initial release. diff --git a/python-packages/contract_wrappers/setup.py b/python-packages/contract_wrappers/setup.py index 780608d725..7d7da3da6c 100755 --- a/python-packages/contract_wrappers/setup.py +++ b/python-packages/contract_wrappers/setup.py @@ -4,7 +4,7 @@ import subprocess # nosec from shutil import copy, rmtree -from os import environ, path +from os import environ, path, remove from pathlib import Path from sys import argv from importlib.util import find_spec @@ -34,17 +34,37 @@ def run(self): "packages", "python-contract-wrappers", "generated", - "erc20_token.py", + "erc20_token", + "__init__.py", + ), + path.join( + pkgdir, "src", "zero_ex", "contract_wrappers", "erc20_token" + ), + ) + copy( + path.join( + pkgdir, + "..", + "..", + "packages", + "python-contract-wrappers", + "generated", + "exchange", + "__init__.py", + ), + path.join( + pkgdir, "src", "zero_ex", "contract_wrappers", "exchange" ), - path.join(pkgdir, "src", "zero_ex", "contract_wrappers"), ) if find_spec("black") is None: subprocess.check_call("pip install black".split()) # nosec - subprocess.check_call( # nosec - ( - BLACK_COMMAND + " src/zero_ex/contract_wrappers/erc20_token.py" - ).split() + black_command = ( + BLACK_COMMAND + + " src/zero_ex/contract_wrappers/erc20_token/__init__.py" + + " src/zero_ex/contract_wrappers/exchange/__init__.py" ) + print(f"Running command `{black_command}`...") + subprocess.check_call(black_command.split()) # nosec class TestCommandExtension(TestCommand): @@ -112,6 +132,9 @@ def run(self): rmtree(".tox", ignore_errors=True) rmtree(".pytest_cache", ignore_errors=True) rmtree("src/0x_contract_wrappers.egg-info", ignore_errors=True) + # generated files: + remove("src/zero_ex/contract_wrappers/exchange/__init__.py") + remove("src/zero_ex/contract_wrappers/erc20_token/__init__.py") class TestPublishCommand(distutils.command.build_py.build_py): @@ -255,6 +278,7 @@ def run(self): "build_sphinx": { "source_dir": ("setup.py", "src"), "build_dir": ("setup.py", "build/docs"), + "warning_is_error": ("setup.py", "true"), } }, ) diff --git a/python-packages/contract_wrappers/src/index.rst b/python-packages/contract_wrappers/src/index.rst index 6fe9885d55..4112445962 100644 --- a/python-packages/contract_wrappers/src/index.rst +++ b/python-packages/contract_wrappers/src/index.rst @@ -31,6 +31,38 @@ zero_ex.contract_wrappers.TxParams .. autoclass:: zero_ex.contract_wrappers.TxParams :members: +zero_ex.contract_wrappers.exchange.types +======================================== + +.. automodule:: zero_ex.contract_wrappers.exchange.types + +.. autoclass:: zero_ex.contract_wrappers.exchange.types.Order + +.. autoclass:: zero_ex.contract_wrappers.exchange.types.OrderInfo + +.. autoclass:: zero_ex.contract_wrappers.exchange.types.FillResults + +.. autoclass:: zero_ex.contract_wrappers.exchange.types.MatchedFillResults + +zero_ex.contract_wrappers.exchange: Generated Tuples +==================================================== + +.. autoclass:: zero_ex.contract_wrappers.exchange.Tuple0x260219a2 + + This is the generated class representing `the Order struct `_. + +.. autoclass:: zero_ex.contract_wrappers.exchange.Tuple0xbb41e5b3 + + This is the generated class representing `the FillResults struct `_. + +.. autoclass:: zero_ex.contract_wrappers.exchange.Tuple0x054ca44e + + This is the generated class representing `the MatchedFillResults struct `_. + +.. autoclass:: zero_ex.contract_wrappers.exchange.Tuple0xb1e4a1ae + + This is the generated class representing `the OrderInfo struct `_. + Indices and tables ================== diff --git a/python-packages/contract_wrappers/src/zero_ex/contract_wrappers/__init__.py b/python-packages/contract_wrappers/src/zero_ex/contract_wrappers/__init__.py index 4e9725f672..a92a6d8653 100644 --- a/python-packages/contract_wrappers/src/zero_ex/contract_wrappers/__init__.py +++ b/python-packages/contract_wrappers/src/zero_ex/contract_wrappers/__init__.py @@ -91,24 +91,24 @@ balance: >>> from zero_ex.contract_wrappers import ERC20Token ->>> zrx_wrapper = ERC20Token( +>>> zrx_token = ERC20Token( ... provider=ganache, ... contract_address=NETWORK_TO_ADDRESSES[NetworkId.GANACHE].zrx_token, ... ) ->>> weth_wrapper = ERC20Token( +>>> weth_token = ERC20Token( ... provider=ganache, ... contract_address=NETWORK_TO_ADDRESSES[NetworkId.GANACHE].ether_token, ... ) >>> erc20_proxy_addr = NETWORK_TO_ADDRESSES[NetworkId.GANACHE].erc20_proxy ->>> tx = zrx_wrapper.approve( +>>> tx = zrx_token.approve( ... erc20_proxy_addr, ... to_wei(100, 'ether'), ... tx_params=TxParams(from_=maker_address), ... ) ->>> tx = weth_wrapper.approve( +>>> tx = weth_token.approve( ... erc20_proxy_addr, ... to_wei(100, 'ether'), ... tx_params=TxParams(from_=taker_address), @@ -117,8 +117,8 @@ Constructing an order --------------------- ->>> from zero_ex.order_utils import asset_data_utils, Order ->>> from eth_utils import remove_0x_prefix +>>> from zero_ex.contract_wrappers.exchange.types import Order +>>> from zero_ex.order_utils import asset_data_utils >>> from datetime import datetime, timedelta >>> import random >>> order = Order( @@ -143,8 +143,8 @@ >>> from zero_ex.order_utils import generate_order_hash_hex >>> order_hash_hex = generate_order_hash_hex(order, exchange_address) ->>> from zero_ex.order_utils import sign_hash ->>> maker_signature = sign_hash( +>>> from zero_ex.order_utils import sign_hash_to_bytes +>>> maker_signature = sign_hash_to_bytes( ... ganache, Web3.toChecksumAddress(maker_address), order_hash_hex ... ) @@ -162,13 +162,13 @@ too. >>> from zero_ex.contract_wrappers import Exchange ->>> exchange_contract = Exchange( +>>> exchange = Exchange( ... provider=ganache, ... contract_address=NETWORK_TO_ADDRESSES[NetworkId.GANACHE].exchange, ... ) ->>> tx_hash = exchange_contract.fill_order( +>>> tx_hash = exchange.fill_order( ... order=order, -... taker_amount=order["takerAssetAmount"], +... taker_asset_fill_amount=order["takerAssetAmount"], ... signature=maker_signature, ... tx_params=TxParams(from_=taker_address) ... ) @@ -176,10 +176,10 @@ Once the transaction is mined, we can get the details of our exchange through the exchange wrapper: ->>> exchange_contract.get_fill_event(tx_hash) +>>> exchange.get_fill_event(tx_hash) (AttributeDict({'args': ...({'makerAddress': ...}), 'event': 'Fill', ...}),) >>> from pprint import pprint ->>> pprint(exchange_contract.get_fill_event(tx_hash)[0].args.__dict__) +>>> pprint(exchange.get_fill_event(tx_hash)[0].args.__dict__) {'feeRecipientAddress': '0x0000000000000000000000000000000000000000', 'makerAddress': '0x...', 'makerAssetData': b..., @@ -191,7 +191,7 @@ 'takerAssetData': b..., 'takerAssetFilledAmount': 100000000000000000, 'takerFeePaid': 0} ->>> exchange_contract.get_fill_event(tx_hash)[0].args.takerAssetFilledAmount +>>> exchange.get_fill_event(tx_hash)[0].args.takerAssetFilledAmount 100000000000000000 Cancelling an order @@ -217,23 +217,23 @@ ... ) ... ) ->>> tx_hash = exchange_contract.cancel_order( +>>> tx_hash = exchange.cancel_order( ... order=order, tx_params=TxParams(from_=maker_address) ... ) Once the transaction is mined, we can get the details of the cancellation through the Exchange wrapper: ->>> exchange_contract.get_cancel_event(tx_hash) +>>> exchange.get_cancel_event(tx_hash) (AttributeDict({'args': ...({'makerAddress': ...}), 'event': 'Cancel', ...}),) ->>> pprint(exchange_contract.get_cancel_event(tx_hash)[0].args.__dict__) +>>> pprint(exchange.get_cancel_event(tx_hash)[0].args.__dict__) {'feeRecipientAddress': '0x0000000000000000000000000000000000000000', 'makerAddress': '0x...', 'makerAssetData': b..., 'orderHash': b..., 'senderAddress': '0x...', 'takerAssetData': b...} ->>> exchange_contract.get_cancel_event(tx_hash)[0].args.feeRecipientAddress +>>> exchange.get_cancel_event(tx_hash)[0].args.feeRecipientAddress '0x0000000000000000000000000000000000000000' Batching orders @@ -258,10 +258,10 @@ ... (datetime.utcnow() + timedelta(days=1)).timestamp() ... ) ... ) ->>> signature_1 = sign_hash( +>>> signature_1 = sign_hash_to_bytes( ... ganache, ... Web3.toChecksumAddress(maker_address), -... generate_order_hash_hex(order_1, exchange_contract.address) +... generate_order_hash_hex(order_1, exchange.contract_address) ... ) >>> order_2 = Order( ... makerAddress=maker_address, @@ -279,17 +279,17 @@ ... (datetime.utcnow() + timedelta(days=1)).timestamp() ... ) ... ) ->>> signature_2 = sign_hash( +>>> signature_2 = sign_hash_to_bytes( ... ganache, ... Web3.toChecksumAddress(maker_address), -... generate_order_hash_hex(order_2, exchange_contract.address) +... generate_order_hash_hex(order_2, exchange.contract_address) ... ) Fill order_1 and order_2 together: ->>> exchange_contract.batch_fill_orders( +>>> exchange.batch_fill_orders( ... orders=[order_1, order_2], -... taker_amounts=[1, 2], +... taker_asset_fill_amounts=[1, 2], ... signatures=[signature_1, signature_2], ... tx_params=TxParams(from_=taker_address)) HexBytes('0x...') @@ -297,4 +297,4 @@ from .tx_params import TxParams from .erc20_token import ERC20Token -from .exchange_wrapper import Exchange +from .exchange import Exchange diff --git a/python-packages/contract_wrappers/src/zero_ex/contract_wrappers/_base_contract_wrapper.py b/python-packages/contract_wrappers/src/zero_ex/contract_wrappers/_base_contract_wrapper.py index 782c8a9735..0ac4847f8b 100644 --- a/python-packages/contract_wrappers/src/zero_ex/contract_wrappers/_base_contract_wrapper.py +++ b/python-packages/contract_wrappers/src/zero_ex/contract_wrappers/_base_contract_wrapper.py @@ -34,7 +34,7 @@ def __init__( self._private_key = private_key self._web3 = Web3(provider) self._web3_eth = self._web3.eth # pylint: disable=no-member - self._contract_address = self._validate_and_checksum_address( + self.contract_address = self._validate_and_checksum_address( contract_address ) @@ -120,7 +120,7 @@ def execute_method( :returns: str of transaction hash """ contract_instance = self._contract_instance( - address=self._contract_address, abi=abi + address=self.contract_address, abi=abi ) if args is None: args = [] @@ -131,6 +131,6 @@ def execute_method( ) raise Exception( "No method {} found on contract {}.".format( - self._contract_address, method + self.contract_address, method ) ) diff --git a/python-packages/contract_wrappers/src/zero_ex/contract_wrappers/erc20_token/.gitkeep b/python-packages/contract_wrappers/src/zero_ex/contract_wrappers/erc20_token/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/python-packages/contract_wrappers/src/zero_ex/contract_wrappers/exchange/.gitkeep b/python-packages/contract_wrappers/src/zero_ex/contract_wrappers/exchange/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/python-packages/contract_wrappers/src/zero_ex/contract_wrappers/exchange/types.py b/python-packages/contract_wrappers/src/zero_ex/contract_wrappers/exchange/types.py new file mode 100644 index 0000000000..3bdb3e4e75 --- /dev/null +++ b/python-packages/contract_wrappers/src/zero_ex/contract_wrappers/exchange/types.py @@ -0,0 +1,200 @@ +"""Conveniences for handling types representing Exchange Solidity structs. + +The `TypedDict`:code: classes in the .exchange module represent tuples +encountered in the Exchange contract's ABI. However, they have weird names, +containing hashes of the tuple's field names, because the name of a Solidity +`struct`:code: isn't conveyed through the ABI. This module provides type +aliases with human-friendly names. + +Converting between the JSON wire format and the types accepted by Web3.py (eg +`bytes` vs `str`) can be onerous. This module provides conveniences for +converting Exchange structs between JSON and Python objects. +""" + +from copy import copy +from typing import cast, Dict + +from eth_utils import remove_0x_prefix + +from zero_ex.json_schemas import assert_valid + +from . import ( + Tuple0xbb41e5b3, + Tuple0x260219a2, + Tuple0x054ca44e, + Tuple0xb1e4a1ae, +) + + +# Would rather not repeat ourselves below, but base classes are mentioned in +# the class docstrings because of a bug in sphinx rendering. Using the `.. +# autoclass` directive, with the `:show-inheritance:` role, results in docs +# being rendered with just "Bases: dict", and no mention of the direct ancestor +# of each of these classes. + + +class FillResults(Tuple0xbb41e5b3): + """The `FillResults`:code: Solidity struct. + + Also known as + `zero_ex.contract_wrappers.exchange.Tuple0xbb41e5b3`:py:class:. + """ + + +class Order(Tuple0x260219a2): + """The `Order`:code: Solidity struct. + + Also known as + `zero_ex.contract_wrappers.exchange.Tuple0x260219a2`:py:class:. + """ + + +class MatchedFillResults(Tuple0x054ca44e): + """The `MatchedFillResults`:code: Solidity struct. + + Also known as + `zero_ex.contract_wrappers.exchange.Tuple0x054ca44e`:py:class:. + """ + + +class OrderInfo(Tuple0xb1e4a1ae): + """The `OrderInfo`:code: Solidity struct. + + Also known as + `zero_ex.contract_wrappers.exchange.Tuple0xb1e4a1ae`:py:class:. + """ + + +def order_to_jsdict( + order: Order, + exchange_address="0x0000000000000000000000000000000000000000", + signature: str = None, +) -> dict: + """Convert a Web3-compatible order struct to a JSON-schema-compatible dict. + + More specifically, do explicit decoding for the `bytes`:code: fields, and + convert numerics to strings. + + >>> import pprint + >>> pprint.pprint(order_to_jsdict( + ... { + ... 'makerAddress': "0x0000000000000000000000000000000000000000", + ... 'takerAddress': "0x0000000000000000000000000000000000000000", + ... 'feeRecipientAddress': + ... "0x0000000000000000000000000000000000000000", + ... 'senderAddress': "0x0000000000000000000000000000000000000000", + ... 'makerAssetAmount': 1, + ... 'takerAssetAmount': 1, + ... 'makerFee': 0, + ... 'takerFee': 0, + ... 'expirationTimeSeconds': 1, + ... 'salt': 1, + ... 'makerAssetData': (0).to_bytes(1, byteorder='big') * 20, + ... 'takerAssetData': (0).to_bytes(1, byteorder='big') * 20, + ... }, + ... )) + {'exchangeAddress': '0x0000000000000000000000000000000000000000', + 'expirationTimeSeconds': '1', + 'feeRecipientAddress': '0x0000000000000000000000000000000000000000', + 'makerAddress': '0x0000000000000000000000000000000000000000', + 'makerAssetAmount': '1', + 'makerAssetData': '0x0000000000000000000000000000000000000000', + 'makerFee': '0', + 'salt': '1', + 'senderAddress': '0x0000000000000000000000000000000000000000', + 'takerAddress': '0x0000000000000000000000000000000000000000', + 'takerAssetAmount': '1', + 'takerAssetData': '0x0000000000000000000000000000000000000000', + 'takerFee': '0'} + """ + jsdict = cast(Dict, copy(order)) + + # encode bytes fields + jsdict["makerAssetData"] = "0x" + order["makerAssetData"].hex() + jsdict["takerAssetData"] = "0x" + order["takerAssetData"].hex() + + jsdict["exchangeAddress"] = exchange_address + + jsdict["expirationTimeSeconds"] = str(order["expirationTimeSeconds"]) + + jsdict["makerAssetAmount"] = str(order["makerAssetAmount"]) + jsdict["takerAssetAmount"] = str(order["takerAssetAmount"]) + + jsdict["makerFee"] = str(order["makerFee"]) + jsdict["takerFee"] = str(order["takerFee"]) + + jsdict["salt"] = str(order["salt"]) + + if signature is not None: + jsdict["signature"] = signature + + assert_valid(jsdict, "/orderSchema") + + return jsdict + + +def jsdict_to_order(jsdict: dict) -> Order: + r"""Convert a JSON-schema-compatible dict order to a Web3-compatible struct. + + More specifically, do explicit encoding of the `bytes`:code: fields, and + parse integers from strings. + + >>> import pprint + >>> pprint.pprint(jsdict_to_order( + ... { + ... 'makerAddress': "0x0000000000000000000000000000000000000000", + ... 'takerAddress': "0x0000000000000000000000000000000000000000", + ... 'feeRecipientAddress': "0x0000000000000000000000000000000000000000", + ... 'senderAddress': "0x0000000000000000000000000000000000000000", + ... 'makerAssetAmount': "1000000000000000000", + ... 'takerAssetAmount': "1000000000000000000", + ... 'makerFee': "0", + ... 'takerFee': "0", + ... 'expirationTimeSeconds': "12345", + ... 'salt': "12345", + ... 'makerAssetData': "0x0000000000000000000000000000000000000000", + ... 'takerAssetData': "0x0000000000000000000000000000000000000000", + ... 'exchangeAddress': "0x0000000000000000000000000000000000000000", + ... }, + ... )) + {'expirationTimeSeconds': 12345, + 'feeRecipientAddress': '0x0000000000000000000000000000000000000000', + 'makerAddress': '0x0000000000000000000000000000000000000000', + 'makerAssetAmount': 1000000000000000000, + 'makerAssetData': b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' + b'\x00\x00\x00\x00\x00\x00\x00\x00', + 'makerFee': 0, + 'salt': 12345, + 'senderAddress': '0x0000000000000000000000000000000000000000', + 'takerAddress': '0x0000000000000000000000000000000000000000', + 'takerAssetAmount': 1000000000000000000, + 'takerAssetData': b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' + b'\x00\x00\x00\x00\x00\x00\x00\x00', + 'takerFee': 0} + """ # noqa: E501 (line too long) + assert_valid(jsdict, "/orderSchema") + + order = cast(Order, copy(jsdict)) + + order["makerAssetData"] = bytes.fromhex( + remove_0x_prefix(jsdict["makerAssetData"]) + ) + order["takerAssetData"] = bytes.fromhex( + remove_0x_prefix(jsdict["takerAssetData"]) + ) + + order["makerAssetAmount"] = int(jsdict["makerAssetAmount"]) + order["takerAssetAmount"] = int(jsdict["takerAssetAmount"]) + + order["makerFee"] = int(jsdict["makerFee"]) + order["takerFee"] = int(jsdict["takerFee"]) + + order["expirationTimeSeconds"] = int(jsdict["expirationTimeSeconds"]) + + order["salt"] = int(jsdict["salt"]) + + del order["exchangeAddress"] # type: ignore + # silence mypy pending release of + # https://github.com/python/mypy/issues/3550 + + return order diff --git a/python-packages/contract_wrappers/src/zero_ex/contract_wrappers/exchange/validator.py b/python-packages/contract_wrappers/src/zero_ex/contract_wrappers/exchange/validator.py new file mode 100644 index 0000000000..27932db2bd --- /dev/null +++ b/python-packages/contract_wrappers/src/zero_ex/contract_wrappers/exchange/validator.py @@ -0,0 +1,47 @@ +"""Validate inputs to the Exchange contract.""" + +from typing import Any + +from web3.providers.base import BaseProvider + +from zero_ex import json_schemas + +from . import ExchangeValidatorBase +from .types import order_to_jsdict + + +class ExchangeValidator(ExchangeValidatorBase): + """Validate inputs to Exchange methods.""" + + def __init__( + self, + provider: BaseProvider, + contract_address: str, + private_key: str = None, + ): + """Initialize the class.""" + super().__init__(provider, contract_address, private_key) + self.contract_address = contract_address + + def assert_valid( + self, method_name: str, parameter_name: str, argument_value: Any + ) -> None: + """Raise an exception if method input is not valid. + + :param method_name: Name of the method whose input is to be validated. + :param parameter_name: Name of the parameter whose input is to be + validated. + :param argument_value: Value of argument to parameter to be validated. + """ + if parameter_name == "order": + json_schemas.assert_valid( + order_to_jsdict(argument_value, self.contract_address), + "/orderSchema", + ) + + if parameter_name == "orders": + for order in argument_value: + json_schemas.assert_valid( + order_to_jsdict(order, self.contract_address), + "/orderSchema", + ) diff --git a/python-packages/contract_wrappers/src/zero_ex/contract_wrappers/exchange_wrapper.py b/python-packages/contract_wrappers/src/zero_ex/contract_wrappers/exchange_wrapper.py deleted file mode 100644 index 12d14bab0f..0000000000 --- a/python-packages/contract_wrappers/src/zero_ex/contract_wrappers/exchange_wrapper.py +++ /dev/null @@ -1,327 +0,0 @@ -"""Wrapper for 0x Exchange smart contract.""" - -from typing import List, Optional, Tuple, Union -from itertools import repeat - -from eth_utils import remove_0x_prefix -from hexbytes import HexBytes -from web3.providers.base import BaseProvider -from web3.datastructures import AttributeDict - -from zero_ex.contract_addresses import NETWORK_TO_ADDRESSES, NetworkId -from zero_ex.contract_artifacts import abi_by_name -from zero_ex.json_schemas import assert_valid -from zero_ex.order_utils import ( - Order, - generate_order_hash_hex, - is_valid_signature, - order_to_jsdict, -) - -from ._base_contract_wrapper import BaseContractWrapper -from .tx_params import TxParams - - -class CancelDisallowedError(Exception): - """Exception for when Cancel is not allowed.""" - - -class Exchange(BaseContractWrapper): - """Wrapper class for 0x Exchange smart contract.""" - - def __init__( - self, - provider: BaseProvider, - contract_address: str, - private_key: str = None, - ): - """Get an instance of the 0x Exchange smart contract wrapper. - - :param provider: instance of :class:`web3.providers.base.BaseProvider` - :param private_key: str of private_key - """ - super(Exchange, self).__init__( - provider=provider, - contract_address=contract_address, - private_key=private_key, - ) - self._web3_net = self._web3.net # pylint: disable=no-member - self.address = NETWORK_TO_ADDRESSES[ - NetworkId(int(self._web3_net.version)) - ].exchange - self._exchange = self._contract_instance( - address=self.address, abi=abi_by_name("Exchange") - ) - - # pylint: disable=too-many-arguments - def fill_order( - self, - order: Order, - taker_amount: int, - signature: str, - tx_params: Optional[TxParams] = None, - view_only: bool = False, - ) -> Union[HexBytes, bytes]: - """Fill a signed order with given amount of taker asset. - - This is the most basic way to fill an order. All of the other methods - call fillOrder under the hood with additional logic. This function - will attempt to fill the amount specified by the caller. However, if - the remaining fillable amount is less than the amount specified, the - remaining amount will be filled. Partial fills are allowed when - filling orders. - - See the specification docs for `fillOrder - `_. - - :param order: instance of :class:`zero_ex.order_utils.Order` - :param taker_amount: integer taker amount in Wei (1 Wei is 10e-18 ETH) - :param signature: str or hexstr or bytes of order hash signature - :param tx_params: default None, :class:`TxParams` transaction params - :param view_only: default False, boolean of whether to transact or - view only - - :returns: transaction hash - """ - assert_valid(order_to_jsdict(order, self.address), "/orderSchema") - is_valid_signature( - self._provider, - generate_order_hash_hex(order, self.address), - signature, - order["makerAddress"], - ) - # safeguard against fractional inputs - taker_fill_amount = int(taker_amount) - normalized_signature = bytes.fromhex(remove_0x_prefix(signature)) - func = self._exchange.functions.fillOrder( - order, taker_fill_amount, normalized_signature - ) - return self._invoke_function_call( - func=func, tx_params=tx_params, view_only=view_only - ) - - # pylint: disable=too-many-arguments - def batch_fill_orders( - self, - orders: List[Order], - taker_amounts: List[int], - signatures: List[str], - tx_params: Optional[TxParams] = None, - view_only: bool = False, - ) -> Union[HexBytes, bytes]: - """Call `fillOrder` sequentially for orders, amounts and signatures. - - :param orders: list of instances of :class:`zero_ex.order_utils.Order` - :param taker_amounts: list of integer taker amounts in Wei - :param signatures: list of str|hexstr|bytes of order hash signature - :param tx_params: default None, :class:`TxParams` transaction params - :param view_only: default False, boolean of whether to transact or - view only - - :returns: transaction hash - """ - order_jsdicts = [ - order_to_jsdict(order, self.address) for order in orders - ] - map(assert_valid, order_jsdicts, repeat("/orderSchema")) - # safeguard against fractional inputs - normalized_fill_amounts = [ - int(taker_fill_amount) for taker_fill_amount in taker_amounts - ] - normalized_signatures = [ - bytes.fromhex(remove_0x_prefix(signature)) - for signature in signatures - ] - func = self._exchange.functions.batchFillOrders( - orders, normalized_fill_amounts, normalized_signatures - ) - return self._invoke_function_call( - func=func, tx_params=tx_params, view_only=view_only - ) - - # pylint: disable=too-many-arguments - def fill_or_kill_order( - self, - order: Order, - taker_amount: int, - signature: str, - tx_params: Optional[TxParams] = None, - view_only: bool = False, - ) -> Union[HexBytes, bytes]: - """Attemp to `fillOrder`, revert if fill is not exact amount. - - :param order: instance of :class:`zero_ex.order_utils.Order` - :param taker_amount: integer taker amount in Wei (1 Wei is 10e-18 ETH) - :param signature: str or hexstr or bytes of order hash signature - :param tx_params: default None, :class:`TxParams` transaction params - :param view_only: default False, boolean of whether to transact or - view only - - :returns: transaction hash - """ - assert_valid(order_to_jsdict(order, self.address), "/orderSchema") - is_valid_signature( - self._provider, - generate_order_hash_hex(order, self.address), - signature, - order["makerAddress"], - ) - # safeguard against fractional inputs - taker_fill_amount = int(taker_amount) - normalized_signature = bytes.fromhex(remove_0x_prefix(signature)) - func = self._exchange.functions.fillOrKillOrder( - order, taker_fill_amount, normalized_signature - ) - return self._invoke_function_call( - func=func, tx_params=tx_params, view_only=view_only - ) - - # pylint: disable=too-many-arguments - def batch_fill_or_kill_orders( - self, - orders: List[Order], - taker_amounts: List[int], - signatures: List[str], - tx_params: Optional[TxParams] = None, - view_only: bool = False, - ) -> Union[HexBytes, bytes]: - """Call `fillOrKillOrder` sequentially for orders. - - :param orders: list of instances of :class:`zero_ex.order_utils.Order` - :param taker_amounts: list of integer taker amounts in Wei - :param signatures: list of str|hexstr|bytes of order hash signature - :param tx_params: default None, :class:`TxParams` transaction params - :param view_only: default False, boolean of whether to transact or - view only - - :returns: transaction hash - """ - order_jsdicts = [ - order_to_jsdict(order, self.address) for order in orders - ] - map(assert_valid, order_jsdicts, repeat("/orderSchema")) - # safeguard against fractional inputs - normalized_fill_amounts = [ - int(taker_fill_amount) for taker_fill_amount in taker_amounts - ] - normalized_signatures = [ - bytes.fromhex(remove_0x_prefix(signature)) - for signature in signatures - ] - func = self._exchange.functions.batchFillOrKillOrders( - orders, normalized_fill_amounts, normalized_signatures - ) - return self._invoke_function_call( - func=func, tx_params=tx_params, view_only=view_only - ) - - def cancel_order( - self, - order: Order, - tx_params: Optional[TxParams] = None, - view_only: bool = False, - ) -> Union[HexBytes, bytes]: - """Cancel an order. - - See the specification docs for `cancelOrder - `_. - - :param order: instance of :class:`zero_ex.order_utils.Order` - :param tx_params: default None, :class:`TxParams` transaction params - :param view_only: default False, boolean of whether to transact or - view only - - :returns: transaction hash - """ - assert_valid(order_to_jsdict(order, self.address), "/orderSchema") - maker_address = self._validate_and_checksum_address( - order["makerAddress"] - ) - - if tx_params and tx_params.from_: - self._raise_if_maker_not_canceller( - maker_address, - self._validate_and_checksum_address(tx_params.from_), - ) - elif self._web3_eth.defaultAccount: - self._raise_if_maker_not_canceller( - maker_address, self._web3_eth.defaultAccount - ) - func = self._exchange.functions.cancelOrder(order) - return self._invoke_function_call( - func=func, tx_params=tx_params, view_only=view_only - ) - - def batch_cancel_orders( - self, - orders: List[Order], - tx_params: Optional[TxParams] = None, - view_only: bool = False, - ) -> Union[HexBytes, bytes]: - """Call `cancelOrder` sequentially for provided orders. - - :param orders: list of instance of :class:`zero_ex.order_utils.Order` - :param tx_params: default None, :class:`TxParams` transaction params - :param view_only: default False, boolean of whether to transact or - view only - - :returns: transaction hash - """ - order_jsdicts = [ - order_to_jsdict(order, self.address) for order in orders - ] - map(assert_valid, order_jsdicts, repeat("/orderSchema")) - maker_addresses = [ - self._validate_and_checksum_address(order["makerAddress"]) - for order in orders - ] - if tx_params and tx_params.from_: - map( - self._raise_if_maker_not_canceller, - maker_addresses, - repeat(tx_params.from_), - ) - elif self._web3_eth.defaultAccount: - map( - self._raise_if_maker_not_canceller, - maker_addresses, - repeat(self._web3_eth.defaultAccount), - ) - func = self._exchange.functions.batchCancelOrders(orders) - return self._invoke_function_call( - func=func, tx_params=tx_params, view_only=view_only - ) - - def get_fill_event( - self, tx_hash: Union[HexBytes, bytes] - ) -> Tuple[AttributeDict]: - """Get fill event for a fill transaction. - - :param tx_hash: `HexBytes` hash of fill transaction - - :returns: fill event - """ - tx_receipt = self._web3_eth.getTransactionReceipt(tx_hash) - return self._exchange.events.Fill().processReceipt(tx_receipt) - - def get_cancel_event( - self, tx_hash: Union[HexBytes, bytes] - ) -> Tuple[AttributeDict]: - """Get cancel event for cancel transaction. - - :param tx_hash: `HexBytes` hash of cancel transaction - """ - tx_receipt = self._web3_eth.getTransactionReceipt(tx_hash) - return self._exchange.events.Cancel().processReceipt(tx_receipt) - - @staticmethod - def _raise_if_maker_not_canceller(maker_address, canceller_address): - """Raise exception is maker is not same as canceller.""" - if maker_address != canceller_address: - raise CancelDisallowedError( - "Order with makerAddress {} can not be cancelled by {}".format( - maker_address, canceller_address - ) - ) diff --git a/python-packages/contract_wrappers/test/test_exchange_wrapper.py b/python-packages/contract_wrappers/test/test_exchange_wrapper.py index f5f50b2a50..64896234c4 100644 --- a/python-packages/contract_wrappers/test/test_exchange_wrapper.py +++ b/python-packages/contract_wrappers/test/test_exchange_wrapper.py @@ -7,8 +7,9 @@ from zero_ex.contract_addresses import NETWORK_TO_ADDRESSES, NetworkId from zero_ex.contract_wrappers import Exchange, TxParams +from zero_ex.contract_wrappers.exchange.types import Order from zero_ex.json_schemas import assert_valid -from zero_ex.order_utils import generate_order_hash_hex, Order, sign_hash +from zero_ex.order_utils import generate_order_hash_hex, sign_hash_to_bytes @pytest.fixture(scope="module") @@ -28,20 +29,20 @@ def create_test_order( taker_asset_data, ): """Create a test order.""" - order: Order = { - "makerAddress": maker_address.lower(), - "takerAddress": "0x0000000000000000000000000000000000000000", - "feeRecipientAddress": "0x0000000000000000000000000000000000000000", - "senderAddress": "0x0000000000000000000000000000000000000000", - "makerAssetAmount": maker_asset_amount, - "takerAssetAmount": taker_asset_amount, - "makerFee": 0, - "takerFee": 0, - "expirationTimeSeconds": 100000000000000, - "salt": random.randint(1, 1000000000), - "makerAssetData": maker_asset_data, - "takerAssetData": taker_asset_data, - } + order = Order( + makerAddress=maker_address.lower(), + takerAddress="0x0000000000000000000000000000000000000000", + feeRecipientAddress="0x0000000000000000000000000000000000000000", + senderAddress="0x0000000000000000000000000000000000000000", + makerAssetAmount=maker_asset_amount, + takerAssetAmount=taker_asset_amount, + makerFee=0, + takerFee=0, + expirationTimeSeconds=100000000000000, + salt=random.randint(1, 1000000000), + makerAssetData=maker_asset_data, + takerAssetData=taker_asset_data, + ) return order @@ -69,16 +70,16 @@ def test_exchange_wrapper__fill_order( """Test filling an order.""" taker = accounts[0] maker = accounts[1] - exchange_address = exchange_wrapper.address + exchange_address = exchange_wrapper.contract_address order = create_test_order(maker, 1, weth_asset_data, 1, weth_asset_data) order_hash = generate_order_hash_hex( order=order, exchange_address=exchange_address ) - order_signature = sign_hash(ganache_provider, maker, order_hash) + order_signature = sign_hash_to_bytes(ganache_provider, maker, order_hash) tx_hash = exchange_wrapper.fill_order( order=order, - taker_amount=order["takerAssetAmount"], + taker_asset_fill_amount=order["takerAssetAmount"], signature=order_signature, tx_params=TxParams(from_=taker), ) @@ -98,7 +99,7 @@ def test_exchange_wrapper__batch_fill_orders( """Test filling a batch of orders.""" taker = accounts[0] maker = accounts[1] - exchange_address = exchange_wrapper.address + exchange_address = exchange_wrapper.contract_address orders = [] order_1 = create_test_order(maker, 1, weth_asset_data, 1, weth_asset_data) order_2 = create_test_order(maker, 1, weth_asset_data, 1, weth_asset_data) @@ -109,13 +110,13 @@ def test_exchange_wrapper__batch_fill_orders( for order in orders ] order_signatures = [ - sign_hash(ganache_provider, maker, order_hash) + sign_hash_to_bytes(ganache_provider, maker, order_hash) for order_hash in order_hashes ] taker_amounts = [order["takerAssetAmount"] for order in orders] tx_hash = exchange_wrapper.batch_fill_orders( orders=orders, - taker_amounts=taker_amounts, + taker_asset_fill_amounts=taker_amounts, signatures=order_signatures, tx_params=TxParams(from_=taker), ) diff --git a/python-packages/install_editable b/python-packages/install_editable index 6ac68b289c..d044c0e7c3 100755 --- a/python-packages/install_editable +++ b/python-packages/install_editable @@ -1,13 +1,3 @@ -#!/usr/bin/env python +#!/usr/bin/env bash -"""Script to install all packages in editable mode (pip install -e .).""" - -from os import path -import subprocess - -# install all packages -subprocess.check_call( - ( - path.join(".", "cmd_pkgs_in_dep_order.py") + " pip install -e .[dev]" - ).split() -) +./parallel pip install -e .[dev] diff --git a/python-packages/json_schemas/setup.py b/python-packages/json_schemas/setup.py index 3aa39ee7c5..03a57cdbed 100755 --- a/python-packages/json_schemas/setup.py +++ b/python-packages/json_schemas/setup.py @@ -5,7 +5,7 @@ import distutils.command.build_py from distutils.command.clean import clean import subprocess # nosec -from shutil import rmtree +from shutil import copytree, rmtree from os import environ, path from sys import argv @@ -13,6 +13,26 @@ from setuptools.command.test import test as TestCommand +class PreInstallCommand(distutils.command.build_py.build_py): + """Custom setuptools command class for pulling in schemas.""" + + description = "Pull in the schemas that live in the TypeScript package." + + def run(self): + """Copy files from TS area to local src.""" + pkgdir = path.dirname(path.realpath(argv[0])) + rmtree( + path.join(pkgdir, "src", "zero_ex", "json_schemas", "schemas"), + ignore_errors=True, + ) + copytree( + path.join( + pkgdir, "..", "..", "packages", "json-schemas", "schemas" + ), + path.join(pkgdir, "src", "zero_ex", "json_schemas", "schemas"), + ) + + class TestCommandExtension(TestCommand): """Run pytest tests.""" @@ -41,15 +61,6 @@ def run(self): "mypy src test setup.py".split(), # security issue checker: "bandit -r src ./setup.py".split(), - # HACK: ensure json schemas don't differ from the authoritative - # copies: this is a hack. ideally we would symlink to the - # authoritative copies, but a problem with setuptools is preventing - # it from following symlinks when gathering package_data. see - # https://github.com/pypa/setuptools/issues/415. - ( - "diff src/zero_ex/json_schemas/schemas" - + " ../../packages/json-schemas/schemas" - ).split(), # general linter: "pylint src test setup.py".split(), # pylint takes relatively long to run, so it runs last, to enable @@ -138,6 +149,7 @@ def run(self): author="F. Eugene Aumson", author_email="feuGeneA@users.noreply.github.com", cmdclass={ + "pre_install": PreInstallCommand, "clean": CleanCommandExtension, "lint": LintCommand, "test": TestCommandExtension, @@ -196,6 +208,7 @@ def run(self): "build_sphinx": { "source_dir": ("setup.py", "src"), "build_dir": ("setup.py", "build/docs"), + "warning_is_error": ("setup.py", "true"), } }, ) diff --git a/python-packages/json_schemas/src/zero_ex/json_schemas/__init__.py b/python-packages/json_schemas/src/zero_ex/json_schemas/__init__.py index b9345a009f..e74717d6ea 100644 --- a/python-packages/json_schemas/src/zero_ex/json_schemas/__init__.py +++ b/python-packages/json_schemas/src/zero_ex/json_schemas/__init__.py @@ -61,9 +61,10 @@ def assert_valid(data: Mapping, schema_id: str) -> None: >>> from zero_ex.json_schemas import assert_valid >>> from zero_ex.contract_addresses import NETWORK_TO_ADDRESSES, NetworkId - >>> from zero_ex.order_utils import ( - ... asset_data_utils, Order, order_to_jsdict + >>> from zero_ex.contract_wrappers.exchange.types import ( + ... Order, order_to_jsdict ... ) + >>> from zero_ex.order_utils import asset_data_utils >>> from eth_utils import remove_0x_prefix >>> import random >>> from datetime import datetime, timedelta diff --git a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/address_schema.json b/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/address_schema.json deleted file mode 100644 index 0dc02d3313..0000000000 --- a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/address_schema.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "id": "/addressSchema", - "type": "string", - "pattern": "^0x[0-9a-f]{40}$" -} diff --git a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/asset_pairs_request_opts_schema.json b/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/asset_pairs_request_opts_schema.json deleted file mode 100644 index fad0bd3719..0000000000 --- a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/asset_pairs_request_opts_schema.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "id": "/AssetPairsRequestOptsSchema", - "type": "object", - "properties": { - "assetDataA": { "$ref": "/hexSchema" }, - "assetDataB": { "$ref": "/hexSchema" } - } -} diff --git a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/block_param_schema.json b/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/block_param_schema.json deleted file mode 100644 index ed4dd1e875..0000000000 --- a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/block_param_schema.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "id": "/blockParamSchema", - "oneOf": [ - { - "type": "number" - }, - { - "enum": ["latest", "earliest", "pending"] - } - ] -} diff --git a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/block_range_schema.json b/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/block_range_schema.json deleted file mode 100644 index b142946490..0000000000 --- a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/block_range_schema.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "id": "/blockRangeSchema", - "properties": { - "fromBlock": { "$ref": "/blockParamSchema" }, - "toBlock": { "$ref": "/blockParamSchema" } - }, - "type": "object" -} diff --git a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/call_data_schema.json b/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/call_data_schema.json deleted file mode 100644 index e5e6e3282e..0000000000 --- a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/call_data_schema.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "id": "/callDataSchema", - "properties": { - "from": { "$ref": "/addressSchema" }, - "to": { "$ref": "/addressSchema" }, - "value": { - "oneOf": [{ "$ref": "/numberSchema" }, { "$ref": "/jsNumberSchema" }] - }, - "gas": { - "oneOf": [{ "$ref": "/numberSchema" }, { "$ref": "/jsNumberSchema" }] - }, - "gasPrice": { - "oneOf": [{ "$ref": "/numberSchema" }, { "$ref": "/jsNumberSchema" }] - }, - "data": { - "type": "string", - "pattern": "^0x[0-9a-f]*$" - }, - "nonce": { - "type": "number", - "minimum": 0 - } - }, - "required": [], - "type": "object", - "additionalProperties": false -} diff --git a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/ec_signature_parameter_schema.json b/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/ec_signature_parameter_schema.json deleted file mode 100644 index 0c08ec2403..0000000000 --- a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/ec_signature_parameter_schema.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "id": "/ecSignatureParameterSchema", - "type": "string", - "pattern": "^0[xX][0-9A-Fa-f]{64}$" -} diff --git a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/ec_signature_schema.json b/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/ec_signature_schema.json deleted file mode 100644 index 52ccfe7bb4..0000000000 --- a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/ec_signature_schema.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "id": "/ecSignatureSchema", - "properties": { - "v": { - "type": "number", - "minimum": 27, - "maximum": 28 - }, - "r": { "$ref": "/ecSignatureParameterSchema" }, - "s": { "$ref": "/ecSignatureParameterSchema" } - }, - "required": ["v", "r", "s"], - "type": "object" -} diff --git a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/eip712_typed_data_schema.json b/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/eip712_typed_data_schema.json deleted file mode 100644 index 8efd6de448..0000000000 --- a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/eip712_typed_data_schema.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "id": "/eip712TypedDataSchema", - "type": "object", - "properties": { - "types": { - "type": "object", - "properties": { - "EIP712Domain": { "type": "array" } - }, - "additionalProperties": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { "type": "string" }, - "type": { "type": "string" } - }, - "required": ["name", "type"] - } - }, - "required": ["EIP712Domain"] - }, - "primaryType": { "type": "string" }, - "domain": { "type": "object" }, - "message": { "type": "object" } - }, - "required": ["types", "primaryType", "domain", "message"] -} diff --git a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/hex_schema.json b/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/hex_schema.json deleted file mode 100644 index f37815d5bd..0000000000 --- a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/hex_schema.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "id": "/hexSchema", - "type": "string", - "pattern": "^0x(([0-9a-f][0-9a-f])+)?$" -} diff --git a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/index_filter_values_schema.json b/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/index_filter_values_schema.json deleted file mode 100644 index bec00d79e8..0000000000 --- a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/index_filter_values_schema.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "id": "/indexFilterValuesSchema", - "additionalProperties": { - "oneOf": [{ "$ref": "/numberSchema" }, { "$ref": "/addressSchema" }, { "$ref": "/orderHashSchema" }] - }, - "type": "object" -} diff --git a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/js_number_schema.json b/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/js_number_schema.json deleted file mode 100644 index 7df1c47472..0000000000 --- a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/js_number_schema.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "id": "/jsNumberSchema", - "type": "number", - "minimum": 0 -} diff --git a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/number_schema.json b/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/number_schema.json deleted file mode 100644 index a48f3e8cff..0000000000 --- a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/number_schema.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "id": "/numberSchema", - "type": "string", - "pattern": "^\\d+(\\.\\d+)?$" -} diff --git a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/order_cancel_schema.json b/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/order_cancel_schema.json deleted file mode 100644 index 8d0999941a..0000000000 --- a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/order_cancel_schema.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "id": "/orderCancellationRequestsSchema", - "type": "array", - "items": { - "properties": { - "order": { "$ref": "/orderSchema" }, - "takerTokenCancelAmount": { "$ref": "/wholeNumberSchema" } - }, - "required": ["order", "takerTokenCancelAmount"], - "type": "object" - } -} diff --git a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/order_config_request_schema.json b/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/order_config_request_schema.json deleted file mode 100644 index 19b043e7f9..0000000000 --- a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/order_config_request_schema.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "id": "/OrderConfigRequestSchema", - "type": "object", - "properties": { - "makerAddress": { "$ref": "/addressSchema" }, - "takerAddress": { "$ref": "/addressSchema" }, - "makerAssetAmount": { "$ref": "/wholeNumberSchema" }, - "takerAssetAmount": { "$ref": "/wholeNumberSchema" }, - "makerAssetData": { "$ref": "/hexSchema" }, - "takerAssetData": { "$ref": "/hexSchema" }, - "exchangeAddress": { "$ref": "/addressSchema" }, - "expirationTimeSeconds": { "$ref": "/wholeNumberSchema" } - }, - "required": [ - "makerAddress", - "takerAddress", - "makerAssetAmount", - "takerAssetAmount", - "makerAssetData", - "takerAssetData", - "exchangeAddress", - "expirationTimeSeconds" - ] -} diff --git a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/order_fill_or_kill_requests_schema.json b/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/order_fill_or_kill_requests_schema.json deleted file mode 100644 index 73bbf20bb1..0000000000 --- a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/order_fill_or_kill_requests_schema.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "id": "/orderFillOrKillRequestsSchema", - "type": "array", - "items": { - "properties": { - "signedOrder": { "$ref": "/signedOrderSchema" }, - "fillTakerAmount": { "$ref": "/wholeNumberSchema" } - }, - "required": ["signedOrder", "fillTakerAmount"], - "type": "object" - } -} diff --git a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/order_fill_requests_schema.json b/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/order_fill_requests_schema.json deleted file mode 100644 index d06fb19a29..0000000000 --- a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/order_fill_requests_schema.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "id": "/orderFillRequestsSchema", - "type": "array", - "items": { - "properties": { - "signedOrder": { "$ref": "/signedOrderSchema" }, - "takerTokenFillAmount": { "$ref": "/wholeNumberSchema" } - }, - "required": ["signedOrder", "takerTokenFillAmount"], - "type": "object" - } -} diff --git a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/order_hash_schema.json b/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/order_hash_schema.json deleted file mode 100644 index 4a770579fc..0000000000 --- a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/order_hash_schema.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "id": "/orderHashSchema", - "type": "string", - "pattern": "^0x[0-9a-fA-F]{64}$" -} diff --git a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/order_schema.json b/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/order_schema.json deleted file mode 100644 index c70b9e2ddf..0000000000 --- a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/order_schema.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "id": "/orderSchema", - "properties": { - "makerAddress": { "$ref": "/addressSchema" }, - "takerAddress": { "$ref": "/addressSchema" }, - "makerFee": { "$ref": "/wholeNumberSchema" }, - "takerFee": { "$ref": "/wholeNumberSchema" }, - "senderAddress": { "$ref": "/addressSchema" }, - "makerAssetAmount": { "$ref": "/wholeNumberSchema" }, - "takerAssetAmount": { "$ref": "/wholeNumberSchema" }, - "makerAssetData": { "$ref": "/hexSchema" }, - "takerAssetData": { "$ref": "/hexSchema" }, - "salt": { "$ref": "/wholeNumberSchema" }, - "exchangeAddress": { "$ref": "/addressSchema" }, - "feeRecipientAddress": { "$ref": "/addressSchema" }, - "expirationTimeSeconds": { "$ref": "/wholeNumberSchema" } - }, - "required": [ - "makerAddress", - "takerAddress", - "makerFee", - "takerFee", - "senderAddress", - "makerAssetAmount", - "takerAssetAmount", - "makerAssetData", - "takerAssetData", - "salt", - "exchangeAddress", - "feeRecipientAddress", - "expirationTimeSeconds" - ], - "type": "object" -} diff --git a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/order_watcher_web_socket_request_schema.json b/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/order_watcher_web_socket_request_schema.json deleted file mode 100644 index b0c419f94f..0000000000 --- a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/order_watcher_web_socket_request_schema.json +++ /dev/null @@ -1,52 +0,0 @@ -{ - "id": "/orderWatcherWebSocketRequestSchema", - "type": "object", - "definitions": { - "signedOrderParam": { - "type": "object", - "properties": { - "signedOrder": { "$ref": "/signedOrderSchema" } - }, - "required": ["signedOrder"] - }, - "orderHashParam": { - "type": "object", - "properties": { - "orderHash": { "$ref": "/hexSchema" } - }, - "required": ["orderHash"] - } - }, - "oneOf": [ - { - "type": "object", - "properties": { - "id": { "type": "number" }, - "jsonrpc": { "type": "string" }, - "method": { "enum": ["ADD_ORDER"] }, - "params": { "$ref": "#/definitions/signedOrderParam" } - }, - "required": ["id", "jsonrpc", "method", "params"] - }, - { - "type": "object", - "properties": { - "id": { "type": "number" }, - "jsonrpc": { "type": "string" }, - "method": { "enum": ["REMOVE_ORDER"] }, - "params": { "$ref": "#/definitions/orderHashParam" } - }, - "required": ["id", "jsonrpc", "method", "params"] - }, - { - "type": "object", - "properties": { - "id": { "type": "number" }, - "jsonrpc": { "type": "string" }, - "method": { "enum": ["GET_STATS"] }, - "params": {} - }, - "required": ["id", "jsonrpc", "method"] - } - ] -} \ No newline at end of file diff --git a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/order_watcher_web_socket_utf8_message_schema.json b/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/order_watcher_web_socket_utf8_message_schema.json deleted file mode 100644 index 154d6d754d..0000000000 --- a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/order_watcher_web_socket_utf8_message_schema.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "id": "/orderWatcherWebSocketUtf8MessageSchema", - "properties": { - "utf8Data": { "type": "string" } - }, - "required": [ - "utf8Data" - ], - "type": "object" -} diff --git a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/orderbook_request_schema.json b/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/orderbook_request_schema.json deleted file mode 100644 index 5ce6e8ab0d..0000000000 --- a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/orderbook_request_schema.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "id": "/OrderbookRequestSchema", - "type": "object", - "properties": { - "baseAssetData": { "$ref": "/hexSchema" }, - "quoteAssetData": { "$ref": "/hexSchema" } - }, - "required": ["baseAssetData", "quoteAssetData"] -} diff --git a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/orders_request_opts_schema.json b/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/orders_request_opts_schema.json deleted file mode 100644 index 4c1b9b4e98..0000000000 --- a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/orders_request_opts_schema.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "id": "/OrdersRequestOptsSchema", - "type": "object", - "properties": { - "makerAssetProxyId": { "$ref": "/hexSchema" }, - "takerAssetProxyId": { "$ref": "/hexSchema" }, - "makerAssetAddress": { "$ref": "/addressSchema" }, - "takerAssetAddress": { "$ref": "/addressSchema" }, - "exchangeAddress": { "$ref": "/addressSchema" }, - "senderAddress": { "$ref": "/addressSchema" }, - "makerAssetData": { "$ref": "/hexSchema" }, - "takerAssetData": { "$ref": "/hexSchema" }, - "traderAssetData": { "$ref": "/hexSchema" }, - "makerAddress": { "$ref": "/addressSchema" }, - "takerAddress": { "$ref": "/addressSchema" }, - "traderAddress": { "$ref": "/addressSchema" }, - "feeRecipientAddress": { "$ref": "/addressSchema" } - } -} diff --git a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/orders_schema.json b/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/orders_schema.json deleted file mode 100644 index 1e1c6a8751..0000000000 --- a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/orders_schema.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "id": "/ordersSchema", - "type": "array", - "items": { "$ref": "/orderSchema" } -} diff --git a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/paged_request_opts_schema.json b/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/paged_request_opts_schema.json deleted file mode 100644 index f143c28b0f..0000000000 --- a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/paged_request_opts_schema.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "id": "/PagedRequestOptsSchema", - "type": "object", - "properties": { - "page": { "type": "number" }, - "perPage": { "type": "number" } - } -} diff --git a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/paginated_collection_schema.json b/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/paginated_collection_schema.json deleted file mode 100644 index 9dcedf5b47..0000000000 --- a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/paginated_collection_schema.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "id": "/paginatedCollectionSchema", - "type": "object", - "properties": { - "total": { "type": "number" }, - "perPage": { "type": "number" }, - "page": { "type": "number" } - }, - "required": ["total", "perPage", "page"] -} diff --git a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/relayer_api_asset_data_pairs_response_schema.json b/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/relayer_api_asset_data_pairs_response_schema.json deleted file mode 100644 index d1150d3dbc..0000000000 --- a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/relayer_api_asset_data_pairs_response_schema.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "id": "/relayerApiAssetDataPairsResponseSchema", - "type": "object", - "allOf": [ - { "$ref": "/paginatedCollectionSchema" }, - { - "properties": { - "records": { "$ref": "/relayerApiAssetDataPairsSchema" } - }, - "required": ["records"] - } - ] -} diff --git a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/relayer_api_asset_data_pairs_schema.json b/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/relayer_api_asset_data_pairs_schema.json deleted file mode 100644 index 62d4745b8c..0000000000 --- a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/relayer_api_asset_data_pairs_schema.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "id": "/relayerApiAssetDataPairsSchema", - "type": "array", - "items": { - "properties": { - "assetDataA": { "$ref": "/relayerApiAssetDataTradeInfoSchema" }, - "assetDataB": { "$ref": "/relayerApiAssetDataTradeInfoSchema" } - }, - "required": ["assetDataA", "assetDataB"], - "type": "object" - } -} diff --git a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/relayer_api_asset_data_trade_info_schema.json b/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/relayer_api_asset_data_trade_info_schema.json deleted file mode 100644 index e0f274c5d8..0000000000 --- a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/relayer_api_asset_data_trade_info_schema.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "id": "/relayerApiAssetDataTradeInfoSchema", - "type": "object", - "properties": { - "assetData": { "$ref": "/hexSchema" }, - "minAmount": { "$ref": "/wholeNumberSchema" }, - "maxAmount": { "$ref": "/wholeNumberSchema" }, - "precision": { "type": "number" } - }, - "required": ["assetData"] -} diff --git a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/relayer_api_error_response_schema.json b/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/relayer_api_error_response_schema.json deleted file mode 100644 index be4659b0bd..0000000000 --- a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/relayer_api_error_response_schema.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "id": "/relayerApiErrorResponseSchema", - "type": "object", - "properties": { - "code": { "type": "integer", "minimum": 100, "maximum": 103 }, - "reason": { "type": "string" }, - "validationErrors": { - "type": "array", - "items": { - "type": "object", - "properties": { - "field": { "type": "string" }, - "code": { "type": "integer", "minimum": 1000, "maximum": 1006 }, - "reason": { "type": "string" } - }, - "required": ["field", "code", "reason"] - } - } - }, - "required": ["code", "reason"] -} diff --git a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/relayer_api_fee_recipients_response_schema.json b/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/relayer_api_fee_recipients_response_schema.json deleted file mode 100644 index c73506dbb1..0000000000 --- a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/relayer_api_fee_recipients_response_schema.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "id": "/relayerApiFeeRecipientsResponseSchema", - "type": "object", - "allOf": [ - { "$ref": "/paginatedCollectionSchema" }, - { - "properties": { - "records": { - "type": "array", - "items": { "$ref": "/addressSchema" } - } - }, - "required": ["records"] - } - ] -} diff --git a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/relayer_api_order_config_payload_schema.json b/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/relayer_api_order_config_payload_schema.json deleted file mode 100644 index f4583fc625..0000000000 --- a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/relayer_api_order_config_payload_schema.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "id": "/relayerApiOrderConfigPayloadSchema", - "type": "object", - "properties": { - "makerAddress": { "$ref": "/addressSchema" }, - "takerAddress": { "$ref": "/addressSchema" }, - "makerAssetAmount": { "$ref": "/wholeNumberSchema" }, - "takerAssetAmount": { "$ref": "/wholeNumberSchema" }, - "makerAssetData": { "$ref": "/hexSchema" }, - "takerAssetData": { "$ref": "/hexSchema" }, - "exchangeAddress": { "$ref": "/addressSchema" }, - "expirationTimeSeconds": { "$ref": "/wholeNumberSchema" } - }, - "required": [ - "makerAddress", - "takerAddress", - "makerAssetAmount", - "takerAssetAmount", - "makerAssetData", - "takerAssetData", - "exchangeAddress", - "expirationTimeSeconds" - ] -} diff --git a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/relayer_api_order_config_response_schema.json b/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/relayer_api_order_config_response_schema.json deleted file mode 100644 index 8193861e12..0000000000 --- a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/relayer_api_order_config_response_schema.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "id": "/relayerApiOrderConfigResponseSchema", - "type": "object", - "properties": { - "makerFee": { "$ref": "/wholeNumberSchema" }, - "takerFee": { "$ref": "/wholeNumberSchema" }, - "feeRecipientAddress": { "$ref": "/addressSchema" }, - "senderAddress": { "$ref": "/addressSchema" } - }, - "required": ["makerFee", "takerFee", "feeRecipientAddress", "senderAddress"] -} diff --git a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/relayer_api_order_schema.json b/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/relayer_api_order_schema.json deleted file mode 100644 index e0f6539b9f..0000000000 --- a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/relayer_api_order_schema.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "id": "/relayerApiOrderSchema", - "type": "object", - "properties": { - "order": { "$ref": "/orderSchema" }, - "metaData": { "type": "object" } - }, - "required": ["order", "metaData"] -} diff --git a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/relayer_api_orderbook_response_schema.json b/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/relayer_api_orderbook_response_schema.json deleted file mode 100644 index b44f2a7408..0000000000 --- a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/relayer_api_orderbook_response_schema.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "id": "/relayerApiOrderbookResponseSchema", - "type": "object", - "properties": { - "bids": { "$ref": "/relayerApiOrdersResponseSchema" }, - "asks": { "$ref": "/relayerApiOrdersResponseSchema" } - }, - "required": ["bids", "asks"] -} diff --git a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/relayer_api_orders_channel_subscribe_payload_schema.json b/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/relayer_api_orders_channel_subscribe_payload_schema.json deleted file mode 100644 index 274ef1625a..0000000000 --- a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/relayer_api_orders_channel_subscribe_payload_schema.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "id": "/relayerApiOrdersChannelSubscribePayloadSchema", - "type": "object", - "properties": { - "makerAssetProxyId": { "$ref": "/hexSchema" }, - "takerAssetProxyId": { "$ref": "/hexSchema" }, - "networkId": { "type": "number" }, - "makerAssetAddress": { "$ref": "/addressSchema" }, - "takerAssetAddress": { "$ref": "/addressSchema" }, - "makerAssetData": { "$ref": "/hexSchema" }, - "takerAssetData": { "$ref": "/hexSchema" }, - "traderAssetData": { "$ref": "/hexSchema" } - } -} diff --git a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/relayer_api_orders_channel_subscribe_schema.json b/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/relayer_api_orders_channel_subscribe_schema.json deleted file mode 100644 index 29561d09fc..0000000000 --- a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/relayer_api_orders_channel_subscribe_schema.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "id": "/relayerApiOrdersChannelSubscribeSchema", - "type": "object", - "properties": { - "type": { "enum": ["subscribe"] }, - "channel": { "enum": ["orders"] }, - "requestId": { "type": "string" }, - "payload": { "$ref": "/relayerApiOrdersChannelSubscribePayloadSchema" } - }, - "required": ["type", "channel", "requestId"] -} diff --git a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/relayer_api_orders_channel_update_response_schema.json b/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/relayer_api_orders_channel_update_response_schema.json deleted file mode 100644 index 239e7c5861..0000000000 --- a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/relayer_api_orders_channel_update_response_schema.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "id": "/relayerApiOrdersChannelUpdateSchema", - "type": "object", - "properties": { - "type": { "enum": ["update"] }, - "channel": { "enum": ["orders"] }, - "requestId": { "type": "string" }, - "payload": { "$ref": "/relayerApiOrdersSchema" } - }, - "required": ["type", "channel", "requestId"] -} diff --git a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/relayer_api_orders_response_schema.json b/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/relayer_api_orders_response_schema.json deleted file mode 100644 index a5023a3fc1..0000000000 --- a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/relayer_api_orders_response_schema.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "id": "/relayerApiOrdersResponseSchema", - "type": "object", - "allOf": [ - { "$ref": "/paginatedCollectionSchema" }, - { - "properties": { - "records": { "$ref": "/relayerApiOrdersSchema" } - }, - "required": ["records"] - } - ] -} diff --git a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/relayer_api_orders_schema.json b/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/relayer_api_orders_schema.json deleted file mode 100644 index 84e75cd045..0000000000 --- a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/relayer_api_orders_schema.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "id": "/relayerApiOrdersSchema", - "type": "array", - "items": { "$ref": "/relayerApiOrderSchema" } -} diff --git a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/request_opts_schema.json b/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/request_opts_schema.json deleted file mode 100644 index 2206f5016f..0000000000 --- a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/request_opts_schema.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "id": "/RequestOptsSchema", - "type": "object", - "properties": { - "networkId": { "type": "number" } - } -} diff --git a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/signed_order_schema.json b/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/signed_order_schema.json deleted file mode 100644 index 137ae4a249..0000000000 --- a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/signed_order_schema.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "id": "/signedOrderSchema", - "allOf": [ - { "$ref": "/orderSchema" }, - { - "properties": { - "signature": { "$ref": "/hexSchema" } - }, - "required": ["signature"] - } - ] -} diff --git a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/signed_orders_schema.json b/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/signed_orders_schema.json deleted file mode 100644 index e7c3a0b6c9..0000000000 --- a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/signed_orders_schema.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "id": "/signedOrdersSchema", - "type": "array", - "items": { "$ref": "/signedOrderSchema" } -} diff --git a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/token_schema.json b/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/token_schema.json deleted file mode 100644 index 31e41c4b87..0000000000 --- a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/token_schema.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "id": "/tokenSchema", - "properties": { - "name": { "type": "string" }, - "symbol": { "type": "string" }, - "decimals": { "type": "number" }, - "address": { "$ref": "/addressSchema" } - }, - "required": ["name", "symbol", "decimals", "address"], - "type": "object" -} diff --git a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/tx_data_schema.json b/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/tx_data_schema.json deleted file mode 100644 index 8c3daba4e5..0000000000 --- a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/tx_data_schema.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "id": "/txDataSchema", - "properties": { - "from": { "$ref": "/addressSchema" }, - "to": { "$ref": "/addressSchema" }, - "value": { - "oneOf": [{ "$ref": "/numberSchema" }, { "$ref": "/jsNumberSchema" }] - }, - "gas": { - "oneOf": [{ "$ref": "/numberSchema" }, { "$ref": "/jsNumberSchema" }] - }, - "gasPrice": { - "oneOf": [{ "$ref": "/numberSchema" }, { "$ref": "/jsNumberSchema" }] - }, - "data": { - "type": "string", - "pattern": "^0x[0-9a-f]*$" - }, - "nonce": { - "type": "number", - "minimum": 0 - } - }, - "required": ["from"], - "type": "object" -} diff --git a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/whole_number_schema.json b/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/whole_number_schema.json deleted file mode 100644 index aa469954ca..0000000000 --- a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/whole_number_schema.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "id": "/wholeNumberSchema", - "anyOf": [ - { - "type": "string", - "pattern": "^\\d+$" - }, - { - "type": "integer" - } - ] -} diff --git a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/zero_ex_transaction_schema.json b/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/zero_ex_transaction_schema.json deleted file mode 100644 index ffdf1f2295..0000000000 --- a/python-packages/json_schemas/src/zero_ex/json_schemas/schemas/zero_ex_transaction_schema.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "id": "/zeroExTransactionSchema", - "properties": { - "verifyingContractAddress": { "$ref": "/addressSchema" }, - "data": { "$ref": "/hexSchema" }, - "signerAddress": { "$ref": "/addressSchema" }, - "salt": { "$ref": "/wholeNumberSchema" } - }, - "required": ["verifyingContractAddress", "data", "salt", "signerAddress"], - "type": "object" -} diff --git a/python-packages/json_schemas/test/test_json_schemas.py b/python-packages/json_schemas/test/test_json_schemas.py index 1d1efdd120..cfd2787ee6 100644 --- a/python-packages/json_schemas/test/test_json_schemas.py +++ b/python-packages/json_schemas/test/test_json_schemas.py @@ -1,7 +1,6 @@ """Tests of zero_ex.json_schemas""" -from zero_ex.order_utils import make_empty_order, order_to_jsdict from zero_ex.json_schemas import _LOCAL_RESOLVER, assert_valid @@ -34,7 +33,7 @@ def test_assert_valid_caches_resources(): """ _LOCAL_RESOLVER._remote_cache.cache_clear() # pylint: disable=W0212 - assert_valid(order_to_jsdict(make_empty_order()), "/orderSchema") + assert_valid(EMPTY_ORDER, "/orderSchema") cache_info = ( _LOCAL_RESOLVER._remote_cache.cache_info() # pylint: disable=W0212 ) diff --git a/python-packages/lint b/python-packages/lint index 0974f273c6..e9d12a296b 100755 --- a/python-packages/lint +++ b/python-packages/lint @@ -1,13 +1,3 @@ -#!/usr/bin/env python +#!/usr/bin/env bash -"""Script to run linters against local copy of all components.""" - -from os import path -import subprocess - -subprocess.check_call( - ( - f"{path.join('.', 'cmd_pkgs_in_dep_order.py')}" - + f" {path.join('.', 'setup.py')} lint" - ).split() -) +./parallel ./setup.py lint diff --git a/python-packages/middlewares/setup.py b/python-packages/middlewares/setup.py index 24b0aab8af..79dc36f64e 100755 --- a/python-packages/middlewares/setup.py +++ b/python-packages/middlewares/setup.py @@ -212,6 +212,7 @@ def run(self): "build_sphinx": { "source_dir": ("setup.py", "src"), "build_dir": ("setup.py", "build/docs"), + "warning_is_error": ("setup.py", "true"), } }, ) diff --git a/python-packages/middlewares/test/test_local_message_signer.py b/python-packages/middlewares/test/test_local_message_signer.py index 10484ffcf6..c189652012 100644 --- a/python-packages/middlewares/test/test_local_message_signer.py +++ b/python-packages/middlewares/test/test_local_message_signer.py @@ -10,7 +10,6 @@ from zero_ex.order_utils import ( generate_order_hash_hex, is_valid_signature, - make_empty_order, sign_hash, ) @@ -31,7 +30,20 @@ def test_local_message_signer__sign_order(): web3_instance.middleware_stack.add( construct_local_message_signer(private_key) ) - order = make_empty_order() + order = { + "makerAddress": "0x0000000000000000000000000000000000000000", + "takerAddress": "0x0000000000000000000000000000000000000000", + "senderAddress": "0x0000000000000000000000000000000000000000", + "feeRecipientAddress": "0x0000000000000000000000000000000000000000", + "makerAssetData": (b"\x00") * 20, + "takerAssetData": (b"\x00") * 20, + "salt": 0, + "makerFee": 0, + "takerFee": 0, + "makerAssetAmount": 0, + "takerAssetAmount": 0, + "expirationTimeSeconds": 0, + } order_hash = generate_order_hash_hex(order, exchange) signature = sign_hash(ganache, to_checksum_address(address), order_hash) assert signature == expected_signature diff --git a/python-packages/order_utils/CHANGELOG.md b/python-packages/order_utils/CHANGELOG.md index 8be78e0775..de0f1f701d 100644 --- a/python-packages/order_utils/CHANGELOG.md +++ b/python-packages/order_utils/CHANGELOG.md @@ -1,8 +1,8 @@ # Changelog -## 1.1.1 - 2019-02-26 +## 3.0.0 - TBD -- Replaced dependency on web3 with dependency on 0x-web3, to ease coexistence of those two packages. +- Major breaking changes: removal of definitions for Order, OrderInfo, order_to_jsdict, jsdict_to_order, all of which have been moved to contract_wrappers.exchange.types; removal of signature validation. ## 2.0.0 - 2019-04-30 @@ -10,3 +10,7 @@ - Deprecated methods `encode_erc20_asset_data()` and `encode_erc721_asset_data()`, in favor of new methods `encode_erc20()` and `encode_erc721()`. The old methods return a string, which is less than convenient for building orders using the provided `Order` type, which expects asset data to be `bytes`. The new methods return `bytes`. - Expanded documentation. - Stopped using deprecated web3.py interface `contract.call()` in favor of `contract.functions.X.call()`. This provides compatibility with the upcoming 5.x release of web3.py, and it also eliminates some runtime warning messages. + +## 1.1.1 - 2019-02-26 + +- Replaced dependency on web3 with dependency on 0x-web3, to ease coexistence of those two packages. diff --git a/python-packages/order_utils/setup.py b/python-packages/order_utils/setup.py index 4745866ae8..38ab5f00b6 100755 --- a/python-packages/order_utils/setup.py +++ b/python-packages/order_utils/setup.py @@ -229,6 +229,7 @@ def run(self): "build_sphinx": { "source_dir": ("setup.py", "src"), "build_dir": ("setup.py", "build/docs"), + "warning_is_error": ("setup.py", "true"), } }, ) diff --git a/python-packages/order_utils/src/index.rst b/python-packages/order_utils/src/index.rst index 313a36c38d..1308f18c62 100644 --- a/python-packages/order_utils/src/index.rst +++ b/python-packages/order_utils/src/index.rst @@ -10,10 +10,6 @@ Python zero_ex.order_utils .. automodule:: zero_ex.order_utils :members: -.. autoclass:: zero_ex.order_utils.Order - - See source for class properties. Sphinx is having problems generating docs for ``TypedDict`` declarations; pull requests welcome. - zero_ex.order_utils.asset_data_utils ------------------------------------ diff --git a/python-packages/order_utils/src/zero_ex/order_utils/__init__.py b/python-packages/order_utils/src/zero_ex/order_utils/__init__.py index 0cc772f947..ef2f6ce232 100644 --- a/python-packages/order_utils/src/zero_ex/order_utils/__init__.py +++ b/python-packages/order_utils/src/zero_ex/order_utils/__init__.py @@ -14,58 +14,11 @@ just this purpose. To start it: `docker run -d -p 8545:8545 0xorg/ganache-cli:2.2.2`:code:. -Constructing an order ---------------------- - -Here is a short demonstration on how to create a 0x order. - ->>> from zero_ex.contract_addresses import NETWORK_TO_ADDRESSES, NetworkId ->>> from zero_ex.order_utils import asset_data_utils, Order ->>> from datetime import datetime, timedelta ->>> import random ->>> my_address = "0x5409ed021d9299bf6814279a6a1411a7e866a631" ->>> example_order = Order( -... makerAddress=my_address, -... takerAddress="0x0000000000000000000000000000000000000000", -... exchangeAddress=NETWORK_TO_ADDRESSES[NetworkId.MAINNET].exchange, -... senderAddress="0x0000000000000000000000000000000000000000", -... feeRecipientAddress="0x0000000000000000000000000000000000000000", -... makerAssetData=asset_data_utils.encode_erc20( -... NETWORK_TO_ADDRESSES[NetworkId.MAINNET].ether_token -... ), -... takerAssetData=asset_data_utils.encode_erc20( -... NETWORK_TO_ADDRESSES[NetworkId.MAINNET].zrx_token -... ), -... salt=random.randint(1, 100000000000000000), -... makerFee=0, -... takerFee=0, -... makerAssetAmount=1 * 10 ** 18, # Convert token amount to base unit with 18 decimals -... takerAssetAmount=500 * 10 ** 18, # Convert token amount to base unit with 18 decimals -... expirationTimeSeconds=round( -... (datetime.utcnow() + timedelta(days=1)).timestamp() -... ) -... ) ->>> import pprint ->>> pprint.pprint(example_order) -{'exchangeAddress': '0x...', - 'expirationTimeSeconds': ..., - 'feeRecipientAddress': '0x0000000000000000000000000000000000000000', - 'makerAddress': '0x...', - 'makerAssetAmount': 1000000000000000000, - 'makerAssetData': b..., - 'makerFee': 0, - 'salt': ..., - 'senderAddress': '0x0000000000000000000000000000000000000000', - 'takerAddress': '0x0000000000000000000000000000000000000000', - 'takerAssetAmount': 500000000000000000000, - 'takerAssetData': b..., - 'takerFee': 0} -""" # noqa E501 - -from copy import copy +""" + from enum import auto, Enum import json -from typing import cast, Dict, NamedTuple, Tuple +from typing import Tuple from pkg_resources import resource_string from mypy_extensions import TypedDict @@ -78,6 +31,7 @@ from zero_ex.contract_addresses import NETWORK_TO_ADDRESSES, NetworkId import zero_ex.contract_artifacts +from zero_ex.contract_wrappers.exchange.types import Order, order_to_jsdict from zero_ex.dev_utils.type_assertions import ( assert_is_address, assert_is_hex_string, @@ -133,238 +87,6 @@ class SignatureType(Enum): N_SIGNATURE_TYPES = auto() -class Order(TypedDict): # pylint: disable=too-many-instance-attributes - """A Web3-compatible representation of the Exchange.Order struct. - - >>> from zero_ex.order_utils import asset_data_utils - >>> from eth_utils import remove_0x_prefix - >>> from datetime import datetime, timedelta - >>> import random - >>> order = Order( - ... makerAddress=maker_address, - ... takerAddress='0x0000000000000000000000000000000000000000', - ... senderAddress='0x0000000000000000000000000000000000000000', - ... feeRecipientAddress='0x0000000000000000000000000000000000000000', - ... makerAssetData=asset_data_utils.encode_erc20(zrx_address), - ... takerAssetData=asset_data_utils.encode_erc20(weth_address), - ... salt=random.randint(1, 100000000000000000), - ... makerFee=0, - ... takerFee=0, - ... makerAssetAmount=1, - ... takerAssetAmount=1, - ... expirationTimeSeconds=round( - ... (datetime.utcnow() + timedelta(days=1)).timestamp() - ... ) - ... ) - """ - - makerAddress: str - """Address that created the order.""" - - takerAddress: str - """Address that is allowed to fill the order. - - If set to 0, any address is allowed to fill the order. - """ - - feeRecipientAddress: str - """Address that will recieve fees when order is filled.""" - - senderAddress: str - """Address that is allowed to call Exchange contract methods that affect - this order. If set to 0, any address is allowed to call these methods. - """ - - makerAssetAmount: int - """Amount of makerAsset being offered by maker. Must be greater than 0.""" - - takerAssetAmount: int - """Amount of takerAsset being bid on by maker. Must be greater than 0.""" - - makerFee: int - """Amount of ZRX paid to feeRecipient by maker when order is filled. If - set to 0, no transfer of ZRX from maker to feeRecipient will be attempted. - """ - - takerFee: int - """Amount of ZRX paid to feeRecipient by taker when order is filled. If - set to 0, no transfer of ZRX from taker to feeRecipient will be attempted. - """ - - expirationTimeSeconds: int - """Timestamp in seconds at which order expires.""" - - salt: int - """Arbitrary number to facilitate uniqueness of the order's hash.""" - - makerAssetData: bytes - """Encoded data that can be decoded by a specified proxy contract when - transferring makerAsset. The last byte references the id of this proxy. - """ - - takerAssetData: bytes - """Encoded data that can be decoded by a specified proxy contract when - transferring takerAsset. The last byte references the id of this proxy. - """ - - -def make_empty_order() -> Order: - """Construct an empty order. - - Initializes all strings to "0x0000000000000000000000000000000000000000", - all numbers to 0, and all bytes to nulls. - """ - return { - "makerAddress": _Constants.null_address, - "takerAddress": _Constants.null_address, - "senderAddress": _Constants.null_address, - "feeRecipientAddress": _Constants.null_address, - "makerAssetData": (b"\x00") * 20, - "takerAssetData": (b"\x00") * 20, - "salt": 0, - "makerFee": 0, - "takerFee": 0, - "makerAssetAmount": 0, - "takerAssetAmount": 0, - "expirationTimeSeconds": 0, - } - - -def order_to_jsdict( - order: Order, - exchange_address="0x0000000000000000000000000000000000000000", - signature: str = None, -) -> dict: - """Convert a Web3-compatible order struct to a JSON-schema-compatible dict. - - More specifically, do explicit decoding for the `bytes`:code: fields, and - convert numerics to strings. - - >>> import pprint - >>> pprint.pprint(order_to_jsdict( - ... { - ... 'makerAddress': "0x0000000000000000000000000000000000000000", - ... 'takerAddress': "0x0000000000000000000000000000000000000000", - ... 'feeRecipientAddress': - ... "0x0000000000000000000000000000000000000000", - ... 'senderAddress': "0x0000000000000000000000000000000000000000", - ... 'makerAssetAmount': 1, - ... 'takerAssetAmount': 1, - ... 'makerFee': 0, - ... 'takerFee': 0, - ... 'expirationTimeSeconds': 1, - ... 'salt': 1, - ... 'makerAssetData': (0).to_bytes(1, byteorder='big') * 20, - ... 'takerAssetData': (0).to_bytes(1, byteorder='big') * 20, - ... }, - ... )) - {'exchangeAddress': '0x0000000000000000000000000000000000000000', - 'expirationTimeSeconds': '1', - 'feeRecipientAddress': '0x0000000000000000000000000000000000000000', - 'makerAddress': '0x0000000000000000000000000000000000000000', - 'makerAssetAmount': '1', - 'makerAssetData': '0x0000000000000000000000000000000000000000', - 'makerFee': '0', - 'salt': '1', - 'senderAddress': '0x0000000000000000000000000000000000000000', - 'takerAddress': '0x0000000000000000000000000000000000000000', - 'takerAssetAmount': '1', - 'takerAssetData': '0x0000000000000000000000000000000000000000', - 'takerFee': '0'} - """ - jsdict = cast(Dict, copy(order)) - - # encode bytes fields - jsdict["makerAssetData"] = "0x" + order["makerAssetData"].hex() - jsdict["takerAssetData"] = "0x" + order["takerAssetData"].hex() - - jsdict["exchangeAddress"] = exchange_address - - jsdict["expirationTimeSeconds"] = str(order["expirationTimeSeconds"]) - - jsdict["makerAssetAmount"] = str(order["makerAssetAmount"]) - jsdict["takerAssetAmount"] = str(order["takerAssetAmount"]) - - jsdict["makerFee"] = str(order["makerFee"]) - jsdict["takerFee"] = str(order["takerFee"]) - - jsdict["salt"] = str(order["salt"]) - - if signature is not None: - jsdict["signature"] = signature - - assert_valid(jsdict, "/orderSchema") - - return jsdict - - -def jsdict_to_order(jsdict: dict) -> Order: - r"""Convert a JSON-schema-compatible dict order to a Web3-compatible struct. - - More specifically, do explicit encoding of the `bytes`:code: fields, and - parse integers from strings. - - >>> import pprint - >>> pprint.pprint(jsdict_to_order( - ... { - ... 'makerAddress': "0x0000000000000000000000000000000000000000", - ... 'takerAddress': "0x0000000000000000000000000000000000000000", - ... 'feeRecipientAddress': "0x0000000000000000000000000000000000000000", - ... 'senderAddress': "0x0000000000000000000000000000000000000000", - ... 'makerAssetAmount': "1000000000000000000", - ... 'takerAssetAmount': "1000000000000000000", - ... 'makerFee': "0", - ... 'takerFee': "0", - ... 'expirationTimeSeconds': "12345", - ... 'salt': "12345", - ... 'makerAssetData': "0x0000000000000000000000000000000000000000", - ... 'takerAssetData': "0x0000000000000000000000000000000000000000", - ... 'exchangeAddress': "0x0000000000000000000000000000000000000000", - ... }, - ... )) - {'expirationTimeSeconds': 12345, - 'feeRecipientAddress': '0x0000000000000000000000000000000000000000', - 'makerAddress': '0x0000000000000000000000000000000000000000', - 'makerAssetAmount': 1000000000000000000, - 'makerAssetData': b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' - b'\x00\x00\x00\x00\x00\x00\x00\x00', - 'makerFee': 0, - 'salt': 12345, - 'senderAddress': '0x0000000000000000000000000000000000000000', - 'takerAddress': '0x0000000000000000000000000000000000000000', - 'takerAssetAmount': 1000000000000000000, - 'takerAssetData': b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' - b'\x00\x00\x00\x00\x00\x00\x00\x00', - 'takerFee': 0} - """ # noqa: E501 (line too long) - assert_valid(jsdict, "/orderSchema") - - order = cast(Order, copy(jsdict)) - - order["makerAssetData"] = bytes.fromhex( - remove_0x_prefix(jsdict["makerAssetData"]) - ) - order["takerAssetData"] = bytes.fromhex( - remove_0x_prefix(jsdict["takerAssetData"]) - ) - - order["makerAssetAmount"] = int(jsdict["makerAssetAmount"]) - order["takerAssetAmount"] = int(jsdict["takerAssetAmount"]) - - order["makerFee"] = int(jsdict["makerFee"]) - order["takerFee"] = int(jsdict["takerFee"]) - - order["expirationTimeSeconds"] = int(jsdict["expirationTimeSeconds"]) - - order["salt"] = int(jsdict["salt"]) - - del order["exchangeAddress"] # type: ignore - # silence mypy pending release of - # https://github.com/python/mypy/issues/3550 - - return order - - def generate_order_hash_hex(order: Order, exchange_address: str) -> str: """Calculate the hash of the given order as a hexadecimal string. @@ -374,20 +96,20 @@ def generate_order_hash_hex(order: Order, exchange_address: str) -> str: :returns: A string, of ASCII hex digits, representing the order hash. >>> generate_order_hash_hex( - ... { - ... 'makerAddress': "0x0000000000000000000000000000000000000000", - ... 'takerAddress': "0x0000000000000000000000000000000000000000", - ... 'feeRecipientAddress': "0x0000000000000000000000000000000000000000", - ... 'senderAddress': "0x0000000000000000000000000000000000000000", - ... 'makerAssetAmount': "1000000000000000000", - ... 'takerAssetAmount': "1000000000000000000", - ... 'makerFee': "0", - ... 'takerFee': "0", - ... 'expirationTimeSeconds': "12345", - ... 'salt': "12345", - ... 'makerAssetData': (0).to_bytes(1, byteorder='big') * 20, - ... 'takerAssetData': (0).to_bytes(1, byteorder='big') * 20, - ... }, + ... Order( + ... makerAddress="0x0000000000000000000000000000000000000000", + ... takerAddress="0x0000000000000000000000000000000000000000", + ... feeRecipientAddress="0x0000000000000000000000000000000000000000", + ... senderAddress="0x0000000000000000000000000000000000000000", + ... makerAssetAmount="1000000000000000000", + ... takerAssetAmount="1000000000000000000", + ... makerFee="0", + ... takerFee="0", + ... expirationTimeSeconds="12345", + ... salt="12345", + ... makerAssetData=((0).to_bytes(1, byteorder='big') * 20), + ... takerAssetData=((0).to_bytes(1, byteorder='big') * 20), + ... ), ... exchange_address="0x0000000000000000000000000000000000000000", ... ) '55eaa6ec02f3224d30873577e9ddd069a288c16d6fb407210eecbc501fa76692' @@ -429,19 +151,6 @@ def int_to_32_big_endian_bytes(i: int): ).hex() -class OrderInfo(NamedTuple): - """A Web3-compatible representation of the Exchange.OrderInfo struct.""" - - order_status: str - """A `str`:code: describing the order's validity and fillability.""" - - order_hash: bytes - """A `bytes`:code: object representing the EIP712 hash of the order.""" - - order_taker_asset_filled_amount: int - """An `int`:code: indicating the amount that has already been filled.""" - - def is_valid_signature( provider: BaseProvider, data: str, signature: str, signer_address: str ) -> Tuple[bool, str]: @@ -636,3 +345,21 @@ def sign_hash( "Signature returned from web3 provider is in an unknown format." + " Attempted to parse as RSV and as VRS." ) + + +def sign_hash_to_bytes( + provider: BaseProvider, signer_address: str, hash_hex: str +) -> bytes: + """Sign a message with the given hash, and return the signature. + + >>> provider = Web3.HTTPProvider("http://127.0.0.1:8545") + >>> sign_hash_to_bytes( + ... provider, + ... Web3(provider).personal.listAccounts[0], + ... '0x34decbedc118904df65f379a175bb39ca18209d6ce41d5ed549d54e6e0a95004', + ... ).decode(encoding='utf_8') + '1b117902c86dfb95fe0d1badd983ee166ad259b27acb220174cbb4460d872871137feabdfe76e05924b484789f79af4ee7fa29ec006cedce1bbf369320d034e10b03' + """ # noqa: E501 (line too long) + return remove_0x_prefix( + sign_hash(provider, signer_address, hash_hex) + ).encode(encoding="utf_8") diff --git a/python-packages/order_utils/test/test_generate_order_hash_hex.py b/python-packages/order_utils/test/test_generate_order_hash_hex.py index 38b503289b..21b8dda2db 100644 --- a/python-packages/order_utils/test/test_generate_order_hash_hex.py +++ b/python-packages/order_utils/test/test_generate_order_hash_hex.py @@ -1,6 +1,6 @@ """Test zero_ex.order_utils.get_order_hash_hex().""" -from zero_ex.order_utils import generate_order_hash_hex, make_empty_order +from zero_ex.order_utils import generate_order_hash_hex def test_get_order_hash_hex__empty_order(): @@ -9,6 +9,22 @@ def test_get_order_hash_hex__empty_order(): "faa49b35faeb9197e9c3ba7a52075e6dad19739549f153b77dfcf59408a4b422" ) actual_hash_hex = generate_order_hash_hex( - make_empty_order(), "0x0000000000000000000000000000000000000000" + { + "makerAddress": "0x0000000000000000000000000000000000000000", + "takerAddress": "0x0000000000000000000000000000000000000000", + "senderAddress": "0x0000000000000000000000000000000000000000", + "feeRecipientAddress": ( + "0x0000000000000000000000000000000000000000" + ), + "makerAssetData": (b"\x00") * 20, + "takerAssetData": (b"\x00") * 20, + "salt": 0, + "makerFee": 0, + "takerFee": 0, + "makerAssetAmount": 0, + "takerAssetAmount": 0, + "expirationTimeSeconds": 0, + }, + "0x0000000000000000000000000000000000000000", ) assert actual_hash_hex == expected_hash_hex diff --git a/python-packages/order_utils/test/test_signature_utils.py b/python-packages/order_utils/test/test_signature_utils.py index c5acc9d627..8c5ec18443 100644 --- a/python-packages/order_utils/test/test_signature_utils.py +++ b/python-packages/order_utils/test/test_signature_utils.py @@ -3,7 +3,7 @@ import pytest from web3 import Web3 -from zero_ex.order_utils import is_valid_signature +from zero_ex.order_utils import is_valid_signature, sign_hash_to_bytes def test_is_valid_signature__provider_wrong_type(): @@ -126,3 +126,17 @@ def test_is_valid_signature__unsupported_sig_types(): ) assert is_valid is False assert reason == "SIGNATURE_UNSUPPORTED" + + +def test_sign_hash_to_bytes__golden_path(): + """Test the happy path through sign_hash_to_bytes().""" + provider = Web3.HTTPProvider("http://127.0.0.1:8545") + signature = sign_hash_to_bytes( + provider, + Web3(provider).personal.listAccounts[0], # pylint: disable=no-member + "0x34decbedc118904df65f379a175bb39ca18209d6ce41d5ed549d54e6e0a95004", + ) + assert ( + signature + == b"1b117902c86dfb95fe0d1badd983ee166ad259b27acb220174cbb4460d872871137feabdfe76e05924b484789f79af4ee7fa29ec006cedce1bbf369320d034e10b03" # noqa: E501 (line too long) + ) diff --git a/python-packages/parallel b/python-packages/parallel new file mode 100755 index 0000000000..12f385baaf --- /dev/null +++ b/python-packages/parallel @@ -0,0 +1,44 @@ +#!/usr/bin/env python + +"""Run the given command in all packages in parallel. + +Handy for quick verification test runs, but annoying in that all of the output +is interleaved. + +$ ./parallel ./setup.py lint + +This will `cd` into each package, run `./setup.py lint`, then `cd ..`, all in +parallel, in a separate process for each package. The number of processes is +decided by ProcessPoolExecutor. Replace "lint" with any of "test", "clean", +"build_sphinx" (for docs), etc. + +Also consider: + +$ ./parallel pip install -e .[dev] # install all the packages in editable mode + +$ ./parallel pip uninstall $(basename $(pwd)) + +>>>""" + +from concurrent.futures import ProcessPoolExecutor +from os import chdir +from subprocess import check_call +from sys import argv + +PACKAGES = [ + "contract_addresses", + "contract_artifacts", + "contract_wrappers", + "json_schemas", + "sra_client", + "order_utils", + "middlewares", +] + +def run_cmd_on_package(package: str): + """cd to the package dir, ./setup.py lint, cd ..""" + chdir(package) + check_call(f"{' '.join(argv[1:])}".split()) + chdir("..") + +ProcessPoolExecutor().map(run_cmd_on_package, PACKAGES) diff --git a/python-packages/pre_install b/python-packages/pre_install index dca70e5bce..42e561ca88 100755 --- a/python-packages/pre_install +++ b/python-packages/pre_install @@ -5,17 +5,21 @@ from os import chdir, path import subprocess +from concurrent.futures import ProcessPoolExecutor +from os import chdir +from subprocess import check_call +from sys import argv + PACKAGES = [ "contract_wrappers", "contract_artifacts", + "json_schemas", ] -for package in PACKAGES: - print(f"Running command `pre_install` in package {package}") +def run_cmd_on_package(package: str): + """cd to the package dir, ./setup.py pre_install, cd ..""" chdir(package) - subprocess.check_call( - ( - path.join(".", "setup.py") + " pre_install" - ).split() - ) + check_call(f"{path.join('.', 'setup.py')} pre_install".split()) chdir("..") + +ProcessPoolExecutor().map(run_cmd_on_package, PACKAGES) diff --git a/python-packages/sra_client/setup.py b/python-packages/sra_client/setup.py index 1fef09400a..b61c6e7d92 100755 --- a/python-packages/sra_client/setup.py +++ b/python-packages/sra_client/setup.py @@ -193,6 +193,7 @@ def run(self): "build_sphinx": { "source_dir": ("setup.py", "src"), "build_dir": ("setup.py", "build/docs"), + "warning_is_error": ("setup.py", "true"), } }, ) diff --git a/python-packages/sra_client/src/zero_ex/sra_client/__init__.py b/python-packages/sra_client/src/zero_ex/sra_client/__init__.py index 9cbdcd2a81..de7e254ade 100644 --- a/python-packages/sra_client/src/zero_ex/sra_client/__init__.py +++ b/python-packages/sra_client/src/zero_ex/sra_client/__init__.py @@ -105,10 +105,9 @@ Post an order for our Maker to trade ZRX for WETH: +>>> from zero_ex.contract_wrappers.exchange.types import Order, order_to_jsdict >>> from zero_ex.order_utils import ( ... asset_data_utils, -... Order, -... order_to_jsdict, ... sign_hash) >>> import random >>> from datetime import datetime, timedelta @@ -254,7 +253,7 @@ Select an order from the orderbook ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ->>> from zero_ex.order_utils import jsdict_to_order +>>> from zero_ex.contract_wrappers.exchange.types import jsdict_to_order >>> order = jsdict_to_order(orderbook.bids.records[0].order) >>> from pprint import pprint >>> pprint(order) @@ -322,8 +321,8 @@ ... ) >>> exchange.fill_order( ... order=order, -... taker_amount=order['makerAssetAmount']/2, # note the half fill -... signature=order['signature'], +... taker_asset_fill_amount=order['makerAssetAmount']/2, # note the half fill +... signature=order['signature'].replace('0x', '').encode('utf-8'), ... tx_params=TxParams(from_=taker_address) ... ) HexBytes('0x...') diff --git a/python-packages/test b/python-packages/test index 5bf37cca3f..62c25dc1ec 100755 --- a/python-packages/test +++ b/python-packages/test @@ -1,13 +1,3 @@ -#!/usr/bin/env python +#!/usr/bin/env bash -"""Script to run tests against local copy of all components.""" - -from os import path -import subprocess - -subprocess.check_call( - ( - f"{path.join('.', 'cmd_pkgs_in_dep_order.py')}" - + f" {path.join('.', 'setup.py')} test" - ).split() -) +./parallel ./setup.py test