Smart contracts for access control and token gated Status communities.
This projects implements smart contracts that are used by Status to enable token gated communities and access control for various roles within communities.
- [Installation and development](#installation-and-development)
- [Prerequisites](#prerequisites)
- [Development](#development)
- [Build](#build)
- [Clean](#clean)
- [Compile](#compile)
- [Coverage](#coverage)
- [Deploy](#deploy)
- [Format](#format)
- [Gas usage](#gas-usage)
- [Lint](#lint)
- [Test](#test)
## About the project
[Status](https://status.im) provides a platform for users to create communities with shared interests.
A community is similar to a chat server that comes with various channels that users can join to talk to each other and exchange messages. Communities can be configured that only selected users can join, provided they satisfy certain criteria.
This criteria is expressed via different types of tokens for different roles within the community.
The smart contracts of this repository implement these tokens and how they'll be deployed by Status community owners.
## Understanding roles
There are different roles in a Status community. Gaining roles in a community is done by proving ownership of certain assets and tokens. Below is a summary of the existing roles and what token funds are necessary to get a role:
A token master is allowed to create community tokens (`CommunityERC721`, `CommunityERC20`), new token permissions as well as airdropping tokens to other accounts.
To create roles and other token permissions in a Status community, certain tokens have to be created or referenced in the system.
While any `ERC721` and `ERC20` tokens can be referenced and used to create membership, view and post, or admin permissions in a community, the tokens necessary to be an owner or token master of a community are specifically deployed from within that community using a Status application.
Below is a description of all community tokens that can be deployed and minted through Status.
Not all inheriting contracts make use of all of the custom functionality.
### `OwnerToken`
The token that represents ownership of a Status community. `OwnerToken` inherits from `BaseToken` and immediately mints a token to the deployer. There can only ever be one owner of a community, so the max supply is kept at one.
An `OwnerToken` can however be transferred to another account to effectively transfer ownership of a community.
This token also maintains a `signerPublicKey` which is the public key of a Status account that signs of changes in the Status community.
### `MasterToken`
The `MasterToken` is coexists with the `OwnerToken`, however there's no mechanism in place that guarantees the minting of such a token. The `MasterToken` represents the token master role within a community and also inherits `BaseToken`.
`MasterToken` are not transferrable but remote burnable. This ensures malicious users can't allow other users to create or airdrop tokens via Status communities.
The use case for these tokens are role based permissions.
Owners or token masters might deploy instances of this token to create token permissions that introduce an admin role, or permissoins to view and/or post to channels.
Creators of such a token can also specify their maximum supply.
### `CommunityERC20`
This token is a custom `ERC20` implementation that adds some functionality needed in Status communities. Status users can specify a custom `decimals` value for this token as well as a custom maximum supply.
Similar to `BaseToken`, this token comes with a `mintTo` function that allows for minting this token to multiple addresses.
## Deploying community tokens
Some of the tokens listed above, namely `OwnerToken` and `MasterToken`, are tokens that give special privileges to users of a Status community. To ensure users can't temper with the validity of contract addresses for `OwnerToken`s, and other users of the network can verify that such a token was indeed deployed by a community via a Status application, there's a special deployment process for these tokens which we cover in this section.
_For more information on the reasoning of this process, see the discussion in [this issue](https://github.com/status-im/status-desktop/issues/11954)._
Below is a graphic that shows the system from a birds-eye view:
A Status community is essentially a private/public key pair.
The `OwnerToken` and `MasterToken` will be deployed by a community owner, on behalf of the community.
To ensure accounts can only deploy the tokens for the community they have created, they need to provide a signature that was created by the community.
Here's how the deployment of community `OwnerToken`/`MasterToken` generally works:
1. Status community creates a signature which includes the address of the community, the address of the owner (who'll do the deployment), and an expiration date of the signature.
2. Status community owner takes the signature and sends it along with some deployment parameters to the `CommunityTokenDeployer` contract.
3.`CommunityTokenDeployer` contract verifies
3.1. If the community has not already deployed its token
3.2. If the provided signature is valid and the sender of the transaction is indeed the account that can do the deployment
4. If all checks are okay, the `CommunityTokenDeployer` will create and instance of `OwnerToken` and `MasterToken` using `CommunityOwnerTokenFactory` and `CommunityMasterTokenFactory` contracts.
4.1. The `OwnerToken` will be minted to the owner account that performed the deployment
5. The contract address of `OwnerToken` is added to the `CommunityOwnerTokenRegistry`
It's important to note that Status deploys `CommunityTokenDeployer`, `CommunityOwnerTokenRegistry`, `CommunityOwnerTokenFactory` and `CommunityMasterTokenFactory`.
Status clients will talk directly to the deployer contract when users attempt to create their communities `OwnerToken` and `MasterToken`.
Also, Status may deploy these contracts on multiple EVM chains.
### Deployment contracts
#### `CommunityTokenDeployer`
This contract is deployed by Status and responsible for deploying `OwnerToken` and `MasterToken` instances via `CommunityOwnerTokenFactory` and `CommunityMasterTokenFactory`.
It maintains addresses for the aforementioned factories, as well as for the `CommunityOwnerTokenRegistry`, which is used to store known `OwnerToken` addresses for communities.
It's `deploy()` function is the entry point for end users.
#### `BaseTokenFactory`
An abstract contract that implements shared functionality for token factories used within the system.
The functionality provided by this contract are custom modifiers to check token metadata validity and authorization.
#### `CommunityOwnerTokenFactory`
This contract inherits `BaseTokenFactory` and implements a `create()` function that deploys and instance of `OwnerToken` using the supplied token metadata.
#### `CommunityMasterTokenFactory`
This contract inherits `BaseTokenFactory` and implements a `create()` function that deploys and instance of `MasterToken` using the supplied token metadata.
#### `CommunityOwnerTokenRegistry`
This contract implements a global registry for community addresses and their `OwnerToken` addresses.
After `CommunityTokenDeployer` has successfully deployed the `OwnerToken`, it will add its address to the registry, allowing anyone to verify the owner token address provided by any community.