# IQ Protocol NFT

## Docs

- [Contract documentation](https://iqlabsorg.github.io/iq-smart-contracts-nft/)

## Setup

1. Clone repository
2. Run `yarn`

## Compilation

```shell
yarn compile
```

## Testing
```shell
yarn test
```

## Generate docs

```shell
pip install -r requirements.txt
yarn hardhato docgen
mkdocs serve
```


## Deployment

The deployment process is automated via hardhat tasks, which can be found under `tasks/deployment` directory.
Process of registration the full dataset required for testing is exampled below.

### Parameters

All deployment tasks have following optional parameters:
1. `unsafe` defines way of deployment (by default: false)
2. `ignore-cache` defines usage of deployment cache (by default: true)
3. `is-serial-deployment` defines usage of how many deployments would be (by default: false)
3. `clear-cache` defines pre-deployment cache cleaning (by default: false)

### Networks

Currently the following networks are supported:

1. Polygon Mumbai Testnet (mumbaiTestnet)
2. BSC Testnet (bscTestnet)
3. Polygon
4. BSC Mainnet

### Creating environemnt

Create a `.env` file that resembles the `.env.example` file in the current directory.

```bash
# .env.example parameters FAQ

### Ethereum Private Key
DEPLOYMENT_PRIVATE_KEY=0xabc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc1
### For PRC calls project is using Ankr: https://www.ankr.com/
ANKR_PROJECT_KEY=basdkjbaskdbaksdbaksdbakjsbdaksdkabsdkasbdkjabsdkjabdkjabsdkabks
### PolygonScan API Key: https://docs.polygonscan.com/getting-started/viewing-api-usage-statistics
ETHERSCAN_API_KEY_POLYGON=NAKJDNASNDASNDAJNEQOWNEIOQWASDLASD
### BscScan API Key: https://docs.bscscan.com/getting-started/viewing-api-usage-statistics
ETHERSCAN_API_KEY_BSC=NASFDNAOISDNQOWINEOIQWNASNDKJANSDA
```

### Flow 1 - using custom Hardhat Runtime Environemnt tasks

1. Deploy ERC20 contract
```bash
yarn hardhat deploy:test:mock:erc20 --network [network name] --name [erc20 name] --symbol [erc20 symbol] --decimals [erc20 decimals] --total-supply [erc20 total supply]
```

Example:

```bash
yarn hardhat deploy:test:mock:erc20 --network bscTestnet --name BscCoin --symbol BCC --decimals 18 --total-supply 1000000000000 --ignore-cache false --is-serial-deployment true
```

2. Deploy ACL contract
```bash
yarn hardhat deploy:acl --network [network name]
```

Example:

```bash
yarn hardhat deploy:acl --network bscTestnet --ignore-cache false --is-serial-deployment true
```

3. Initial deployment
```bash
yarn hardhat deploy:initial-deployment --network [network name] --acl [address] --base-token [address] --protocol-external-fees-collector [address]
```

Example:

```bash
yarn hardhat deploy:initial-deployment --network bscTestnet --acl 0x0000000000000000000000000000000000000000 --base-token 0x0000000000000000000000000000000000000000 --protocol-external-fees-collector 0x0000000000000000000000000000000000000000 --ignore-cache false
```

## Upgrades
**Beware:** Upgrading smart contracts requires extra caution, as this can lead to data loss and break the protocol.

Some protocol contracts are upgradeable. This allows extending functionality and fixing the security issues.
The upgradeability process can be automated via hardhat tasks. You can find some examples of upgrade tasks under `tasks/upgrades` directory.
In order to reduce the risks, the protocol relies on [OZ Upgrades Plugin](https://docs.openzeppelin.com/upgrades-plugins/1.x/) for deploying and upgrading contracts.

### List of upgradeable contracts

1. accounting/distributors/ERC20RewardDistributor.sol
2. accounting/TokenQuote.sol
3. acl/ACL.sol
4. asset/AssetClassRegistry.sol
5. listing/listing-configurator/ListingConfiguratorPresetFactory.sol
6. listing/listing-configurator/ListingConfiguratorRegistry.sol
7. listing/listing-strategies/fixed-rate/FixedRateListingController.sol
8. listing/listing-strategies/fixed-rate-with-reward/FixedRateWithRewardListingController.sol
9. listing/listing-manager/ListingManager.sol
10. listing/listing-strategy-registry/ListingStrategyRegistry.sol
11. listing/listing-terms-registry/ListingTermsRegistry.sol
12. metahub/core/Metahub.sol
13. renting/renting-manager/RentingManager.sol
14. tax/tax-strategies/fixed-rate/FixedRateTaxController.sol
15. tax/tax-strategies/fixed-rate-with-reward/FixedRateWithRewardTaxController.sol
16. tax/tax-strategy-registry/TaxStrategyRegistry.sol
17. tax/tax-terms-registry/TaxTermsRegistry.sol
18. universe/universe-registry/UniverseRegistry.sol
19. warper/preset-factory/WarperPresetFactory.sol
20. warper/warper-manager/WarperManager.sol



## Tasks
Many of the protocol maintenance routines are automated using [hardhat tasks](https://hardhat.org/hardhat-runner/docs/guides/tasks-and-scripts#writing-hardhat-tasks). Find the list of available commands by running:
```shell
hardhat --help
```

## Toolkit

In order to simplify different workflows with smart contracts,
which can be found under `tasks/toolkit` directory.

1. `data-checks`: Tasks for post-deployment checking.
2. `data-model-dump`: Tasks for generating data model changes cache.
3. `data-registration`: Tasks for registering connections between different controller contracts and registries during deployment.
4. `datagen`: Tasks for generating dummy data for showcase purposes.
5. `deployment-cache`: Tasks for interacting with contracts deployment data caching mechanisms.

### Data Checks (`./tasks/toolkit/data-checks`)

In order to simplify post deployment checks contracts set and automate process of data validation in a chain agnostic and extendable way there is a set of tasks, which can be found under `tasks/toolkit/data-checks` directory.

1. Check that all required data was registered and contract registered filled with correct data
```shell
yarn hardhat toolkit:checks:all --network [network name]
```

2. Check that certain contract entity was registered
```shell
yarn hardhat toolkit:checks:check-registered-entity --network [network name] --contract-name [name of the contract] --contract-registry [address of metahub] --contract-key [unique contract entity key] --expected-contract-address [address of contract]
```

3. Check contract registry that all contracts were registered using `deployment-cache` data from `./active-deployment/[networkName]`

```shell
yarn hardhat toolkit:checks:check-registry --network [network name]
```

4. Check that ERC721 Configurable Preset was registered
```shell
yarn hardhat toolkit:checks:check-registered-erc721-configurable-preset --network [network name] --warper-preset-factory [address] --erc721-configurable-preset [address]
```

5. Check that ERC721 Asset Class was registered
```shell
yarn hardhat toolkit:checks:check-registered-erc721-asset-class --network [network name] --asset-class-registry [address]
```

6. Check that FixedRate listing controller was registered
```shell
yarn hardhat toolkit:checks:check-registered-fixed-rate-listing-controller --network [network name] --listing-strategy-registry [address] --fixed-rate-listing-controller [address]
```

7. Check that FixedRateWithReward listing controller was registered
```shell
yarn hardhat toolkit:checks:check-registered-fixed-rate-listing-controller --network [network name] --listing-strategy-registry [address] --fixed-rate-with-reward-listing-controller [address]
```

8. Check that FixedRate tax controller was registered
```shell
yarn hardhat toolkit:checks:check-registered-fixed-rate-tax-controller --network [network name] --tax-strategy-registry [address] --fixed-rate-tax-controller [address]
```

9. Check that FixedRateWithReward tax controller was registered
```shell
yarn hardhat toolkit:checks:check-registered-fixed-rate-with-reward-tax-controller --network [network name] --tax-strategy-registry [address] --fixed-rate-with-reward-tax-controller [address]
```

10. Check that GeneralGuildPreset was registered
```shell
yarn hardhat toolkit:checks:check-registered-guild-preset --network [network name] --listing-configurator-preset-factory [address] --general-guild-preset [address]
```

### Data Model Dump (`./tasks/toolkit/data-model-dump`)

In order to make smart contract structs, events, functions and other structure dependent changeable parts more visible for overview and comparison with previous versions, there is a set of tasks, which can be found under `tasks/toolkit/`.

Tasks are developed using `@solidity-parser/parser`
[@solidity-parser/parser](https://www.npmjs.com/package/@solidity-parser/parser) library, that gives an opportunity to parse and interact with Solidity AST Nodes.

1. Create fresh dump of smart contracts using contract files from `./contracts/` and their artifacts from `./artifacts/contracts`
```shell
yarn hardhat toolkit:dump:create
```

2. Compare two different versions of dumps or version from dump and actual contracts from `./contracts/`
```shell
# 'version1' is option, 'version2' is required

yarn hardhat toolkit:dump:compare --version1 ['latest' by default] --version2 ['undefined' by default]
```

#### Example of 'version*' field variations

1. `latest`: contracts from `./contracts/` directory would be taken.
2. `x.x.x`: contracts from `./data-model-dump/latest` or `./data-model-dump/history` would be taked.
3. `undefined`: would lead to an error.

### Datagen (`./tasks/toolkit/datagen`)

In order to simplify testing on testnet/mainnet networks there is set of tasks, which can be found under `tasks/toolkit/datagen` directory.

#### Detailed flow (Multiple steps)
1. Define protocol tax terms
```shell
yarn hardhat toolkit:datagen:register-protocol-terms --network [network name] --metahub [address]
```
This will set protocol tax terms to default values `25% for listing fees` and `50% for tournament reward fees`.

Or setup custom fee:
```shell
yarn hardhat toolkit:datagen:register-protocol-terms --network [network name] --metahub [address] --base-tax-rate 10 --reward-tax-rate 15
```
Where `--base-tax-rate` and `--reward-tax-rate` parameters are percentage and has maximum value of `100`.

2. Deploy mock of Universe Token
```shell
yarn hardhat toolkit:deploy:test:mock:erc721 --network [network name] --name UniverseName --symbol UNIS
```
3. Setup Universe and Warper
```shell
yarn hardhat toolkit:datagen:setup-universe-and-warper --network [network name] --metahub [address] --universe-token [address] --base-token [address] --universe-name UniverseName
```
This will set universe tax terms to default values `25% for listing fees` and `50% for tournament reward fees` and other parameters for default values.
More details can be found in `tasks/datagen/setup-universe-and-warper.ts` file.

Or setup custom parameters (if you already have a warper):
```shell
yarn hardhat datagen:setup-universe-and-warper --network [network name] --metahub [address] --universe-token [address] --base-token [address] --universe-name UniverseName --existing-warper-address [address] --base-tax-rate 20 --reward-tax-rate 40 --payment-tokens ["0x0000000000000000000000000000000000000000"] --warper-name WarperName --warper-preset-id 0x0000000000000000000000000000000000000000 --warper-init-data 0x0000000000000000000000000000000000000000 --warper-paused false
```
4. Mint tokens
```shell
yarn hardhat datagen:mint-tokens --network [network name] --metahub [address] --universe-token [address] --nft-collection-size 2
```

5. Creating listing
```shell
yarn hardhat datagen:list --network [network name] --metahub [address] --universe-token [address] --universe-id 1 --token-id 1
```

Or setup custom parameters:

```shell
yarn hardhat datagen:list --network [network name] --metahub [address] --universe-token [address] --universe-id 1 --token-id 1 --base-fee 100 --reward-fee 25 --max-lock-period 36000 --immediate-payout false --configurator [address]
```

7. Creating renting
```shell
l [network name] --metahub [address] --listing-id 1 --listing-terms-id 1 --warper [addresss] --payment-token [addresss]
```

Or setup custom parameters:

```shell
yarn hardhat datagen:rent --network [network name] --metahub [address] --listing-id 1 --listing-terms-id 1 --warper [addresss] --payment-token [addresss] --rental-period 36000
```

### Simple flow (2 steps)

1. Deploy mock of Universe Token
```shell
yarn hardhat deploy:test:mock:erc721 --network [network name] --name UniverseName --symbol UNIS
```

2. Deploy mock of Universe Token
```shell
yarn hardhat datagen:initialize --network [network name] --metahub [address] --base-token [address] --universe-token [address]
```

### Testing purposes (for testnet deployments)

1. A payment token: `yarn hardhat --network [network name] deploy:mock:ERC20 --name USDC --symbol USDC`
2. An NFT collection: `yarn hardhat --network [network name] deploy:mock:ERC721-internal-tests --name TEST --symbol TT`

## Publish to NPM

1. manually update the version in `package.json`
2. yarn build
3. yarn run publish


## Manual contract verification

- Every time the deployment command is executed, a new set of deployment artifacts is created under
`deployments/<network>`. The `deployments/<network>/solcInputs` directory will contain a new [Standard JSON-input](https://docs.soliditylang.org/en/latest/using-the-compiler.html#input-description) file which can be used for
contract verification.
- Verifying Metahub requires extra care. It uses dynamically linked libraries, but those do not get attached to the deployment artifact. It means that you need to edit this JSON field manually and add the deployed library addresses:

```json
...
  "settings": {
    "optimizer": {
      "enabled": true,
      "runs": 200
    },
    "outputSelection": {
      "*": {
        "*": [
          "storageLayout",
          "abi",
          "evm.bytecode",
          "evm.deployedBytecode",
          "evm.methodIdentifiers",
          "metadata",
          "devdoc",
          "userdoc",
          "evm.gasEstimates"
        ],
        "": [
          "ast"
        ]
      }
    },
    "metadata": {
      "useLiteralContent": true
    },
    // This is the part you need to add manually
    "libraries": {
      "contracts/renting/Rentings.sol": {
        // The addresses get logged to the terminal when deploying the Metahub contract.
        "Rentings": "0xF6188F991962dBcEF5621312515BeEE566989Df0"
      },
      "contracts/listing/Listings.sol": {
        "Listings": "0xd0bdF81Aca69FC6B28de655c0464451f25A0cdfA"
      },
      "contracts/asset/Assets.sol": {
        "Assets": "0x4778CE9b59c5E9e287Ed50f4671c98F4b7557A72"
      },
      "contracts/warper/Warpers.sol": {
        "Warpers": "0x529Bd1D28bECeC204a817D2dE6530638A8AEda72"
      },
      "contracts/accounting/Accounts.sol": {
        "Accounts": "0xD40925d61751BDFab9ff4b163a3793177EbDc0AA"
      }
    }
  }
...
```
