---
# System prepended metadata

title: RIF Marketplace Specification

---

# RIF Marketplace Specification

## Marketplace roles

There are different roles in the marketplace. Each role can perform specific actions into the system. The roles can be managed by the owner of the marketplace.

### Owner

The marketplace owner is able to perform any action into the marketplace. 
Ideally this will be handled by a multisig or to a governance token.

### Administrator

The administrator is able to perform the following tasks:

- Change marketplace configuration parameters
- Whitelist other roles in the system


### Asset Manager

The asset Manager take place when the markeplace has the parameter requireWhitelistedAsset in true.
This role is in charge of approving or removing accepted assets types into the marketplace. It is the role that manage the accepted token whitelisting.

### Asset Validator Manager

This role takes place when the configuration parameter assetsNeedValidation is true. 

This role is in charge of managing the whitelist of validators in the system.

### Finance Manager

Anything related to cryptocurrencies, payments, withdraw, fees should be handle it by this role.

- Change finance parameters (fees for example)
- Withdraw money earned by fees

### Asset Providers Manager

This roles takes place when the configuration parameter requireWhitelistedAssetProvider is in true. In this case this role is in charge of managing the whitelist of assets providers.

### Asset Validator Delegate

Sometimes the assets validators can be institutions (for example an art gallery for a ecommerce of art NFT). Probably this institutions will have a group of persons in charge of make the validating of the assets (for example if an art piece is really unique and is created with the minimum quality required by the marketplace). This is the role who will manage this delegates.

Any asset validator delegate will have to be assigned to one asset validator at minimum. But a delegate can work for many validators (for example an art critic can work to many museums or art galleries).

## Marketplace configuration parameters

#### Require whitelisted asset

| Name                | Type         | 
| --------            | --------     | 
| SCHEDULER_ADDRESS       | Boolean      | 

Defines whether the marketplace will require the asset type to be whitelisted before the asset can be registered.

- **IF TRUE:** the marketplace will accept any asset from any source (contract address). For example in the case of NFTs it will accept any ERC721 or ERC1155 without restriction to the contract address. 
- **IF FALSE:** only whitelisted tokens could be listed in the marketplace

#### Require whitelisted asset provider

| Name                  | Type         | 
| --------              | --------     | 
| requireWhitelistedAssetProvider | Boolean      | 

We should be able to create marketplaces where anyone can list their assets into that marketplace (example opensea), or marketplaces were the assets providers (the accounts who put items to sell) are whitelisted or restricted to some accounts (for example if we want to create a marketplace to sell just specific products)

- **IF TRUE:** the providers of assets will have to be whitelisted before registering assets
- **IF FALSE:** any account will be able to register assets for sale into the marketplace.

#### Assets needs validation/approval before been accepted into the marketplace

| Name                  | Type         | 
| --------              | --------     | 
| assetsNeedValidation  | Boolean      | 

There will be some marketplaces were the content listed for sale will need some validation or curation process. The owner of the marketplace should be able to setup this aspect.

- **IF TRUE:** an asset can be registered but it can't be placed on sell until is approved. The validators (the role who can validate an assets) are whitelisted accounts.
- **IF FALSE:** any provider can put any asset on sale without any validation and/or approval

#### All assets uses the same sale strategy

| Name                           | Type         | 
| --------                       | --------     | 
| allAssetsUsesSameSaleStrategy  | Boolean      | 

The markeplace will have one or multiple sale strategies (like fixed price, auction, etc.). The marketplace admins will be able to register multiple supported sale strategies.

- **IF TRUE:** all the assets will accepts the same strategi(es).
- **IF FALSE:** the provider should select which strategy to use on his asset (from the avaiable ones)

#### All assets accepts the same currencies

| Name                            | Type         | 
| --------                        | --------     | 
| allAssetsAcceptsSameCurrencias  | Boolean      | 

We will develop the marketplace to accept any ERC20 token. But marketplace owners can define which are the tokens they want to accepto in their marketplaces (like RIF, RDOC, etc.). 

- **IF TRUE:** all the accepts into the marketplace will accept the same currencies (the ones the owner of the Marketplace defined)
- **IF FALSE:** the asset provider can select which currencies accept for their asset(s).

#### Create a RNS subdomain for each asset

| Name                         | Type         | 
| --------                     | --------     | 
| createSubdomainForEachAsset  | Boolean      |

In order to increase usability it may be worth to associate a RNS subdomain to each asset listed on the marketplace.

- **IF TRUE:** Each asset registered on the markeplace will have a subdomain associated.
- **IF FALSE:** No subdomain will be associated with the listed assets.

#### Supports staking and slashing

| Name                        | Type         | 
| --------                    | --------     | 
| supportsStakingAndSlashing  | Boolean      |


- **IF TRUE:** The providers may need to make staking in order to provide services/assets
- **IF FALSE:** staking is not required in any place of the marketplace

We will not implement the staking and slashing mechanisms on the MVP


## Features/Stories

### As a Markeplace owner I want to deploy the marketplace smart contracts for my own marketplace instance

Deploy a new instance of the marketplace  should be straight forward to any project. 
The marketplace should be fully parametrizable.

```sequence
Marketplace Owner->Blockchain: constructor(params)
Blockchain-->Marketplace Owner:
```



| Param Name | Type    | Description |
| ---------- | --- | ---- |
| requireWhitelistedAsset   | boolean    | See section: Marketplace configuration parameters |
|requireWhitelistedAssetProvider|boolean| See section: Marketplace configuration parameters |
|assetsNeedValidation|boolean| See section: Marketplace configuration parameters |
|allAssetsUsesSameSaleStrategy| boolean | See section: Marketplace configuration parameters |
|allAssetsAcceptsSameCurrencies| boolean | See section: Marketplace configuration parameters |
|createSubdomainForEachAsset | boolean | See section: Marketplace configuration parameters |
|supportsStakingAndSlashing | boolean | See section: Marketplace configuration parameters |


### As a Marketplace owner I want to manage the list of authorized system administrators

The marketplace owner should be able to add and remove the administrators on the system. 
The ONLY allowed to manage this is the marketplace owner account.

### As a Marketplace administrator I want to manage the asset managers whitelist

### As a Marketplace administrator I want to manage the asset validator managers whitelist

### As a Marketplace owner I want to manage the finance role whitelist

### As a Marketplace administrator I want to manage the asset provider manager whitelist

### As a Marketplace administrator I want to manage the asset validator delegate whitelist

### As a Marketplace administrator I want to manage the configuration properties of the marketplace

The administrator will be able to change the parameters of the marketplace in any momment. Please see the section "Marketplace configuration parameters", for more information about the different configuration properties.

### As a finance manager I want to add an ERC20 token as a payment currency into the marketplace

The finance rol should be able to add new ERC20 tokens as accepted tokens into the marketplace.

```sequence
Finance Rol->IMarketplace: addAcceptedCurrency(address _tokenERC20)
IMarketplace->IMarketplace: check if address is ERC20
IMarketplace->ERC20 Token: name()
ERC20 Token-->IMarketplace:
IMarketplace->ERC20 Token: symbol()
ERC20 Token-->IMarketplace:
IMarketplace->ERC20 Token: decimals()
ERC20 Token-->IMarketplace:
IMarketplace->IMarketplace: create accepted currency struct
IMarketplace->IMarketplace: add accepted currency struct into contract state
IMarketplace-->Finance Rol:
```

### As a finance manager I want to remove an ERC20 token as a payment currency into the marketplace

The finance rol should be able to remove an ERC20 token as accepted token into the marketplace.
This could be a costly action in terms of gas, because it will need to remove an item from a list.

```sequence
Finance Rol->IMarketplace: removeAcceptedCurrency(address _tokenERC20)
IMarketplace->IMarketplace: remove currency struct from contract state
IMarketplace-->Finance Rol:
```

### As a finance manager I want to withdraw contract funds to an account

The financial manager should be able to withdraw the funds of the contract (collected form marketplace fees) to any account he wants.

```sequence
Finance Rol->IMarketplace: withdraw(address _to, int amount)
IMarketplace->IMarketplace: check if the contract has enough balance
IMarketplace->IMarketplace: to account must be different of null
IMarketplace->IMarketplace: transfer funds 
IMarketplace-->Finance Rol:
```

### As an asset validator I want to add an asset validator delegate

The asset validators can have multiple accounts who can validate assets in their name.
The use case could be an art gallery who has multiple art experts working for them in order to validate the work. 
An asset validator delegate can work for multiple asset validators (for example an art expert can work for multiple art galleries).

We should evaluate to associate the asset validators delegates to a DID and generate reputation to this (same to validator delegate).

```sequence
AssetValidator->IMarketplace: addAssetValidatorDelegate(address _account)
IMarketplace->IMarketplace: check if asset validator exists in the marketplace
IMarketplace->IMarketplace: check if _account is not null
IMarketplace->IMarketplace: add asset validator delegate
IMarketplace-->AssetValidator:
```

### As an asset validator I want to remove an asset validator delegate from my allowed delegate list

Remove asset validator delegate from the list of allowed delegates

A valid use case could be an art gallery removing an art expert from his list of allowed validators.

```sequence
AssetValidator->IMarketplace: removeAssetValidatorDelegate(address _account)
IMarketplace->IMarketplace: check if asset validator exists in the marketplace
IMarketplace->IMarketplace: check if the delegate is part of the validator whitelist
IMarketplace->IMarketplace: remove asset validator delegate from asset validator whitelist
IMarketplace-->AssetValidator:
```

### As an administrator I want to assign a RNS domain or subdomain to the marketplace contract in order to create subdomains for assets

The markeplace can create subdomains on a RNS domain to all the registered assets. This can be usefull for user experience.

```sequence
Administrator->RNS: transfer domain to Marketplace instance
RNS-->Administrator:
Administrator->IMarketplace: assignRnsDomain(_rnsDomain) void
IMarketplace-->Administrator:
```

### As an administrator I want to add a RNS name generation strategy

When the marketplace has active the flag createSubdomainForEachAsset it needs to generate a subdomain name for each asset registered in the system.
For this we will have the name generation strategy. This strategy basically takes an asset as a parameter and returns the name to be used in RNS.

### As an asset provider I want to register a new asset into the marketplace

We have to design the marketplace to support any type of asset, but for the sake of the MVP we will focus on NFTs.

```mermaid
flowchart TD
    A[Asset Provider try to register a new asset] --> B{Mkp allows any type of assets?}
    B --> |No| C{The asset is in the whitelist?}
    C --> |No| D[Error]
    B --> |Yes| E{Mkp allows any provider?}
    C --> |Yes| E
    E --> |No| F{Provider is in the whitelist?}
    F --> |No| D
    E --> |Yes| G{Asset requires validator?}
    F --> |Yes| G
    G --> |Yes| H[Asset is moved to pending validation]
    H --> I{Validator approves asset?}
    J[Asset Validator] -- feedback --> I
    I --> |No| K[Asset Rejected]
    G --> |No| L[Asset Ready]
    I --> |Yes| L
    J -- new validator feedback --> M{valiator approves asset?}
    K --> M
    M --> |No| K
    M --> |Yes| L
    L --> N{Must create RNS subdomain?}
    N --> |Yes| O[Call strategy to get name]
    N --> |No| Z
    O --> P[Call RNS and create subdomain]
    P --> Q[Update asset with subdomain]
    Q --> Z[Finish]
```

### As an asset validator delegate I want to approve an asset

A validator delegate can approves assets that requires validation. This approval is made in name of a asset validator.
The delegates can work for more than one validator, for that reason the delegate must provide in name of which validator he is working.

### As an asset validator delegate I want to reject an asset

A validator delegate can rejects assets that requires validation. This rejection is made in name of a asset validator.
The delegates can work for more than one validator, for that reason the delegate must provide in name of which validator he is working.

### As an asset provider I want to sell my asset

```mermaid
flowchart TD
    AssetProvider[Asset Provider initiate asset sell process]
    AssetProvider --> AssetReady?{Asset is in state ready?}
    AssetReady? --> |No| Error
    AssetReady? --> |Yes| ProviderIsOwner?{Provider is owner of the asset?}
    ProviderIsOwner? --> |No| Error
    ProviderIsOwner? --> |Yes| AllAssetsUseSameSS?{All Assets use same sale strategy?}
    AllAssetsUseSameSS? --> |Yes| GetSaleStrategy[Get sale strategy for the marketplace]
    AllAssetsUseSameSS? --> |No| AssetProviderSelectSS[Asset Provider Select the strategy]
    GetSaleStrategy --> AllAssetsUseSameCurr?{All assets accepts the same currency?}
    AssetProviderSelectSS --> AllAssetsUseSameCurr?
    AllAssetsUseSameCurr? --> |Yes| GetAvailableCurr[Get currencies in marketplace]
    AllAssetsUseSameCurr? --> |No| AssetProviderSelectCurr[Asset provider select the currencies to be used]
    AssetProviderSetupPrices[Asset provider setup prices for each currency]
    GetAvailableCurr --> AssetProviderSetupPrices
    AssetProviderSelectCurr --> AssetProviderSetupPrices
    AssetProviderSetupPrices --> EscrowSetup[Escrow instance is created and setup with all the sale parameters]
    EscrowSetup --> AssetTransfer[The asset is transfered to the escrow]
    AssetTransfer --> OrderIdGeneration[Order Id generator strategy is called to generate a new order id]
    OrderIdGeneration --> OrderCreation[An order is created with status open]
    OrderCreation --> SaleStartsInmediatly?{Sale strategy starts inmediatly?}
    SaleStartsInmediatly? --> |Yes| OrderActive[Order pass to active state]
    OrderActive --> End
    SaleStartsInmediatly? --> |No| End
```

### As an administrator I want to set an order id generation strategy for orders creation

Everytime an order is created we need to generate a new order id, this order id must be unique across all the system.

## Design

### Class Diagram

```mermaid
classDiagram

    class AssetApprovalRejectionRecord {
    
    }
    <<struct>> AssetApprovalRejectionRecord

    class Asset {
        -List~AssetApprovalRejectionRecord~ validatorHistory
    }

    class RNSResolver {
    
    }
    
    class NFTTokenResolver {
        -address tokenAddress
        -String tokenId
    }
    RNSResolver <|-- NFTTokenResolver

    class AssetValidator {
        -String name
        -address account
        -List~address~ delegates
        
        +constructor(String _name, address _account)
        +name() String
        +account() address
        +delegates() List~address~
    }
    <<struct>> AssetValidator

    class IMarketplace {                
        +addAcceptedCurrency(address _tokenERC20) void
        +removeAcceptedCurrency(address _tokenERC20) void
        +withdraw(address _to, int amount) void
        +addAssetValidatorDelegate(address _account) void
        +removeAssetValidatorDelegate(address _account) void
        +assignRnsDomain(RNSDomain _rnsDomain) void
        +assignRnsNameGenerationStrategy(address _strategy) void
        +registerAsset(Asset _asset) void
        +validatorDelegateApprovesAsset(Validator, Asset) void
        +validatorDelegateRejectAsset(Validator, Asset) void
        +assignOrderIdGeneratorStrategy(address _strategy) void
        +sellAsset(Asset _asset) int
    }
    <<Interface>> IMarketplace
    
    class IMarketplaceConfiguration {
        +changeAllowAnyAssetConfig(bool _newValue) void
        +changeAllowAnyAssetProviderConfig(bool _newValue) void
        +changeAssetsNeedValidationConfig(bool _newValue) void
        +changeAllAssetsUsesSameSaleStrategyConfig(bool _newValue) void
        +changeAllAssetsAcceptsSameCurrenciesConfig(bool _newValue) void
        +changeCreateSubdomainForEachAssetConfig(bool _newValue) void
        +changeSupportsStakingSlashing(bool _newValue) void
    }
    <<Interface>> IMarketplaceConfiguration
    IMarketplaceConfiguration <|-- RIFMarketplace
    
    class IMarketplaceAccessControl {
        +addAdministrator(address _adminAddr) void
        +removeAdministrator(address _adminAddr) void
        +addAssetManager(address _assetManagerAddr) void
        +removeAssetManager(address _assetManagerAddr) void
        +addAssetValidatorManager(address _assetValidatorManagerAddr) void
        +removeAssetValidatorManager(address _assetValidatorManagerAddr) void
        +addFinance(address _financeAddr) void
        +removeFinance(address _financeAddr) void
        +addAssetProviderManager(address _assetProviderManager) void
        +removeAssetProviderManager(address _assetProviderManager) void
        +addAssetValidatorDelegate(address _assetValidatorDelegate) void
        +removeAssetValidatorDelegate(address _assetValidatorDelegate) void
    }
    <<Interface>> IMarketplaceAccessControl
    IMarketplaceAccessControl <|-- RIFMarketplace
    
    class Ownable
    <<OpenZeppelin>> Ownable
    Ownable <|-- RIFMarketplace
    
    class AccessControl
    <<OpenZeppelin>> AccessControl
    AccessControl <|-- RIFMarketplace
    
    class MarketplaceAcceptedCurrency {
        -String name
        -String symbol
        -int decimals
        +constructor(String name, String symbol, int decimals) void
        +getName() String
        +getSymbol() String
        +getDecimals() int
    }
    <<struct>> MarketplaceAcceptedCurrency
    
    class RNSNameGenerationStrategy {
        +generate(Asset _asset) String    
    }
    <<interface>> RNSNameGenerationStrategy
    
    class NFTRNSNameGenerationStrategy {
    
    }
    RNSNameGenerationStrategy <|-- NFTRNSNameGenerationStrategy
    
    class OrderIdGenerationStrategy {
        +generate(Asset _asset) int
    }
    <<interface>> OrderIdGenerationStrategy
    
    class Order {
        int orderId
        enum status
        address escrow
        int blockNumber
    }
    <<struct>> Order
    
    class RIFMarketplace {
        -bool requireWhitelistedAsset
        -bool requireWhitelistedAssetProvider
        -bool assetsNeedValidation
        -bool allAssetsUsesSameSaleStrategy
        -bool allAssetsAcceptsSameCurrencies
        -bool createSubdomainForEachAsset
        -bool supportsStakingSlashing
        -List~MarketplaceAccceptedCurrency~ acceptedCurrencies
        -List~AssetValidator~ assetValidators
        -RNSDomain rnsDomain
        -RNSNameGenerationStrategy rnsNameGenerationStrategy
        -OrderIdGenerationStrategy orderIdGenerationStrategy
        -Map~Order~ orders
        
        +constructor(bool _requireWhitelistedAsset, bool _requireWhitelistedAssetProvider, _assetsNeedValidation, bool _allAssetsUsesSameSaleStrategy, bool _allAssetsAcceptsSameCurrencies, bool _createSubdomainForEachAsset) void
    }
    IMarketplace <|-- RIFMarketplace
```

