Skip to content
This repository has been archived by the owner on Dec 1, 2023. It is now read-only.

Deploy through Accounts #276

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
3ea6b8d
feat: add main logic
ericnordelo Nov 2, 2022
0dc42e5
Merge branch 'main' of github.com:OpenZeppelin/nile into feat/deploy-…
ericnordelo Nov 3, 2022
4d60c2a
feat: finish main logic
ericnordelo Nov 3, 2022
7e93f8c
feat: format files
ericnordelo Nov 3, 2022
c06dd64
feat: add deprecation warning and update README
ericnordelo Nov 3, 2022
f061781
fix: format and linter
ericnordelo Nov 3, 2022
f9166bc
feat: format code
ericnordelo Nov 3, 2022
7b6b9af
feat: organize code
ericnordelo Nov 3, 2022
2dba075
Merge branch 'main' of github.com:OpenZeppelin/nile into feat/deploy-…
ericnordelo Nov 7, 2022
6d3897b
feat: update tests
ericnordelo Nov 7, 2022
a6e919f
refactor: format files
ericnordelo Nov 7, 2022
ae32dba
Update README.md
ericnordelo Nov 8, 2022
7a4b484
feat: add tests
ericnordelo Nov 8, 2022
b88b44d
Merge branch 'feat/deploy-through-account-#259' of github.com:ericnor…
ericnordelo Nov 8, 2022
f648d89
fix: linter issues
ericnordelo Nov 8, 2022
9969311
fix: linter issue
ericnordelo Nov 8, 2022
bf3ea83
Merge branch 'main' of github.com:OpenZeppelin/nile into feat/deploy-…
ericnordelo Nov 8, 2022
d969342
update README
ericnordelo Nov 9, 2022
dba3394
feat: parse get_class_hash
ericnordelo Nov 10, 2022
9856871
refactor: format files
ericnordelo Nov 10, 2022
34704c7
refactor: remove misleading comment
ericnordelo Nov 11, 2022
953e831
Update src/nile/core/deploy.py
ericnordelo Nov 11, 2022
8777ed0
refactor: update comment
ericnordelo Nov 11, 2022
6281b3c
Merge branch 'feat/deploy-through-account-#259' of github.com:ericnor…
ericnordelo Nov 11, 2022
2f62263
Merge branch 'main' of github.com:OpenZeppelin/nile into feat/deploy-…
ericnordelo Nov 11, 2022
3cface7
feat: add more tests
ericnordelo Nov 11, 2022
a53ec32
refactor: tests
ericnordelo Nov 11, 2022
f41c22e
feat: refactor udc to deployer
ericnordelo Nov 14, 2022
ce03ca1
feat: change deploy cli api
ericnordelo Nov 15, 2022
048568e
feat: update README
ericnordelo Nov 15, 2022
bb949c6
Update src/nile/core/account.py
ericnordelo Nov 15, 2022
24f396a
Update README.md
ericnordelo Nov 15, 2022
9d6b9e5
Merge branch 'main' of github.com:OpenZeppelin/nile into feat/deploy-…
ericnordelo Nov 17, 2022
08cd4f2
fix: test and linter
ericnordelo Nov 17, 2022
7c97c42
Merge branch 'feat/deploy-through-account-#259' of github.com:ericnor…
ericnordelo Nov 17, 2022
4df6e18
fix: bug in debug
ericnordelo Nov 17, 2022
21e85eb
feat: fix comment
ericnordelo Nov 17, 2022
a480804
fix: bug in address generation
ericnordelo Nov 17, 2022
765a7c2
feat: fix tests
ericnordelo Nov 17, 2022
f544ad5
feat: remove _tx in sign methods
ericnordelo Nov 18, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 15 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,30 +119,35 @@ 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 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 <contract> [--alias ALIAS] [--network NETWORK] [--track | --debug]
nile deploy <private_key_alias> <contract> [--alias ALIAS] [--network NETWORK] [--track | --debug]
```

For example:

```sh
nile deploy contract --alias my_contract
nile deploy <private_key_alias> contract --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 note here:

- `nile deploy <contract_name>` looks for an artifact with the same name.
- This creates or updates the `localhost.deployments.txt` file storing all data related to deployments.
- 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.
- By default Nile works on local, but you can use the `--network` parameter to interact with `mainnet`, `goerli`, and the default `localhost`.
- By default, the ABI corresponding to the contract will be registered with the deployment. To register a different ABI file, use the `--abi` parameter.
- `--track` and `--debug` flags can be used to watch the status of the deployment transaction. See `status` below for a complete description.
1. `nile deploy <contract_name>` 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 `--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`.
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.

### `setup`

Expand Down
68 changes: 53 additions & 15 deletions src/nile/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,24 +92,62 @@ async def run(path, network):


@cli.command()
@click.argument("artifact", nargs=1)
@click.argument("arguments", nargs=-1)
@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("--alias")
@click.option("--abi")
@network_option
@click.option("--deployer_address")
@click.option(
"--ignore_account",
is_flag=True,
help="Deploy without Account.",
)
@mainnet_token_option
@network_option
@watch_option
async def deploy(artifact, arguments, network, alias, abi, token, watch_mode):
"""Deploy StarkNet smart contract."""
await deploy_command(
artifact,
arguments,
network,
alias,
abi=abi,
mainnet_token=token,
watch_mode=watch_mode,
)
async def deploy(
signer,
contract_name,
salt,
params,
max_fee,
martriay marked this conversation as resolved.
Show resolved Hide resolved
unique,
alias,
abi,
deployer_address,
ignore_account,
token,
network,
watch_mode,
):
"""Deploy a StarkNet smart contract."""
if not ignore_account:
account = await Account(signer, network)
await account.deploy_contract(
contract_name,
salt,
unique,
params,
alias,
deployer_address=deployer_address,
max_fee=max_fee,
abi=abi,
martriay marked this conversation as resolved.
Show resolved Hide resolved
watch_mode=watch_mode,
)
else:
await deploy_command(
contract_name,
params,
network,
alias,
abi=abi,
mainnet_token=token,
watch_mode=watch_mode,
)


@cli.command()
Expand All @@ -131,7 +169,7 @@ async def declare(
overriding_path,
token,
):
"""Declare StarkNet smart contract."""
"""Declare a StarkNet smart contract through an Account."""
account = await Account(signer, network)
await account.declare(
contract_name,
Expand Down
8 changes: 3 additions & 5 deletions src/nile/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -126,12 +126,10 @@ 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 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):
Expand Down
43 changes: 27 additions & 16 deletions src/nile/core/account.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +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_deployer
from nile.utils.get_nonce import get_nonce_without_log as get_nonce

try:
Expand Down Expand Up @@ -82,6 +83,8 @@ async def __init__(self, signer, network, predeployed_info=None, watch_mode=None
self.address = address
self.index = index

assert type(self.address) == int
martriay marked this conversation as resolved.
Show resolved Hide resolved

async def deploy(self, watch_mode=None):
"""Deploy an Account contract for the given private key."""
index = accounts.current_index(self.network)
Expand Down Expand Up @@ -113,7 +116,7 @@ async def declare(
mainnet_token=None,
watch_mode=None,
):
"""Declare a contract through an Account contract."""
"""Declare a contract through an Account."""
max_fee, nonce, _ = await self._process_arguments(max_fee, nonce)

contract_class = get_contract_class(
Expand All @@ -140,20 +143,31 @@ async def declare(

async def deploy_contract(
self,
class_hash,
contract_name,
salt,
unique,
calldata,
alias,
max_fee=None,
deployer_address=None,
abi=None,
watch_mode=None,
):
"""Deploy a contract through an Account contract."""
return await 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."""
deployer_address = normalize_number(
deployer_address or UNIVERSAL_DEPLOYER_ADDRESS
)

await deploy_with_deployer(
self,
contract_name,
salt,
unique,
calldata,
alias,
deployer_address,
max_fee,
abi=abi,
watch_mode=watch_mode,
)

Expand All @@ -167,19 +181,17 @@ async def send(
query_type=None,
watch_mode=None,
):
"""Execute a query or invoke call for a tx going through an Account contract."""
# get target address with the right format
"""Execute or simulate an Account transaction."""
target_address = self._get_target_address(address_or_alias)

# process and parse arguments
max_fee, nonce, calldata = await self._process_arguments(
max_fee, nonce, calldata
)

# 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(
sender=self.address,
calls=[[target_address, method, calldata]],
nonce=nonce,
Expand Down Expand Up @@ -215,10 +227,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
)
target_address, _ = next(
deployments.load(address_or_alias, self.network), None
) or (address_or_alias, None)

return target_address

Expand Down
83 changes: 79 additions & 4 deletions src/nile/core/deploy.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,18 @@
"""Command to deploy StarkNet smart contracts."""
import logging

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,
)

from nile import deployments
from nile.common import ABIS_DIRECTORY, BUILD_DIRECTORY, parse_information
from nile.common import (
ABIS_DIRECTORY,
BUILD_DIRECTORY,
get_class_hash,
parse_information,
)
from nile.starknet_cli import execute_call
from nile.utils import hex_address
from nile.utils.status import status
Expand All @@ -18,9 +28,12 @@ async def deploy(
mainnet_token=None,
watch_mode=None,
):
"""Deploy StarkNet smart contracts."""
logging.info(f"🚀 Deploying {contract_name}")

"""Deploy StarkNet smart contracts (DEPRECATED)."""
logging.info(
f"🚀 Deploying {contract_name} without Account. "
+ "This method is deprecated and will be removed soon. "
+ "Use the --account option."
)
base_path = (
overriding_path if overriding_path else (BUILD_DIRECTORY, ABIS_DIRECTORY)
)
Expand Down Expand Up @@ -50,3 +63,65 @@ async def deploy(
return

return address, register_abi


async def deploy_contract(
account,
contract_name,
salt,
unique,
calldata,
alias,
deployer_address,
max_fee,
overriding_path=None,
abi=None,
watch_mode=None,
):
"""Deploy StarkNet smart contracts."""
logging.info(f"🚀 Deploying {contract_name}")

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 = 0

if salt is None:
salt = 0

_salt = salt

if unique:
# Match UDC address generation
_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 = await 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)}"
)
logging.info(f"🧾 Transaction hash: {hex(tx_hash)}")

deployments.register(address, register_abi, account.network, alias)

if watch_mode is not None:
tx_status = await status(tx_hash, account.network, watch_mode)
if tx_status.status.is_rejected:
deployments.unregister(address, account.network, alias, abi=register_abi)
return

return address, register_abi
10 changes: 4 additions & 6 deletions src/nile/signer.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def sign_declare(self, sender, contract_class, nonce, max_fee):
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,
Expand All @@ -44,10 +44,8 @@ def sign_declare(self, sender, contract_class, nonce, max_fee):

return self.sign(message_hash=transaction_hash)

def sign_transaction(
self, sender, calls, nonce, max_fee, version=TRANSACTION_VERSION
):
"""Sign a transaction."""
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 = [
len(call_array),
Expand Down Expand Up @@ -93,7 +91,7 @@ def from_call_to_call_array(calls):
return (call_array, calldata)


def get_declare_hash(sender, contract_class, max_fee, nonce, chain_id):
def get_declare_tx_hash(sender, contract_class, max_fee, nonce, chain_id):
"""Compute the hash of a declare transaction."""
return calculate_declare_transaction_hash(
contract_class=contract_class,
Expand Down
Loading