Smart contracts for access control and token gated Status communities.
Go to file
r4bbit 8773220abe
feat: add certora CI integration (#24)
This backports Certora CI integration to this repository, resulting in
GitHub Actions being extended to run formal verification on any change
to contracts that comes in via pull requests.
2023-12-14 08:53:57 +01:00
.github feat: add certora CI integration (#24) 2023-12-14 08:53:57 +01:00
certora feat: add certora CI integration (#24) 2023-12-14 08:53:57 +01:00
contracts add CommunityVault contract (#22) 2023-12-12 23:10:27 +01:00
lib refactor: move project to foundry template and introduce tests 2023-09-08 12:36:20 +02:00
script add CommunityVault contract (#22) 2023-12-12 23:10:27 +01:00
test add CommunityVault contract (#22) 2023-12-12 23:10:27 +01:00
.editorconfig refactor: move project to foundry template and introduce tests 2023-09-08 12:36:20 +02:00
.env.example refactor: move project to foundry template and introduce tests 2023-09-08 12:36:20 +02:00
.gas-snapshot add CommunityVault contract (#22) 2023-12-12 23:10:27 +01:00
.gitattributes refactor: move project to foundry template and introduce tests 2023-09-08 12:36:20 +02:00
.gitignore refactor: move project to foundry template and introduce tests 2023-09-08 12:36:20 +02:00
.gitmodules refactor: move project to foundry template and introduce tests 2023-09-08 12:36:20 +02:00
.prettierignore refactor: move project to foundry template and introduce tests 2023-09-08 12:36:20 +02:00
.solhint.json refactor: move project to foundry template and introduce tests 2023-09-08 12:36:20 +02:00
PROPERTIES.md refactor: move project to foundry template and introduce tests 2023-09-08 12:36:20 +02:00
README.md chore: add goerli deployment addresses (#23) 2023-11-20 15:58:59 +01:00
codecov.yml refactor: move project to foundry template and introduce tests 2023-09-08 12:36:20 +02:00
community-token-deployer.png docs: fix readme image path (#12) 2023-09-19 18:50:24 +02:00
foundry.toml chore: add goerli deployment addresses (#23) 2023-11-20 15:58:59 +01:00
package.json feat: add certora CI integration (#24) 2023-12-14 08:53:57 +01:00
pnpm-lock.yaml refactor: move project to foundry template and introduce tests 2023-09-08 12:36:20 +02:00
prettierrc.yml refactor: move project to foundry template and introduce tests 2023-09-08 12:36:20 +02:00
remappings.txt refactor: move project to foundry template and introduce tests 2023-09-08 12:36:20 +02:00
slither.config.json refactor: move project to foundry template and introduce tests 2023-09-08 12:36:20 +02:00
specs.sh feat: implement `CommunityTokenDeployer` contract (#2) 2023-09-19 11:39:55 +02:00

README.md

Communities Contracts Github Actions Codecov Foundry

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.

Deployments

Contract Address Snapshot
Goerli
CommunityTokenDeployer 0x81f4951ff8859d305F47A4574B206cF64C0d2645 105ee8
CommunityOwnerTokenRegistry 0x59510D0b235c75d7bCAEb66A420e9bb0edC976AE 1085ee8
CommunityOwnerTokenFactory 0xf7b6EC76aCa97b395dc48f7A2861aD810B34b52e 1085ee8
CommunityMasterTokenFactory 0x0936792b0efa243a5Ddff7035E84749E5a54FA9c 1085ee8
Sepolia
CommunityTokenDeployer 0xCDE984e57cdb88c70b53437cc694345B646371f9 ea7ef0e
CommunityOwnerTokenRegistry 0x98E0A38A9c198F9F49a4F6b49475aE0c92aBbB66 ea7ef0e
CommunityOwnerTokenFactory 0xfFa8A255D905c909379859eA45B959D090DDC2d4 ea7ef0e
CommunityMasterTokenFactory 0xcE2A896eEA2F585BC0C3753DC8116BbE2AbaE541 ea7ef0e
Optimism Goerli
CommunityTokenDeployer 0xfFa8A255D905c909379859eA45B959D090DDC2d4 e7d799b76
CommunityOwnerTokenRegistry 0x99F0Eeb7E9F1Da6CA9DDf77dD7810B665FD85750 e7d799b76
CommunityOwnerTokenFactory 0x76d0E484e7c3398922636960Ab33bDe6E9936D81 e7d799b76
CommunityMasterTokenFactory 0x420BE6568c6E09782CEAE1575495Cd6C1c7EA04D e7d799b76
Arbitrum Goerli
CommunityTokenDeployer 0x7Ff554af5b6624db2135E4364F416d1D397f43e6 105ee8
CommunityOwnerTokenRegistry 0x9C84f9f9970B22E67f1B2BE46ABb1C09741FF7d7 1085ee8
CommunityOwnerTokenFactory 0x0B5DAd18B8791ddb24252B433ec4f21f9e6e5Ed0 1085ee8
CommunityMasterTokenFactory 0x35Cded11D75cC10d38ED4456b8caDC9F36E85E42 1085ee8
Arbitrum Sepolia
CommunityTokenDeployer 0x7Ff554af5b6624db2135E4364F416d1D397f43e6 105ee8
CommunityOwnerTokenRegistry 0x9C84f9f9970B22E67f1B2BE46ABb1C09741FF7d7 1085ee8
CommunityOwnerTokenFactory 0x0B5DAd18B8791ddb24252B433ec4f21f9e6e5Ed0 1085ee8
CommunityMasterTokenFactory 0x35Cded11D75cC10d38ED4456b8caDC9F36E85E42 1085ee8

Documentation

Table of Contents

About the project

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.

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:

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 CollectibleV1, CommunityERC20, ERC721, ERC20
Member Member of the community. 0-n None or any combintion of CollectibleV1, CommunityER20, ERC721, ERC20

Owners

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 (CollectiveV1, 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.

Token Masters

A token master is a Status user that has special privileges within a Status community. A token master is allowed to create community tokens (CollectibleV1, 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.

Admins

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 CollectibleV1, 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, CollectibleV1 and CommunityERC20 tokens are part of this repository.

Community tokens

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

BaseToken is an abstract contract that OwnerToken, MasterToken, and CollectibleV1 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 wither OwnerToken or MasterToken
  • The ability to configure a maximum supply. This is used for both MasterToken and CollectibleV1 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.

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.

CollectibleV1

CollectibleV1 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.

CollectibleV1 tokens can also be configured to be transferrable or remote burnable. 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 OwnerTokens, 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:

Community deployer contract

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.

Installation and development

Prerequisites

The following tools need to be installed first:

Instructions

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

Development

This is a list of the most frequently needed commands.

Build

Build the contracts:

$ forge build

Clean

Delete the build artifacts and cache directories:

$ forge clean

Compile

Compile the contracts:

$ forge build

Coverage

Get a test coverage report:

$ forge coverage

Deploy

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

Format the contracts:

$ forge fmt

Gas Usage

Get a gas report:

$ forge test --gas-report

Lint

Lint the contracts:

$ pnpm lint

Test

Run the tests:

$ forge test