From 93d008e444ff9c0193aecf7483ab6cd8b4b671dd Mon Sep 17 00:00:00 2001 From: Rob Date: Sun, 7 May 2023 17:38:58 -0700 Subject: [PATCH] Updating cli scripts to Moonworm v0.6.2 --- dao/Diamond.py | 19 +- dao/DiamondCutFacet.py | 21 +- dao/DiamondLoupeFacet.py | 73 +++- dao/ERC1155WithTerminusStorage.py | 553 ++++++++++++++++++++++++++++++ dao/ERC20Facet.py | 114 +++--- dao/ERC20Initializer.py | 31 +- dao/ERC20WithCommonStorage.py | 465 +++++++++++++++++++++++++ dao/MoonstreamTokenFaucet.py | 91 +++-- dao/OwnershipFacet.py | 27 +- dao/TerminusControllerFacet.py | 2 +- dao/TerminusFacet.py | 2 +- dao/TerminusInitializer.py | 21 +- dao/TerminusPermissions.py | 207 +++++++++++ dao/TokenDrainerFacet.py | 367 ++++++++++++++++++++ 14 files changed, 1881 insertions(+), 112 deletions(-) create mode 100644 dao/ERC1155WithTerminusStorage.py create mode 100644 dao/ERC20WithCommonStorage.py create mode 100644 dao/TerminusPermissions.py create mode 100644 dao/TokenDrainerFacet.py diff --git a/dao/Diamond.py b/dao/Diamond.py index 2103bad..8583552 100644 --- a/dao/Diamond.py +++ b/dao/Diamond.py @@ -1,5 +1,5 @@ # Code generated by moonworm : https://github.com/bugout-dev/moonworm -# Moonworm version : 0.1.14 +# Moonworm version : 0.6.2 import argparse import json @@ -30,8 +30,8 @@ def boolean_argument_type(raw_value: str) -> bool: ) -def bytes_argument_type(raw_value: str) -> bytes: - return raw_value.encode() +def bytes_argument_type(raw_value: str) -> str: + return raw_value def get_abi_json(abi_name: str) -> List[Dict[str, Any]]: @@ -92,6 +92,7 @@ def deploy( ) self.address = deployed_contract.address self.contract = deployed_contract + return deployed_contract.tx def assert_contract_is_instantiated(self) -> None: if self.contract is None: @@ -127,6 +128,12 @@ def add_default_arguments(parser: argparse.ArgumentParser, transact: bool) -> No "--address", required=False, help="Address of deployed contract to connect to" ) if not transact: + parser.add_argument( + "--block-number", + required=False, + type=int, + help="Call at the given block number, defaults to latest", + ) return parser.add_argument( "--sender", required=True, help="Path to keystore file for transaction sender" @@ -158,6 +165,10 @@ def add_default_arguments(parser: argparse.ArgumentParser, transact: bool) -> No parser.add_argument( "--nonce", type=int, default=None, help="Nonce for the transaction (optional)" ) + parser.add_argument( + "--value", default=None, help="Value of the transaction in wei(optional)" + ) + parser.add_argument("--verbose", action="store_true", help="Print verbose output") def handle_deploy(args: argparse.Namespace) -> None: @@ -170,6 +181,8 @@ def handle_deploy(args: argparse.Namespace) -> None: transaction_config=transaction_config, ) print(result) + if args.verbose: + print(result.info()) def handle_verify_contract(args: argparse.Namespace) -> None: diff --git a/dao/DiamondCutFacet.py b/dao/DiamondCutFacet.py index e0822d4..85a41ad 100644 --- a/dao/DiamondCutFacet.py +++ b/dao/DiamondCutFacet.py @@ -1,5 +1,5 @@ # Code generated by moonworm : https://github.com/bugout-dev/moonworm -# Moonworm version : 0.1.14 +# Moonworm version : 0.6.2 import argparse import json @@ -30,8 +30,8 @@ def boolean_argument_type(raw_value: str) -> bool: ) -def bytes_argument_type(raw_value: str) -> bytes: - return raw_value.encode() +def bytes_argument_type(raw_value: str) -> str: + return raw_value def get_abi_json(abi_name: str) -> List[Dict[str, Any]]: @@ -85,6 +85,7 @@ def deploy(self, transaction_config): deployed_contract = contract_class.deploy(transaction_config) self.address = deployed_contract.address self.contract = deployed_contract + return deployed_contract.tx def assert_contract_is_instantiated(self) -> None: if self.contract is None: @@ -132,6 +133,12 @@ def add_default_arguments(parser: argparse.ArgumentParser, transact: bool) -> No "--address", required=False, help="Address of deployed contract to connect to" ) if not transact: + parser.add_argument( + "--block-number", + required=False, + type=int, + help="Call at the given block number, defaults to latest", + ) return parser.add_argument( "--sender", required=True, help="Path to keystore file for transaction sender" @@ -163,6 +170,10 @@ def add_default_arguments(parser: argparse.ArgumentParser, transact: bool) -> No parser.add_argument( "--nonce", type=int, default=None, help="Nonce for the transaction (optional)" ) + parser.add_argument( + "--value", default=None, help="Value of the transaction in wei(optional)" + ) + parser.add_argument("--verbose", action="store_true", help="Print verbose output") def handle_deploy(args: argparse.Namespace) -> None: @@ -171,6 +182,8 @@ def handle_deploy(args: argparse.Namespace) -> None: contract = DiamondCutFacet(None) result = contract.deploy(transaction_config=transaction_config) print(result) + if args.verbose: + print(result.info()) def handle_verify_contract(args: argparse.Namespace) -> None: @@ -191,6 +204,8 @@ def handle_diamond_cut(args: argparse.Namespace) -> None: transaction_config=transaction_config, ) print(result) + if args.verbose: + print(result.info()) def generate_cli() -> argparse.ArgumentParser: diff --git a/dao/DiamondLoupeFacet.py b/dao/DiamondLoupeFacet.py index 203a806..84af63d 100644 --- a/dao/DiamondLoupeFacet.py +++ b/dao/DiamondLoupeFacet.py @@ -1,5 +1,5 @@ # Code generated by moonworm : https://github.com/bugout-dev/moonworm -# Moonworm version : 0.1.14 +# Moonworm version : 0.6.2 import argparse import json @@ -30,8 +30,8 @@ def boolean_argument_type(raw_value: str) -> bool: ) -def bytes_argument_type(raw_value: str) -> bytes: - return raw_value.encode() +def bytes_argument_type(raw_value: str) -> str: + return raw_value def get_abi_json(abi_name: str) -> List[Dict[str, Any]]: @@ -85,6 +85,7 @@ def deploy(self, transaction_config): deployed_contract = contract_class.deploy(transaction_config) self.address = deployed_contract.address self.contract = deployed_contract + return deployed_contract.tx def assert_contract_is_instantiated(self) -> None: if self.contract is None: @@ -95,25 +96,43 @@ def verify_contract(self): contract_class = contract_from_build(self.contract_name) contract_class.publish_source(self.contract) - def facet_address(self, _function_selector: bytes) -> Any: + def facet_address( + self, + _function_selector: bytes, + block_number: Optional[Union[str, int]] = "latest", + ) -> Any: self.assert_contract_is_instantiated() - return self.contract.facetAddress.call(_function_selector) + return self.contract.facetAddress.call( + _function_selector, block_identifier=block_number + ) - def facet_addresses(self) -> Any: + def facet_addresses( + self, block_number: Optional[Union[str, int]] = "latest" + ) -> Any: self.assert_contract_is_instantiated() - return self.contract.facetAddresses.call() + return self.contract.facetAddresses.call(block_identifier=block_number) - def facet_function_selectors(self, _facet: ChecksumAddress) -> Any: + def facet_function_selectors( + self, + _facet: ChecksumAddress, + block_number: Optional[Union[str, int]] = "latest", + ) -> Any: self.assert_contract_is_instantiated() - return self.contract.facetFunctionSelectors.call(_facet) + return self.contract.facetFunctionSelectors.call( + _facet, block_identifier=block_number + ) - def facets(self) -> Any: + def facets(self, block_number: Optional[Union[str, int]] = "latest") -> Any: self.assert_contract_is_instantiated() - return self.contract.facets.call() + return self.contract.facets.call(block_identifier=block_number) - def supports_interface(self, _interface_id: bytes) -> Any: + def supports_interface( + self, _interface_id: bytes, block_number: Optional[Union[str, int]] = "latest" + ) -> Any: self.assert_contract_is_instantiated() - return self.contract.supportsInterface.call(_interface_id) + return self.contract.supportsInterface.call( + _interface_id, block_identifier=block_number + ) def get_transaction_config(args: argparse.Namespace) -> Dict[str, Any]: @@ -140,6 +159,12 @@ def add_default_arguments(parser: argparse.ArgumentParser, transact: bool) -> No "--address", required=False, help="Address of deployed contract to connect to" ) if not transact: + parser.add_argument( + "--block-number", + required=False, + type=int, + help="Call at the given block number, defaults to latest", + ) return parser.add_argument( "--sender", required=True, help="Path to keystore file for transaction sender" @@ -171,6 +196,10 @@ def add_default_arguments(parser: argparse.ArgumentParser, transact: bool) -> No parser.add_argument( "--nonce", type=int, default=None, help="Nonce for the transaction (optional)" ) + parser.add_argument( + "--value", default=None, help="Value of the transaction in wei(optional)" + ) + parser.add_argument("--verbose", action="store_true", help="Print verbose output") def handle_deploy(args: argparse.Namespace) -> None: @@ -179,6 +208,8 @@ def handle_deploy(args: argparse.Namespace) -> None: contract = DiamondLoupeFacet(None) result = contract.deploy(transaction_config=transaction_config) print(result) + if args.verbose: + print(result.info()) def handle_verify_contract(args: argparse.Namespace) -> None: @@ -191,35 +222,41 @@ def handle_verify_contract(args: argparse.Namespace) -> None: def handle_facet_address(args: argparse.Namespace) -> None: network.connect(args.network) contract = DiamondLoupeFacet(args.address) - result = contract.facet_address(_function_selector=args.function_selector_arg) + result = contract.facet_address( + _function_selector=args.function_selector_arg, block_number=args.block_number + ) print(result) def handle_facet_addresses(args: argparse.Namespace) -> None: network.connect(args.network) contract = DiamondLoupeFacet(args.address) - result = contract.facet_addresses() + result = contract.facet_addresses(block_number=args.block_number) print(result) def handle_facet_function_selectors(args: argparse.Namespace) -> None: network.connect(args.network) contract = DiamondLoupeFacet(args.address) - result = contract.facet_function_selectors(_facet=args.facet_arg) + result = contract.facet_function_selectors( + _facet=args.facet_arg, block_number=args.block_number + ) print(result) def handle_facets(args: argparse.Namespace) -> None: network.connect(args.network) contract = DiamondLoupeFacet(args.address) - result = contract.facets() + result = contract.facets(block_number=args.block_number) print(result) def handle_supports_interface(args: argparse.Namespace) -> None: network.connect(args.network) contract = DiamondLoupeFacet(args.address) - result = contract.supports_interface(_interface_id=args.interface_id_arg) + result = contract.supports_interface( + _interface_id=args.interface_id_arg, block_number=args.block_number + ) print(result) diff --git a/dao/ERC1155WithTerminusStorage.py b/dao/ERC1155WithTerminusStorage.py new file mode 100644 index 0000000..41518ee --- /dev/null +++ b/dao/ERC1155WithTerminusStorage.py @@ -0,0 +1,553 @@ +# Code generated by moonworm : https://github.com/bugout-dev/moonworm +# Moonworm version : 0.6.2 + +import argparse +import json +import os +from pathlib import Path +from typing import Any, Dict, List, Optional, Union + +from brownie import Contract, network, project +from brownie.network.contract import ContractContainer +from eth_typing.evm import ChecksumAddress + + +PROJECT_DIRECTORY = os.path.abspath(os.path.join(os.path.dirname(__file__), "..")) +BUILD_DIRECTORY = os.path.join(PROJECT_DIRECTORY, "build", "contracts") + + +def boolean_argument_type(raw_value: str) -> bool: + TRUE_VALUES = ["1", "t", "y", "true", "yes"] + FALSE_VALUES = ["0", "f", "n", "false", "no"] + + if raw_value.lower() in TRUE_VALUES: + return True + elif raw_value.lower() in FALSE_VALUES: + return False + + raise ValueError( + f"Invalid boolean argument: {raw_value}. Value must be one of: {','.join(TRUE_VALUES + FALSE_VALUES)}" + ) + + +def bytes_argument_type(raw_value: str) -> str: + return raw_value + + +def get_abi_json(abi_name: str) -> List[Dict[str, Any]]: + abi_full_path = os.path.join(BUILD_DIRECTORY, f"{abi_name}.json") + if not os.path.isfile(abi_full_path): + raise IOError( + f"File does not exist: {abi_full_path}. Maybe you have to compile the smart contracts?" + ) + + with open(abi_full_path, "r") as ifp: + build = json.load(ifp) + + abi_json = build.get("abi") + if abi_json is None: + raise ValueError(f"Could not find ABI definition in: {abi_full_path}") + + return abi_json + + +def contract_from_build(abi_name: str) -> ContractContainer: + # This is workaround because brownie currently doesn't support loading the same project multiple + # times. This causes problems when using multiple contracts from the same project in the same + # python project. + PROJECT = project.main.Project("moonworm", Path(PROJECT_DIRECTORY)) + + abi_full_path = os.path.join(BUILD_DIRECTORY, f"{abi_name}.json") + if not os.path.isfile(abi_full_path): + raise IOError( + f"File does not exist: {abi_full_path}. Maybe you have to compile the smart contracts?" + ) + + with open(abi_full_path, "r") as ifp: + build = json.load(ifp) + + return ContractContainer(PROJECT, build) + + +class ERC1155WithTerminusStorage: + def __init__(self, contract_address: Optional[ChecksumAddress]): + self.contract_name = "ERC1155WithTerminusStorage" + self.address = contract_address + self.contract = None + self.abi = get_abi_json("ERC1155WithTerminusStorage") + if self.address is not None: + self.contract: Optional[Contract] = Contract.from_abi( + self.contract_name, self.address, self.abi + ) + + def deploy(self, transaction_config): + contract_class = contract_from_build(self.contract_name) + deployed_contract = contract_class.deploy(transaction_config) + self.address = deployed_contract.address + self.contract = deployed_contract + return deployed_contract.tx + + def assert_contract_is_instantiated(self) -> None: + if self.contract is None: + raise Exception("contract has not been instantiated") + + def verify_contract(self): + self.assert_contract_is_instantiated() + contract_class = contract_from_build(self.contract_name) + contract_class.publish_source(self.contract) + + def approve_for_pool( + self, pool_id: int, operator: ChecksumAddress, transaction_config + ) -> Any: + self.assert_contract_is_instantiated() + return self.contract.approveForPool(pool_id, operator, transaction_config) + + def balance_of( + self, + account: ChecksumAddress, + id: int, + block_number: Optional[Union[str, int]] = "latest", + ) -> Any: + self.assert_contract_is_instantiated() + return self.contract.balanceOf.call(account, id, block_identifier=block_number) + + def balance_of_batch( + self, + accounts: List, + ids: List, + block_number: Optional[Union[str, int]] = "latest", + ) -> Any: + self.assert_contract_is_instantiated() + return self.contract.balanceOfBatch.call( + accounts, ids, block_identifier=block_number + ) + + def is_approved_for_all( + self, + account: ChecksumAddress, + operator: ChecksumAddress, + block_number: Optional[Union[str, int]] = "latest", + ) -> Any: + self.assert_contract_is_instantiated() + return self.contract.isApprovedForAll.call( + account, operator, block_identifier=block_number + ) + + def is_approved_for_pool( + self, + pool_id: int, + operator: ChecksumAddress, + block_number: Optional[Union[str, int]] = "latest", + ) -> Any: + self.assert_contract_is_instantiated() + return self.contract.isApprovedForPool.call( + pool_id, operator, block_identifier=block_number + ) + + def safe_batch_transfer_from( + self, + from_: ChecksumAddress, + to: ChecksumAddress, + ids: List, + amounts: List, + data: bytes, + transaction_config, + ) -> Any: + self.assert_contract_is_instantiated() + return self.contract.safeBatchTransferFrom( + from_, to, ids, amounts, data, transaction_config + ) + + def safe_transfer_from( + self, + from_: ChecksumAddress, + to: ChecksumAddress, + id: int, + amount: int, + data: bytes, + transaction_config, + ) -> Any: + self.assert_contract_is_instantiated() + return self.contract.safeTransferFrom( + from_, to, id, amount, data, transaction_config + ) + + def set_approval_for_all( + self, operator: ChecksumAddress, approved: bool, transaction_config + ) -> Any: + self.assert_contract_is_instantiated() + return self.contract.setApprovalForAll(operator, approved, transaction_config) + + def supports_interface( + self, interface_id: bytes, block_number: Optional[Union[str, int]] = "latest" + ) -> Any: + self.assert_contract_is_instantiated() + return self.contract.supportsInterface.call( + interface_id, block_identifier=block_number + ) + + def unapprove_for_pool( + self, pool_id: int, operator: ChecksumAddress, transaction_config + ) -> Any: + self.assert_contract_is_instantiated() + return self.contract.unapproveForPool(pool_id, operator, transaction_config) + + def uri( + self, pool_id: int, block_number: Optional[Union[str, int]] = "latest" + ) -> Any: + self.assert_contract_is_instantiated() + return self.contract.uri.call(pool_id, block_identifier=block_number) + + +def get_transaction_config(args: argparse.Namespace) -> Dict[str, Any]: + signer = network.accounts.load(args.sender, args.password) + transaction_config: Dict[str, Any] = {"from": signer} + if args.gas_price is not None: + transaction_config["gas_price"] = args.gas_price + if args.max_fee_per_gas is not None: + transaction_config["max_fee"] = args.max_fee_per_gas + if args.max_priority_fee_per_gas is not None: + transaction_config["priority_fee"] = args.max_priority_fee_per_gas + if args.confirmations is not None: + transaction_config["required_confs"] = args.confirmations + if args.nonce is not None: + transaction_config["nonce"] = args.nonce + return transaction_config + + +def add_default_arguments(parser: argparse.ArgumentParser, transact: bool) -> None: + parser.add_argument( + "--network", required=True, help="Name of brownie network to connect to" + ) + parser.add_argument( + "--address", required=False, help="Address of deployed contract to connect to" + ) + if not transact: + parser.add_argument( + "--block-number", + required=False, + type=int, + help="Call at the given block number, defaults to latest", + ) + return + parser.add_argument( + "--sender", required=True, help="Path to keystore file for transaction sender" + ) + parser.add_argument( + "--password", + required=False, + help="Password to keystore file (if you do not provide it, you will be prompted for it)", + ) + parser.add_argument( + "--gas-price", default=None, help="Gas price at which to submit transaction" + ) + parser.add_argument( + "--max-fee-per-gas", + default=None, + help="Max fee per gas for EIP1559 transactions", + ) + parser.add_argument( + "--max-priority-fee-per-gas", + default=None, + help="Max priority fee per gas for EIP1559 transactions", + ) + parser.add_argument( + "--confirmations", + type=int, + default=None, + help="Number of confirmations to await before considering a transaction completed", + ) + parser.add_argument( + "--nonce", type=int, default=None, help="Nonce for the transaction (optional)" + ) + parser.add_argument( + "--value", default=None, help="Value of the transaction in wei(optional)" + ) + parser.add_argument("--verbose", action="store_true", help="Print verbose output") + + +def handle_deploy(args: argparse.Namespace) -> None: + network.connect(args.network) + transaction_config = get_transaction_config(args) + contract = ERC1155WithTerminusStorage(None) + result = contract.deploy(transaction_config=transaction_config) + print(result) + if args.verbose: + print(result.info()) + + +def handle_verify_contract(args: argparse.Namespace) -> None: + network.connect(args.network) + contract = ERC1155WithTerminusStorage(args.address) + result = contract.verify_contract() + print(result) + + +def handle_approve_for_pool(args: argparse.Namespace) -> None: + network.connect(args.network) + contract = ERC1155WithTerminusStorage(args.address) + transaction_config = get_transaction_config(args) + result = contract.approve_for_pool( + pool_id=args.pool_id, + operator=args.operator, + transaction_config=transaction_config, + ) + print(result) + if args.verbose: + print(result.info()) + + +def handle_balance_of(args: argparse.Namespace) -> None: + network.connect(args.network) + contract = ERC1155WithTerminusStorage(args.address) + result = contract.balance_of( + account=args.account, id=args.id, block_number=args.block_number + ) + print(result) + + +def handle_balance_of_batch(args: argparse.Namespace) -> None: + network.connect(args.network) + contract = ERC1155WithTerminusStorage(args.address) + result = contract.balance_of_batch( + accounts=args.accounts, ids=args.ids, block_number=args.block_number + ) + print(result) + + +def handle_is_approved_for_all(args: argparse.Namespace) -> None: + network.connect(args.network) + contract = ERC1155WithTerminusStorage(args.address) + result = contract.is_approved_for_all( + account=args.account, operator=args.operator, block_number=args.block_number + ) + print(result) + + +def handle_is_approved_for_pool(args: argparse.Namespace) -> None: + network.connect(args.network) + contract = ERC1155WithTerminusStorage(args.address) + result = contract.is_approved_for_pool( + pool_id=args.pool_id, operator=args.operator, block_number=args.block_number + ) + print(result) + + +def handle_safe_batch_transfer_from(args: argparse.Namespace) -> None: + network.connect(args.network) + contract = ERC1155WithTerminusStorage(args.address) + transaction_config = get_transaction_config(args) + result = contract.safe_batch_transfer_from( + from_=args.from_arg, + to=args.to, + ids=args.ids, + amounts=args.amounts, + data=args.data, + transaction_config=transaction_config, + ) + print(result) + if args.verbose: + print(result.info()) + + +def handle_safe_transfer_from(args: argparse.Namespace) -> None: + network.connect(args.network) + contract = ERC1155WithTerminusStorage(args.address) + transaction_config = get_transaction_config(args) + result = contract.safe_transfer_from( + from_=args.from_arg, + to=args.to, + id=args.id, + amount=args.amount, + data=args.data, + transaction_config=transaction_config, + ) + print(result) + if args.verbose: + print(result.info()) + + +def handle_set_approval_for_all(args: argparse.Namespace) -> None: + network.connect(args.network) + contract = ERC1155WithTerminusStorage(args.address) + transaction_config = get_transaction_config(args) + result = contract.set_approval_for_all( + operator=args.operator, + approved=args.approved, + transaction_config=transaction_config, + ) + print(result) + if args.verbose: + print(result.info()) + + +def handle_supports_interface(args: argparse.Namespace) -> None: + network.connect(args.network) + contract = ERC1155WithTerminusStorage(args.address) + result = contract.supports_interface( + interface_id=args.interface_id, block_number=args.block_number + ) + print(result) + + +def handle_unapprove_for_pool(args: argparse.Namespace) -> None: + network.connect(args.network) + contract = ERC1155WithTerminusStorage(args.address) + transaction_config = get_transaction_config(args) + result = contract.unapprove_for_pool( + pool_id=args.pool_id, + operator=args.operator, + transaction_config=transaction_config, + ) + print(result) + if args.verbose: + print(result.info()) + + +def handle_uri(args: argparse.Namespace) -> None: + network.connect(args.network) + contract = ERC1155WithTerminusStorage(args.address) + result = contract.uri(pool_id=args.pool_id, block_number=args.block_number) + print(result) + + +def generate_cli() -> argparse.ArgumentParser: + parser = argparse.ArgumentParser(description="CLI for ERC1155WithTerminusStorage") + parser.set_defaults(func=lambda _: parser.print_help()) + subcommands = parser.add_subparsers() + + deploy_parser = subcommands.add_parser("deploy") + add_default_arguments(deploy_parser, True) + deploy_parser.set_defaults(func=handle_deploy) + + verify_contract_parser = subcommands.add_parser("verify-contract") + add_default_arguments(verify_contract_parser, False) + verify_contract_parser.set_defaults(func=handle_verify_contract) + + approve_for_pool_parser = subcommands.add_parser("approve-for-pool") + add_default_arguments(approve_for_pool_parser, True) + approve_for_pool_parser.add_argument( + "--pool-id", required=True, help="Type: uint256", type=int + ) + approve_for_pool_parser.add_argument( + "--operator", required=True, help="Type: address" + ) + approve_for_pool_parser.set_defaults(func=handle_approve_for_pool) + + balance_of_parser = subcommands.add_parser("balance-of") + add_default_arguments(balance_of_parser, False) + balance_of_parser.add_argument("--account", required=True, help="Type: address") + balance_of_parser.add_argument( + "--id", required=True, help="Type: uint256", type=int + ) + balance_of_parser.set_defaults(func=handle_balance_of) + + balance_of_batch_parser = subcommands.add_parser("balance-of-batch") + add_default_arguments(balance_of_batch_parser, False) + balance_of_batch_parser.add_argument( + "--accounts", required=True, help="Type: address[]", nargs="+" + ) + balance_of_batch_parser.add_argument( + "--ids", required=True, help="Type: uint256[]", nargs="+" + ) + balance_of_batch_parser.set_defaults(func=handle_balance_of_batch) + + is_approved_for_all_parser = subcommands.add_parser("is-approved-for-all") + add_default_arguments(is_approved_for_all_parser, False) + is_approved_for_all_parser.add_argument( + "--account", required=True, help="Type: address" + ) + is_approved_for_all_parser.add_argument( + "--operator", required=True, help="Type: address" + ) + is_approved_for_all_parser.set_defaults(func=handle_is_approved_for_all) + + is_approved_for_pool_parser = subcommands.add_parser("is-approved-for-pool") + add_default_arguments(is_approved_for_pool_parser, False) + is_approved_for_pool_parser.add_argument( + "--pool-id", required=True, help="Type: uint256", type=int + ) + is_approved_for_pool_parser.add_argument( + "--operator", required=True, help="Type: address" + ) + is_approved_for_pool_parser.set_defaults(func=handle_is_approved_for_pool) + + safe_batch_transfer_from_parser = subcommands.add_parser("safe-batch-transfer-from") + add_default_arguments(safe_batch_transfer_from_parser, True) + safe_batch_transfer_from_parser.add_argument( + "--from-arg", required=True, help="Type: address" + ) + safe_batch_transfer_from_parser.add_argument( + "--to", required=True, help="Type: address" + ) + safe_batch_transfer_from_parser.add_argument( + "--ids", required=True, help="Type: uint256[]", nargs="+" + ) + safe_batch_transfer_from_parser.add_argument( + "--amounts", required=True, help="Type: uint256[]", nargs="+" + ) + safe_batch_transfer_from_parser.add_argument( + "--data", required=True, help="Type: bytes", type=bytes_argument_type + ) + safe_batch_transfer_from_parser.set_defaults(func=handle_safe_batch_transfer_from) + + safe_transfer_from_parser = subcommands.add_parser("safe-transfer-from") + add_default_arguments(safe_transfer_from_parser, True) + safe_transfer_from_parser.add_argument( + "--from-arg", required=True, help="Type: address" + ) + safe_transfer_from_parser.add_argument("--to", required=True, help="Type: address") + safe_transfer_from_parser.add_argument( + "--id", required=True, help="Type: uint256", type=int + ) + safe_transfer_from_parser.add_argument( + "--amount", required=True, help="Type: uint256", type=int + ) + safe_transfer_from_parser.add_argument( + "--data", required=True, help="Type: bytes", type=bytes_argument_type + ) + safe_transfer_from_parser.set_defaults(func=handle_safe_transfer_from) + + set_approval_for_all_parser = subcommands.add_parser("set-approval-for-all") + add_default_arguments(set_approval_for_all_parser, True) + set_approval_for_all_parser.add_argument( + "--operator", required=True, help="Type: address" + ) + set_approval_for_all_parser.add_argument( + "--approved", required=True, help="Type: bool", type=boolean_argument_type + ) + set_approval_for_all_parser.set_defaults(func=handle_set_approval_for_all) + + supports_interface_parser = subcommands.add_parser("supports-interface") + add_default_arguments(supports_interface_parser, False) + supports_interface_parser.add_argument( + "--interface-id", required=True, help="Type: bytes4", type=bytes_argument_type + ) + supports_interface_parser.set_defaults(func=handle_supports_interface) + + unapprove_for_pool_parser = subcommands.add_parser("unapprove-for-pool") + add_default_arguments(unapprove_for_pool_parser, True) + unapprove_for_pool_parser.add_argument( + "--pool-id", required=True, help="Type: uint256", type=int + ) + unapprove_for_pool_parser.add_argument( + "--operator", required=True, help="Type: address" + ) + unapprove_for_pool_parser.set_defaults(func=handle_unapprove_for_pool) + + uri_parser = subcommands.add_parser("uri") + add_default_arguments(uri_parser, False) + uri_parser.add_argument("--pool-id", required=True, help="Type: uint256", type=int) + uri_parser.set_defaults(func=handle_uri) + + return parser + + +def main() -> None: + parser = generate_cli() + args = parser.parse_args() + args.func(args) + + +if __name__ == "__main__": + main() diff --git a/dao/ERC20Facet.py b/dao/ERC20Facet.py index f6225ec..626b628 100644 --- a/dao/ERC20Facet.py +++ b/dao/ERC20Facet.py @@ -1,5 +1,5 @@ # Code generated by moonworm : https://github.com/bugout-dev/moonworm -# Moonworm version : 0.1.14 +# Moonworm version : 0.6.2 import argparse import json @@ -30,8 +30,8 @@ def boolean_argument_type(raw_value: str) -> bool: ) -def bytes_argument_type(raw_value: str) -> bytes: - return raw_value.encode() +def bytes_argument_type(raw_value: str) -> str: + return raw_value def get_abi_json(abi_name: str) -> List[Dict[str, Any]]: @@ -85,6 +85,7 @@ def deploy(self, transaction_config): deployed_contract = contract_class.deploy(transaction_config) self.address = deployed_contract.address self.contract = deployed_contract + return deployed_contract.tx def assert_contract_is_instantiated(self) -> None: if self.contract is None: @@ -95,21 +96,32 @@ def verify_contract(self): contract_class = contract_from_build(self.contract_name) contract_class.publish_source(self.contract) - def allowance(self, owner: ChecksumAddress, spender: ChecksumAddress) -> Any: + def allowance( + self, + owner: ChecksumAddress, + spender: ChecksumAddress, + block_number: Optional[Union[str, int]] = "latest", + ) -> Any: self.assert_contract_is_instantiated() - return self.contract.allowance.call(owner, spender) + return self.contract.allowance.call( + owner, spender, block_identifier=block_number + ) def approve(self, spender: ChecksumAddress, amount: int, transaction_config) -> Any: self.assert_contract_is_instantiated() return self.contract.approve(spender, amount, transaction_config) - def balance_of(self, account: ChecksumAddress) -> Any: + def balance_of( + self, + account: ChecksumAddress, + block_number: Optional[Union[str, int]] = "latest", + ) -> Any: self.assert_contract_is_instantiated() - return self.contract.balanceOf.call(account) + return self.contract.balanceOf.call(account, block_identifier=block_number) - def decimals(self) -> Any: + def decimals(self, block_number: Optional[Union[str, int]] = "latest") -> Any: self.assert_contract_is_instantiated() - return self.contract.decimals.call() + return self.contract.decimals.call(block_identifier=block_number) def decrease_allowance( self, spender: ChecksumAddress, subtracted_value: int, transaction_config @@ -129,25 +141,23 @@ def mint(self, account: ChecksumAddress, amount: int, transaction_config) -> Any self.assert_contract_is_instantiated() return self.contract.mint(account, amount, transaction_config) - def moonstream_controller(self) -> Any: - self.assert_contract_is_instantiated() - return self.contract.moonstreamController.call() - - def name(self) -> Any: + def moonstream_controller( + self, block_number: Optional[Union[str, int]] = "latest" + ) -> Any: self.assert_contract_is_instantiated() - return self.contract.name.call() + return self.contract.moonstreamController.call(block_identifier=block_number) - def set_erc20_metadata(self, name_: str, symbol_: str, transaction_config) -> Any: + def name(self, block_number: Optional[Union[str, int]] = "latest") -> Any: self.assert_contract_is_instantiated() - return self.contract.setERC20Metadata(name_, symbol_, transaction_config) + return self.contract.name.call(block_identifier=block_number) - def symbol(self) -> Any: + def symbol(self, block_number: Optional[Union[str, int]] = "latest") -> Any: self.assert_contract_is_instantiated() - return self.contract.symbol.call() + return self.contract.symbol.call(block_identifier=block_number) - def total_supply(self) -> Any: + def total_supply(self, block_number: Optional[Union[str, int]] = "latest") -> Any: self.assert_contract_is_instantiated() - return self.contract.totalSupply.call() + return self.contract.totalSupply.call(block_identifier=block_number) def transfer( self, recipient: ChecksumAddress, amount: int, transaction_config @@ -190,6 +200,12 @@ def add_default_arguments(parser: argparse.ArgumentParser, transact: bool) -> No "--address", required=False, help="Address of deployed contract to connect to" ) if not transact: + parser.add_argument( + "--block-number", + required=False, + type=int, + help="Call at the given block number, defaults to latest", + ) return parser.add_argument( "--sender", required=True, help="Path to keystore file for transaction sender" @@ -221,6 +237,10 @@ def add_default_arguments(parser: argparse.ArgumentParser, transact: bool) -> No parser.add_argument( "--nonce", type=int, default=None, help="Nonce for the transaction (optional)" ) + parser.add_argument( + "--value", default=None, help="Value of the transaction in wei(optional)" + ) + parser.add_argument("--verbose", action="store_true", help="Print verbose output") def handle_deploy(args: argparse.Namespace) -> None: @@ -229,6 +249,8 @@ def handle_deploy(args: argparse.Namespace) -> None: contract = ERC20Facet(None) result = contract.deploy(transaction_config=transaction_config) print(result) + if args.verbose: + print(result.info()) def handle_verify_contract(args: argparse.Namespace) -> None: @@ -241,7 +263,9 @@ def handle_verify_contract(args: argparse.Namespace) -> None: def handle_allowance(args: argparse.Namespace) -> None: network.connect(args.network) contract = ERC20Facet(args.address) - result = contract.allowance(owner=args.owner, spender=args.spender) + result = contract.allowance( + owner=args.owner, spender=args.spender, block_number=args.block_number + ) print(result) @@ -253,19 +277,21 @@ def handle_approve(args: argparse.Namespace) -> None: spender=args.spender, amount=args.amount, transaction_config=transaction_config ) print(result) + if args.verbose: + print(result.info()) def handle_balance_of(args: argparse.Namespace) -> None: network.connect(args.network) contract = ERC20Facet(args.address) - result = contract.balance_of(account=args.account) + result = contract.balance_of(account=args.account, block_number=args.block_number) print(result) def handle_decimals(args: argparse.Namespace) -> None: network.connect(args.network) contract = ERC20Facet(args.address) - result = contract.decimals() + result = contract.decimals(block_number=args.block_number) print(result) @@ -279,6 +305,8 @@ def handle_decrease_allowance(args: argparse.Namespace) -> None: transaction_config=transaction_config, ) print(result) + if args.verbose: + print(result.info()) def handle_increase_allowance(args: argparse.Namespace) -> None: @@ -291,6 +319,8 @@ def handle_increase_allowance(args: argparse.Namespace) -> None: transaction_config=transaction_config, ) print(result) + if args.verbose: + print(result.info()) def handle_mint(args: argparse.Namespace) -> None: @@ -301,45 +331,35 @@ def handle_mint(args: argparse.Namespace) -> None: account=args.account, amount=args.amount, transaction_config=transaction_config ) print(result) + if args.verbose: + print(result.info()) def handle_moonstream_controller(args: argparse.Namespace) -> None: network.connect(args.network) contract = ERC20Facet(args.address) - result = contract.moonstream_controller() + result = contract.moonstream_controller(block_number=args.block_number) print(result) def handle_name(args: argparse.Namespace) -> None: network.connect(args.network) contract = ERC20Facet(args.address) - result = contract.name() - print(result) - - -def handle_set_erc20_metadata(args: argparse.Namespace) -> None: - network.connect(args.network) - contract = ERC20Facet(args.address) - transaction_config = get_transaction_config(args) - result = contract.set_erc20_metadata( - name_=args.name_arg, - symbol_=args.symbol_arg, - transaction_config=transaction_config, - ) + result = contract.name(block_number=args.block_number) print(result) def handle_symbol(args: argparse.Namespace) -> None: network.connect(args.network) contract = ERC20Facet(args.address) - result = contract.symbol() + result = contract.symbol(block_number=args.block_number) print(result) def handle_total_supply(args: argparse.Namespace) -> None: network.connect(args.network) contract = ERC20Facet(args.address) - result = contract.total_supply() + result = contract.total_supply(block_number=args.block_number) print(result) @@ -353,6 +373,8 @@ def handle_transfer(args: argparse.Namespace) -> None: transaction_config=transaction_config, ) print(result) + if args.verbose: + print(result.info()) def handle_transfer_from(args: argparse.Namespace) -> None: @@ -366,6 +388,8 @@ def handle_transfer_from(args: argparse.Namespace) -> None: transaction_config=transaction_config, ) print(result) + if args.verbose: + print(result.info()) def generate_cli() -> argparse.ArgumentParser: @@ -438,16 +462,6 @@ def generate_cli() -> argparse.ArgumentParser: add_default_arguments(name_parser, False) name_parser.set_defaults(func=handle_name) - set_erc20_metadata_parser = subcommands.add_parser("set-erc20-metadata") - add_default_arguments(set_erc20_metadata_parser, True) - set_erc20_metadata_parser.add_argument( - "--name-arg", required=True, help="Type: string", type=str - ) - set_erc20_metadata_parser.add_argument( - "--symbol-arg", required=True, help="Type: string", type=str - ) - set_erc20_metadata_parser.set_defaults(func=handle_set_erc20_metadata) - symbol_parser = subcommands.add_parser("symbol") add_default_arguments(symbol_parser, False) symbol_parser.set_defaults(func=handle_symbol) diff --git a/dao/ERC20Initializer.py b/dao/ERC20Initializer.py index 4a2500f..2c02884 100644 --- a/dao/ERC20Initializer.py +++ b/dao/ERC20Initializer.py @@ -1,5 +1,5 @@ # Code generated by moonworm : https://github.com/bugout-dev/moonworm -# Moonworm version : 0.1.14 +# Moonworm version : 0.6.2 import argparse import json @@ -30,8 +30,8 @@ def boolean_argument_type(raw_value: str) -> bool: ) -def bytes_argument_type(raw_value: str) -> bytes: - return raw_value.encode() +def bytes_argument_type(raw_value: str) -> str: + return raw_value def get_abi_json(abi_name: str) -> List[Dict[str, Any]]: @@ -85,6 +85,7 @@ def deploy(self, transaction_config): deployed_contract = contract_class.deploy(transaction_config) self.address = deployed_contract.address self.contract = deployed_contract + return deployed_contract.tx def assert_contract_is_instantiated(self) -> None: if self.contract is None: @@ -95,9 +96,9 @@ def verify_contract(self): contract_class = contract_from_build(self.contract_name) contract_class.publish_source(self.contract) - def init(self, transaction_config) -> Any: + def init(self, name: str, symbol: str, transaction_config) -> Any: self.assert_contract_is_instantiated() - return self.contract.init(transaction_config) + return self.contract.init(name, symbol, transaction_config) def get_transaction_config(args: argparse.Namespace) -> Dict[str, Any]: @@ -124,6 +125,12 @@ def add_default_arguments(parser: argparse.ArgumentParser, transact: bool) -> No "--address", required=False, help="Address of deployed contract to connect to" ) if not transact: + parser.add_argument( + "--block-number", + required=False, + type=int, + help="Call at the given block number, defaults to latest", + ) return parser.add_argument( "--sender", required=True, help="Path to keystore file for transaction sender" @@ -155,6 +162,10 @@ def add_default_arguments(parser: argparse.ArgumentParser, transact: bool) -> No parser.add_argument( "--nonce", type=int, default=None, help="Nonce for the transaction (optional)" ) + parser.add_argument( + "--value", default=None, help="Value of the transaction in wei(optional)" + ) + parser.add_argument("--verbose", action="store_true", help="Print verbose output") def handle_deploy(args: argparse.Namespace) -> None: @@ -163,6 +174,8 @@ def handle_deploy(args: argparse.Namespace) -> None: contract = ERC20Initializer(None) result = contract.deploy(transaction_config=transaction_config) print(result) + if args.verbose: + print(result.info()) def handle_verify_contract(args: argparse.Namespace) -> None: @@ -176,8 +189,12 @@ def handle_init(args: argparse.Namespace) -> None: network.connect(args.network) contract = ERC20Initializer(args.address) transaction_config = get_transaction_config(args) - result = contract.init(transaction_config=transaction_config) + result = contract.init( + name=args.name, symbol=args.symbol, transaction_config=transaction_config + ) print(result) + if args.verbose: + print(result.info()) def generate_cli() -> argparse.ArgumentParser: @@ -195,6 +212,8 @@ def generate_cli() -> argparse.ArgumentParser: init_parser = subcommands.add_parser("init") add_default_arguments(init_parser, True) + init_parser.add_argument("--name", required=True, help="Type: string", type=str) + init_parser.add_argument("--symbol", required=True, help="Type: string", type=str) init_parser.set_defaults(func=handle_init) return parser diff --git a/dao/ERC20WithCommonStorage.py b/dao/ERC20WithCommonStorage.py new file mode 100644 index 0000000..4b9216a --- /dev/null +++ b/dao/ERC20WithCommonStorage.py @@ -0,0 +1,465 @@ +# Code generated by moonworm : https://github.com/bugout-dev/moonworm +# Moonworm version : 0.6.2 + +import argparse +import json +import os +from pathlib import Path +from typing import Any, Dict, List, Optional, Union + +from brownie import Contract, network, project +from brownie.network.contract import ContractContainer +from eth_typing.evm import ChecksumAddress + + +PROJECT_DIRECTORY = os.path.abspath(os.path.join(os.path.dirname(__file__), "..")) +BUILD_DIRECTORY = os.path.join(PROJECT_DIRECTORY, "build", "contracts") + + +def boolean_argument_type(raw_value: str) -> bool: + TRUE_VALUES = ["1", "t", "y", "true", "yes"] + FALSE_VALUES = ["0", "f", "n", "false", "no"] + + if raw_value.lower() in TRUE_VALUES: + return True + elif raw_value.lower() in FALSE_VALUES: + return False + + raise ValueError( + f"Invalid boolean argument: {raw_value}. Value must be one of: {','.join(TRUE_VALUES + FALSE_VALUES)}" + ) + + +def bytes_argument_type(raw_value: str) -> str: + return raw_value + + +def get_abi_json(abi_name: str) -> List[Dict[str, Any]]: + abi_full_path = os.path.join(BUILD_DIRECTORY, f"{abi_name}.json") + if not os.path.isfile(abi_full_path): + raise IOError( + f"File does not exist: {abi_full_path}. Maybe you have to compile the smart contracts?" + ) + + with open(abi_full_path, "r") as ifp: + build = json.load(ifp) + + abi_json = build.get("abi") + if abi_json is None: + raise ValueError(f"Could not find ABI definition in: {abi_full_path}") + + return abi_json + + +def contract_from_build(abi_name: str) -> ContractContainer: + # This is workaround because brownie currently doesn't support loading the same project multiple + # times. This causes problems when using multiple contracts from the same project in the same + # python project. + PROJECT = project.main.Project("moonworm", Path(PROJECT_DIRECTORY)) + + abi_full_path = os.path.join(BUILD_DIRECTORY, f"{abi_name}.json") + if not os.path.isfile(abi_full_path): + raise IOError( + f"File does not exist: {abi_full_path}. Maybe you have to compile the smart contracts?" + ) + + with open(abi_full_path, "r") as ifp: + build = json.load(ifp) + + return ContractContainer(PROJECT, build) + + +class ERC20WithCommonStorage: + def __init__(self, contract_address: Optional[ChecksumAddress]): + self.contract_name = "ERC20WithCommonStorage" + self.address = contract_address + self.contract = None + self.abi = get_abi_json("ERC20WithCommonStorage") + if self.address is not None: + self.contract: Optional[Contract] = Contract.from_abi( + self.contract_name, self.address, self.abi + ) + + def deploy(self, transaction_config): + contract_class = contract_from_build(self.contract_name) + deployed_contract = contract_class.deploy(transaction_config) + self.address = deployed_contract.address + self.contract = deployed_contract + return deployed_contract.tx + + def assert_contract_is_instantiated(self) -> None: + if self.contract is None: + raise Exception("contract has not been instantiated") + + def verify_contract(self): + self.assert_contract_is_instantiated() + contract_class = contract_from_build(self.contract_name) + contract_class.publish_source(self.contract) + + def allowance( + self, + owner: ChecksumAddress, + spender: ChecksumAddress, + block_number: Optional[Union[str, int]] = "latest", + ) -> Any: + self.assert_contract_is_instantiated() + return self.contract.allowance.call( + owner, spender, block_identifier=block_number + ) + + def approve(self, spender: ChecksumAddress, amount: int, transaction_config) -> Any: + self.assert_contract_is_instantiated() + return self.contract.approve(spender, amount, transaction_config) + + def balance_of( + self, + account: ChecksumAddress, + block_number: Optional[Union[str, int]] = "latest", + ) -> Any: + self.assert_contract_is_instantiated() + return self.contract.balanceOf.call(account, block_identifier=block_number) + + def decimals(self, block_number: Optional[Union[str, int]] = "latest") -> Any: + self.assert_contract_is_instantiated() + return self.contract.decimals.call(block_identifier=block_number) + + def decrease_allowance( + self, spender: ChecksumAddress, subtracted_value: int, transaction_config + ) -> Any: + self.assert_contract_is_instantiated() + return self.contract.decreaseAllowance( + spender, subtracted_value, transaction_config + ) + + def increase_allowance( + self, spender: ChecksumAddress, added_value: int, transaction_config + ) -> Any: + self.assert_contract_is_instantiated() + return self.contract.increaseAllowance(spender, added_value, transaction_config) + + def name(self, block_number: Optional[Union[str, int]] = "latest") -> Any: + self.assert_contract_is_instantiated() + return self.contract.name.call(block_identifier=block_number) + + def symbol(self, block_number: Optional[Union[str, int]] = "latest") -> Any: + self.assert_contract_is_instantiated() + return self.contract.symbol.call(block_identifier=block_number) + + def total_supply(self, block_number: Optional[Union[str, int]] = "latest") -> Any: + self.assert_contract_is_instantiated() + return self.contract.totalSupply.call(block_identifier=block_number) + + def transfer( + self, recipient: ChecksumAddress, amount: int, transaction_config + ) -> Any: + self.assert_contract_is_instantiated() + return self.contract.transfer(recipient, amount, transaction_config) + + def transfer_from( + self, + sender: ChecksumAddress, + recipient: ChecksumAddress, + amount: int, + transaction_config, + ) -> Any: + self.assert_contract_is_instantiated() + return self.contract.transferFrom(sender, recipient, amount, transaction_config) + + +def get_transaction_config(args: argparse.Namespace) -> Dict[str, Any]: + signer = network.accounts.load(args.sender, args.password) + transaction_config: Dict[str, Any] = {"from": signer} + if args.gas_price is not None: + transaction_config["gas_price"] = args.gas_price + if args.max_fee_per_gas is not None: + transaction_config["max_fee"] = args.max_fee_per_gas + if args.max_priority_fee_per_gas is not None: + transaction_config["priority_fee"] = args.max_priority_fee_per_gas + if args.confirmations is not None: + transaction_config["required_confs"] = args.confirmations + if args.nonce is not None: + transaction_config["nonce"] = args.nonce + return transaction_config + + +def add_default_arguments(parser: argparse.ArgumentParser, transact: bool) -> None: + parser.add_argument( + "--network", required=True, help="Name of brownie network to connect to" + ) + parser.add_argument( + "--address", required=False, help="Address of deployed contract to connect to" + ) + if not transact: + parser.add_argument( + "--block-number", + required=False, + type=int, + help="Call at the given block number, defaults to latest", + ) + return + parser.add_argument( + "--sender", required=True, help="Path to keystore file for transaction sender" + ) + parser.add_argument( + "--password", + required=False, + help="Password to keystore file (if you do not provide it, you will be prompted for it)", + ) + parser.add_argument( + "--gas-price", default=None, help="Gas price at which to submit transaction" + ) + parser.add_argument( + "--max-fee-per-gas", + default=None, + help="Max fee per gas for EIP1559 transactions", + ) + parser.add_argument( + "--max-priority-fee-per-gas", + default=None, + help="Max priority fee per gas for EIP1559 transactions", + ) + parser.add_argument( + "--confirmations", + type=int, + default=None, + help="Number of confirmations to await before considering a transaction completed", + ) + parser.add_argument( + "--nonce", type=int, default=None, help="Nonce for the transaction (optional)" + ) + parser.add_argument( + "--value", default=None, help="Value of the transaction in wei(optional)" + ) + parser.add_argument("--verbose", action="store_true", help="Print verbose output") + + +def handle_deploy(args: argparse.Namespace) -> None: + network.connect(args.network) + transaction_config = get_transaction_config(args) + contract = ERC20WithCommonStorage(None) + result = contract.deploy(transaction_config=transaction_config) + print(result) + if args.verbose: + print(result.info()) + + +def handle_verify_contract(args: argparse.Namespace) -> None: + network.connect(args.network) + contract = ERC20WithCommonStorage(args.address) + result = contract.verify_contract() + print(result) + + +def handle_allowance(args: argparse.Namespace) -> None: + network.connect(args.network) + contract = ERC20WithCommonStorage(args.address) + result = contract.allowance( + owner=args.owner, spender=args.spender, block_number=args.block_number + ) + print(result) + + +def handle_approve(args: argparse.Namespace) -> None: + network.connect(args.network) + contract = ERC20WithCommonStorage(args.address) + transaction_config = get_transaction_config(args) + result = contract.approve( + spender=args.spender, amount=args.amount, transaction_config=transaction_config + ) + print(result) + if args.verbose: + print(result.info()) + + +def handle_balance_of(args: argparse.Namespace) -> None: + network.connect(args.network) + contract = ERC20WithCommonStorage(args.address) + result = contract.balance_of(account=args.account, block_number=args.block_number) + print(result) + + +def handle_decimals(args: argparse.Namespace) -> None: + network.connect(args.network) + contract = ERC20WithCommonStorage(args.address) + result = contract.decimals(block_number=args.block_number) + print(result) + + +def handle_decrease_allowance(args: argparse.Namespace) -> None: + network.connect(args.network) + contract = ERC20WithCommonStorage(args.address) + transaction_config = get_transaction_config(args) + result = contract.decrease_allowance( + spender=args.spender, + subtracted_value=args.subtracted_value, + transaction_config=transaction_config, + ) + print(result) + if args.verbose: + print(result.info()) + + +def handle_increase_allowance(args: argparse.Namespace) -> None: + network.connect(args.network) + contract = ERC20WithCommonStorage(args.address) + transaction_config = get_transaction_config(args) + result = contract.increase_allowance( + spender=args.spender, + added_value=args.added_value, + transaction_config=transaction_config, + ) + print(result) + if args.verbose: + print(result.info()) + + +def handle_name(args: argparse.Namespace) -> None: + network.connect(args.network) + contract = ERC20WithCommonStorage(args.address) + result = contract.name(block_number=args.block_number) + print(result) + + +def handle_symbol(args: argparse.Namespace) -> None: + network.connect(args.network) + contract = ERC20WithCommonStorage(args.address) + result = contract.symbol(block_number=args.block_number) + print(result) + + +def handle_total_supply(args: argparse.Namespace) -> None: + network.connect(args.network) + contract = ERC20WithCommonStorage(args.address) + result = contract.total_supply(block_number=args.block_number) + print(result) + + +def handle_transfer(args: argparse.Namespace) -> None: + network.connect(args.network) + contract = ERC20WithCommonStorage(args.address) + transaction_config = get_transaction_config(args) + result = contract.transfer( + recipient=args.recipient, + amount=args.amount, + transaction_config=transaction_config, + ) + print(result) + if args.verbose: + print(result.info()) + + +def handle_transfer_from(args: argparse.Namespace) -> None: + network.connect(args.network) + contract = ERC20WithCommonStorage(args.address) + transaction_config = get_transaction_config(args) + result = contract.transfer_from( + sender=args.sender_arg, + recipient=args.recipient, + amount=args.amount, + transaction_config=transaction_config, + ) + print(result) + if args.verbose: + print(result.info()) + + +def generate_cli() -> argparse.ArgumentParser: + parser = argparse.ArgumentParser(description="CLI for ERC20WithCommonStorage") + parser.set_defaults(func=lambda _: parser.print_help()) + subcommands = parser.add_subparsers() + + deploy_parser = subcommands.add_parser("deploy") + add_default_arguments(deploy_parser, True) + deploy_parser.set_defaults(func=handle_deploy) + + verify_contract_parser = subcommands.add_parser("verify-contract") + add_default_arguments(verify_contract_parser, False) + verify_contract_parser.set_defaults(func=handle_verify_contract) + + allowance_parser = subcommands.add_parser("allowance") + add_default_arguments(allowance_parser, False) + allowance_parser.add_argument("--owner", required=True, help="Type: address") + allowance_parser.add_argument("--spender", required=True, help="Type: address") + allowance_parser.set_defaults(func=handle_allowance) + + approve_parser = subcommands.add_parser("approve") + add_default_arguments(approve_parser, True) + approve_parser.add_argument("--spender", required=True, help="Type: address") + approve_parser.add_argument( + "--amount", required=True, help="Type: uint256", type=int + ) + approve_parser.set_defaults(func=handle_approve) + + balance_of_parser = subcommands.add_parser("balance-of") + add_default_arguments(balance_of_parser, False) + balance_of_parser.add_argument("--account", required=True, help="Type: address") + balance_of_parser.set_defaults(func=handle_balance_of) + + decimals_parser = subcommands.add_parser("decimals") + add_default_arguments(decimals_parser, False) + decimals_parser.set_defaults(func=handle_decimals) + + decrease_allowance_parser = subcommands.add_parser("decrease-allowance") + add_default_arguments(decrease_allowance_parser, True) + decrease_allowance_parser.add_argument( + "--spender", required=True, help="Type: address" + ) + decrease_allowance_parser.add_argument( + "--subtracted-value", required=True, help="Type: uint256", type=int + ) + decrease_allowance_parser.set_defaults(func=handle_decrease_allowance) + + increase_allowance_parser = subcommands.add_parser("increase-allowance") + add_default_arguments(increase_allowance_parser, True) + increase_allowance_parser.add_argument( + "--spender", required=True, help="Type: address" + ) + increase_allowance_parser.add_argument( + "--added-value", required=True, help="Type: uint256", type=int + ) + increase_allowance_parser.set_defaults(func=handle_increase_allowance) + + name_parser = subcommands.add_parser("name") + add_default_arguments(name_parser, False) + name_parser.set_defaults(func=handle_name) + + symbol_parser = subcommands.add_parser("symbol") + add_default_arguments(symbol_parser, False) + symbol_parser.set_defaults(func=handle_symbol) + + total_supply_parser = subcommands.add_parser("total-supply") + add_default_arguments(total_supply_parser, False) + total_supply_parser.set_defaults(func=handle_total_supply) + + transfer_parser = subcommands.add_parser("transfer") + add_default_arguments(transfer_parser, True) + transfer_parser.add_argument("--recipient", required=True, help="Type: address") + transfer_parser.add_argument( + "--amount", required=True, help="Type: uint256", type=int + ) + transfer_parser.set_defaults(func=handle_transfer) + + transfer_from_parser = subcommands.add_parser("transfer-from") + add_default_arguments(transfer_from_parser, True) + transfer_from_parser.add_argument( + "--sender-arg", required=True, help="Type: address" + ) + transfer_from_parser.add_argument( + "--recipient", required=True, help="Type: address" + ) + transfer_from_parser.add_argument( + "--amount", required=True, help="Type: uint256", type=int + ) + transfer_from_parser.set_defaults(func=handle_transfer_from) + + return parser + + +def main() -> None: + parser = generate_cli() + args = parser.parse_args() + args.func(args) + + +if __name__ == "__main__": + main() diff --git a/dao/MoonstreamTokenFaucet.py b/dao/MoonstreamTokenFaucet.py index b9cb143..2a46b9a 100644 --- a/dao/MoonstreamTokenFaucet.py +++ b/dao/MoonstreamTokenFaucet.py @@ -1,5 +1,5 @@ # Code generated by moonworm : https://github.com/bugout-dev/moonworm -# Moonworm version : 0.1.14 +# Moonworm version : 0.6.2 import argparse import json @@ -30,8 +30,8 @@ def boolean_argument_type(raw_value: str) -> bool: ) -def bytes_argument_type(raw_value: str) -> bytes: - return raw_value.encode() +def bytes_argument_type(raw_value: str) -> str: + return raw_value def get_abi_json(abi_name: str) -> List[Dict[str, Any]]: @@ -98,6 +98,7 @@ def deploy( ) self.address = deployed_contract.address self.contract = deployed_contract + return deployed_contract.tx def assert_contract_is_instantiated(self) -> None: if self.contract is None: @@ -112,29 +113,49 @@ def claim(self, transaction_config) -> Any: self.assert_contract_is_instantiated() return self.contract.claim(transaction_config) - def get_faucet_amount(self) -> Any: + def get_faucet_amount( + self, block_number: Optional[Union[str, int]] = "latest" + ) -> Any: self.assert_contract_is_instantiated() - return self.contract.getFaucetAmount.call() + return self.contract.getFaucetAmount.call(block_identifier=block_number) - def get_faucet_block_interval(self) -> Any: + def get_faucet_block_interval( + self, block_number: Optional[Union[str, int]] = "latest" + ) -> Any: self.assert_contract_is_instantiated() - return self.contract.getFaucetBlockInterval.call() + return self.contract.getFaucetBlockInterval.call(block_identifier=block_number) - def get_last_claimed_block(self, _address: ChecksumAddress) -> Any: + def get_last_claimed_block( + self, + _address: ChecksumAddress, + block_number: Optional[Union[str, int]] = "latest", + ) -> Any: self.assert_contract_is_instantiated() - return self.contract.getLastClaimedBlock.call(_address) + return self.contract.getLastClaimedBlock.call( + _address, block_identifier=block_number + ) - def get_moonstream_token_address(self) -> Any: + def get_moonstream_token_address( + self, block_number: Optional[Union[str, int]] = "latest" + ) -> Any: self.assert_contract_is_instantiated() - return self.contract.getMoonstreamTokenAddress.call() + return self.contract.getMoonstreamTokenAddress.call( + block_identifier=block_number + ) - def get_moonstream_token_balance(self, _address: ChecksumAddress) -> Any: + def get_moonstream_token_balance( + self, + _address: ChecksumAddress, + block_number: Optional[Union[str, int]] = "latest", + ) -> Any: self.assert_contract_is_instantiated() - return self.contract.getMoonstreamTokenBalance.call(_address) + return self.contract.getMoonstreamTokenBalance.call( + _address, block_identifier=block_number + ) - def owner(self) -> Any: + def owner(self, block_number: Optional[Union[str, int]] = "latest") -> Any: self.assert_contract_is_instantiated() - return self.contract.owner.call() + return self.contract.owner.call(block_identifier=block_number) def renounce_ownership(self, transaction_config) -> Any: self.assert_contract_is_instantiated() @@ -189,6 +210,12 @@ def add_default_arguments(parser: argparse.ArgumentParser, transact: bool) -> No "--address", required=False, help="Address of deployed contract to connect to" ) if not transact: + parser.add_argument( + "--block-number", + required=False, + type=int, + help="Call at the given block number, defaults to latest", + ) return parser.add_argument( "--sender", required=True, help="Path to keystore file for transaction sender" @@ -220,6 +247,10 @@ def add_default_arguments(parser: argparse.ArgumentParser, transact: bool) -> No parser.add_argument( "--nonce", type=int, default=None, help="Nonce for the transaction (optional)" ) + parser.add_argument( + "--value", default=None, help="Value of the transaction in wei(optional)" + ) + parser.add_argument("--verbose", action="store_true", help="Print verbose output") def handle_deploy(args: argparse.Namespace) -> None: @@ -234,6 +265,8 @@ def handle_deploy(args: argparse.Namespace) -> None: transaction_config=transaction_config, ) print(result) + if args.verbose: + print(result.info()) def handle_verify_contract(args: argparse.Namespace) -> None: @@ -249,47 +282,53 @@ def handle_claim(args: argparse.Namespace) -> None: transaction_config = get_transaction_config(args) result = contract.claim(transaction_config=transaction_config) print(result) + if args.verbose: + print(result.info()) def handle_get_faucet_amount(args: argparse.Namespace) -> None: network.connect(args.network) contract = MoonstreamTokenFaucet(args.address) - result = contract.get_faucet_amount() + result = contract.get_faucet_amount(block_number=args.block_number) print(result) def handle_get_faucet_block_interval(args: argparse.Namespace) -> None: network.connect(args.network) contract = MoonstreamTokenFaucet(args.address) - result = contract.get_faucet_block_interval() + result = contract.get_faucet_block_interval(block_number=args.block_number) print(result) def handle_get_last_claimed_block(args: argparse.Namespace) -> None: network.connect(args.network) contract = MoonstreamTokenFaucet(args.address) - result = contract.get_last_claimed_block(_address=args.address_arg) + result = contract.get_last_claimed_block( + _address=args.address_arg, block_number=args.block_number + ) print(result) def handle_get_moonstream_token_address(args: argparse.Namespace) -> None: network.connect(args.network) contract = MoonstreamTokenFaucet(args.address) - result = contract.get_moonstream_token_address() + result = contract.get_moonstream_token_address(block_number=args.block_number) print(result) def handle_get_moonstream_token_balance(args: argparse.Namespace) -> None: network.connect(args.network) contract = MoonstreamTokenFaucet(args.address) - result = contract.get_moonstream_token_balance(_address=args.address_arg) + result = contract.get_moonstream_token_balance( + _address=args.address_arg, block_number=args.block_number + ) print(result) def handle_owner(args: argparse.Namespace) -> None: network.connect(args.network) contract = MoonstreamTokenFaucet(args.address) - result = contract.owner() + result = contract.owner(block_number=args.block_number) print(result) @@ -299,6 +338,8 @@ def handle_renounce_ownership(args: argparse.Namespace) -> None: transaction_config = get_transaction_config(args) result = contract.renounce_ownership(transaction_config=transaction_config) print(result) + if args.verbose: + print(result.info()) def handle_set_faucet_amount(args: argparse.Namespace) -> None: @@ -309,6 +350,8 @@ def handle_set_faucet_amount(args: argparse.Namespace) -> None: _faucet_amount=args.faucet_amount_arg, transaction_config=transaction_config ) print(result) + if args.verbose: + print(result.info()) def handle_set_faucet_block_interval(args: argparse.Namespace) -> None: @@ -320,6 +363,8 @@ def handle_set_faucet_block_interval(args: argparse.Namespace) -> None: transaction_config=transaction_config, ) print(result) + if args.verbose: + print(result.info()) def handle_set_moonstream_token_address(args: argparse.Namespace) -> None: @@ -331,6 +376,8 @@ def handle_set_moonstream_token_address(args: argparse.Namespace) -> None: transaction_config=transaction_config, ) print(result) + if args.verbose: + print(result.info()) def handle_transfer_ownership(args: argparse.Namespace) -> None: @@ -341,6 +388,8 @@ def handle_transfer_ownership(args: argparse.Namespace) -> None: new_owner=args.new_owner, transaction_config=transaction_config ) print(result) + if args.verbose: + print(result.info()) def generate_cli() -> argparse.ArgumentParser: diff --git a/dao/OwnershipFacet.py b/dao/OwnershipFacet.py index a585c2c..c222c8b 100644 --- a/dao/OwnershipFacet.py +++ b/dao/OwnershipFacet.py @@ -1,5 +1,5 @@ # Code generated by moonworm : https://github.com/bugout-dev/moonworm -# Moonworm version : 0.1.14 +# Moonworm version : 0.6.2 import argparse import json @@ -30,8 +30,8 @@ def boolean_argument_type(raw_value: str) -> bool: ) -def bytes_argument_type(raw_value: str) -> bytes: - return raw_value.encode() +def bytes_argument_type(raw_value: str) -> str: + return raw_value def get_abi_json(abi_name: str) -> List[Dict[str, Any]]: @@ -85,6 +85,7 @@ def deploy(self, transaction_config): deployed_contract = contract_class.deploy(transaction_config) self.address = deployed_contract.address self.contract = deployed_contract + return deployed_contract.tx def assert_contract_is_instantiated(self) -> None: if self.contract is None: @@ -95,9 +96,9 @@ def verify_contract(self): contract_class = contract_from_build(self.contract_name) contract_class.publish_source(self.contract) - def owner(self) -> Any: + def owner(self, block_number: Optional[Union[str, int]] = "latest") -> Any: self.assert_contract_is_instantiated() - return self.contract.owner.call() + return self.contract.owner.call(block_identifier=block_number) def transfer_ownership( self, _new_owner: ChecksumAddress, transaction_config @@ -130,6 +131,12 @@ def add_default_arguments(parser: argparse.ArgumentParser, transact: bool) -> No "--address", required=False, help="Address of deployed contract to connect to" ) if not transact: + parser.add_argument( + "--block-number", + required=False, + type=int, + help="Call at the given block number, defaults to latest", + ) return parser.add_argument( "--sender", required=True, help="Path to keystore file for transaction sender" @@ -161,6 +168,10 @@ def add_default_arguments(parser: argparse.ArgumentParser, transact: bool) -> No parser.add_argument( "--nonce", type=int, default=None, help="Nonce for the transaction (optional)" ) + parser.add_argument( + "--value", default=None, help="Value of the transaction in wei(optional)" + ) + parser.add_argument("--verbose", action="store_true", help="Print verbose output") def handle_deploy(args: argparse.Namespace) -> None: @@ -169,6 +180,8 @@ def handle_deploy(args: argparse.Namespace) -> None: contract = OwnershipFacet(None) result = contract.deploy(transaction_config=transaction_config) print(result) + if args.verbose: + print(result.info()) def handle_verify_contract(args: argparse.Namespace) -> None: @@ -181,7 +194,7 @@ def handle_verify_contract(args: argparse.Namespace) -> None: def handle_owner(args: argparse.Namespace) -> None: network.connect(args.network) contract = OwnershipFacet(args.address) - result = contract.owner() + result = contract.owner(block_number=args.block_number) print(result) @@ -193,6 +206,8 @@ def handle_transfer_ownership(args: argparse.Namespace) -> None: _new_owner=args.new_owner_arg, transaction_config=transaction_config ) print(result) + if args.verbose: + print(result.info()) def generate_cli() -> argparse.ArgumentParser: diff --git a/dao/TerminusControllerFacet.py b/dao/TerminusControllerFacet.py index 64a79eb..2d9d2d6 100644 --- a/dao/TerminusControllerFacet.py +++ b/dao/TerminusControllerFacet.py @@ -1,5 +1,5 @@ # Code generated by moonworm : https://github.com/bugout-dev/moonworm -# Moonworm version : 0.2.4 +# Moonworm version : 0.6.2 import argparse import json diff --git a/dao/TerminusFacet.py b/dao/TerminusFacet.py index 9ba0d84..a590447 100644 --- a/dao/TerminusFacet.py +++ b/dao/TerminusFacet.py @@ -1,5 +1,5 @@ # Code generated by moonworm : https://github.com/bugout-dev/moonworm -# Moonworm version : 0.6.0 +# Moonworm version : 0.6.2 import argparse import json diff --git a/dao/TerminusInitializer.py b/dao/TerminusInitializer.py index 5e6b0f7..021d8f3 100644 --- a/dao/TerminusInitializer.py +++ b/dao/TerminusInitializer.py @@ -1,5 +1,5 @@ # Code generated by moonworm : https://github.com/bugout-dev/moonworm -# Moonworm version : 0.1.14 +# Moonworm version : 0.6.2 import argparse import json @@ -30,8 +30,8 @@ def boolean_argument_type(raw_value: str) -> bool: ) -def bytes_argument_type(raw_value: str) -> bytes: - return raw_value.encode() +def bytes_argument_type(raw_value: str) -> str: + return raw_value def get_abi_json(abi_name: str) -> List[Dict[str, Any]]: @@ -85,6 +85,7 @@ def deploy(self, transaction_config): deployed_contract = contract_class.deploy(transaction_config) self.address = deployed_contract.address self.contract = deployed_contract + return deployed_contract.tx def assert_contract_is_instantiated(self) -> None: if self.contract is None: @@ -124,6 +125,12 @@ def add_default_arguments(parser: argparse.ArgumentParser, transact: bool) -> No "--address", required=False, help="Address of deployed contract to connect to" ) if not transact: + parser.add_argument( + "--block-number", + required=False, + type=int, + help="Call at the given block number, defaults to latest", + ) return parser.add_argument( "--sender", required=True, help="Path to keystore file for transaction sender" @@ -155,6 +162,10 @@ def add_default_arguments(parser: argparse.ArgumentParser, transact: bool) -> No parser.add_argument( "--nonce", type=int, default=None, help="Nonce for the transaction (optional)" ) + parser.add_argument( + "--value", default=None, help="Value of the transaction in wei(optional)" + ) + parser.add_argument("--verbose", action="store_true", help="Print verbose output") def handle_deploy(args: argparse.Namespace) -> None: @@ -163,6 +174,8 @@ def handle_deploy(args: argparse.Namespace) -> None: contract = TerminusInitializer(None) result = contract.deploy(transaction_config=transaction_config) print(result) + if args.verbose: + print(result.info()) def handle_verify_contract(args: argparse.Namespace) -> None: @@ -178,6 +191,8 @@ def handle_init(args: argparse.Namespace) -> None: transaction_config = get_transaction_config(args) result = contract.init(transaction_config=transaction_config) print(result) + if args.verbose: + print(result.info()) def generate_cli() -> argparse.ArgumentParser: diff --git a/dao/TerminusPermissions.py b/dao/TerminusPermissions.py new file mode 100644 index 0000000..10f73dc --- /dev/null +++ b/dao/TerminusPermissions.py @@ -0,0 +1,207 @@ +# Code generated by moonworm : https://github.com/bugout-dev/moonworm +# Moonworm version : 0.6.2 + +import argparse +import json +import os +from pathlib import Path +from typing import Any, Dict, List, Optional, Union + +from brownie import Contract, network, project +from brownie.network.contract import ContractContainer +from eth_typing.evm import ChecksumAddress + + +PROJECT_DIRECTORY = os.path.abspath(os.path.join(os.path.dirname(__file__), "..")) +BUILD_DIRECTORY = os.path.join(PROJECT_DIRECTORY, "build", "contracts") + + +def boolean_argument_type(raw_value: str) -> bool: + TRUE_VALUES = ["1", "t", "y", "true", "yes"] + FALSE_VALUES = ["0", "f", "n", "false", "no"] + + if raw_value.lower() in TRUE_VALUES: + return True + elif raw_value.lower() in FALSE_VALUES: + return False + + raise ValueError( + f"Invalid boolean argument: {raw_value}. Value must be one of: {','.join(TRUE_VALUES + FALSE_VALUES)}" + ) + + +def bytes_argument_type(raw_value: str) -> str: + return raw_value + + +def get_abi_json(abi_name: str) -> List[Dict[str, Any]]: + abi_full_path = os.path.join(BUILD_DIRECTORY, f"{abi_name}.json") + if not os.path.isfile(abi_full_path): + raise IOError( + f"File does not exist: {abi_full_path}. Maybe you have to compile the smart contracts?" + ) + + with open(abi_full_path, "r") as ifp: + build = json.load(ifp) + + abi_json = build.get("abi") + if abi_json is None: + raise ValueError(f"Could not find ABI definition in: {abi_full_path}") + + return abi_json + + +def contract_from_build(abi_name: str) -> ContractContainer: + # This is workaround because brownie currently doesn't support loading the same project multiple + # times. This causes problems when using multiple contracts from the same project in the same + # python project. + PROJECT = project.main.Project("moonworm", Path(PROJECT_DIRECTORY)) + + abi_full_path = os.path.join(BUILD_DIRECTORY, f"{abi_name}.json") + if not os.path.isfile(abi_full_path): + raise IOError( + f"File does not exist: {abi_full_path}. Maybe you have to compile the smart contracts?" + ) + + with open(abi_full_path, "r") as ifp: + build = json.load(ifp) + + return ContractContainer(PROJECT, build) + + +class TerminusPermissions: + def __init__(self, contract_address: Optional[ChecksumAddress]): + self.contract_name = "TerminusPermissions" + self.address = contract_address + self.contract = None + self.abi = get_abi_json("TerminusPermissions") + if self.address is not None: + self.contract: Optional[Contract] = Contract.from_abi( + self.contract_name, self.address, self.abi + ) + + def deploy(self, transaction_config): + contract_class = contract_from_build(self.contract_name) + deployed_contract = contract_class.deploy(transaction_config) + self.address = deployed_contract.address + self.contract = deployed_contract + return deployed_contract.tx + + def assert_contract_is_instantiated(self) -> None: + if self.contract is None: + raise Exception("contract has not been instantiated") + + def verify_contract(self): + self.assert_contract_is_instantiated() + contract_class = contract_from_build(self.contract_name) + contract_class.publish_source(self.contract) + + +def get_transaction_config(args: argparse.Namespace) -> Dict[str, Any]: + signer = network.accounts.load(args.sender, args.password) + transaction_config: Dict[str, Any] = {"from": signer} + if args.gas_price is not None: + transaction_config["gas_price"] = args.gas_price + if args.max_fee_per_gas is not None: + transaction_config["max_fee"] = args.max_fee_per_gas + if args.max_priority_fee_per_gas is not None: + transaction_config["priority_fee"] = args.max_priority_fee_per_gas + if args.confirmations is not None: + transaction_config["required_confs"] = args.confirmations + if args.nonce is not None: + transaction_config["nonce"] = args.nonce + return transaction_config + + +def add_default_arguments(parser: argparse.ArgumentParser, transact: bool) -> None: + parser.add_argument( + "--network", required=True, help="Name of brownie network to connect to" + ) + parser.add_argument( + "--address", required=False, help="Address of deployed contract to connect to" + ) + if not transact: + parser.add_argument( + "--block-number", + required=False, + type=int, + help="Call at the given block number, defaults to latest", + ) + return + parser.add_argument( + "--sender", required=True, help="Path to keystore file for transaction sender" + ) + parser.add_argument( + "--password", + required=False, + help="Password to keystore file (if you do not provide it, you will be prompted for it)", + ) + parser.add_argument( + "--gas-price", default=None, help="Gas price at which to submit transaction" + ) + parser.add_argument( + "--max-fee-per-gas", + default=None, + help="Max fee per gas for EIP1559 transactions", + ) + parser.add_argument( + "--max-priority-fee-per-gas", + default=None, + help="Max priority fee per gas for EIP1559 transactions", + ) + parser.add_argument( + "--confirmations", + type=int, + default=None, + help="Number of confirmations to await before considering a transaction completed", + ) + parser.add_argument( + "--nonce", type=int, default=None, help="Nonce for the transaction (optional)" + ) + parser.add_argument( + "--value", default=None, help="Value of the transaction in wei(optional)" + ) + parser.add_argument("--verbose", action="store_true", help="Print verbose output") + + +def handle_deploy(args: argparse.Namespace) -> None: + network.connect(args.network) + transaction_config = get_transaction_config(args) + contract = TerminusPermissions(None) + result = contract.deploy(transaction_config=transaction_config) + print(result) + if args.verbose: + print(result.info()) + + +def handle_verify_contract(args: argparse.Namespace) -> None: + network.connect(args.network) + contract = TerminusPermissions(args.address) + result = contract.verify_contract() + print(result) + + +def generate_cli() -> argparse.ArgumentParser: + parser = argparse.ArgumentParser(description="CLI for TerminusPermissions") + parser.set_defaults(func=lambda _: parser.print_help()) + subcommands = parser.add_subparsers() + + deploy_parser = subcommands.add_parser("deploy") + add_default_arguments(deploy_parser, True) + deploy_parser.set_defaults(func=handle_deploy) + + verify_contract_parser = subcommands.add_parser("verify-contract") + add_default_arguments(verify_contract_parser, False) + verify_contract_parser.set_defaults(func=handle_verify_contract) + + return parser + + +def main() -> None: + parser = generate_cli() + args = parser.parse_args() + args.func(args) + + +if __name__ == "__main__": + main() diff --git a/dao/TokenDrainerFacet.py b/dao/TokenDrainerFacet.py new file mode 100644 index 0000000..7d6d67d --- /dev/null +++ b/dao/TokenDrainerFacet.py @@ -0,0 +1,367 @@ +# Code generated by moonworm : https://github.com/bugout-dev/moonworm +# Moonworm version : 0.6.2 + +import argparse +import json +import os +from pathlib import Path +from typing import Any, Dict, List, Optional, Union + +from brownie import Contract, network, project +from brownie.network.contract import ContractContainer +from eth_typing.evm import ChecksumAddress + + +PROJECT_DIRECTORY = os.path.abspath(os.path.join(os.path.dirname(__file__), "..")) +BUILD_DIRECTORY = os.path.join(PROJECT_DIRECTORY, "build", "contracts") + + +def boolean_argument_type(raw_value: str) -> bool: + TRUE_VALUES = ["1", "t", "y", "true", "yes"] + FALSE_VALUES = ["0", "f", "n", "false", "no"] + + if raw_value.lower() in TRUE_VALUES: + return True + elif raw_value.lower() in FALSE_VALUES: + return False + + raise ValueError( + f"Invalid boolean argument: {raw_value}. Value must be one of: {','.join(TRUE_VALUES + FALSE_VALUES)}" + ) + + +def bytes_argument_type(raw_value: str) -> str: + return raw_value + + +def get_abi_json(abi_name: str) -> List[Dict[str, Any]]: + abi_full_path = os.path.join(BUILD_DIRECTORY, f"{abi_name}.json") + if not os.path.isfile(abi_full_path): + raise IOError( + f"File does not exist: {abi_full_path}. Maybe you have to compile the smart contracts?" + ) + + with open(abi_full_path, "r") as ifp: + build = json.load(ifp) + + abi_json = build.get("abi") + if abi_json is None: + raise ValueError(f"Could not find ABI definition in: {abi_full_path}") + + return abi_json + + +def contract_from_build(abi_name: str) -> ContractContainer: + # This is workaround because brownie currently doesn't support loading the same project multiple + # times. This causes problems when using multiple contracts from the same project in the same + # python project. + PROJECT = project.main.Project("moonworm", Path(PROJECT_DIRECTORY)) + + abi_full_path = os.path.join(BUILD_DIRECTORY, f"{abi_name}.json") + if not os.path.isfile(abi_full_path): + raise IOError( + f"File does not exist: {abi_full_path}. Maybe you have to compile the smart contracts?" + ) + + with open(abi_full_path, "r") as ifp: + build = json.load(ifp) + + return ContractContainer(PROJECT, build) + + +class TokenDrainerFacet: + def __init__(self, contract_address: Optional[ChecksumAddress]): + self.contract_name = "TokenDrainerFacet" + self.address = contract_address + self.contract = None + self.abi = get_abi_json("TokenDrainerFacet") + if self.address is not None: + self.contract: Optional[Contract] = Contract.from_abi( + self.contract_name, self.address, self.abi + ) + + def deploy(self, transaction_config): + contract_class = contract_from_build(self.contract_name) + deployed_contract = contract_class.deploy(transaction_config) + self.address = deployed_contract.address + self.contract = deployed_contract + return deployed_contract.tx + + def assert_contract_is_instantiated(self) -> None: + if self.contract is None: + raise Exception("contract has not been instantiated") + + def verify_contract(self): + self.assert_contract_is_instantiated() + contract_class = contract_from_build(self.contract_name) + contract_class.publish_source(self.contract) + + def drain_erc1155( + self, + token_address: ChecksumAddress, + token_id: int, + receiver_address: ChecksumAddress, + transaction_config, + ) -> Any: + self.assert_contract_is_instantiated() + return self.contract.drainERC1155( + token_address, token_id, receiver_address, transaction_config + ) + + def drain_erc20( + self, + token_address: ChecksumAddress, + receiver_address: ChecksumAddress, + transaction_config, + ) -> Any: + self.assert_contract_is_instantiated() + return self.contract.drainERC20( + token_address, receiver_address, transaction_config + ) + + def withdraw_erc1155( + self, + token_address: ChecksumAddress, + token_id: int, + amount: int, + receiver_address: ChecksumAddress, + transaction_config, + ) -> Any: + self.assert_contract_is_instantiated() + return self.contract.withdrawERC1155( + token_address, token_id, amount, receiver_address, transaction_config + ) + + def withdraw_erc20( + self, + token_address: ChecksumAddress, + amount: int, + receiver_address: ChecksumAddress, + transaction_config, + ) -> Any: + self.assert_contract_is_instantiated() + return self.contract.withdrawERC20( + token_address, amount, receiver_address, transaction_config + ) + + +def get_transaction_config(args: argparse.Namespace) -> Dict[str, Any]: + signer = network.accounts.load(args.sender, args.password) + transaction_config: Dict[str, Any] = {"from": signer} + if args.gas_price is not None: + transaction_config["gas_price"] = args.gas_price + if args.max_fee_per_gas is not None: + transaction_config["max_fee"] = args.max_fee_per_gas + if args.max_priority_fee_per_gas is not None: + transaction_config["priority_fee"] = args.max_priority_fee_per_gas + if args.confirmations is not None: + transaction_config["required_confs"] = args.confirmations + if args.nonce is not None: + transaction_config["nonce"] = args.nonce + return transaction_config + + +def add_default_arguments(parser: argparse.ArgumentParser, transact: bool) -> None: + parser.add_argument( + "--network", required=True, help="Name of brownie network to connect to" + ) + parser.add_argument( + "--address", required=False, help="Address of deployed contract to connect to" + ) + if not transact: + parser.add_argument( + "--block-number", + required=False, + type=int, + help="Call at the given block number, defaults to latest", + ) + return + parser.add_argument( + "--sender", required=True, help="Path to keystore file for transaction sender" + ) + parser.add_argument( + "--password", + required=False, + help="Password to keystore file (if you do not provide it, you will be prompted for it)", + ) + parser.add_argument( + "--gas-price", default=None, help="Gas price at which to submit transaction" + ) + parser.add_argument( + "--max-fee-per-gas", + default=None, + help="Max fee per gas for EIP1559 transactions", + ) + parser.add_argument( + "--max-priority-fee-per-gas", + default=None, + help="Max priority fee per gas for EIP1559 transactions", + ) + parser.add_argument( + "--confirmations", + type=int, + default=None, + help="Number of confirmations to await before considering a transaction completed", + ) + parser.add_argument( + "--nonce", type=int, default=None, help="Nonce for the transaction (optional)" + ) + parser.add_argument( + "--value", default=None, help="Value of the transaction in wei(optional)" + ) + parser.add_argument("--verbose", action="store_true", help="Print verbose output") + + +def handle_deploy(args: argparse.Namespace) -> None: + network.connect(args.network) + transaction_config = get_transaction_config(args) + contract = TokenDrainerFacet(None) + result = contract.deploy(transaction_config=transaction_config) + print(result) + if args.verbose: + print(result.info()) + + +def handle_verify_contract(args: argparse.Namespace) -> None: + network.connect(args.network) + contract = TokenDrainerFacet(args.address) + result = contract.verify_contract() + print(result) + + +def handle_drain_erc1155(args: argparse.Namespace) -> None: + network.connect(args.network) + contract = TokenDrainerFacet(args.address) + transaction_config = get_transaction_config(args) + result = contract.drain_erc1155( + token_address=args.token_address, + token_id=args.token_id, + receiver_address=args.receiver_address, + transaction_config=transaction_config, + ) + print(result) + if args.verbose: + print(result.info()) + + +def handle_drain_erc20(args: argparse.Namespace) -> None: + network.connect(args.network) + contract = TokenDrainerFacet(args.address) + transaction_config = get_transaction_config(args) + result = contract.drain_erc20( + token_address=args.token_address, + receiver_address=args.receiver_address, + transaction_config=transaction_config, + ) + print(result) + if args.verbose: + print(result.info()) + + +def handle_withdraw_erc1155(args: argparse.Namespace) -> None: + network.connect(args.network) + contract = TokenDrainerFacet(args.address) + transaction_config = get_transaction_config(args) + result = contract.withdraw_erc1155( + token_address=args.token_address, + token_id=args.token_id, + amount=args.amount, + receiver_address=args.receiver_address, + transaction_config=transaction_config, + ) + print(result) + if args.verbose: + print(result.info()) + + +def handle_withdraw_erc20(args: argparse.Namespace) -> None: + network.connect(args.network) + contract = TokenDrainerFacet(args.address) + transaction_config = get_transaction_config(args) + result = contract.withdraw_erc20( + token_address=args.token_address, + amount=args.amount, + receiver_address=args.receiver_address, + transaction_config=transaction_config, + ) + print(result) + if args.verbose: + print(result.info()) + + +def generate_cli() -> argparse.ArgumentParser: + parser = argparse.ArgumentParser(description="CLI for TokenDrainerFacet") + parser.set_defaults(func=lambda _: parser.print_help()) + subcommands = parser.add_subparsers() + + deploy_parser = subcommands.add_parser("deploy") + add_default_arguments(deploy_parser, True) + deploy_parser.set_defaults(func=handle_deploy) + + verify_contract_parser = subcommands.add_parser("verify-contract") + add_default_arguments(verify_contract_parser, False) + verify_contract_parser.set_defaults(func=handle_verify_contract) + + drain_erc1155_parser = subcommands.add_parser("drain-erc1155") + add_default_arguments(drain_erc1155_parser, True) + drain_erc1155_parser.add_argument( + "--token-address", required=True, help="Type: address" + ) + drain_erc1155_parser.add_argument( + "--token-id", required=True, help="Type: uint256", type=int + ) + drain_erc1155_parser.add_argument( + "--receiver-address", required=True, help="Type: address" + ) + drain_erc1155_parser.set_defaults(func=handle_drain_erc1155) + + drain_erc20_parser = subcommands.add_parser("drain-erc20") + add_default_arguments(drain_erc20_parser, True) + drain_erc20_parser.add_argument( + "--token-address", required=True, help="Type: address" + ) + drain_erc20_parser.add_argument( + "--receiver-address", required=True, help="Type: address" + ) + drain_erc20_parser.set_defaults(func=handle_drain_erc20) + + withdraw_erc1155_parser = subcommands.add_parser("withdraw-erc1155") + add_default_arguments(withdraw_erc1155_parser, True) + withdraw_erc1155_parser.add_argument( + "--token-address", required=True, help="Type: address" + ) + withdraw_erc1155_parser.add_argument( + "--token-id", required=True, help="Type: uint256", type=int + ) + withdraw_erc1155_parser.add_argument( + "--amount", required=True, help="Type: uint256", type=int + ) + withdraw_erc1155_parser.add_argument( + "--receiver-address", required=True, help="Type: address" + ) + withdraw_erc1155_parser.set_defaults(func=handle_withdraw_erc1155) + + withdraw_erc20_parser = subcommands.add_parser("withdraw-erc20") + add_default_arguments(withdraw_erc20_parser, True) + withdraw_erc20_parser.add_argument( + "--token-address", required=True, help="Type: address" + ) + withdraw_erc20_parser.add_argument( + "--amount", required=True, help="Type: uint256", type=int + ) + withdraw_erc20_parser.add_argument( + "--receiver-address", required=True, help="Type: address" + ) + withdraw_erc20_parser.set_defaults(func=handle_withdraw_erc20) + + return parser + + +def main() -> None: + parser = generate_cli() + args = parser.parse_args() + args.func(args) + + +if __name__ == "__main__": + main()