Factory
A factory is a smart contract that stores a global contract id, and automatizes deploying contracts onto new sub-accounts.
We have a A Generic Factory that deploys new contracts based on global contract id. The global contract id can be global account id or hash. You can change the global contract id by calling update_global_contract_id
method. The factory creates sub-accounts of itself and deploys corresponding contract on them.
You can learn more about global contracts on NEAR here.
Overview
The factory is a smart contract that:
- Creates sub-accounts of itself and deploys its contract on them (
deploy
). - Can manage its settings using the
update_global_contract_id
andupdate_min_deposit
methods.
- 🦀 Rust
- deploy.rs
- manager.rs
Loading...
Loading...
Quickstart
- Make sure you have installed rust.
- Install the
NEAR CLI
- Install the
cargo near
extension.
Build and Deploy the Factory
You can automatically compile and deploy the contract in the NEAR testnet by running:
cargo near deploy
Deploy the Stored Contract Into a Sub-Account
Method deploy
will create a sub-account of the factory and deploy contract on it using stored global contract id. It also asserts that the attached deposit is at least the minimum required deposit stored in the factory.
Technically, there is no need to attach any deposit just to deploy a contract using global contracts. But to initialize it further, you will need some NEAR tokens to cover the storage cost. Since initiliazing method can't accept deposit, it makes sense to attach some minimum amount of tokens during creating account and deploying a contract.
The following command will create the sub.<factory-account>
, which will have a global contract deployed on it.
near contract call-function as-transaction <factory-account> deploy json-args '{"name": "sub"}' prepaid-gas '100.0 Tgas' attached-deposit '0.2 NEAR' sign-as <your-account> network-config testnet sign-with-keychain send
By default, the global contract is the Fungible Token primitive contract ft.globals.primitives.testnet
. To initilize the contract, you can call its new_default_meta
method:
near contract call-function as-transaction sub.<factory-account> new_default_meta json-args '{"owner_id": "<your-account>", "total_supply": "100000000000000000000000000"}' prepaid-gas '100.0 Tgas' attached-deposit '0 NEAR' sign-as <your-account> network-config testnet sign-with-keychain send
Then you can call ft_metadata
method to verify that the contract is deployed and initialized correctly:
near contract call-function as-read-only sub.<factory-account> ft_metadata json-args {} network-config testnet now
# The response should be like this:
# {
# "decimals": 24,
# "icon": "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 288 288'%3E%3Cg id='l' data-name='l'%3E%3Cpath d='M187.58,79.81l-30.1,44.69a3.2,3.2,0,0,0,4.75,4.2L191.86,103a1.2,1.2,0,0,1,2,.91v80.46a1.2,1.2,0,0,1-2.12.77L102.18,77.93A15.35,15.35,0,0,0,90.47,72.5H87.34A15.34,15.34,0,0,0,72,87.84V201.16A15.34,15.34,0,0,0,87.34,216.5h0a15.35,15.35,0,0,0,13.08-7.31l30.1-44.69a3.2,3.2,0,0,0-4.75-4.2L96.14,186a1.2,1.2,0,0,1-2-.91V104.61a1.2,1.2,0,0,1,2.12-.77l89.55,107.23a15.35,15.35,0,0,0,11.71,5.43h3.13A15.34,15.34,0,0,0,216,201.16V87.84A15.34,15.34,0,0,0,200.66,72.5h0A15.35,15.35,0,0,0,187.58,79.81Z'/%3E%3C/g%3E%3C/svg%3E",
# "name": "Example NEAR fungible token",
# "reference": null,
# "reference_hash": null,
# "spec": "ft-1.0.0",
# "symbol": "EXAMPLE"
#}
Update the Stored Contract
update_global_contract_id
enables to change the global contract id that the factory stores.
The method is interesting because it has no declared parameters, and yet it takes an input: the new contract to store as a stream of bytes.
To use it, we need to pass the contract id we want to store. It can be in form of account id or global contract hash. What is the difference between them you can read in Global Contracts section.
near contract call-function as-transaction <factory-account> update_global_contract_id json-args '{"contract_id": "3vaopJ7aRoivvzZLngPQRBEd8VJr2zPLTxQfnRCoFgNX"}' prepaid-gas '100.0 Tgas' attached-deposit '0 NEAR' sign-as <factory-account> network-config testnet sign-with-keychain send
Factories - Concepts & Limitations
Factories are an interesting concept, here we further explain some of their implementation aspects, as well as their limitations.
Automatically Creating Accounts
NEAR accounts can only create sub-accounts of itself, therefore, the factory
can only create and
deploy contracts on its own sub-accounts.
This means that the factory:
- Can create
sub.factory.testnet
and deploy a contract on it. - Cannot create sub-accounts of the
predecessor
. - Can create new accounts (e.g.
account.testnet
), but cannot deploy contracts on them.
It is important to remember that, while factory.testnet
can create sub.factory.testnet
, it has
no control over it after its creation.
The Deploy Method
During the creation of a sub-account we add signers public key to the new sub-account as a full access key. It means that the predecessor will be able to control the new sub-account after its creation.
Also, in the tutorial, we attach deposit to the deploy
call which goes straight to the new sub-account. When we deploy a new contract using global contracts, we need to initialize it after deployment. That tokens will cover the storage after the deployed contract is initialized.