You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
description: "A factory is a smart contract that stores a compiled contract, and automatizes deploying the stored contract onto new sub-accounts."
3
+
title: How to Deploy Contracts from Contracts
4
+
description: "Learn how to implement the factory pattern on NEAR to programmatically deploy smart contracts from within other smart contracts."
5
5
---
6
6
7
7
import Tabs from '@theme/Tabs';
8
8
import TabItem from '@theme/TabItem';
9
9
import {CodeTabs, Language, Github} from "@site/src/components/codetabs"
10
10
11
-
A factory is a smart contract that stores a compiled contract, and automatizes deploying the stored contract onto new sub-accounts.
11
+
# How to Deploy Contracts from Contracts
12
12
13
-
We have a [**A Generic Factory**](https://github.com/near-examples/factory-rust) that deploys the [donation contract](./donation.md). This donation contract can be changed for whichever compiled contract you like (e.g. a fungible token or DAO).
13
+
The factory pattern is a powerful design pattern that allows one smart contract to deploy and manage other smart contracts programmatically. This tutorial will teach you how to build a factory contract that can store compiled contract code and deploy it to new sub-accounts automatically.
14
+
15
+
## What is a Factory Contract?
16
+
17
+
A factory contract is a smart contract that acts as a template deployer. Instead of manually deploying each instance of a contract, the factory automates this process by:
18
+
19
+
- Storing compiled contract bytecode
20
+
- Creating new sub-accounts
21
+
- Deploying the stored contract to those sub-accounts
22
+
- Managing and updating the stored contract code
23
+
24
+
This pattern is particularly useful when you need to deploy many instances of the same contract type, such as creating multiple DAOs, token contracts, or any standardized smart contract.
25
+
26
+
## Why Use the Factory Pattern?
27
+
28
+
**Cost Efficiency**: Deploy once, reuse many times without re-uploading contract code.
29
+
30
+
**Standardization**: Ensure all deployed contracts follow the same tested pattern.
31
+
32
+
**Automation**: Programmatically create contracts without manual intervention.
33
+
34
+
**Upgradability**: Update the stored contract template for future deployments.
35
+
36
+
**Access Control**: Implement permissions for who can deploy new instances.
14
37
15
38
---
16
39
17
-
## Overview {#generic-factory}
40
+
## Understanding NEAR Account Limitations
41
+
42
+
Before implementing a factory, it's crucial to understand NEAR's account creation rules:
43
+
44
+
### What Factories Can Do
45
+
- Create sub-accounts of themselves (e.g., `factory.near` can create `instance1.factory.near`)
46
+
- Deploy contracts to their own sub-accounts
47
+
- Manage the stored contract bytecode
48
+
49
+
### What Factories Cannot Do
50
+
- Create sub-accounts for other accounts
51
+
- Deploy contracts to accounts they don't own
52
+
- Control sub-accounts after creation (they become independent)
53
+
54
+
This means your factory at `factory.testnet` can create `dao1.factory.testnet` and `dao2.factory.testnet`, but cannot create `dao1.alice.testnet`.
55
+
56
+
---
18
57
19
-
The factory is a smart contract that:
58
+
## Building Your Factory Contract
20
59
21
-
1. Creates sub-accounts of itself and deploys its contract on them (`create_factory_subaccount_and_deploy`).
22
-
2. Can change the stored contract using the `update_stored_contract` method.
60
+
Let's examine the core components of a factory contract:
23
61
24
62
<CodeTabs>
25
63
<Languagevalue="rust"language="rust">
@@ -32,123 +70,165 @@ The factory is a smart contract that:
32
70
</Language>
33
71
</CodeTabs>
34
72
35
-
---
73
+
### Core Factory Methods
36
74
37
-
## Quickstart
75
+
The factory implements two essential methods:
38
76
39
-
1. Make sure you have installed [rust](https://www.rust-lang.org/).
40
-
2. Install the [`NEAR CLI`](/tools/near-cli#installation)
77
+
**`create_factory_subaccount_and_deploy`**: Creates a new sub-account and deploys the stored contract to it.
41
78
42
-
<hrclassName="subsection" />
79
+
**`update_stored_contract`**: Updates the contract bytecode that will be deployed to future instances.
43
80
44
-
### Build and Deploy the Factory
81
+
---
45
82
46
-
You can automatically compile and deploy the contract in the NEAR testnet by running:
83
+
## Implementing Contract Deployment
47
84
48
-
```bash
49
-
./deploy.sh
50
-
```
85
+
When you call `create_factory_subaccount_and_deploy`, the factory:
51
86
52
-
Once finished, check the `neardev/dev-account` file to find the address in which the contract was deployed:
87
+
1.**Creates the sub-account** using NEAR's account creation APIs
88
+
2.**Transfers the required deposit** for account creation and storage
89
+
3.**Deploys the stored contract** bytecode to the new account
90
+
4.**Initializes the contract** with the provided parameters
One of the factory pattern's key advantages is the ability to update the stored contract for future deployments:
106
+
107
+
### The Update Method Implementation
108
+
109
+
```rust
110
+
#[private]
111
+
pubfnupdate_stored_contract(&mutself) {
112
+
self.code =env::input().expect("Error: No input").to_vec();
113
+
}
68
114
```
69
115
70
-
This will create the `sub.<factory-account>`, which will have a `donation` contract deployed on it:
116
+
This method uses a clever optimization: instead of deserializing the input parameters (which would consume excessive gas for large files), it reads the raw input directly using `env::input()`.
117
+
118
+
### Why This Optimization Matters
119
+
120
+
Standard parameter deserialization would:
121
+
1. Parse the entire WASM file from JSON
122
+
2. Validate the input format
123
+
3. Convert it to the appropriate data type
124
+
125
+
For large contract files, this process consumes the entire gas limit. The direct input approach bypasses this overhead.
126
+
127
+
### Updating Your Stored Contract
71
128
72
129
```bash
73
-
near view sub.<factory-account> get_beneficiary
74
-
# expected response is: <account-to-be-beneficiary>
> This works because the arguments of a call can be either a `JSON` object or a `String Buffer`
159
+
### 3. Verify the Deployment
96
160
97
-
---
161
+
```bash
162
+
near view test-instance.<factory-account> get_beneficiary
163
+
# Expected: alice.testnet
164
+
```
98
165
99
-
## Factories - Concepts & Limitations
166
+
---
100
167
101
-
Factories are an interesting concept, here we further explain some of their implementation aspects,
102
-
as well as their limitations.
168
+
## Best Practices and Considerations
103
169
104
-
<hrclassName="subsection" />
170
+
### Gas Management
171
+
- Contract deployment requires significant gas (200-300 TGas)
172
+
- Always specify sufficient gas limits
173
+
- Test gas requirements with smaller contracts first
105
174
106
-
### Automatically Creating Accounts
175
+
### Storage Costs
176
+
- Factor in storage costs for both factory and deployed contracts
177
+
- Require sufficient deposit to cover all costs
178
+
- Consider implementing deposit refund mechanisms
107
179
108
-
NEAR accounts can only create sub-accounts of itself, therefore, the `factory` can only create and
109
-
deploy contracts on its own sub-accounts.
180
+
### Security Considerations
181
+
- Implement access controls for who can deploy contracts
182
+
- Validate initialization parameters before deployment
183
+
- Consider implementing factory ownership and permissions
110
184
111
-
This means that the factory:
185
+
### Contract Versioning
186
+
- Implement version tracking for stored contracts
187
+
- Consider allowing multiple contract versions
188
+
- Document breaking changes between versions
112
189
113
-
1.**Can** create `sub.factory.testnet` and deploy a contract on it.
114
-
2.**Cannot** create sub-accounts of the `predecessor`.
115
-
3.**Can** create new accounts (e.g. `account.testnet`), but **cannot** deploy contracts on them.
190
+
---
116
191
117
-
It is important to remember that, while `factory.testnet` can create `sub.factory.testnet`, it has
118
-
no control over it after its creation.
192
+
## Alternative Approaches
119
193
120
-
<hrclassName="subsection" />
194
+
### Direct Account Creation
195
+
Instead of using a factory, you could create accounts directly, but this requires:
196
+
- Manual contract deployment for each instance
197
+
- Separate storage costs for each deployment
198
+
- More complex coordination between deployments
121
199
122
-
### The Update Method
200
+
### Proxy Pattern
201
+
For upgradeable contracts, consider the proxy pattern where:
202
+
- A proxy contract delegates calls to an implementation contract
203
+
- Updates change the implementation address
204
+
- All instances can be upgraded simultaneously
123
205
124
-
The `update_stored_contracts` has a very short implementation:
206
+
### When to Use Factories
207
+
Factories work best when:
208
+
- You need many instances of similar contracts
209
+
- Instances should be independent after creation
210
+
- You want to standardize deployment parameters
211
+
- Cost optimization is important for multiple deployments
125
212
126
-
```rust
127
-
#[private]
128
-
pubfnupdate_stored_contract(&mutself) {
129
-
self.code =env::input().expect("Error: No input").to_vec();
130
-
}
131
-
```
213
+
---
132
214
133
-
On first sight it looks like the method takes no input parameters, but we can see that its only
134
-
line of code reads from `env::input()`. What is happening here is that `update_stored_contract`
135
-
**bypasses** the step of **deserializing the input**.
215
+
## Common Pitfalls to Avoid
136
216
137
-
You could implement `update_stored_contract(&mut self, new_code: Vec<u8>)`,
138
-
which takes the compiled code to store as a `Vec<u8>`, but that would trigger the contract to:
217
+
**Insufficient Deposits**: Always calculate the minimum required deposit including account creation, storage, and initialization costs.
139
218
140
-
1. Deserialize the `new_code` variable from the input.
141
-
2. Sanitize it, making sure it is correctly built.
219
+
**Gas Limit Errors**: Contract deployment is gas-intensive. Start with higher limits and optimize down.
142
220
143
-
When dealing with big streams of input data (as is the compiled `wasm` file to be stored), this process
144
-
of deserializing/checking the input ends up **consuming the whole GAS** for the transaction.
221
+
**Access Control**: Implement proper permissions to prevent unauthorized contract deployments.
145
222
146
-
:::note Versioning for this article
223
+
**Storage Management**: Monitor storage costs as they accumulate with each stored contract and deployment.
147
224
148
-
At the time of this writing, this example works with the following versions:
225
+
**Sub-account Naming**: Plan your naming convention carefully as sub-accounts cannot be renamed after creation.
149
226
227
+
:::note Development Environment
228
+
This tutorial works with:
150
229
- near-cli: `4.0.13`
151
-
- node: `18.19.1`
230
+
- node: `18.19.1`
152
231
- rustc: `1.77.0`
153
-
154
232
:::
233
+
234
+
The factory pattern provides a powerful way to scale smart contract deployment on NEAR. By understanding the account limitations, gas considerations, and implementation details, you can build efficient factory contracts that automate and standardize your deployment process.
0 commit comments