npm package: @mattereum/assetpassport-smartcontract
Description: On-chain code for commiting to claims and selling warranties.
Author: team_technical@mattereum.com
Latest version: 0.7.2

# Mattereum Asset Passport Smart Contracts

[![pipeline status](https://gitlab.com/mattereum-public/assetpassport-smartcontract/badges/master/pipeline.svg)](https://gitlab.com/mattereum-public/assetpassport-smartcontract/-/commits/master) [![coverage report](https://gitlab.com/mattereum-public/assetpassport-smartcontract/badges/master/coverage.svg)](https://gitlab.com/mattereum-public/assetpassport-smartcontract/-/commits/master)

This repository holds the smart contracts necessary to create Non-Fungible Tokens (NFTs) that act as key components of the Mattereum Asset Passports (MAP).

## Index

- [Capabilities](#capabilities)
- [Technical How-to](#technical-how-to)

# Capabilities

## Standard ERC-721 (NFT) Functionality

The Mattereum collection of NFT contracts (`SimpleExchangeNFT.sol`, `ReceiptNFT.sol`, and `CidNFT.sol`) all inherit the basic functionality of an ERC-721 NFT. Additionally, for the inheritance from `SimpleExchangeNFT.sol` to `CidNFT.sol`, they specifically use the initializable version, `ERC721Upgradeable.sol` by Open Zeppelin.

The Basic functionality of an ERC-721 NFT includes:

- Minting
- Safe minting (ensures receiving address can specifically receive ERC-721s, otherwise, reverts)
- Burning
- Setting approval
- Transfer
- Safe Transfer (ensures receiving address can specifically receive ERC-721s, otherwise, reverts)
- Obtain basic information about NFT (owner, balance, name, ID, tokenURI)

For `SimpleExchangeNFT.sol`, it inherits from the `ERC721Upgradeable.sol` version due to the design using [_Upgradeable Beacon Proxies_](https://blog.openzeppelin.com/the-state-of-smart-contract-upgrades/#beacons) to generate new Mattereum NFT collections in association with its Mattereum Asset Passports (MAP). The beacon proxies are created in `NFTFactory.sol`.

## Proxy Factory Pattern

The Proxy Factory Pattern is used in the `NFTFactory.sol` contract in order to simply and cheaply call and create beacon proxy contracts, which point to an upgradeable Beacon contract. This upgradeable Beacon contract simply stores and retrieves the address of the original set of smart contracts first deployed, that are used as the basis for the implementation contract. In other words, an original set of the Mattereum collection of NFT contracts are first deployed, and then cloned for future NFT collections that are deployed. This greatly reduces gas cost for deployment of a full set of smart contracts associated with a MAP, which is quite necessary when running on the Ethereum network. Within `NFTFactory.sol`, the function `createNewCollection()` is used to generate the new set of cloned contracts. Using this setup also allows the ability to later upgrade the primary Beacon contract to point to a new implementation address, effectively allowing for bug fixes, new feature roll outs, etc. The ability to upgrade the master implementation contracts is secured by Open Zeppelin's Role Based Access Controls.

## Pauseable Functionality

Several additional features have been included on top of the base ERC-721 contract; one of them to make the contract "pauseable". A pauseable contract has mechanisms to stop smart contract functionalities such as transfer or approval. The primary benefit of the pauseable token contract is safety. In case of any contract vulnerability which may be needed to update the contract, pausing can stop transfers and other core functionalities which reduces overall risk. This functionality is added in `CidNFT.sol`.

It is important to properly handle access control when allowing additional features like pausing, burning, and locking by users other than the token owner, this is handled by "Role-Based Access Control (RBAC)". This is added in `CidNFT.sol`.

## Role-Based Access Control Functionality

Open Zeppelin provides a robust system to utilize RBAC through their `AccessControl[Upgradeable].sol` contract. Additional information can be found in their [documentation](https://docs.openzeppelin.com/contracts/4.x/access-control). In essence, we will be defining multiple roles, each allowed to perform different sets of actions. An account may have, for example, 'moderator', 'minter' or 'admin' roles, which you will then check for instead of simply using `onlyOwner`. This check can be enforced through the `onlyRole` modifier. Separately, you will be able to define rules for how accounts can be granted a role, have it revoked, and more.

Most software uses access control systems that are role-based: some users are regular users, some may be supervisors or managers, and a few will often have administrative privileges.

For the Mattereum set of smart contracts, the following Access Control Roles are used:

- DEFAULT_ADMIN_ROLE
- MINTER_ROLE
- BURNER_ROLE
- PAUSER_ROLE
- TOKEN_LOCK_ROLE
- HANDLE_USER

Currently, in the last deployment script in this repository, a script changes all of the Access Control roles above from the `deployer` address to the Gnosis-Safe `Mattereum Multisig` wallet address, and then revokes access to the `deployer` address once complete.

## Token Lock Functionality

The Token Lock functionality is very similar to token pausing ability, but is an in-house developed access control handled by a mapping array so that we can enable a locking feature on a "per token basis" rather than "per contract". It simply tracks each NFT's token ID and returns whether `isTokenLocked[]` is `true` or `false`. It requires the `TOKEN_LOCK_ROLE` discussed above to alter its state. This functionality is added in `SimpleExchangeNFT.sol`.

## Transfer Handler Functionality

The transfer handler functionality added in `SimpleExchangeNFT.sol` was necessary to properly integrate and track secondary sales within the OpenSea NFT Marketplace. It is handled within the contracts in the `/contracts/nft/handlers/` folder. Additionally, once certain checks pass, it also mints a simple NFT from the `ReceiptNFT.sol` contract. This functionality may change in the future as new logic is created to integrate with OpenSea as well as other NFT Marketplaces.

# Technical How-to

## Installation

Clone the repository and set up the project with the following commands:

```
git clone git@gitlab.com:mattereum-public/assetpassport-smartcontract.git
cd assetpassport-smartcontract
npm install
```

## Deployment

Deployment is semi-automatic (and should be fully automatic!). The GitLab CI/CD pipeline has the following two steps that must currently be manually started:

- snapshot-deploy (deploy to testnet)
- mainnet-deploy (deploy to mainnet)

When deployment completes, it is necessary to note the address of the main proxy contract, which is used as the value of the `--nftContractAddress` argument to `map`.

To find this address, go to the pipeline for the job you just ran; if it’s not still open, start at the [pipelines page](https://gitlab.com/mattereum-public/assetpassport-smartcontract/-/pipelines) and find the relevant pipeline run. Then in the logs search box, search for “collection proxy”. The address needed is that of the collection proxy.