Skip to content

Commit

Permalink
docs: more updates to the deploy user guide (#1858)
Browse files Browse the repository at this point in the history
Co-authored-by: El De-dog-lo <[email protected]>
  • Loading branch information
antazoey and fubuloubu authored Jan 10, 2024
1 parent fb6a57a commit 615cbaa
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 49 deletions.
101 changes: 52 additions & 49 deletions docs/userguides/contracts.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,84 +8,87 @@ The other way is to initialize an already-deployed contract using its address.
## From Deploy

Deploy contracts from your project using the `project` root-level object.
The names of your contracts are attributes on the `project` object (e.g. `project.MyContract`) and their types are [ContractContainer](../methoddocs/contracts.html#ape.contracts.base.ContractContainer).
You deploy contracts using Python functions such as [AccountAPI.deploy](../methoddocs/api.html#ape.api.accounts.AccountAPI.deploy) or [ContractContainer.deploy](../methoddocs/contracts.html#ape.contracts.base.ContractContainer.deploy).

**NOTE**: To avoid naming collisions with other properties on the `project` object, you can also use the [get_contract()](../methoddocs/managers.html#ape.managers.project.manager.ProjectManager.get_contract) method to retrieve contract containers.
**NOTE**: You can run Ape's deploy functions from anywhere you run Python!

When you deploy contracts, you get back a `ContractInstance`.
You need both an account and a contract in order to deploy a contract, as the deployment process requires a transaction to submit the contract data to the blockchain.
To learn about accounts and how to use them, see the [Accounts Guide](./accounts.html).
You also need the contract.
You can access contract types from Ape's root-level `project` object (e.g. `project.MyContract`) and their types are [ContractContainer](../methoddocs/contracts.html#ape.contracts.base.ContractContainer).

Here is an example using Python and Ape to deploy a contract.
(Note: this code be run from anywhere you run Python, such as a script, an [Ape script](./scripts.html), a TTY, or the [ape console](./console.html)).
Let's assume you have a Vyper contract like this:

```python
from ape import accounts, project
```vyper
contract MySmartContract:
owner: public(address)
balance: public(uint256)
dev = accounts.load("dev")
contract = project.MyContract.deploy(sender=dev)
@public
@payable
@public
def __init__(arg1: uint256, arg2: address):
self.owner = arg2
self.balance = arg1
```

You can alternatively use this syntax instead:

```python
from ape import accounts, project

dev = accounts.load("dev")
contract = dev.deploy(project.MyContract)
```
Before you can deploy this contract, you must ensure it was compiled.
To learn about compiling in Ape, please see [this guide](./compile.html).

If your contract requires constructor arguments then you will need to pass them to the contract in the [args](./transactions.html) when deploying like this:
After it is compiled, you can deploy it.
Here is a basic example of Python code to deploy a contract:

```python
from ape import accounts, project

dev = accounts.load("dev")
contract = project.MyContract.deploy("argument1", "argument2", sender=dev)
```

you can alternatively use this syntax instead:

```python
from ape import accounts, project
# You need an account to deploy, as it requires a transaction.
account = accounts.load("<ALIAS>") # NOTE: <ALIAS> refers to your account alias!
contract = project.MyContract.deploy(1, account, sender=account)

dev = accounts.load("dev")
contract = accounts.dev.deploy(project.MyContract, "argument1", "argument2")
# NOTE: You can also do it this way:
contract2 = account.deploy(project.MyContract, 1, account)
```

With this technique, you can feed as many constructor arguments as your contract constructor requires.
The arguments to the constructor (`1, account`) can be in Python form.
Ape will automatically convert values in your transactions, thus allowing you to provide higher-level objects or abstractions as input types.
That is why, as you can see, the second argument is an `AccountAPI` object for the type `address` in the contract.

**NOTE**: You can also publish the contract source code to an explorer upon deployment using the `publish=` kwarg on the deploy methods.
More information on publishing contracts can be found in [this guide](./publishing.html).
Notice in the example, we use `project.MyContract` to access the contract type.
To avoid naming collisions with other properties on the `project` object, you can alternatively use the [get_contract()](../methoddocs/managers.html#ape.managers.project.manager.ProjectManager.get_contract) method to retrieve contract containers.

If you do not pass the correct amount of constructor arguments when deploying, you will get an error showing your arguments don't match what is in the ABI:
```python
from ape import project

```bash
ArgumentsLengthError: The number of the given arguments (0) do not match what is defined in the ABI (2).
contract = property.get_contract("MyContract") # Same as `project.MyContract`.
```

In this case it is saying that you have fed 0 constructor arguments but the contract requires 2 constructor arguments to deploy.

To show the arguments that your constructor requires you can use the .constructor method to see the constructor arguments that your contract requires:

```python
In [0]: project.MyContract.constructor
Out[0]: constructor(string argument1, string argument2)
```
Notice when deploying, we have to specify the `sender=` kwarg because `deploy` operations are transactions.
To learn more about contract interaction via transactions, see the \[Contract Interaction\](#Conract Interaction) section below and the [guide on transactions](./transactions.html).

### Deploy Scripts

Often times, users will create an Ape script if their deployment process is repeatable or called from CI.
Review the [scripting guide](./scripts.html) for more information on scripting in Ape and how to use scripts to track your deployment logic.
Once a deploy script is created, it can be invoked like:
Often time, the deployment process may be unique or complex.
Or possibly, you need to run the deploy-logic from CI or in a repeatable fashion.
Or perhaps, you just want to avoid having to invoking Python directly.
In those cases, you can use Ape's scripting system to save time and store your deployment logic.
Simply copy your Python logic into an Ape script and run it via:

```shell
ape run <script-name>
ape run <my-deploy-script>
```

There is no root `ape` command to deploy contracts; only the scripting-system, the `console`, or merely using Ape as a Python library.
Learn how to do this and scripting in its entirity by reviewing [the scripting user-guide](./scripts.html).

**There is no root `ape` command to deploy contracts; only the scripting-system, the `console`, or merely using Ape as a Python library**.

If your deployment process is simple, it is easy to use `ape console` to achieve a deployment.
If your deployment process is simple or only needs to happen once, it is easy to use `ape console` to achieve a deployment.
More information on how to use `ape console` can be found [here](./console.html).

### Publishing

You can also publish the contract source code to an explorer upon deployment using the `publish=` kwarg on the deploy methods.
More information on publishing contracts can be found in [this guide](./publishing.html).

## From Project Contract Address

You can also use the [at() method](../methoddocs/contracts.html#ape.contracts.base.ContractContainer.at) from the same top-level project manager when you know the address of an already-deployed contract:
Expand Down Expand Up @@ -295,7 +298,7 @@ To directly call an address, such as invoking a contract's `fallback` or `receiv
```python
from ape import Contract, accounts

sender = accounts.load("dev")
sender = accounts.load("<ALIAS>") # NOTE: <ALIAS> refers to your account alias!
contract = Contract("0x123...")

# Call the contract's fallback method.
Expand Down
12 changes: 12 additions & 0 deletions src/ape/contracts/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -1316,6 +1316,18 @@ def __call__(self, *args, **kwargs) -> TransactionAPI:
return self.constructor.serialize_transaction(*args, **kwargs)

def deploy(self, *args, publish: bool = False, **kwargs) -> ContractInstance:
"""
Deploy a contract.
Args:
*args (Any): The contract's constructor arguments as Python types.
publish (bool): Whether to also perform contract-verification.
Defaults to ``False``.
Returns:
:class:`~ape.contracts.base.ContractInstance`
"""

txn = self(*args, **kwargs)
private = kwargs.get("private", False)

Expand Down

0 comments on commit 615cbaa

Please sign in to comment.