From 3ea6b8d9f979ba9f8903662610a6b76cd9898296 Mon Sep 17 00:00:00 2001 From: Eric Nordelo Date: Wed, 2 Nov 2022 15:50:10 +0100 Subject: [PATCH 01/32] feat: add main logic --- setup.cfg | 4 +- src/nile/cli.py | 26 ++++++++----- src/nile/common.py | 2 +- src/nile/core/account.py | 58 ++++++++++++++++------------ src/nile/core/deploy.py | 69 ++++++++++++++++++++++++++++++++-- src/nile/nre.py | 9 ----- src/nile/signer.py | 10 ++--- tests/commands/test_account.py | 20 +++++----- tests/test_signer.py | 2 +- 9 files changed, 136 insertions(+), 64 deletions(-) diff --git a/setup.cfg b/setup.cfg index 323a0090..b5f941ef 100644 --- a/setup.cfg +++ b/setup.cfg @@ -26,8 +26,8 @@ install_requires = click>=8.0,<9.0 importlib-metadata>=4.0 python-dotenv>=0.19.2 - starknet-devnet>=0.3.1,<0.3.4 - cairo-lang==0.10.0 + starknet-devnet>=0.3.1 + cairo-lang==0.10.1 pytest>=7.1.3 pytest-asyncio>=0.19.0 requests>=2.28.1 diff --git a/src/nile/cli.py b/src/nile/cli.py index fa3ecf84..b6b4455d 100644 --- a/src/nile/cli.py +++ b/src/nile/cli.py @@ -9,7 +9,6 @@ from nile.core.call_or_invoke import call_or_invoke as call_or_invoke_command from nile.core.clean import clean as clean_command from nile.core.compile import compile as compile_command -from nile.core.deploy import deploy as deploy_command from nile.core.init import init as init_command from nile.core.node import node as node_command from nile.core.plugins import load_plugins @@ -76,14 +75,23 @@ def run(path, network): @cli.command() -@click.argument("artifact", nargs=1) -@click.argument("arguments", nargs=-1) -@network_option +@click.argument("signer", nargs=1) +@click.argument("contract_name", nargs=1) +@click.argument("salt", nargs=1) +@click.argument("params", nargs=-1) +@click.option("--max_fee", nargs=1) +@click.option("--unique", is_flag=True) @click.option("--alias") @click.option("--abi") -def deploy(artifact, arguments, network, alias, abi=None): - """Deploy StarkNet smart contract.""" - deploy_command(artifact, arguments, network, alias, abi=abi) +@network_option +def deploy( + signer, contract_name, salt, params, max_fee, unique, network, alias=None, abi=None +): + """Deploy StarkNet smart contract through an Account.""" + account = Account(signer, network) + account.deploy_contract( + contract_name, salt, unique, params, alias, max_fee=None, abi=abi + ) @cli.command() @@ -96,7 +104,7 @@ def deploy(artifact, arguments, network, alias, abi=None): def declare( signer, contract_name, network, max_fee=None, alias=None, overriding_path=None ): - """Declare StarkNet smart contract.""" + """Declare StarkNet smart contract through an Account.""" account = Account(signer, network) account.declare( contract_name, @@ -174,7 +182,7 @@ def test(contracts): @cli.command() @click.argument("contracts", nargs=-1) @click.option("--directory") -@click.option("--account_contract", is_flag="True") +@click.option("--account_contract", is_flag=True) @click.option("--disable-hint-validation", is_flag=True) def compile(contracts, directory, account_contract, disable_hint_validation): """ diff --git a/src/nile/common.py b/src/nile/common.py index d54a5876..4039eac2 100644 --- a/src/nile/common.py +++ b/src/nile/common.py @@ -194,7 +194,7 @@ def get_contract_class(contract_name, overriding_path=None): return contract_class -def get_hash(contract_name, overriding_path=None): +def get_class_hash(contract_name, overriding_path=None): """Return the class_hash for a given contract name.""" contract_class = get_contract_class(contract_name, overriding_path) return compute_class_hash(contract_class=contract_class, hash_func=pedersen_hash) diff --git a/src/nile/core/account.py b/src/nile/core/account.py index 024da3b9..68cab9e3 100644 --- a/src/nile/core/account.py +++ b/src/nile/core/account.py @@ -15,7 +15,7 @@ ) from nile.core.call_or_invoke import call_or_invoke from nile.core.declare import declare -from nile.core.deploy import deploy +from nile.core.deploy import deploy_contract, deprecated_deploy from nile.utils.get_nonce import get_nonce_without_log as get_nonce try: @@ -70,7 +70,7 @@ def deploy(self): pt = os.path.dirname(os.path.realpath(__file__)).replace("/core", "") overriding_path = (f"{pt}/artifacts", f"{pt}/artifacts/abis") - address, _ = deploy( + address, _ = deprecated_deploy( "Account", [self.signer.public_key], self.network, @@ -87,20 +87,14 @@ def deploy(self): def declare( self, contract_name, max_fee=None, nonce=None, alias=None, overriding_path=None ): - """Declare a contract through an Account contract.""" - if nonce is None: - nonce = get_nonce(self.address, self.network) - - if max_fee is None: - max_fee = 0 - else: - max_fee = int(max_fee) + """Declare a contract through an Account.""" + _, max_fee, nonce = self._process_arguments([], max_fee, nonce) contract_class = get_contract_class( contract_name=contract_name, overriding_path=overriding_path ) - sig_r, sig_s = self.signer.sign_declare( + sig_r, sig_s = self.signer.sign_declare_tx( sender=self.address, contract_class=contract_class, nonce=nonce, @@ -117,30 +111,46 @@ def declare( ) def deploy_contract( - self, class_hash, salt, unique, calldata, max_fee=None, deployer_address=None + self, + contract_name, + salt, + unique, + calldata, + alias, + max_fee=None, + deployer_address=None, + abi=None, ): - """Deploy a contract through an Account contract.""" - return self.send( - to=deployer_address or UNIVERSAL_DEPLOYER_ADDRESS, - method="deployContract", - calldata=[class_hash, salt, unique, len(calldata), *calldata], - max_fee=max_fee, + """Deploy a contract through an Account.""" + deploy_contract( + self, + contract_name, + salt, + unique, + calldata, + self.network, + alias, + deployer_address or UNIVERSAL_DEPLOYER_ADDRESS, + abi=abi, ) def send( - self, address_or_alias, method, calldata, max_fee, nonce=None, query_type=None + self, + address_or_alias, + method, + calldata, + max_fee=None, + nonce=None, + query_type=None, ): - """Execute a query or invoke call for a tx going through an Account contract.""" - # get target address with the right format + """Execute a query or invoke call for a tx going through an Account.""" target_address = self._get_target_address(address_or_alias) - # process and parse arguments calldata, max_fee, nonce = self._process_arguments(calldata, max_fee, nonce) - # get tx version tx_version = QUERY_VERSION if query_type else TRANSACTION_VERSION - calldata, sig_r, sig_s = self.signer.sign_transaction( + calldata, sig_r, sig_s = self.signer.sign_invoke_tx( sender=self.address, calls=[[target_address, method, calldata]], nonce=nonce, diff --git a/src/nile/core/deploy.py b/src/nile/core/deploy.py index 0aedfdc6..1cff25c3 100644 --- a/src/nile/core/deploy.py +++ b/src/nile/core/deploy.py @@ -1,13 +1,26 @@ """Command to deploy StarkNet smart contracts.""" import logging +from starkware.cairo.common.hash_state import compute_hash_on_elements +from starkware.starknet.core.os.contract_address.contract_address import ( + calculate_contract_address_from_hash, +) + from nile import deployments -from nile.common import ABIS_DIRECTORY, BUILD_DIRECTORY, parse_information, run_command +from nile.common import ( + ABIS_DIRECTORY, + BUILD_DIRECTORY, + get_class_hash, + parse_information, + run_command, +) from nile.utils import hex_address -def deploy(contract_name, arguments, network, alias, overriding_path=None, abi=None): - """Deploy StarkNet smart contracts.""" +def deprecated_deploy( + contract_name, arguments, network, alias, overriding_path=None, abi=None +): + """Deploy StarkNet smart contracts (deprecated).""" logging.info(f"🚀 Deploying {contract_name}") base_path = ( overriding_path if overriding_path else (BUILD_DIRECTORY, ABIS_DIRECTORY) @@ -30,3 +43,53 @@ def deploy(contract_name, arguments, network, alias, overriding_path=None, abi=N deployments.register(address, register_abi, network, alias) return address, register_abi + + +def deploy_contract( + account, + contract_name, + salt, + unique, + calldata, + network, + alias, + deployer_address, + max_fee, + overriding_path=None, + abi=None, +): + """Deploy StarkNet smart contracts through UDC.""" + logging.info(f"🚀 Deploying {contract_name}") + + class_hash = get_class_hash(contract_name=contract_name) + + output = account.send( + to=deployer_address, + method="deployContract", + calldata=[class_hash, salt, unique, len(calldata), *calldata], + max_fee=max_fee, + ) + + base_path = ( + overriding_path if overriding_path else (BUILD_DIRECTORY, ABIS_DIRECTORY) + ) + register_abi = abi if abi is not None else f"{base_path[1]}/{contract_name}.json" + deployer_for_address_generation = deployer_address + + if unique: + # Match UDC address generation + salt = compute_hash_on_elements(data=[account.address, salt]) + deployer_for_address_generation = 0 + + address = calculate_contract_address_from_hash( + salt, class_hash, calldata, deployer_for_address_generation + ) + + logging.info( + f"⏳ ️Deployment of {contract_name} successfully sent at {hex_address(address)}" + ) + # TODO: Get transaction hash from output + logging.info(f"🧾 Transaction hash: {output}") + + deployments.register(address, register_abi, network, alias) + return address, register_abi diff --git a/src/nile/nre.py b/src/nile/nre.py index 4df5a5f9..2f237da6 100644 --- a/src/nile/nre.py +++ b/src/nile/nre.py @@ -4,7 +4,6 @@ from nile.core.account import Account from nile.core.call_or_invoke import call_or_invoke from nile.core.compile import compile -from nile.core.deploy import deploy from nile.core.plugins import get_installed_plugins, skip_click_exit from nile.utils import normalize_number from nile.utils.get_accounts import get_accounts, get_predeployed_accounts @@ -24,14 +23,6 @@ def compile(self, contracts): """Compile a list of contracts.""" return compile(contracts) - def deploy( - self, contract, arguments=None, alias=None, overriding_path=None, abi=None - ): - """Deploy a smart contract.""" - return deploy( - contract, arguments, self.network, alias, overriding_path, abi=abi - ) - def call(self, address_or_alias, method, params=None): """Call a view function in a smart contract.""" if not is_alias(address_or_alias): diff --git a/src/nile/signer.py b/src/nile/signer.py index da7d7851..c9151b79 100644 --- a/src/nile/signer.py +++ b/src/nile/signer.py @@ -24,12 +24,12 @@ def sign(self, message_hash): """Sign a message hash.""" return sign(msg_hash=message_hash, priv_key=self.private_key) - def sign_declare(self, sender, contract_class, nonce, max_fee): + def sign_declare_tx(self, sender, contract_class, nonce, max_fee): """Sign a declare transaction.""" if isinstance(sender, str): sender = int(sender, 16) - transaction_hash = get_declare_hash( + transaction_hash = get_declare_tx_hash( sender=sender, contract_class=contract_class, max_fee=max_fee, @@ -38,10 +38,10 @@ def sign_declare(self, sender, contract_class, nonce, max_fee): return self.sign(message_hash=transaction_hash) - def sign_transaction( + def sign_invoke_tx( self, sender, calls, nonce, max_fee, version=TRANSACTION_VERSION ): - """Sign a transaction.""" + """Sign an invoke transaction.""" call_array, calldata = from_call_to_call_array(calls) execute_calldata = [ len(call_array), @@ -86,7 +86,7 @@ def from_call_to_call_array(calls): return (call_array, calldata) -def get_declare_hash(sender, contract_class, max_fee, nonce): +def get_declare_tx_hash(sender, contract_class, max_fee, nonce): """Compute the hash of a declare transaction.""" return calculate_declare_transaction_hash( contract_class=contract_class, diff --git a/tests/commands/test_account.py b/tests/commands/test_account.py index c29bd63b..97b3169f 100644 --- a/tests/commands/test_account.py +++ b/tests/commands/test_account.py @@ -85,7 +85,7 @@ def test_declare(mock_declare, mock_get_class, mock_deploy): alias = "my_contract" overriding_path = (BUILD_DIRECTORY, ABIS_DIRECTORY) - account.signer.sign_declare = MagicMock(return_value=signature) + account.signer.sign_declare_tx = MagicMock(return_value=signature) account.declare( contract_name, @@ -100,8 +100,8 @@ def test_declare(mock_declare, mock_get_class, mock_deploy): contract_name=contract_name, overriding_path=overriding_path ) - # Check values are correctly passed to 'sign_declare' - account.signer.sign_declare.assert_called_once_with( + # Check values are correctly passed to 'sign_declare_tx' + account.signer.sign_declare_tx.assert_called_once_with( sender=account.address, contract_class="ContractClass", nonce=nonce, @@ -141,14 +141,14 @@ def test_send_nonce_call(mock_target_address, mock_call, mock_nonce, mock_deploy @patch( "nile.core.account.Account._get_target_address", return_value=MOCK_TARGET_ADDRESS ) -def test_send_sign_transaction_and_execute(mock_target_address, mock_deploy): +def test_send_sign_invoke_tx_and_execute(mock_target_address, mock_deploy): account = Account(KEY, NETWORK) calldata = ["111", "222", "333"] sig_r, sig_s = [999, 888] return_signature = [calldata, sig_r, sig_s] - account.signer.sign_transaction = MagicMock(return_value=return_signature) + account.signer.sign_invoke_tx = MagicMock(return_value=return_signature) with patch("nile.core.account.call_or_invoke") as mock_call: send_args = [MOCK_TARGET_ADDRESS, "method", [1, 2, 3]] @@ -156,8 +156,8 @@ def test_send_sign_transaction_and_execute(mock_target_address, mock_deploy): max_fee = 1 account.send(*send_args, max_fee, nonce) - # Check values are correctly passed to 'sign_transaction' - account.signer.sign_transaction.assert_called_once_with( + # Check values are correctly passed to 'sign_invoke_tx' + account.signer.sign_invoke_tx.assert_called_once_with( calls=[send_args], nonce=nonce, sender=account.address, @@ -221,14 +221,14 @@ def test_execute_query( sig_r, sig_s = [999, 888] return_signature = [calldata, sig_r, sig_s] - # Mock sign_transaction - account.signer.sign_transaction = MagicMock(return_value=return_signature) + # Mock sign_invoke_tx + account.signer.sign_invoke_tx = MagicMock(return_value=return_signature) account.send( account.address, "method", [1, 2, 3], max_fee=MAX_FEE, query_type=query_type ) - account.signer.sign_transaction.assert_called_once_with( + account.signer.sign_invoke_tx.assert_called_once_with( calls=[send_args], nonce=0, sender=account.address, diff --git a/tests/test_signer.py b/tests/test_signer.py index 8620723d..3beeef5f 100644 --- a/tests/test_signer.py +++ b/tests/test_signer.py @@ -40,7 +40,7 @@ async def send_transactions(signer, account, calls, nonce=None, max_fee=0): nonce = await state.state.get_nonce_at(account.contract_address) # get signature - calldata, sig_r, sig_s = signer.sign_transaction( + calldata, sig_r, sig_s = signer.sign_invoke_tx( account.contract_address, calls, nonce, max_fee, TRANSACTION_VERSION ) From 4d60c2ac682dcff95bbeb09b050417e9fe89dad1 Mon Sep 17 00:00:00 2001 From: Eric Nordelo Date: Thu, 3 Nov 2022 13:54:24 +0100 Subject: [PATCH 02/32] feat: finish main logic --- src/nile/cli.py | 22 +++++++++++++--------- src/nile/common.py | 2 +- src/nile/core/account.py | 10 +++++++--- src/nile/core/deploy.py | 16 ++++++++-------- src/nile/nre.py | 9 +++++++++ 5 files changed, 38 insertions(+), 21 deletions(-) diff --git a/src/nile/cli.py b/src/nile/cli.py index f03d2dc4..1fb089cc 100644 --- a/src/nile/cli.py +++ b/src/nile/cli.py @@ -9,6 +9,7 @@ from nile.core.call_or_invoke import call_or_invoke as call_or_invoke_command from nile.core.clean import clean as clean_command from nile.core.compile import compile as compile_command +from nile.core.deploy import deploy as deploy_command from nile.core.init import init as init_command from nile.core.node import node as node_command from nile.core.plugins import load_plugins @@ -75,23 +76,26 @@ def run(path, network): @cli.command() -@click.argument("signer", nargs=1) @click.argument("contract_name", nargs=1) -@click.argument("salt", nargs=1) @click.argument("params", nargs=-1) @click.option("--max_fee", nargs=1) +@click.option("--salt", nargs=1, default=0) @click.option("--unique", is_flag=True) +@click.option("--account") @click.option("--alias") @click.option("--abi") @network_option def deploy( - signer, contract_name, salt, params, max_fee, unique, network, alias=None, abi=None + contract_name, salt, params, max_fee, unique, network, account, alias, abi ): - """Deploy StarkNet smart contract through an Account.""" - account = Account(signer, network) - account.deploy_contract( - contract_name, salt, unique, params, alias, max_fee=None, abi=abi - ) + """Deploy StarkNet smart contract.""" + if account is not None: + account = Account(account, network) + account.deploy_contract( + contract_name, salt, unique, params, alias, max_fee=None, abi=abi + ) + else: + deploy_command(contract_name, params, network, alias, abi=abi) @cli.command() @@ -183,7 +187,7 @@ def test(contracts): @click.argument("contracts", nargs=-1) @click.option("--directory") @click.option("--cairo_path") -@click.option("--account_contract", is_flag=True) +@click.option("--account_contract", is_flag="True") @click.option("--disable-hint-validation", is_flag=True) def compile( contracts, directory, cairo_path, account_contract, disable_hint_validation diff --git a/src/nile/common.py b/src/nile/common.py index 29421f01..4e23d25d 100644 --- a/src/nile/common.py +++ b/src/nile/common.py @@ -25,7 +25,7 @@ QUERY_VERSION = QUERY_VERSION_BASE + TRANSACTION_VERSION UNIVERSAL_DEPLOYER_ADDRESS = ( # subject to change - "0x041a78e741e5af2fec34b695679bc6891742439f7afb8484ecd7766661ad02bf" + ("0x0406871d485b8077d8acb8bf17b27f5c4988026b9c80f3e28d954c2174e872c3") ) diff --git a/src/nile/core/account.py b/src/nile/core/account.py index fc1aee7e..c4c3f36a 100644 --- a/src/nile/core/account.py +++ b/src/nile/core/account.py @@ -15,7 +15,7 @@ ) from nile.core.call_or_invoke import call_or_invoke from nile.core.declare import declare -from nile.core.deploy import deploy_contract, deprecated_deploy +from nile.core.deploy import deploy_contract, deploy from nile.utils.get_nonce import get_nonce_without_log as get_nonce try: @@ -70,7 +70,7 @@ def deploy(self): pt = os.path.dirname(os.path.realpath(__file__)).replace("/core", "") overriding_path = (f"{pt}/artifacts", f"{pt}/artifacts/abis") - address, _ = deprecated_deploy( + address, _ = deploy( "Account", [self.signer.public_key], self.network, @@ -122,6 +122,9 @@ def deploy_contract( abi=None, ): """Deploy a contract through an Account.""" + deployer_address = normalize_number(deployer_address or UNIVERSAL_DEPLOYER_ADDRESS) + + deploy_contract( self, contract_name, @@ -131,6 +134,7 @@ def deploy_contract( self.network, alias, deployer_address or UNIVERSAL_DEPLOYER_ADDRESS, + max_fee, abi=abi, ) @@ -185,7 +189,7 @@ def _get_target_address(self, address_or_alias): target_address, _ = ( next(deployments.load(address_or_alias, self.network), None) - or address_or_alias + or (address_or_alias, None) ) return target_address diff --git a/src/nile/core/deploy.py b/src/nile/core/deploy.py index 1cff25c3..dce71e65 100644 --- a/src/nile/core/deploy.py +++ b/src/nile/core/deploy.py @@ -1,7 +1,7 @@ """Command to deploy StarkNet smart contracts.""" import logging -from starkware.cairo.common.hash_state import compute_hash_on_elements +from starkware.cairo.common.hash_chain import compute_hash_chain from starkware.starknet.core.os.contract_address.contract_address import ( calculate_contract_address_from_hash, ) @@ -17,7 +17,7 @@ from nile.utils import hex_address -def deprecated_deploy( +def deploy( contract_name, arguments, network, alias, overriding_path=None, abi=None ): """Deploy StarkNet smart contracts (deprecated).""" @@ -64,7 +64,7 @@ def deploy_contract( class_hash = get_class_hash(contract_name=contract_name) output = account.send( - to=deployer_address, + deployer_address, method="deployContract", calldata=[class_hash, salt, unique, len(calldata), *calldata], max_fee=max_fee, @@ -74,22 +74,22 @@ def deploy_contract( overriding_path if overriding_path else (BUILD_DIRECTORY, ABIS_DIRECTORY) ) register_abi = abi if abi is not None else f"{base_path[1]}/{contract_name}.json" - deployer_for_address_generation = deployer_address + deployer_for_address_generation = 0 if unique: # Match UDC address generation - salt = compute_hash_on_elements(data=[account.address, salt]) - deployer_for_address_generation = 0 + salt = compute_hash_chain(data=[account.address, salt]) + deployer_for_address_generation = deployer_address address = calculate_contract_address_from_hash( salt, class_hash, calldata, deployer_for_address_generation ) + _, tx_hash = parse_information(output) logging.info( f"⏳ ️Deployment of {contract_name} successfully sent at {hex_address(address)}" ) - # TODO: Get transaction hash from output - logging.info(f"🧾 Transaction hash: {output}") + logging.info(f"🧾 Transaction hash: {hex(tx_hash)}") deployments.register(address, register_abi, network, alias) return address, register_abi diff --git a/src/nile/nre.py b/src/nile/nre.py index ef178c1f..c216aa99 100644 --- a/src/nile/nre.py +++ b/src/nile/nre.py @@ -4,6 +4,7 @@ from nile.core.account import Account from nile.core.call_or_invoke import call_or_invoke from nile.core.compile import compile +from nile.core.deploy import deploy from nile.core.plugins import get_installed_plugins, skip_click_exit from nile.utils import normalize_number from nile.utils.get_accounts import get_accounts, get_predeployed_accounts @@ -23,6 +24,14 @@ def compile(self, contracts, cairo_path=None): """Compile a list of contracts.""" return compile(contracts, cairo_path=cairo_path) + def deploy( + self, contract, arguments=None, alias=None, overriding_path=None, abi=None + ): + """Deploy a smart contract.""" + return deploy( + contract, arguments, self.network, alias, overriding_path, abi=abi + ) + def call(self, address_or_alias, method, params=None): """Call a view function in a smart contract.""" if not is_alias(address_or_alias): From 7e93f8ca80079690e3c38f1b9252644502275b77 Mon Sep 17 00:00:00 2001 From: Eric Nordelo Date: Thu, 3 Nov 2022 13:56:18 +0100 Subject: [PATCH 03/32] feat: format files --- src/nile/cli.py | 4 +--- src/nile/common.py | 3 +-- src/nile/core/account.py | 14 +++++++------- src/nile/core/deploy.py | 4 +--- 4 files changed, 10 insertions(+), 15 deletions(-) diff --git a/src/nile/cli.py b/src/nile/cli.py index 1fb089cc..c785a069 100644 --- a/src/nile/cli.py +++ b/src/nile/cli.py @@ -85,9 +85,7 @@ def run(path, network): @click.option("--alias") @click.option("--abi") @network_option -def deploy( - contract_name, salt, params, max_fee, unique, network, account, alias, abi -): +def deploy(contract_name, salt, params, max_fee, unique, network, account, alias, abi): """Deploy StarkNet smart contract.""" if account is not None: account = Account(account, network) diff --git a/src/nile/common.py b/src/nile/common.py index 4e23d25d..5bec7063 100644 --- a/src/nile/common.py +++ b/src/nile/common.py @@ -24,8 +24,7 @@ QUERY_VERSION_BASE = 2**128 QUERY_VERSION = QUERY_VERSION_BASE + TRANSACTION_VERSION UNIVERSAL_DEPLOYER_ADDRESS = ( - # subject to change - ("0x0406871d485b8077d8acb8bf17b27f5c4988026b9c80f3e28d954c2174e872c3") + "0x041a78e741e5af2fec34b695679bc6891742439f7afb8484ecd7766661ad02bf" ) diff --git a/src/nile/core/account.py b/src/nile/core/account.py index c4c3f36a..002ebe99 100644 --- a/src/nile/core/account.py +++ b/src/nile/core/account.py @@ -15,7 +15,7 @@ ) from nile.core.call_or_invoke import call_or_invoke from nile.core.declare import declare -from nile.core.deploy import deploy_contract, deploy +from nile.core.deploy import deploy, deploy_contract from nile.utils.get_nonce import get_nonce_without_log as get_nonce try: @@ -122,8 +122,9 @@ def deploy_contract( abi=None, ): """Deploy a contract through an Account.""" - deployer_address = normalize_number(deployer_address or UNIVERSAL_DEPLOYER_ADDRESS) - + deployer_address = normalize_number( + deployer_address or UNIVERSAL_DEPLOYER_ADDRESS + ) deploy_contract( self, @@ -187,10 +188,9 @@ def _get_target_address(self, address_or_alias): if not is_alias(address_or_alias): address_or_alias = normalize_number(address_or_alias) - target_address, _ = ( - next(deployments.load(address_or_alias, self.network), None) - or (address_or_alias, None) - ) + target_address, _ = next( + deployments.load(address_or_alias, self.network), None + ) or (address_or_alias, None) return target_address diff --git a/src/nile/core/deploy.py b/src/nile/core/deploy.py index dce71e65..9bfffa36 100644 --- a/src/nile/core/deploy.py +++ b/src/nile/core/deploy.py @@ -17,9 +17,7 @@ from nile.utils import hex_address -def deploy( - contract_name, arguments, network, alias, overriding_path=None, abi=None -): +def deploy(contract_name, arguments, network, alias, overriding_path=None, abi=None): """Deploy StarkNet smart contracts (deprecated).""" logging.info(f"🚀 Deploying {contract_name}") base_path = ( From c06dd6452fc5c9a48d32ecec3bee6a98b97cf6e5 Mon Sep 17 00:00:00 2001 From: Eric Nordelo Date: Thu, 3 Nov 2022 15:00:45 +0100 Subject: [PATCH 04/32] feat: add deprecation warning and update README --- README.md | 19 +++++++++++-------- src/nile/cli.py | 14 ++++++++++++-- src/nile/core/deploy.py | 6 ++++-- 3 files changed, 27 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index ce6e82cb..29edf5e5 100644 --- a/README.md +++ b/README.md @@ -113,23 +113,26 @@ Creating artifacts/abis/ to store compilation artifacts ### `deploy` -> NOTICE: this method doesn't use an account, which will be deprecated very soon as StarkNet makes deployments from accounts mandatory. +> NOTICE: Calling this method without the `--account` parameter doesn't use an account, which will be deprecated very soon as StarkNet makes deployments from accounts mandatory. ```sh -nile deploy contract --alias my_contract +nile deploy contract --account setup_account_alias --alias my_contract 🚀 Deploying contract -🌕 artifacts/contract.json successfully deployed to 0x07ec10eb0758f7b1bc5aed0d5b4d30db0ab3c087eba85d60858be46c1a5e4680 +⏳ ️Deployment of contract successfully sent at 0x07ec10eb0758f7b1bc5aed0d5b4d30db0ab3c087eba85d60858be46c1a5e4680 +🧾 Transaction hash: 0x79e596c39cfec555f2d17253d043a0defd64a851a268b68c13811f328baf123 📦 Registering deployment as my_contract in localhost.deployments.txt ``` A few things to notice here: -1. `nile deploy ` looks for an artifact with the same name -2. This created a `localhost.deployments.txt` file storing all data related to my deployment -3. The `--alias` parameter lets me create a unique identifier for future interactions, if no alias is set then the contract's address can be used as identifier -4. By default Nile works on local, but you can use the `--network` parameter to interact with `mainnet`, `goerli`, `goerli2`, `integration`, and the default `localhost`. -5. By default, the ABI corresponding to the contract will be registered with the deployment. To register a different ABI file, use the `--abi` parameter. +1. `nile deploy ` looks for an artifact with the same name. +2. This created a `localhost.deployments.txt` file storing all data related to my deployment. +3. The `--account` parameter deploys using the provided account and the UniversalDeployer contract. +4. The `--alias` parameter lets you create a unique identifier for future interactions, if no alias is set then the contract's address can be used as identifier. +5. The `--udc` parameter lets you specify the UniversalDeployer address if needed. +6. By default Nile works on local, but you can use the `--network` parameter to interact with `mainnet`, `goerli`, `goerli2`, `integration`, and the default `localhost`. +7. By default, the ABI corresponding to the contract will be registered with the deployment. To register a different ABI file, use the `--abi` parameter. ### `setup` diff --git a/src/nile/cli.py b/src/nile/cli.py index c785a069..7469a90d 100644 --- a/src/nile/cli.py +++ b/src/nile/cli.py @@ -84,13 +84,23 @@ def run(path, network): @click.option("--account") @click.option("--alias") @click.option("--abi") +@click.option("--udc") @network_option -def deploy(contract_name, salt, params, max_fee, unique, network, account, alias, abi): +def deploy( + contract_name, salt, params, max_fee, unique, network, account, alias, abi, udc +): """Deploy StarkNet smart contract.""" if account is not None: account = Account(account, network) account.deploy_contract( - contract_name, salt, unique, params, alias, max_fee=None, abi=abi + contract_name, + salt, + unique, + params, + alias, + max_fee=None, + abi=abi, + deployer_address=udc, ) else: deploy_command(contract_name, params, network, alias, abi=abi) diff --git a/src/nile/core/deploy.py b/src/nile/core/deploy.py index 9bfffa36..55b107b9 100644 --- a/src/nile/core/deploy.py +++ b/src/nile/core/deploy.py @@ -18,8 +18,10 @@ def deploy(contract_name, arguments, network, alias, overriding_path=None, abi=None): - """Deploy StarkNet smart contracts (deprecated).""" - logging.info(f"🚀 Deploying {contract_name}") + """(DEPRECATED) Deploy StarkNet smart contracts.""" + logging.info( + f"🚀 Deploying {contract_name} without Account. This method is deprecated and will be removed soon. Try using the --account command option." + ) base_path = ( overriding_path if overriding_path else (BUILD_DIRECTORY, ABIS_DIRECTORY) ) From f061781e6f283be3e74cba027bd914ea26e93ecb Mon Sep 17 00:00:00 2001 From: Eric Nordelo Date: Thu, 3 Nov 2022 15:11:19 +0100 Subject: [PATCH 05/32] fix: format and linter --- src/nile/core/deploy.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/nile/core/deploy.py b/src/nile/core/deploy.py index 55b107b9..40873ff8 100644 --- a/src/nile/core/deploy.py +++ b/src/nile/core/deploy.py @@ -18,9 +18,11 @@ def deploy(contract_name, arguments, network, alias, overriding_path=None, abi=None): - """(DEPRECATED) Deploy StarkNet smart contracts.""" + """Deploy StarkNet smart contracts (DEPRECATED).""" logging.info( - f"🚀 Deploying {contract_name} without Account. This method is deprecated and will be removed soon. Try using the --account command option." + f"🚀 Deploying {contract_name} without Account. " + + "This method is deprecated and will be removed soon. " + + "Try using the --account command option." ) base_path = ( overriding_path if overriding_path else (BUILD_DIRECTORY, ABIS_DIRECTORY) From f9166bc463e1717e98035f047054adcc5d975612 Mon Sep 17 00:00:00 2001 From: Eric Nordelo Date: Thu, 3 Nov 2022 15:13:57 +0100 Subject: [PATCH 06/32] feat: format code --- src/nile/cli.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/nile/cli.py b/src/nile/cli.py index 7469a90d..d8f38d3f 100644 --- a/src/nile/cli.py +++ b/src/nile/cli.py @@ -98,9 +98,9 @@ def deploy( unique, params, alias, + deployer_address=udc, max_fee=None, abi=abi, - deployer_address=udc, ) else: deploy_command(contract_name, params, network, alias, abi=abi) @@ -116,7 +116,7 @@ def deploy( def declare( signer, contract_name, network, max_fee=None, alias=None, overriding_path=None ): - """Declare StarkNet smart contract through an Account.""" + """Declare a StarkNet smart contract through an Account.""" account = Account(signer, network) account.declare( contract_name, From 7b6b9afe4852d3c37707c6549609ecd615a418cd Mon Sep 17 00:00:00 2001 From: Eric Nordelo Date: Thu, 3 Nov 2022 15:17:10 +0100 Subject: [PATCH 07/32] feat: organize code --- src/nile/common.py | 1 + src/nile/core/deploy.py | 18 +++++++++--------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/nile/common.py b/src/nile/common.py index 5bec7063..29421f01 100644 --- a/src/nile/common.py +++ b/src/nile/common.py @@ -24,6 +24,7 @@ QUERY_VERSION_BASE = 2**128 QUERY_VERSION = QUERY_VERSION_BASE + TRANSACTION_VERSION UNIVERSAL_DEPLOYER_ADDRESS = ( + # subject to change "0x041a78e741e5af2fec34b695679bc6891742439f7afb8484ecd7766661ad02bf" ) diff --git a/src/nile/core/deploy.py b/src/nile/core/deploy.py index 40873ff8..f3da48f6 100644 --- a/src/nile/core/deploy.py +++ b/src/nile/core/deploy.py @@ -63,15 +63,6 @@ def deploy_contract( """Deploy StarkNet smart contracts through UDC.""" logging.info(f"🚀 Deploying {contract_name}") - class_hash = get_class_hash(contract_name=contract_name) - - output = account.send( - deployer_address, - method="deployContract", - calldata=[class_hash, salt, unique, len(calldata), *calldata], - max_fee=max_fee, - ) - base_path = ( overriding_path if overriding_path else (BUILD_DIRECTORY, ABIS_DIRECTORY) ) @@ -83,10 +74,19 @@ def deploy_contract( salt = compute_hash_chain(data=[account.address, salt]) deployer_for_address_generation = deployer_address + class_hash = get_class_hash(contract_name=contract_name) + address = calculate_contract_address_from_hash( salt, class_hash, calldata, deployer_for_address_generation ) + output = account.send( + deployer_address, + method="deployContract", + calldata=[class_hash, salt, unique, len(calldata), *calldata], + max_fee=max_fee, + ) + _, tx_hash = parse_information(output) logging.info( f"⏳ ️Deployment of {contract_name} successfully sent at {hex_address(address)}" From 6d3897b98099b7135042da94e3facb31edbf23a1 Mon Sep 17 00:00:00 2001 From: Eric Nordelo Date: Mon, 7 Nov 2022 13:17:05 +0100 Subject: [PATCH 08/32] feat: update tests --- tests/commands/test_account.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/commands/test_account.py b/tests/commands/test_account.py index 080a9a5c..3e0897b6 100644 --- a/tests/commands/test_account.py +++ b/tests/commands/test_account.py @@ -193,12 +193,12 @@ def test_send_defaults(mock_call, mock_nonce, mock_target_address, mock_deploy): sig_r, sig_s = [999, 888] return_signature = [calldata, sig_r, sig_s] - # Mock sign_transaction - account.signer.sign_transaction = MagicMock(return_value=return_signature) + # Mock sign_invoke_tx + account.signer.sign_invoke_tx = MagicMock(return_value=return_signature) account.send(account.address, "method", [1, 2, 3]) - account.signer.sign_transaction.assert_called_once_with( + account.signer.sign_invoke_tx.assert_called_once_with( calls=[send_args], nonce=0, sender=account.address, From a6e919fa16eafcddd21f09cc2f04d0ea0810803c Mon Sep 17 00:00:00 2001 From: Eric Nordelo Date: Mon, 7 Nov 2022 13:17:47 +0100 Subject: [PATCH 09/32] refactor: format files --- src/nile/cli.py | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/nile/cli.py b/src/nile/cli.py index 03fb2c35..48a85a93 100644 --- a/src/nile/cli.py +++ b/src/nile/cli.py @@ -96,7 +96,17 @@ def run(path, network): @mainnet_token_option @network_option def deploy( - contract_name, salt, params, max_fee, unique, account, alias, abi, udc, token, network + contract_name, + salt, + params, + max_fee, + unique, + account, + alias, + abi, + udc, + token, + network, ): """Deploy StarkNet smart contract.""" if account is not None: @@ -112,7 +122,9 @@ def deploy( abi=abi, ) else: - deploy_command(contract_name, params, network, alias, abi=abi, mainnet_token=token) + deploy_command( + contract_name, params, network, alias, abi=abi, mainnet_token=token + ) @cli.command() From ae32dba97b0d2958308e4c42e06edc24b370bb61 Mon Sep 17 00:00:00 2001 From: Eric Nordelo Date: Tue, 8 Nov 2022 12:36:42 +0100 Subject: [PATCH 10/32] Update README.md Co-authored-by: Andrew Fleming --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c2dd5708..9d854974 100644 --- a/README.md +++ b/README.md @@ -129,7 +129,7 @@ nile deploy contract --account setup_account_alias --alias my_contract A few things to notice here: 1. `nile deploy ` looks for an artifact with the same name. -2. This created a `localhost.deployments.txt` file storing all data related to my deployment. +2. This creates a `localhost.deployments.txt` file storing all data related to my deployment. 3. The `--account` parameter deploys using the provided account and the UniversalDeployer contract. 4. The `--alias` parameter lets you create a unique identifier for future interactions, if no alias is set then the contract's address can be used as identifier. 5. The `--udc` parameter lets you specify the UniversalDeployer address if needed. From 7a4b4847383d428077d0bc3f97f932227b39e48b Mon Sep 17 00:00:00 2001 From: Eric Nordelo Date: Tue, 8 Nov 2022 14:09:11 +0100 Subject: [PATCH 11/32] feat: add tests --- README.md | 2 +- src/nile/cli.py | 8 +-- src/nile/core/account.py | 11 ++-- src/nile/core/deploy.py | 3 +- tests/commands/test_account.py | 41 +++++++++++- tests/commands/test_deploy.py | 99 ++++++++++++++++++++++++++++- tests/commands/test_get_accounts.py | 4 +- 7 files changed, 153 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index c2dd5708..0964fdcd 100644 --- a/README.md +++ b/README.md @@ -113,7 +113,7 @@ Creating artifacts/abis/ to store compilation artifacts ### `deploy` -> NOTICE: Calling this method without the `--account` parameter doesn't use an account, which will be deprecated very soon as StarkNet makes deployments from accounts mandatory. +> NOTICE: Calling this method will require an account very soon (using the `--account` param) as StarkNet will make deployments from accounts mandatory. > Token for deployments to Alpha Mainnet can be set with the `--token` option. diff --git a/src/nile/cli.py b/src/nile/cli.py index 48a85a93..edc328d8 100644 --- a/src/nile/cli.py +++ b/src/nile/cli.py @@ -92,7 +92,7 @@ def run(path, network): @click.option("--account") @click.option("--alias") @click.option("--abi") -@click.option("--udc") +@click.option("--udc_address") @mainnet_token_option @network_option def deploy( @@ -104,7 +104,7 @@ def deploy( account, alias, abi, - udc, + udc_address, token, network, ): @@ -117,8 +117,8 @@ def deploy( unique, params, alias, - deployer_address=udc, - max_fee=None, + deployer_address=udc_address, + max_fee=max_fee, abi=abi, ) else: diff --git a/src/nile/core/account.py b/src/nile/core/account.py index 14396bf7..a2ba7432 100644 --- a/src/nile/core/account.py +++ b/src/nile/core/account.py @@ -15,7 +15,8 @@ ) from nile.core.call_or_invoke import call_or_invoke from nile.core.declare import declare -from nile.core.deploy import deploy, deploy_contract +from nile.core.deploy import deploy +from nile.core.deploy import deploy_contract as deploy_with_udc from nile.utils.get_nonce import get_nonce_without_log as get_nonce try: @@ -64,6 +65,9 @@ def __init__(self, signer, network, predeployed_info=None): self.address = address self.index = index + # Internal address must always be of type int + assert type(self.address) == int + def deploy(self): """Deploy an Account contract for the given private key.""" index = accounts.current_index(self.network) @@ -133,15 +137,14 @@ def deploy_contract( deployer_address or UNIVERSAL_DEPLOYER_ADDRESS ) - deploy_contract( + deploy_with_udc( self, contract_name, salt, unique, calldata, - self.network, alias, - deployer_address or UNIVERSAL_DEPLOYER_ADDRESS, + deployer_address, max_fee, abi=abi, ) diff --git a/src/nile/core/deploy.py b/src/nile/core/deploy.py index 6153760f..1510427a 100644 --- a/src/nile/core/deploy.py +++ b/src/nile/core/deploy.py @@ -62,7 +62,6 @@ def deploy_contract( salt, unique, calldata, - network, alias, deployer_address, max_fee, @@ -102,5 +101,5 @@ def deploy_contract( ) logging.info(f"🧾 Transaction hash: {hex(tx_hash)}") - deployments.register(address, register_abi, network, alias) + deployments.register(address, register_abi, account.network, alias) return address, register_abi diff --git a/tests/commands/test_account.py b/tests/commands/test_account.py index 3e0897b6..ad5207cd 100644 --- a/tests/commands/test_account.py +++ b/tests/commands/test_account.py @@ -9,12 +9,14 @@ BUILD_DIRECTORY, QUERY_VERSION, TRANSACTION_VERSION, + UNIVERSAL_DEPLOYER_ADDRESS, ) from nile.core.account import Account +from nile.utils import normalize_number KEY = "TEST_KEY" NETWORK = "localhost" -MOCK_ADDRESS = "0x123" +MOCK_ADDRESS = 0x123 MOCK_TARGET_ADDRESS = 0x987 MOCK_INDEX = 0 MAX_FEE = 10 @@ -120,6 +122,43 @@ def test_declare(mock_declare, mock_get_class, mock_deploy): ) +@pytest.mark.parametrize("deployer_address", [None, 0xDE0]) +@patch("nile.core.account.deploy", return_value=(MOCK_ADDRESS, MOCK_INDEX)) +@patch("nile.core.deploy.get_class_hash", return_value=0x434343) +@patch("nile.core.account.deploy_with_udc") +def test_deploy_contract( + mock_deploy_contract, mock_get_class, mock_deploy, deployer_address +): + account = Account(KEY, NETWORK) + + contract_name = "contract" + salt = 4 + unique = True + calldata = [] + alias = "my_contract" + max_fee = 1 + + account.deploy_contract( + contract_name, salt, unique, calldata, alias, max_fee, deployer_address + ) + + if deployer_address is None: + deployer_address = normalize_number(UNIVERSAL_DEPLOYER_ADDRESS) + + # Check values are correctly passed to 'deploy.deploy.deploy_contract' + mock_deploy_contract.assert_called_with( + account, + contract_name, + salt, + unique, + calldata, + alias, + deployer_address, + max_fee, + abi=None, + ) + + @patch("nile.core.account.deploy", return_value=(MOCK_ADDRESS, MOCK_INDEX)) @patch("nile.core.account.get_nonce", return_value=0) @patch("nile.core.account.call_or_invoke") diff --git a/tests/commands/test_deploy.py b/tests/commands/test_deploy.py index c117ec41..08ba2ca2 100644 --- a/tests/commands/test_deploy.py +++ b/tests/commands/test_deploy.py @@ -3,9 +3,13 @@ from unittest.mock import patch import pytest +from starkware.starknet.core.os.contract_address.contract_address import ( + calculate_contract_address_from_hash, +) from nile.common import ABIS_DIRECTORY, BUILD_DIRECTORY -from nile.core.deploy import deploy +from nile.core.account import Account +from nile.core.deploy import deploy, deploy_contract from nile.utils import hex_address @@ -15,6 +19,8 @@ def tmp_working_dir(monkeypatch, tmp_path): return tmp_path +MOCK_ACC_ADDRESS = 0x123 +MOCK_ACC_INDEX = 0 CONTRACT = "contract" NETWORK = "localhost" ALIAS = "alias" @@ -97,3 +103,94 @@ def test_deploy( in caplog.text ) assert f"🧾 Transaction hash: {hex(TX_HASH)}" in caplog.text + + +@pytest.mark.only +@pytest.mark.parametrize( + "args, exp_class_hash, exp_salt, exp_abi", + [ + ( + [CONTRACT, 0, True, [], ALIAS, 0x424242, 5], # args + 0x434343, + 2575391846029882800677169842619299590487820636126802982795520479739126412818, + ABI, + ), + ( + [CONTRACT, 1, False, [1], ALIAS, 0x454545, 0], # args + 0x464646, + 1, + ABI, + ), + ( + [CONTRACT, 3, True, [1, 2], ALIAS, 0x484848, 0], # args + 0x494949, + 2557841322555501036413859939246042028937187876697248667793106475357514195630, + ABI, + ), + ( + [ + CONTRACT, + 3, + False, + [1, 2, 3], + ALIAS, + 0x515151, + 0, + None, + "TEST_ABI", + ], # args + 0x525252, + 3, + "TEST_ABI", + ), + ], +) +@patch("nile.core.account.deploy", return_value=(MOCK_ACC_ADDRESS, MOCK_ACC_INDEX)) +@patch("nile.core.account.Account.send", return_value=RUN_OUTPUT) +@patch("nile.core.deploy.parse_information", return_value=[ADDRESS, TX_HASH]) +@patch("nile.core.deploy.deployments.register") +def test_deploy_contract( + mock_register, + mock_parse, + mock_send, + mock_deploy, + caplog, + args, + exp_class_hash, + exp_salt, + exp_abi, +): + account = Account("TEST_KEY", NETWORK) + + logging.getLogger().setLevel(logging.INFO) + + # decouple args + (contract_name, salt, unique, calldata, alias, deployer_address, max_fee, *_) = args + + with patch("nile.core.deploy.get_class_hash") as mock_return_account: + mock_return_account.return_value = exp_class_hash + + deployer_for_address_generation = deployer_address if unique else 0 + exp_address = calculate_contract_address_from_hash( + exp_salt, exp_class_hash, calldata, deployer_for_address_generation + ) + # check return values + res = deploy_contract(account, *args) + assert res == (exp_address, exp_abi) + + # check internals + mock_send.assert_called_once_with( + deployer_address, + method="deployContract", + calldata=[exp_class_hash, exp_salt, unique, len(calldata), *calldata], + max_fee=max_fee, + ) + mock_register.assert_called_once_with(exp_address, exp_abi, NETWORK, ALIAS) + + # check logs + assert f"🚀 Deploying {CONTRACT}" in caplog.text + assert ( + f"⏳ ️Deployment of {CONTRACT} successfully sent at {hex_address(exp_address)}" + in caplog.text + ) + assert f"🧾 Transaction hash: {hex(TX_HASH)}" in caplog.text diff --git a/tests/commands/test_get_accounts.py b/tests/commands/test_get_accounts.py index d18b8170..ff56ad8c 100644 --- a/tests/commands/test_get_accounts.py +++ b/tests/commands/test_get_accounts.py @@ -21,12 +21,12 @@ 883045738439352841478194533192765345509759306772397516907181243450667673002, 661519931401775515888740911132355225260405929679788917190706536765421826262, ] -ADDRESSES = ["333", "444"] +ADDRESSES = [333, 333] INDEXES = [0, 1] ALIASES = ["TEST_KEY", "TEST_KEY_2"] -MOCK_ADDRESS = "0x123" +MOCK_ADDRESS = 0x123 MOCK_INDEX = 0 MOCK_ACCOUNTS = { From f648d89a892affa636de6f3e329c4c810a392cc4 Mon Sep 17 00:00:00 2001 From: Eric Nordelo Date: Tue, 8 Nov 2022 14:15:12 +0100 Subject: [PATCH 12/32] fix: linter issues --- tests/commands/test_deploy.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/commands/test_deploy.py b/tests/commands/test_deploy.py index 08ba2ca2..d6131a7a 100644 --- a/tests/commands/test_deploy.py +++ b/tests/commands/test_deploy.py @@ -19,6 +19,10 @@ def tmp_working_dir(monkeypatch, tmp_path): return tmp_path +EXP_SALTS = [ + 2575391846029882800677169842619299590487820636126802982795520479739126412818, + 2557841322555501036413859939246042028937187876697248667793106475357514195630, +] MOCK_ACC_ADDRESS = 0x123 MOCK_ACC_INDEX = 0 CONTRACT = "contract" @@ -112,7 +116,7 @@ def test_deploy( ( [CONTRACT, 0, True, [], ALIAS, 0x424242, 5], # args 0x434343, - 2575391846029882800677169842619299590487820636126802982795520479739126412818, + EXP_SALTS[0], ABI, ), ( @@ -124,7 +128,7 @@ def test_deploy( ( [CONTRACT, 3, True, [1, 2], ALIAS, 0x484848, 0], # args 0x494949, - 2557841322555501036413859939246042028937187876697248667793106475357514195630, + EXP_SALTS[1], ABI, ), ( From 9969311cf81fb95546f8ecd31ae93ace85249042 Mon Sep 17 00:00:00 2001 From: Eric Nordelo Date: Tue, 8 Nov 2022 14:18:44 +0100 Subject: [PATCH 13/32] fix: linter issue --- tests/commands/test_deploy.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/commands/test_deploy.py b/tests/commands/test_deploy.py index d6131a7a..a4558449 100644 --- a/tests/commands/test_deploy.py +++ b/tests/commands/test_deploy.py @@ -194,7 +194,8 @@ def test_deploy_contract( # check logs assert f"🚀 Deploying {CONTRACT}" in caplog.text assert ( - f"⏳ ️Deployment of {CONTRACT} successfully sent at {hex_address(exp_address)}" + f"⏳ ️Deployment of {CONTRACT} successfully" + + f" sent at {hex_address(exp_address)}" in caplog.text ) assert f"🧾 Transaction hash: {hex(TX_HASH)}" in caplog.text From d969342d455dae3e7595a8f7530952a1a1cb6f36 Mon Sep 17 00:00:00 2001 From: Eric Nordelo Date: Wed, 9 Nov 2022 18:46:11 +0100 Subject: [PATCH 14/32] update README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 342ea337..52554420 100644 --- a/README.md +++ b/README.md @@ -132,7 +132,7 @@ A few things to notice here: 2. This creates a `localhost.deployments.txt` file storing all data related to my deployment. 3. The `--account` parameter deploys using the provided account and the UniversalDeployer contract. 4. The `--alias` parameter lets you create a unique identifier for future interactions, if no alias is set then the contract's address can be used as identifier. -5. The `--udc` parameter lets you specify the UniversalDeployer address if needed. +5. The `--udc_address` parameter lets you specify the UniversalDeployer address if needed. 6. By default Nile works on local, but you can use the `--network` parameter to interact with `mainnet`, `goerli`, `goerli2`, `integration`, and the default `localhost`. 7. By default, the ABI corresponding to the contract will be registered with the deployment. To register a different ABI file, use the `--abi` parameter. From dba3394f138d233e118e2f224b6ddd164bdb32a2 Mon Sep 17 00:00:00 2001 From: Eric Nordelo Date: Thu, 10 Nov 2022 21:55:53 +0100 Subject: [PATCH 15/32] feat: parse get_class_hash --- src/nile/core/deploy.py | 3 ++- tests/commands/test_deploy.py | 11 ++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/nile/core/deploy.py b/src/nile/core/deploy.py index 1510427a..06870e71 100644 --- a/src/nile/core/deploy.py +++ b/src/nile/core/deploy.py @@ -82,7 +82,8 @@ def deploy_contract( salt = compute_hash_chain(data=[account.address, salt]) deployer_for_address_generation = deployer_address - class_hash = get_class_hash(contract_name=contract_name) + # This needs to be fixed following the Hex/Int Pattern + class_hash = int(get_class_hash(contract_name=contract_name), 16) address = calculate_contract_address_from_hash( salt, class_hash, calldata, deployer_for_address_generation diff --git a/tests/commands/test_deploy.py b/tests/commands/test_deploy.py index a4558449..d10b904e 100644 --- a/tests/commands/test_deploy.py +++ b/tests/commands/test_deploy.py @@ -109,25 +109,24 @@ def test_deploy( assert f"🧾 Transaction hash: {hex(TX_HASH)}" in caplog.text -@pytest.mark.only @pytest.mark.parametrize( "args, exp_class_hash, exp_salt, exp_abi", [ ( [CONTRACT, 0, True, [], ALIAS, 0x424242, 5], # args - 0x434343, + '0x434343', EXP_SALTS[0], ABI, ), ( [CONTRACT, 1, False, [1], ALIAS, 0x454545, 0], # args - 0x464646, + '0x464646', 1, ABI, ), ( [CONTRACT, 3, True, [1, 2], ALIAS, 0x484848, 0], # args - 0x494949, + '0x494949', EXP_SALTS[1], ABI, ), @@ -143,7 +142,7 @@ def test_deploy( None, "TEST_ABI", ], # args - 0x525252, + '0x525252', 3, "TEST_ABI", ), @@ -174,6 +173,8 @@ def test_deploy_contract( with patch("nile.core.deploy.get_class_hash") as mock_return_account: mock_return_account.return_value = exp_class_hash + exp_class_hash = int(exp_class_hash, 16) + deployer_for_address_generation = deployer_address if unique else 0 exp_address = calculate_contract_address_from_hash( exp_salt, exp_class_hash, calldata, deployer_for_address_generation From 9856871439d4c8465c80146b7445961f8646439a Mon Sep 17 00:00:00 2001 From: Eric Nordelo Date: Thu, 10 Nov 2022 21:58:17 +0100 Subject: [PATCH 16/32] refactor: format files --- tests/commands/test_deploy.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/commands/test_deploy.py b/tests/commands/test_deploy.py index d10b904e..524bfee8 100644 --- a/tests/commands/test_deploy.py +++ b/tests/commands/test_deploy.py @@ -114,19 +114,19 @@ def test_deploy( [ ( [CONTRACT, 0, True, [], ALIAS, 0x424242, 5], # args - '0x434343', + "0x434343", EXP_SALTS[0], ABI, ), ( [CONTRACT, 1, False, [1], ALIAS, 0x454545, 0], # args - '0x464646', + "0x464646", 1, ABI, ), ( [CONTRACT, 3, True, [1, 2], ALIAS, 0x484848, 0], # args - '0x494949', + "0x494949", EXP_SALTS[1], ABI, ), @@ -142,7 +142,7 @@ def test_deploy( None, "TEST_ABI", ], # args - '0x525252', + "0x525252", 3, "TEST_ABI", ), From 34704c73ef3899852a0da17e145be17fb35f1ec2 Mon Sep 17 00:00:00 2001 From: Eric Nordelo Date: Fri, 11 Nov 2022 15:05:18 +0100 Subject: [PATCH 17/32] refactor: remove misleading comment --- src/nile/core/account.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/nile/core/account.py b/src/nile/core/account.py index a2ba7432..722fd4b2 100644 --- a/src/nile/core/account.py +++ b/src/nile/core/account.py @@ -65,7 +65,6 @@ def __init__(self, signer, network, predeployed_info=None): self.address = address self.index = index - # Internal address must always be of type int assert type(self.address) == int def deploy(self): From 953e831e4caecfdb8b6ab4e8cfe5c2e4b35340a0 Mon Sep 17 00:00:00 2001 From: Eric Nordelo Date: Fri, 11 Nov 2022 15:06:54 +0100 Subject: [PATCH 18/32] Update src/nile/core/deploy.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Martín Triay --- src/nile/core/deploy.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nile/core/deploy.py b/src/nile/core/deploy.py index 06870e71..5a395ebe 100644 --- a/src/nile/core/deploy.py +++ b/src/nile/core/deploy.py @@ -30,7 +30,7 @@ def deploy( logging.info( f"🚀 Deploying {contract_name} without Account. " + "This method is deprecated and will be removed soon. " - + "Try using the --account command option." + + "Use the --account option." ) base_path = ( overriding_path if overriding_path else (BUILD_DIRECTORY, ABIS_DIRECTORY) From 8777ed0d07a0dd6df355c5fa640021c96c8f1e8a Mon Sep 17 00:00:00 2001 From: Eric Nordelo Date: Fri, 11 Nov 2022 15:10:24 +0100 Subject: [PATCH 19/32] refactor: update comment --- tests/commands/test_account.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/commands/test_account.py b/tests/commands/test_account.py index ad5207cd..0d67ca4c 100644 --- a/tests/commands/test_account.py +++ b/tests/commands/test_account.py @@ -145,7 +145,7 @@ def test_deploy_contract( if deployer_address is None: deployer_address = normalize_number(UNIVERSAL_DEPLOYER_ADDRESS) - # Check values are correctly passed to 'deploy.deploy.deploy_contract' + # Check values are correctly passed to 'deploy_with_udc' mock_deploy_contract.assert_called_with( account, contract_name, From 3cface7cb47fdfe21fcf2270081cbeaacd051556 Mon Sep 17 00:00:00 2001 From: Eric Nordelo Date: Fri, 11 Nov 2022 16:18:48 +0100 Subject: [PATCH 20/32] feat: add more tests --- tests/commands/test_account.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/tests/commands/test_account.py b/tests/commands/test_account.py index ab6a7b24..cbe89e7f 100644 --- a/tests/commands/test_account.py +++ b/tests/commands/test_account.py @@ -125,8 +125,8 @@ def test_declare(mock_declare, mock_get_class, mock_deploy): @pytest.mark.parametrize("deployer_address", [None, 0xDE0]) -@pytest.mark.parametrize("watch_mode", [None]) -@pytest.mark.parametrize("abi", [None]) +@pytest.mark.parametrize("watch_mode", [None, "debug"]) +@pytest.mark.parametrize("abi", [None, "TEST_ABI"]) @patch("nile.core.account.deploy", return_value=(MOCK_ADDRESS, MOCK_INDEX)) @patch("nile.core.deploy.get_class_hash", return_value=0x434343) @patch("nile.core.account.deploy_with_udc") @@ -143,7 +143,15 @@ def test_deploy_contract( max_fee = 1 account.deploy_contract( - contract_name, salt, unique, calldata, alias, max_fee, deployer_address + contract_name, + salt, + unique, + calldata, + alias, + max_fee, + deployer_address, + abi, + watch_mode, ) if deployer_address is None: From a53ec32d30825c2a569833d399e1b95e8fb19810 Mon Sep 17 00:00:00 2001 From: Eric Nordelo Date: Fri, 11 Nov 2022 16:26:10 +0100 Subject: [PATCH 21/32] refactor: tests --- tests/commands/test_deploy.py | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/tests/commands/test_deploy.py b/tests/commands/test_deploy.py index 524bfee8..4cd7d1b8 100644 --- a/tests/commands/test_deploy.py +++ b/tests/commands/test_deploy.py @@ -23,6 +23,12 @@ def tmp_working_dir(monkeypatch, tmp_path): 2575391846029882800677169842619299590487820636126802982795520479739126412818, 2557841322555501036413859939246042028937187876697248667793106475357514195630, ] +EXP_CLASS_HASHES = [ + "0x434343", + "0x464646", + "0x494949", + "0x525252", +] MOCK_ACC_ADDRESS = 0x123 MOCK_ACC_INDEX = 0 CONTRACT = "contract" @@ -114,19 +120,19 @@ def test_deploy( [ ( [CONTRACT, 0, True, [], ALIAS, 0x424242, 5], # args - "0x434343", + EXP_CLASS_HASHES[0], EXP_SALTS[0], ABI, ), ( [CONTRACT, 1, False, [1], ALIAS, 0x454545, 0], # args - "0x464646", + EXP_CLASS_HASHES[1], 1, ABI, ), ( [CONTRACT, 3, True, [1, 2], ALIAS, 0x484848, 0], # args - "0x494949", + EXP_CLASS_HASHES[2], EXP_SALTS[1], ABI, ), @@ -140,11 +146,11 @@ def test_deploy( 0x515151, 0, None, - "TEST_ABI", + ABI_OVERRIDE, ], # args - "0x525252", + EXP_CLASS_HASHES[3], 3, - "TEST_ABI", + ABI_OVERRIDE, ), ], ) From f41c22e309c7aaa46c0602ab33944e81243db03e Mon Sep 17 00:00:00 2001 From: Eric Nordelo Date: Mon, 14 Nov 2022 13:29:36 +0100 Subject: [PATCH 22/32] feat: refactor udc to deployer --- README.md | 2 +- src/nile/cli.py | 6 +++--- src/nile/core/account.py | 4 ++-- src/nile/core/deploy.py | 2 +- tests/commands/test_account.py | 4 ++-- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index ef2eb476..bb9e0169 100644 --- a/README.md +++ b/README.md @@ -142,7 +142,7 @@ A few things to note here: 2. This creates or updates the `localhost.deployments.txt` file storing all data related to deployments. 3. The `--account` parameter deploys using the provided account and the UniversalDeployer contract. 4. The `--alias` parameter creates a unique identifier for future interactions, if no alias is set then the contract's address can be used as identifier. -5. The `--udc_address` parameter lets you specify the UniversalDeployer address if needed. +5. The `--deployer_address` parameter lets you specify the deployer contract address if needed. 6. By default Nile works on local, but you can use the `--network` parameter to interact with `mainnet`, `goerli`, `goerli2`, `integration`, and the default `localhost`. 7. By default, the ABI corresponding to the contract will be registered with the deployment. To register a different ABI file, use the `--abi` parameter. 8. `--track` and `--debug` flags can be used to watch the status of the deployment transaction. See `status` below for a complete description. diff --git a/src/nile/cli.py b/src/nile/cli.py index b65ef511..91b18880 100644 --- a/src/nile/cli.py +++ b/src/nile/cli.py @@ -99,7 +99,7 @@ def run(path, network): @click.option("--account") @click.option("--alias") @click.option("--abi") -@click.option("--udc_address") +@click.option("--deployer_address") @mainnet_token_option @network_option @watch_option @@ -112,7 +112,7 @@ def deploy( account, alias, abi, - udc_address, + deployer_address, token, network, watch_mode, @@ -126,7 +126,7 @@ def deploy( unique, params, alias, - deployer_address=udc_address, + deployer_address=deployer_address, max_fee=max_fee, abi=abi, watch_mode=watch_mode, diff --git a/src/nile/core/account.py b/src/nile/core/account.py index eab4dc11..c3397124 100644 --- a/src/nile/core/account.py +++ b/src/nile/core/account.py @@ -16,7 +16,7 @@ from nile.core.call_or_invoke import call_or_invoke from nile.core.declare import declare from nile.core.deploy import deploy -from nile.core.deploy import deploy_contract as deploy_with_udc +from nile.core.deploy import deploy_contract as deploy_with_deployer from nile.utils.get_nonce import get_nonce_without_log as get_nonce try: @@ -140,7 +140,7 @@ def deploy_contract( deployer_address or UNIVERSAL_DEPLOYER_ADDRESS ) - deploy_with_udc( + deploy_with_deployer( self, contract_name, salt, diff --git a/src/nile/core/deploy.py b/src/nile/core/deploy.py index e5f6f545..e89e534d 100644 --- a/src/nile/core/deploy.py +++ b/src/nile/core/deploy.py @@ -77,7 +77,7 @@ def deploy_contract( abi=None, watch_mode=None, ): - """Deploy StarkNet smart contracts through UDC.""" + """Deploy StarkNet smart contracts.""" logging.info(f"🚀 Deploying {contract_name}") base_path = ( diff --git a/tests/commands/test_account.py b/tests/commands/test_account.py index cbe89e7f..833afa9b 100644 --- a/tests/commands/test_account.py +++ b/tests/commands/test_account.py @@ -129,7 +129,7 @@ def test_declare(mock_declare, mock_get_class, mock_deploy): @pytest.mark.parametrize("abi", [None, "TEST_ABI"]) @patch("nile.core.account.deploy", return_value=(MOCK_ADDRESS, MOCK_INDEX)) @patch("nile.core.deploy.get_class_hash", return_value=0x434343) -@patch("nile.core.account.deploy_with_udc") +@patch("nile.core.account.deploy_with_deployer") def test_deploy_contract( mock_deploy_contract, mock_get_class, mock_deploy, abi, watch_mode, deployer_address ): @@ -157,7 +157,7 @@ def test_deploy_contract( if deployer_address is None: deployer_address = normalize_number(UNIVERSAL_DEPLOYER_ADDRESS) - # Check values are correctly passed to 'deploy_with_udc' + # Check values are correctly passed to 'deploy_with_deployer' mock_deploy_contract.assert_called_with( account, contract_name, From ce03ca1457132ffa38a6bb0cf5dec8fa749d1c5d Mon Sep 17 00:00:00 2001 From: Eric Nordelo Date: Tue, 15 Nov 2022 13:17:28 +0100 Subject: [PATCH 23/32] feat: change deploy cli api --- src/nile/cli.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/nile/cli.py b/src/nile/cli.py index 91b18880..772637e7 100644 --- a/src/nile/cli.py +++ b/src/nile/cli.py @@ -91,35 +91,41 @@ def run(path, network): @cli.command() +@click.argument("signer", nargs=1) @click.argument("contract_name", nargs=1) @click.argument("params", nargs=-1) @click.option("--max_fee", nargs=1) @click.option("--salt", nargs=1, default=0) @click.option("--unique", is_flag=True) -@click.option("--account") @click.option("--alias") @click.option("--abi") @click.option("--deployer_address") +@click.option( + "--ignore_account", + is_flag=True, + help="Deploy without Account.", +) @mainnet_token_option @network_option @watch_option def deploy( + signer, contract_name, salt, params, max_fee, unique, - account, alias, abi, deployer_address, + ignore_account, token, network, watch_mode, ): - """Deploy StarkNet smart contract.""" - if account is not None: - account = Account(account, network) + """Deploy a StarkNet smart contract.""" + if not ignore_account: + account = Account(signer, network) account.deploy_contract( contract_name, salt, From 048568e74ccc3aa7aec62906e7410b9b4e605f7b Mon Sep 17 00:00:00 2001 From: Eric Nordelo Date: Tue, 15 Nov 2022 21:05:32 +0100 Subject: [PATCH 24/32] feat: update README --- README.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index bb9e0169..b442bf52 100644 --- a/README.md +++ b/README.md @@ -119,16 +119,18 @@ Creating artifacts/abis/ to store compilation artifacts ### `deploy` -> NOTICE: Calling this method will require an account very soon (using the `--account` param) as StarkNet will make deployments from accounts mandatory. +> NOTICE: Calling this method with `--ignore_account` is discouraged and will be removed soon, as StarkNet will make deployments from accounts mandatory. > Token for deployments to Alpha Mainnet can be set with the `--token` option. ```txt -nile deploy [--alias ALIAS] [--network NETWORK] [--track | --debug] +nile deploy [--alias ALIAS] [--network NETWORK] [--track | --debug] ``` +For example: + ```sh -nile deploy contract --account setup_account_alias --alias my_contract +nile deploy setup_account_alias contract --alias my_contract 🚀 Deploying contract ⏳ ️Deployment of contract successfully sent at 0x07ec10eb0758f7b1bc5aed0d5b4d30db0ab3c087eba85d60858be46c1a5e4680 @@ -140,7 +142,7 @@ A few things to note here: 1. `nile deploy ` looks for an artifact with the same name. 2. This creates or updates the `localhost.deployments.txt` file storing all data related to deployments. -3. The `--account` parameter deploys using the provided account and the UniversalDeployer contract. +3. The `--ignore_account` flag deploys without using the account (DEPRECATED). 4. The `--alias` parameter creates a unique identifier for future interactions, if no alias is set then the contract's address can be used as identifier. 5. The `--deployer_address` parameter lets you specify the deployer contract address if needed. 6. By default Nile works on local, but you can use the `--network` parameter to interact with `mainnet`, `goerli`, `goerli2`, `integration`, and the default `localhost`. From bb949c6c2a24e6990c266acbc87009b4152eee69 Mon Sep 17 00:00:00 2001 From: Eric Nordelo Date: Tue, 15 Nov 2022 21:22:05 +0100 Subject: [PATCH 25/32] Update src/nile/core/account.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Martín Triay --- src/nile/core/account.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nile/core/account.py b/src/nile/core/account.py index c3397124..dc2f1b5c 100644 --- a/src/nile/core/account.py +++ b/src/nile/core/account.py @@ -163,7 +163,7 @@ def send( query_type=None, watch_mode=None, ): - """Execute a query or invoke call for a tx going through an Account.""" + """Execute or simulate an Account transaction.""" target_address = self._get_target_address(address_or_alias) calldata, max_fee, nonce = self._process_arguments(calldata, max_fee, nonce) From 24f396ae52218e84ed7f00cd0a03cde9ee42d3c0 Mon Sep 17 00:00:00 2001 From: Eric Nordelo Date: Tue, 15 Nov 2022 21:25:04 +0100 Subject: [PATCH 26/32] Update README.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Martín Triay --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b442bf52..614aae71 100644 --- a/README.md +++ b/README.md @@ -130,7 +130,7 @@ nile deploy [--alias ALIAS] [--network NETWORK] [ For example: ```sh -nile deploy setup_account_alias contract --alias my_contract +nile deploy contract --alias my_contract 🚀 Deploying contract ⏳ ️Deployment of contract successfully sent at 0x07ec10eb0758f7b1bc5aed0d5b4d30db0ab3c087eba85d60858be46c1a5e4680 From 08cd4f2d535ade586f6c1bf66b805cf611958ba5 Mon Sep 17 00:00:00 2001 From: Eric Nordelo Date: Thu, 17 Nov 2022 15:26:27 +0100 Subject: [PATCH 27/32] fix: test and linter --- src/nile/core/deploy.py | 1 - tests/commands/test_deploy.py | 6 +++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/nile/core/deploy.py b/src/nile/core/deploy.py index 2e52596c..f750601b 100644 --- a/src/nile/core/deploy.py +++ b/src/nile/core/deploy.py @@ -12,7 +12,6 @@ BUILD_DIRECTORY, get_class_hash, parse_information, - run_command, ) from nile.starknet_cli import execute_call from nile.utils import hex_address diff --git a/tests/commands/test_deploy.py b/tests/commands/test_deploy.py index 6db50c16..c64091a0 100644 --- a/tests/commands/test_deploy.py +++ b/tests/commands/test_deploy.py @@ -157,7 +157,7 @@ async def test_deploy(mock_register, mock_parse, caplog, args, cmd_args, exp_abi ], ) @patch("nile.core.account.deploy", return_value=(MOCK_ACC_ADDRESS, MOCK_ACC_INDEX)) -@patch("nile.core.account.Account.send", return_value=RUN_OUTPUT) +@patch("nile.core.account.Account.send", return_value=CALL_OUTPUT) @patch("nile.core.deploy.parse_information", return_value=[ADDRESS, TX_HASH]) @patch("nile.core.deploy.deployments.register") async def test_deploy_contract( @@ -171,7 +171,7 @@ async def test_deploy_contract( exp_salt, exp_abi, ): - account = Account("TEST_KEY", NETWORK) + account = await Account("TEST_KEY", NETWORK) logging.getLogger().setLevel(logging.INFO) @@ -188,7 +188,7 @@ async def test_deploy_contract( exp_salt, exp_class_hash, calldata, deployer_for_address_generation ) # check return values - res = deploy_contract(account, *args) + res = await deploy_contract(account, *args) assert res == (exp_address, exp_abi) # check internals From 4df6e181c83a8ff6daf20ed493cd1211be65c1b4 Mon Sep 17 00:00:00 2001 From: Eric Nordelo Date: Thu, 17 Nov 2022 16:16:35 +0100 Subject: [PATCH 28/32] fix: bug in debug --- src/nile/core/deploy.py | 3 +++ src/nile/utils/debug.py | 9 +++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/nile/core/deploy.py b/src/nile/core/deploy.py index f750601b..a958c548 100644 --- a/src/nile/core/deploy.py +++ b/src/nile/core/deploy.py @@ -87,6 +87,9 @@ async def deploy_contract( register_abi = abi if abi is not None else f"{base_path[1]}/{contract_name}.json" deployer_for_address_generation = 0 + if salt is None: + salt = 0 + if unique: # Match UDC address generation salt = compute_hash_chain(data=[account.address, salt]) diff --git a/src/nile/utils/debug.py b/src/nile/utils/debug.py index 665df631..fd110ae0 100644 --- a/src/nile/utils/debug.py +++ b/src/nile/utils/debug.py @@ -3,7 +3,12 @@ import logging import os -from nile.common import BUILD_DIRECTORY, DEPLOYMENTS_FILENAME, get_addresses_from_string +from nile.common import ( + BUILD_DIRECTORY, + DEPLOYMENTS_FILENAME, + get_addresses_from_string, + hex_class_hash, +) from nile.starknet_cli import execute_call @@ -41,7 +46,7 @@ async def debug_message(error_message, tx_hash, network, contracts_file=None): return await execute_call( "tx_status", network, - hash=tx_hash, + hash=hex_class_hash(tx_hash), contracts=",".join(contracts), error_message=True, ) From 21e85eb76eb505c74b7f719d5800da0a52063b1f Mon Sep 17 00:00:00 2001 From: Eric Nordelo Date: Thu, 17 Nov 2022 16:53:31 +0100 Subject: [PATCH 29/32] feat: fix comment --- src/nile/common.py | 6 ++---- src/nile/core/deploy.py | 3 +-- src/nile/utils/debug.py | 8 ++------ src/nile/utils/status.py | 3 ++- tests/commands/test_deploy.py | 10 ++++------ 5 files changed, 11 insertions(+), 19 deletions(-) diff --git a/src/nile/common.py b/src/nile/common.py index 5c433365..f66aec0c 100644 --- a/src/nile/common.py +++ b/src/nile/common.py @@ -7,7 +7,7 @@ from starkware.starknet.core.os.class_hash import compute_class_hash from starkware.starknet.services.api.contract_class import ContractClass -from nile.utils import hex_class_hash, normalize_number, str_to_felt +from nile.utils import normalize_number, str_to_felt CONTRACTS_DIRECTORY = "contracts" BUILD_DIRECTORY = "artifacts" @@ -129,9 +129,7 @@ def get_contract_class(contract_name, overriding_path=None): def get_class_hash(contract_name, overriding_path=None): """Return the class_hash for a given contract name.""" contract_class = get_contract_class(contract_name, overriding_path) - return hex_class_hash( - compute_class_hash(contract_class=contract_class, hash_func=pedersen_hash) - ) + return compute_class_hash(contract_class=contract_class, hash_func=pedersen_hash) def get_addresses_from_string(string): diff --git a/src/nile/core/deploy.py b/src/nile/core/deploy.py index a958c548..9788fc06 100644 --- a/src/nile/core/deploy.py +++ b/src/nile/core/deploy.py @@ -95,8 +95,7 @@ async def deploy_contract( salt = compute_hash_chain(data=[account.address, salt]) deployer_for_address_generation = deployer_address - # This needs to be fixed following the Hex/Int Pattern - class_hash = int(get_class_hash(contract_name=contract_name), 16) + class_hash = get_class_hash(contract_name=contract_name) address = calculate_contract_address_from_hash( salt, class_hash, calldata, deployer_for_address_generation diff --git a/src/nile/utils/debug.py b/src/nile/utils/debug.py index fd110ae0..a30cec6c 100644 --- a/src/nile/utils/debug.py +++ b/src/nile/utils/debug.py @@ -3,13 +3,9 @@ import logging import os -from nile.common import ( - BUILD_DIRECTORY, - DEPLOYMENTS_FILENAME, - get_addresses_from_string, - hex_class_hash, -) +from nile.common import BUILD_DIRECTORY, DEPLOYMENTS_FILENAME, get_addresses_from_string from nile.starknet_cli import execute_call +from nile.utils import hex_class_hash async def debug_message(error_message, tx_hash, network, contracts_file=None): diff --git a/src/nile/utils/status.py b/src/nile/utils/status.py index 6b90f837..48e4d3c0 100644 --- a/src/nile/utils/status.py +++ b/src/nile/utils/status.py @@ -6,8 +6,9 @@ from collections import namedtuple from enum import Enum -from nile.common import RETRY_AFTER_SECONDS, hex_class_hash +from nile.common import RETRY_AFTER_SECONDS from nile.starknet_cli import execute_call +from nile.utils import hex_class_hash from nile.utils.debug import debug_message TransactionStatus = namedtuple( diff --git a/tests/commands/test_deploy.py b/tests/commands/test_deploy.py index c64091a0..243a99b0 100644 --- a/tests/commands/test_deploy.py +++ b/tests/commands/test_deploy.py @@ -24,10 +24,10 @@ def tmp_working_dir(monkeypatch, tmp_path): 2557841322555501036413859939246042028937187876697248667793106475357514195630, ] EXP_CLASS_HASHES = [ - "0x434343", - "0x464646", - "0x494949", - "0x525252", + 0x434343, + 0x464646, + 0x494949, + 0x525252, ] MOCK_ACC_ADDRESS = 0x123 MOCK_ACC_INDEX = 0 @@ -181,8 +181,6 @@ async def test_deploy_contract( with patch("nile.core.deploy.get_class_hash") as mock_return_account: mock_return_account.return_value = exp_class_hash - exp_class_hash = int(exp_class_hash, 16) - deployer_for_address_generation = deployer_address if unique else 0 exp_address = calculate_contract_address_from_hash( exp_salt, exp_class_hash, calldata, deployer_for_address_generation From a4808043695d5a2a8bdbc78ac9ba6c159419b247 Mon Sep 17 00:00:00 2001 From: Eric Nordelo Date: Fri, 18 Nov 2022 00:25:40 +0100 Subject: [PATCH 30/32] fix: bug in address generation --- src/nile/core/deploy.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/nile/core/deploy.py b/src/nile/core/deploy.py index 9788fc06..c009f957 100644 --- a/src/nile/core/deploy.py +++ b/src/nile/core/deploy.py @@ -90,15 +90,17 @@ async def deploy_contract( if salt is None: salt = 0 + _salt = salt + if unique: # Match UDC address generation - salt = compute_hash_chain(data=[account.address, salt]) + _salt = compute_hash_chain(data=[account.address, salt]) deployer_for_address_generation = deployer_address class_hash = get_class_hash(contract_name=contract_name) address = calculate_contract_address_from_hash( - salt, class_hash, calldata, deployer_for_address_generation + _salt, class_hash, calldata, deployer_for_address_generation ) output = await account.send( From 765a7c227d5defc224841f2788e3c447343be131 Mon Sep 17 00:00:00 2001 From: Eric Nordelo Date: Fri, 18 Nov 2022 00:28:38 +0100 Subject: [PATCH 31/32] feat: fix tests --- tests/commands/test_deploy.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/commands/test_deploy.py b/tests/commands/test_deploy.py index 243a99b0..7a45fa65 100644 --- a/tests/commands/test_deploy.py +++ b/tests/commands/test_deploy.py @@ -193,7 +193,7 @@ async def test_deploy_contract( mock_send.assert_called_once_with( deployer_address, method="deployContract", - calldata=[exp_class_hash, exp_salt, unique, len(calldata), *calldata], + calldata=[exp_class_hash, salt, unique, len(calldata), *calldata], max_fee=max_fee, ) mock_register.assert_called_once_with(exp_address, exp_abi, NETWORK, ALIAS) From f544ad54fda92cc69c70ba6a5d4fea62d55321a9 Mon Sep 17 00:00:00 2001 From: Eric Nordelo Date: Sat, 19 Nov 2022 00:17:24 +0100 Subject: [PATCH 32/32] feat: remove _tx in sign methods --- src/nile/core/account.py | 4 ++-- src/nile/signer.py | 6 ++---- tests/commands/test_account.py | 26 +++++++++++++------------- tests/test_signer.py | 2 +- 4 files changed, 18 insertions(+), 20 deletions(-) diff --git a/src/nile/core/account.py b/src/nile/core/account.py index d9b42883..7689a26e 100644 --- a/src/nile/core/account.py +++ b/src/nile/core/account.py @@ -123,7 +123,7 @@ async def declare( contract_name=contract_name, overriding_path=overriding_path ) - sig_r, sig_s = self.signer.sign_declare_tx( + sig_r, sig_s = self.signer.sign_declare( sender=self.address, contract_class=contract_class, nonce=nonce, @@ -191,7 +191,7 @@ async def send( tx_version = QUERY_VERSION if query_type else TRANSACTION_VERSION - calldata, sig_r, sig_s = self.signer.sign_invoke_tx( + calldata, sig_r, sig_s = self.signer.sign_invoke( sender=self.address, calls=[[target_address, method, calldata]], nonce=nonce, diff --git a/src/nile/signer.py b/src/nile/signer.py index f888be8b..c93308ee 100644 --- a/src/nile/signer.py +++ b/src/nile/signer.py @@ -29,7 +29,7 @@ def sign(self, message_hash): """Sign a message hash.""" return sign(msg_hash=message_hash, priv_key=self.private_key) - def sign_declare_tx(self, sender, contract_class, nonce, max_fee): + def sign_declare(self, sender, contract_class, nonce, max_fee): """Sign a declare transaction.""" if isinstance(sender, str): sender = int(sender, 16) @@ -44,9 +44,7 @@ def sign_declare_tx(self, sender, contract_class, nonce, max_fee): return self.sign(message_hash=transaction_hash) - def sign_invoke_tx( - self, sender, calls, nonce, max_fee, version=TRANSACTION_VERSION - ): + def sign_invoke(self, sender, calls, nonce, max_fee, version=TRANSACTION_VERSION): """Sign an invoke transaction.""" call_array, calldata = from_call_to_call_array(calls) execute_calldata = [ diff --git a/tests/commands/test_account.py b/tests/commands/test_account.py index 5cb5bd94..e15c7f60 100644 --- a/tests/commands/test_account.py +++ b/tests/commands/test_account.py @@ -97,7 +97,7 @@ async def test_declare(mock_declare, mock_get_class, mock_deploy): alias = "my_contract" overriding_path = (BUILD_DIRECTORY, ABIS_DIRECTORY) - account.signer.sign_declare_tx = MagicMock(return_value=signature) + account.signer.sign_declare = MagicMock(return_value=signature) await account.declare( contract_name, @@ -112,8 +112,8 @@ async def test_declare(mock_declare, mock_get_class, mock_deploy): contract_name=contract_name, overriding_path=overriding_path ) - # Check values are correctly passed to 'sign_declare_tx' - account.signer.sign_declare_tx.assert_called_once_with( + # Check values are correctly passed to 'sign_declare' + account.signer.sign_declare.assert_called_once_with( sender=account.address, contract_class="ContractClass", nonce=nonce, @@ -206,14 +206,14 @@ async def test_send_nonce_call(mock_target_address, mock_call, mock_nonce, mock_ @patch( "nile.core.account.Account._get_target_address", return_value=MOCK_TARGET_ADDRESS ) -async def test_send_sign_invoke_tx_and_execute(mock_target_address, mock_deploy): +async def test_send_sign_invoke_and_execute(mock_target_address, mock_deploy): account = await Account(KEY, NETWORK) calldata = [111, 222, 333] sig_r, sig_s = [999, 888] return_signature = [calldata, sig_r, sig_s] - account.signer.sign_invoke_tx = MagicMock(return_value=return_signature) + account.signer.sign_invoke = MagicMock(return_value=return_signature) with patch("nile.core.account.call_or_invoke") as mock_call: send_args = [MOCK_TARGET_ADDRESS, "method", [1, 2, 3]] @@ -221,8 +221,8 @@ async def test_send_sign_invoke_tx_and_execute(mock_target_address, mock_deploy) max_fee = 1 await account.send(*send_args, max_fee=max_fee, nonce=nonce) - # Check values are correctly passed to 'sign_invoke_tx' - account.signer.sign_invoke_tx.assert_called_once_with( + # Check values are correctly passed to 'sign_invoke' + account.signer.sign_invoke.assert_called_once_with( calls=[send_args], nonce=nonce, sender=account.address, @@ -259,12 +259,12 @@ async def test_send_defaults(mock_call, mock_nonce, mock_target_address, mock_de sig_r, sig_s = [999, 888] return_signature = [calldata, sig_r, sig_s] - # Mock sign_invoke_tx - account.signer.sign_invoke_tx = MagicMock(return_value=return_signature) + # Mock sign_invoke + account.signer.sign_invoke = MagicMock(return_value=return_signature) await account.send(account.address, "method", [1, 2, 3]) - account.signer.sign_invoke_tx.assert_called_once_with( + account.signer.sign_invoke.assert_called_once_with( calls=[send_args], nonce=0, sender=account.address, @@ -333,8 +333,8 @@ async def test_execute_query( sig_r, sig_s = [999, 888] return_signature = [calldata, sig_r, sig_s] - # Mock sign_invoke_tx - account.signer.sign_invoke_tx = MagicMock(return_value=return_signature) + # Mock sign_invoke + account.signer.sign_invoke = MagicMock(return_value=return_signature) await account.send( account.address, @@ -345,7 +345,7 @@ async def test_execute_query( watch_mode=watch_mode, ) - account.signer.sign_invoke_tx.assert_called_once_with( + account.signer.sign_invoke.assert_called_once_with( calls=[send_args], nonce=0, sender=account.address, diff --git a/tests/test_signer.py b/tests/test_signer.py index c8437021..d40913f1 100644 --- a/tests/test_signer.py +++ b/tests/test_signer.py @@ -42,7 +42,7 @@ async def send_transactions(signer, account, calls, nonce=None, max_fee=0): nonce = await state.state.get_nonce_at(account.contract_address) # get signature - calldata, sig_r, sig_s = signer.sign_invoke_tx( + calldata, sig_r, sig_s = signer.sign_invoke( account.contract_address, calls, nonce, max_fee, TRANSACTION_VERSION )