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.
- About the project
- Understanding roles
- Community tokens
- Deploying community tokens
- Installation and development
Status 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.
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:
Role | Description | Count | Token ownership |
---|---|---|---|
Owner | Owner of the Status community. | 1 | OwnerToken |
Token Master | Helps creating community tokens and airdrops. | 0-n | MasterToken |
Admin | Helps maintaining the community. | 0-n | Combination of CommunityERC721 , CommunityERC20 , ERC721 , ERC20 |
Member | Member of the community. | 0-n | None or any combintion of CommunityERC721 , CommunityER20 , ERC721 , ERC20 |
An owner is a Status user that has typically created a Status community and therefore "owns" it. Owners have special privileges within a Status community, such as:
- transferring community ownership to other accounts
- creating community tokens (
CommunityERC721
,CommunityERC20
) - creating token permissions
- airdropping tokens to other users
The owner role is represented via ownership of the OwnerToken
, which is part of this repository.
The OwnerToken
is an ERC721
token and exists only once per community.
A token master is a Status user that has special privileges within a Status community.
A token master is allowed to create community tokens (CommunityERC721
, CommunityERC20
), new token permissions as well as airdropping tokens to other accounts.
The primary reason for token masters to exist is that they help the single owner of the community with token related actions.
There can be none or multiple token masters within a single Status community.
The token master role is represented via ownership of the MasterToken
, which is part of this repository.
An admin is a member of a Status community with special privileges, such as:
- creating token permissions
- editing information about the community
- creating chat categories and channels
Owners and token masters can create token permissions in the community to make other users admins of the community.
The admin role is represented via ownership of any token combination of CommunityERC721
, CommunityERC20
, ERC721
, and ERC20
tokens.
The owner or token masters have to create a token permission to specify which token ownership is needed to be an admin in the community.
Both, CommunityERC721
and CommunityERC20
tokens are part of this repository.
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.
BaseToken
is an abstract contract that OwnerToken
, MasterToken
, and CommunityERC721
inherit from to get shared functionality.
BaseToken
is an ERC721
token that offers some custom functionality:
- A custom
onlyOwner
modifier that checks for ownership of witherOwnerToken
orMasterToken
- The ability to configure a maximum supply. This is used for both
MasterToken
andCommunityERC721
tokens. - A
mintTo
function that allows for minting tokens to multiple addresses at once. - A mechanism to burn tokens "remotely". The use case here is to remove token masters or admins privileges.
- The ability to batch transfer tokens to multiple receivers.
Not all inheriting contracts make use of all of the custom functionality.
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.
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.
CommunityERC721
token inherits BaseToken
and are used to create custom NFTs for 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.
CommunityERC721
tokens can also be configured to be transferrable or remote burnable.
Creators of such a token can also specify their maximum supply.
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.
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.
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:
- 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.
- Status community owner takes the signature and sends it along with some deployment parameters to the
CommunityTokenDeployer
contract. 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- If all checks are okay, the
CommunityTokenDeployer
will create and instance ofOwnerToken
andMasterToken
usingCommunityOwnerTokenFactory
andCommunityMasterTokenFactory
contracts. 4.1. TheOwnerToken
will be minted to the owner account that performed the deployment - The contract address of
OwnerToken
is added to theCommunityOwnerTokenRegistry
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.
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.
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.
This contract inherits BaseTokenFactory
and implements a create()
function that deploys and instance of OwnerToken
using the supplied token metadata.
This contract inherits BaseTokenFactory
and implements a create()
function that deploys and instance of MasterToken
using the supplied token metadata.
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.
The following tools need to be installed first:
First, clone the repository via git:
$ git clone https://github.com/status-im/communities-contracts.git
Then, navigate into the folder and initialize/update git submodules:
$ cd communities-contracts
$ git submodule deinit --force .
$ git submodule update --init --recursive
Then, install all node dependencies:
$ pnpm install
This is a list of the most frequently needed commands.
Build the contracts:
$ forge build
Delete the build artifacts and cache directories:
$ forge clean
Compile the contracts:
$ forge build
Get a test coverage report:
$ forge coverage
Deploy to Anvil:
$ forge script script/DeployContracts.s.sol --broadcast --fork-url http://localhost:8545
For this script to work, you need to have a MNEMONIC
environment variable set to a valid
BIP39 mnemonic.
For instructions on how to deploy to a testnet or mainnet, check out the Solidity Scripting tutorial.
Format the contracts:
$ forge fmt
Get a gas report:
$ forge test --gas-report
Lint the contracts:
$ pnpm lint
Run the tests:
$ forge test