ERC721Envious & ghostNFT documentation!

ghostNFT is the first application of ERC721Envious Standard aimed at adding collateral to NFTs. ghostNFT introduces an intuitive user experience enabling creators and users to add, redeem, and view collateral to individual NFTs and NFT collections. ghostNFT targets NFT collections, NFT owners, Token Holders, and Web3 Users.

The ERC-721 standard was proposed in January 2018. Starting from Cryptokitties project getting its fame in 2017 to Doodles success in 2021, NFT space attracted a lot of attention resulting in everincreasing ecosystem, spiking trading volumes and diverse sets of NFT collections.

Further innovation in the NFT space was introduced by NFTfi. NFTfi focuses on the NFT floor price to enable the market value of the NFT serve as a collateral in lending protocols. Floor price is impacted by supply-demand dynamics of the NFT market which typically experiences higher volatility relative to price action of the general crypto market. Additionally, potential price increase the floor price accounted for by lending protocols. Using floor price based on the market manipulation in individual NFT collections may artificially increase market prices and, thus, value alone is both volatile and unreliable.

The ERC721Envious standard is an extension of ERC721, similar to OpenZeppelin’s ERC721Enumerable abstract contract. ERC721Envious is designed to ensure compatibility with OpenZeppelin ERC721, making it more convenient to use. This standard permits the collateralization of individual NFTs and NFT collections. Furthermore, EnviousHouse allows for the addition of collateral to previously minted NFTs, turning them into collateralized NFTs.

Warning

ghostNFT is an experimental initiative that seeks to unite the DeFi and NFT communities to benefit both. It is crucial to have a complete understanding of the project’s objectives, examine the code thoroughly, and review the contents of the ./audits folder.

The ERC721Envious framework aims to utilize the smart contract address as a shared ERC20 token vault, with each unique tokenId acting as the key to the partial amount that belongs to the token holder and never leaves their wallet.

Hint

To obtain this documentation, you can access the versions flyout menu located at the bottom-left corner of the page and select the preferred download format, which includes PDF, HTML, or Epub.

Getting Started

1. Create a gNFT.

If you already have a collection, you can use the EnviousHouse wrapper to integrate the ERC721Envious standard and make it compatible with the Envious protocol.

On the other hand, if you are starting a new project, it is recommended to use the ERC721Envious extension or one of the available Presets as a starting point to simplify the process of implementing the Envious standard.

2. ERC721Envious Presets.

Preset contracts combine ERC721Envious with custom extensions and modules, presenting common configurations and business logic that can be easily deployed without the need to write Solidity code.

Hint

Preset contracts are pre-built smart contracts that come with pre-configured extensions and modules, demonstrating common configurations and business logic. They allow intermediate and advanced users to utilize them as a foundation when developing their own contracts, expanding them with custom features to suit their needs. As the GHOST team continues to work on new ideas and real-world use cases, they welcome suggestions for new presets.

Warning

The most battle-tested preset is ERC721EnviousDynamic, which has been thoroughly tested and is recommended for use. Please refer to John McAfee Legacy (JML) NFT Collection for more information on this preset. GHOST team is continuously exploring new opportunities to implement other presets for Web3 use cases.

3. Use Cases.

The ERC721Dynamic preset was first used for the John McAfee Legacy (JML) NFT Collection. However, because of its dynamic nature, it requires the use of a measurementToken called Ghost McAfee Vision (GMV). GMV is utilized to rotate NFT images in accordance with the actual collateral and represents the initial balance for the genesis block on the GHOST Chain.

Hint

Additional information on the Initial NFT Offering (INO) can be found here.

To ensure a decentralized approach, a ghostFaucet has been developed, which represents the first real-world Initial NFT Offering (INO). It gamifies the idea of an airdrop by providing actual collateral in the form of NFTs.

4. Testing.

You can locate full test coverage in the ./coverage folder, while test results and gas reports are stored in the ./gas_reporter folder.

To test smart contracts locally, please execute the following commands:

truffle run coverage                 # prepare test coverage report
truffle test                         # run all tests as single unit
# OR
truffle test tests/FILENAME.test.js  # run specific needed test

You can find Slither reports for each smart contract in the ./audits/slither/ folder. Similarly, Mythril reports can be found in the ./audits/mythril/ folder.

We welcome your feedback and pull requests!

Warning

The Mythril analysis was conducted in a Docker container and took around 1 hour for each smart contract.

Contents

Keyword Index, Search Page

Environment

Requirements

Install git, node, and truffle.

Hint

During the development process, truffle@5.5.18 was utilized. Using other truffle versions may be prone to instability when running the coverage plugin.

Clone git

git clone https://github.com/somegit.git
cd ./envious/

Install dependencies

npm install

Usage

Compile smart contracts

truffle compile

Hint

During the development process, Debian GNU/Linux 10 (buster) was utilized. However, attempts to use Hardhat were unsuccessful due to the size of the generated bytecode. It is worth noting that despite using the same optimizer and optimization runs, Hardhat and Truffle produced different results.

Once the smart contracts are compiled, smart contract testing may begin.

truffle test
# OR
truffle run coverage

Please explore ./audits/slither/ for every smart contract in this project or run slither independently.

slither contracts/FILENAME.sol

Advanced users are strongly recommended to use mytril, which is considered one of the best tools for analyzing Solidity smart contracts.

Extension Usage

Inherit ERC721Envious

To begin minting an ERC721Envious NFT Collection, it is recommended to follow the OpenZeppelin ERC721 standard for actual EIP-721 implementation. Follow the steps outlined below to mint an ERC721Envious NFT Collection.

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./contracts/extension/ERC721Envious.sol";

contract YourCollectionName is ERC721Envious {
  constructor (string memory name, string memory symbol) ERC721(name, symbol) {}
}

Basic Customization

Many NFT collections prefer to use IPFS, which is an excellent tool for Web3 developers. Let’s assume that every new NFT is minted after the asset is designed and uploaded onto IPFS. This way, the NFT collection will have the creator role.

While creating a unique IPFS hash for every new NFT is not a standard way of implementing NFT, it is still feasible by overriding the tokenURI function logic.

Hint

This is a simplified method to incorporate smart contract admin. Make sure to incorporate any logic that suits the project requirements.

Sending native coins to a smart contract by mistake can lead to the permanent loss of those coins. The issue can be resolved by implementing a receive function and rerouting the mistake.

It is recommended to use ERC721Enumerable to improve the search capabilities in the collection.

ERC721Envious standard enables developers to create their own distribution logic for the _disperse function, which is responsible for distributing funds across assets in a collection. The standard also offers customizable templates for this function. However, by default, the _disperse function splits the contract’s balance equally among all NFTs in the collection.

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./contracts/extension/ERC721Envious.sol";
import "@openzeppelin/token/ERC721/extensions/ERC721Enumerable.sol";

contract YourCollectionName is ERC721Envious, ERC721Enumerable  {
  address private immutable _creator;
  uint256 private _tokenNumber;
  mapping(uint256 => string) private _tokenURIs;

  /* --snip-- */

  receive() external payable {
              _disperseTokenCollateral(msg.value, address(0));
      }

  function mint(address who, string memory hash) public override {
    require(_msgSender() == address(this), "only for itself");
    _tokenNumber += 1;
    _safeMint(who, _tokenNumber);
  }

  function creatorMint(address who, string memory hash) external {
    require(_msgSender() == _creator(), "only for creator");
    mint(who);
    _tokenURIs[_tokenNumber] = hash;
  }

  function tokenURI(uint256 tokenId) public view override returns (string memory) {
    _requireMinted(tokenId);
    return _tokenURIs[tokenId];
  }
}

Defining Disperse Function

In most cases the default dispersion method will follow its classic definition in which the entire balance splits equality among all NFTs in the collection. However, the _disperse function is left undefined so that developers can define their own custom dispersion logic tailored to their specific project needs.

Hint

When the _disperse function is executed the collateral amount is not transferred under the corresponding tokenId. To keep track of this intermediate step, it is necessary to store both the total disperse balance and the disperse balance for each tokenId.

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./contracts/extension/ERC721Envious.sol";
import "@openzeppelin/token/ERC721/extensions/ERC721Enumerable.sol";

contract YourCollectionName is ERC721Envious, ERC721Enumerable  {

  /* --snip-- */

  function _disperse(address tokenAddress, uint256 tokenId) internal virtual override {
    uint256 balance = disperseBalance[tokenAddress] / totalSupply();

    if (disperseTotalTaken[tokenAddress] + balance > disperseBalance[tokenAddress]) {
      balance = disperseBalance[tokenAddress] - disperseTotalTaken[tokenAddress];
    }

    if (balance > disperseTaken[tokenId][tokenAddress]) {
      uint256 amount = balance - disperseTaken[tokenId][tokenAddress];
      disperseTaken[tokenId][tokenAddress] += amount;

      (bool shouldAppend,) = _arrayContains(tokenAddress, collateralTokens[tokenId]);
      if (shouldAppend) {
        collateralTokens[tokenId].push(tokenAddress);
      }

      collateralBalances[tokenId][tokenAddress] += amount;
      disperseTotalTaken[tokenAddress] += amount;
    }
  }
}

Clean Up

Since both ERC721Enumerable and ERC721Envious inherit from the ERC721 standard, there may be some intersections that can cause errors during compilation. All intersections should be overridden to compile without issues.

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./contracts/extension/ERC721Envious.sol";
import "@openzeppelin/token/ERC721/extensions/ERC721Enumerable.sol";

contract YourCollectionName is ERC721Envious, ERC721Enumerable  {

  /* --snip-- */

  function supportsInterface(bytes4 interfaceId)
    public
    view
    virtual
    override(ERC721Envious, ERC721Enumerable, ERC721)
    returns (bool)
  {
    return ERC721Envious.supportsInterface(interfaceId) || ERC721Enumerable.supportsInterface(interfaceId);
  }

  function _disperse(address tokenAddress, uint256 tokenId) internal virtual override {
    uint256 balance = disperseBalance[tokenAddress] / totalSupply();

    if (disperseTotalTaken[tokenAddress] + balance > disperseBalance[tokenAddress]) {
      balance = disperseBalance[tokenAddress] - disperseTotalTaken[tokenAddress];
    }

    if (balance > disperseTaken[tokenId][tokenAddress]) {
      uint256 amount = balance - disperseTaken[tokenId][tokenAddress];
      disperseTaken[tokenId][tokenAddress] += amount;

      (bool shouldAppend,) = _arrayContains(tokenAddress, collateralTokens[tokenId]);
      if (shouldAppend) {
        collateralTokens[tokenId].push(tokenAddress);
      }

      collateralBalances[tokenId][tokenAddress] += amount;
      disperseTotalTaken[tokenAddress] += amount;
    }
  }
}

Final Code

Code can now be deployed to any EVM-compatible blockchain network and let the code handle the rest. Developers have the freedom to explore and integrate gamification features around collateralization and/or dispersion as they see fit. More advanced Solidity developers will find this powerful tool inspiring to design creative and diverse solutions that push the boundaries of both NFT and DeFi ecosystems.

Please find the final version of the code below:

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./contracts/extension/ERC721Envious.sol";
import "@openzeppelin/token/ERC721/extensions/ERC721Enumerable.sol";

contract YourCollectionName is ERC721Envious, ERC721Enumerable  {

  address private immutable _creator;
  uint256 private _tokenNumber;
  mapping(uint256 => string) private _tokenURIs;

  constructor (string memory name, string memory symbol) ERC721(name, symbol) {
    _creator = _msgSender();
  }

  receive() external payable {
    _disperseTokenCollateral(msg.value, address(0));
  }

  function mint(address who, string memory hash) public override {
    require(_msgSender() == address(this), "only for itself");
    _tokenNumber += 1;
    _safeMint(who, _tokenNumber);
  }

  function creatorMint(address who, string memory hash) external {
    require(_msgSender() == _creator(), "only for creator");
    mint(who);
    _tokenURIs[_tokenNumber] = hash;
  }

  function tokenURI(uint256 tokenId) public view override returns (string memory) {
    _requireMinted(tokenId);
    return _tokenURIs[tokenId];
  }

  function supportsInterface(bytes4 interfaceId)
    public
    view
    virtual
    override(ERC721Envious, ERC721Enumerable, ERC721)
    returns (bool)
  {
    return ERC721Envious.supportsInterface(interfaceId) || ERC721Enumerable.supportsInterface(interfaceId);
  }
}

EnviousHouse Usage

Concept

This section contains a more comprehensive overview of the EnviousHouse smart contract.

The EnviousHouse contract enables any already deployed ERC721 collection to upgrade to the ERC721Envious standard and gain collateral functionality by simply calling the registerCollection function. This allows any NFT collection to become envious and take advantage of the benefits offered by the ERC721Envious standard.

function registerCollection(address collection, address token, uint256 incoming, uint256 outcoming) external payable override

registerCollection function will require the following parameters:

  • Collection address

  • measurementToken address

  • Incoming fee (collateralization fee)

  • Outcoming fee (uncollateralization fee)

Simply insert an NFT collection address to access EnviousHouse functionality. More information can be found in EnviousHouse Specifications.

Warning

Every NFT Collection can only be registered once, and the set parameters cannot be reversed or updated. It is crucial to ensure that the set parameters are aligned with the goals of the project.

ERC721 Collection Integration

This section provides instructions on how to add an ERC721 NFT collection to ghostNFT. The process comprises six straightforward steps that can be completed in less than two minutes.

Definitions:

Term

Description

Collection address

address of ERC721 NFT collection

Commission Token

ERC20 token that will

Collateralization Fee

percentage fee charged from every collateral deposit

Uncollateralization Fee

percentage fee change from every collateral redemption

Dispersion Amount

minimum amount of the native coin required to register an ERC721 NFT collection

Warning

The Commission Token is an ERC20 token, therefore, do not input an externally owned account (EOA) address in the Commission Token field.

Hint

Holders of Commission Token are granted exclusive access to exchange their tokens for Collateralization Fee and Uncollateralization Fee.

Hint

At the time of deployment, the Dispersion Amount was established at $69.00 in the native coin based on current market prices.

Figure 1. ERC721Envious Registration - Part 1 of 2.

Step 1. Please choose a blockchain network. ghostNFT is currently available on 16 EVM-compatible chains.

Step 2. Press Add your collection button.

Figure 1. ERC721Envious Registration - Part 2 of 2.

Step 3. Provide the Collection Address.

Step 4. Provide the Commission Token.

Hint

It is advisable to either create a new ERC20 token specifically for use as a Commission Token, or utilize an existing ERC20 token that already has a thriving community.

Step 5. Set appropriate Collateralization Fee and Uncollateralization Fee.

Hint

The Collateralization Fee and Uncollateralization Fee should be established at appropriate levels to avoid discouraging users from adding collateral to the collection.

Step 6. Set the Dispersion Amount.

Hint

Dispersion Amount fully goes to all tokenId holders.

That’s it! Congratulations on successfully registering your ERC721 collection with ghostNFT!

Preset Usage

Concept

The primary objective of all presets is to predefine the majority of the template’s functionality for developers, in order to strike a balance between code flexibility and time efficiency. Please read the documentation for all presets to detect already implemented functionality which can be inherited by simply copying the code.

If you have any ideas regarding code improvement or additional presets, pull requests (PRs) are welcome.

Inherit ERC721Envious

ERC721EnviousPreset logic should be simply inherited if the business logic of the project is aligned with the logic of the standard.

Hint

For most NFT collections, the predefined functionalities and structure provided by the EnviousHouse framework and ERC721EnviousPreset will not meet the requirements, and additional customization will be necessary.

// SPDX-License-Identifier: MIT

import "./presets/ERC721EnviousPreset.sol";

pragma solidity ^0.8.0;

contract YourAwesomeName is ERC721EnviousPreset {

  constructor(
    string memory name,
    string memory symbol,
    string memory baseURI
  ) ERC721Envious(name, symbol, baseURI) {}

}

A more detailed description of each existing ERC721Envious Preset can be found in the Presets section of this documentation.

ERC721Envious Extension

Description

ERC721Envious smart contract is an abstract smart contract that extends the functionality of ERC721 by enabling collateral features. The address of an ERC721Envious collection stores the native coin and ERC20 tokens where the tokenId serves as the access key unlocking the corresponding portion of the balance.

Hint

Following best practices, the native coin will be associated with the 0x0000000000000000000000000000000000000000 address to avoid collision between the native coin and ERC20 tokens.

Any user can collateralize any specific tokenID with any combination of the native coin and any ERC20 tokens. ERC721Envious allows each tokenId to store a unique array of token addresses owned, which eliminates the need for token registration and array length.

However, only the owner of the tokenId can redeem or uncollateralize the native coin and ERC20 tokens attached to the tokenId. This ensures that the collateral balance remains with the tokenId owner at any given point of time, and makes it easier to transfer ownership of the tokenId without having to worry about transferring the collateral balance separately.

Hint

When a new ERC20 token is added as collateral, its token address is added to the array of token addresses associated with the tokenId. When the balance of a specific ERC20 token drops to 0, its address is removed from the array of token addresses.

Harvesting is required to collect accumulated commissions. The total token quantity is calculated after aligning the decimals and taking out a proportional value according to the number of communityToken submitted.

Hint

Not all ERC20 tokens support the burn function. To work around this limitation, the ERC721Envious standard includes a specific entity called BlackHole, which serves as an analog to the zero address.

Another important feature of the ERC721Envious standard is to disperse tokens across all assets in the collection in one single transaction.

Hint

When tokens are dispersed to NFTs in a collection the collateral is stored in a temporary variable, and is not immediately reflected in the actual collateral balance behind respective tokenIds. Instead, the dispersed collateral balance for each tokenId is updated when collateral or uncollateral operation takes place on that specific tokenId.

Warning

The dispersion logic relies on the totalSupply function. It is important to ensure that there are no issues with the totalSupply function to prevent any unintended consequences in the dispersion logic.

It is possible to make the collateral, uncollateral, harvest, and disperse functions more flexible by allowing users to specify an array of actions to be performed in a single transaction. This can help reduce the gas fees associated with performing these actions individually.

IERC721Envious

IERC721Envious is an optional Envious extension for ERC-721 Non-Fungible Token Standard.

commissions

function commissions(uint256 index) external view returns (uint256)

commissions are defined by an array with two elements as input, each representing a commission percentage charged on collateral. The first element denotes the commission charged for collateralization, while the second element represents the commission for uncollateralization. It is important to note that a 3 decimal buffer should be added to each commission rate. For example, 1% would be represented as 1000.

commissions function returns the value of the respective commission fee.

_Arguments_

Name

Type

Description

index

uint256

index of value in array

ghostAddress

function ghostAddress() external view returns (address)

ghostAddress function returns the token address for bond payouts. Following the launch of ghostDAO, ghostAddress will be set to the tokenAddress of the GHST token.

ghostBondingAddress

function ghostBondingAddress() external view returns (address)

ghostBondingAddress function returns the smart contract address that facilitates the purchase of bonds using the DeFi 2.0 protocol. Following the launch of ghostDAO, ghostBondingAddress will be set to the bonding smart contract address of ghostDAO.

blackHole

function blackHole() external view returns (address)

blackHole is an address that ensures any tokens sent to it cannot be retrieved.

blackHole function returns the address of the blackHole.

communityToken

function communityToken() external view returns (address)

communityToken is an ERC20 token set by the collection registrant. communityToken can be exchanged to harvest accumulated commissions.

communityToken function returns the address of the communityToken.

communityPool

function communityPool(uint256 index) external view returns (address)

Pool of available tokens for harvesting.

communityPool is an array of ERC20 addresses that can be harvested by communityToken holders.

communityPool function returns the address of a specific ERC20 token available for harvesting by communityToken holders.

_Arguments_

Name

Type

Description

index

uint256

index of value in array

communityBalance

function communityBalance(address tokenAddress) external view returns (uint256)

communityBalance is the amount of ERC20 token available for harvesting.

communityBalance function returns the total balance of a specified ERC20 token that has been accumulated from collected commissions and is currently available for harvesting.

_Arguments_

Name

Type

Description

tokenAddress

address

address of an ERC20 token available for harvesting

disperseTokens

function disperseTokens(uint256 index) external view returns (address)

disperseTokens is an array of ERC20 tokens that have already been dispersed.

disperseTokens function returns the address of a specific ERC20 token that has been dispersed.

_Arguments_

Name

Type

Description

index

uint256

index of value in array

disperseBalance

function disperseBalance(address tokenAddress) external view returns (uint256)

disperseBalance is the total amount of ERC20 tokens that have been distributed to all tokenIds within a particular NFT collection.

disperseBalance function returns the total amount of a particular ERC20 token that has been dispersed to all tokenIds within a particular NFT collection.

_Arguments_

Name

Type

Description

tokenAddress

address

address of a dispersed ERC20 token

disperseTotalTaken

function disperseTotalTaken(address tokenAddress) external view returns (uint256)

disperseTotalTaken is the quantity of ERC20 tokens that has been already claimed from the disperseBalance.

disperseBalance function returns the number of dispersed ERC20 tokens of a specific tokenAddress from the disperseBalance.

_Arguments_

Name

Type

Description

tokenAddress

address

address of a dispersed ERC20 token

disperseTaken

function disperseTaken(uint256 tokenId, address tokenAddress) external view returns (uint256)

disperseTaken is the quantity of ERC20 tokens that has been already claimed from the disperseBalance, specifically in reference to a particular tokenId.

disperseTaken function returns the quantity of a specific ERC20 token that has been distributed from the disperseBalance to a particular tokenId.

_Arguments_

Name

Type

Description

tokenId

uint256

unique token identifier

tokenAddress

address

address of a dispersed ERC20 token

bondPayouts

function bondPayouts(uint256 bondId) external view returns (uint256)

bondPayouts is an estimated quantity of the ghostAddress token to be obtained from the bond upon completion of the vesting period.

bondPayouts function returns the approximate payout quantity of the ghostAddress token to be obtained from a particular bondId after the vesting period is over.

_Arguments_

Name

Type

Description

bondId

uint256

unique bond identifier

bondIndexes


bondIndexes is a mapping that associates each tokenId from a particular NFT collection with an array of bonds.

bondIndexes function returns the index of a bond based on collection address, tokenId, and chronological index position.

_Arguments_

Name

Type

Description

tokenId

uint256

unique token identifier

index

uint256

index in array

collateralTokens

function collateralTokens(uint256 tokenId, uint256 index) external view returns (address)

collateralTokens represents ERC20 tokens used as a collateral for a particular NFT.

collateralTokens function returns the address of an ERC20 token used as a collateral for a particular tokenId, determined by its chronological index position.

_Arguments_

Name

Type

Description

tokenId

uint256

unique token identifier

tokenAddress

address

address of an ERC20 token being held as collateral

collateralBalances


collateralBalances reflects the total quantity of ERC20 tokens that are currently being held as collateral for a particular tokenId.

collateralBalances function returns the quantity of ERC20 tokens held as collateral for a specific tokenId, based on the provided tokenAddress.

_Arguments_

Name

Type

Description

tokenId

uint256

unique token identifier

tokenAddress

address

address of an ERC20 token being held as collateral

getAmount

function getAmount(uint256 amount, address tokenAddress) external view returns (uint256)

getAmount is a calculator for estimating the harvesting amount.

getAmount function returns the harvesting amount for a specific ERC20 token based on the amount of communityToken to be exchanged.

_Arguments_

Name

Type

Description

amount

uint256

amount of communityToken

tokenAddress

address

address of a harvested ERC20 token

harvest

function harvest(uint256[] memory amounts, address[] memory tokenAddresses) external

harvest function collects commission fees in exchange for communityToken.

_Arguments_

Name

Type

Description

amounts

uint256[]

array of amounts to be harvested

tokenAddresses

address[]

array of token addresses to be harvested

collateralize

function collateralize(uint256 tokenId, uint256[] memory amounts, address[] memory tokenAddresses) external payable

collateralize function facilitates the collateralization of a specific tokenId using a specified amount of a designated ERC20 token.

_Arguments_

Name

Type

Description

tokenId

uint256

unique token identifier

amounts

uint256[]

array of amounts to be added to the collateral

tokenAddresses

address[]

array of token addresses to be added to the collateral

uncollateralize

function uncollateralize(uint256 tokenId, uint256[] memory amounts, address[] memory tokenAddresses) external

uncollateralize function facilitates the redemption of a specific tokenId using a specified amount of a designated ERC20 token.

Hint

Only the owner of the tokenId is able to trigger the uncollateralize function.

_Arguments_

Name

Type

Description

tokenId

uint256

unique token identifier

amounts

uint256[]

array of amounts to be redeemed from the collateral

tokenAddresses

address[]

array of token addresses to be redeemed from the collateral

getDiscountedCollateral

function getDiscountedCollateral(uint256 bondId, address quoteToken, uint256 tokenId, uint256 amount, uint256 maxPrice) external

getDiscountedCollateral function enables NFT collateralization with a discount determined by the available bonds. The smart contract acts as the temporary owner of the bond during the bond vesting period.

_Arguments_

Name

Type

Description

bondId

uint256

unique bond identifier

quoteToken

address

address of a token that is accepted as a payment for a bond

tokenId

uint256

unique token identifier

amount

uint256

quantity of the quoteToken paid for the bond

maxPrice

uint256

maximum price allowed to pay for the bond

claimDiscountedCollateral

function claimDiscountedCollateral(uint256 tokenId, uint256[] memory indexes) external

claimDiscountedCollateral function allows for the redemption of the corresponding bond notes for ghostAddress collateral after the bond vesting period has elapsed.

_Arguments_

Name

Type

Description

tokenId

uint256

unique token identifier

indexes

uint256[]

array of note indexes to redeem

disperse

function disperse(uint256[] memory amounts, address[] memory tokenAddresses) external payable

disperse function logs the amounts of tokenAddresses` into ``disperseBalance.

_Arguments_

Name

Type

Description

amounts

uint256[]

array of amounts to be dispersed

tokenAddresses

address[]

array of token addresses to be dispersed

mint

function mint(address who) external

Please refer to full documentation at IERC721-_mint.

_Arguments_

Name

Type

Description

who

address

receiver of NFT

event Collateralized

event Collateralized is triggered every time a collateral transaction occurs on-chain.

_Arguments_

Name

Type

Description

tokenId

uint256

unique token identifier

amount

uint256

amount to be added to the collateral

tokenAddress

address

address of an EC20 token to be added to the collateral

event Uncollateralized

event Uncollateralized is triggered every time an uncollateral transaction occurs on-chain.

_Arguments_

Name

Type

Description

tokenId

uint256

unique token identifier

amount

uint256

amount to be redeemed from the collateral

tokenAddress

address

address of an ERC20 token to be redeemed from the collateral

event Dispersed

event Dispersed is triggered every time a disperse transaction occurs on-chain.

_Arguments_

Name

Type

Description

tokenAddress

address

amount to be dispersed

amount

uint256

address of an ERC20 token to be dispersed

event Harvested

event Harvested is triggered every time a harvest transaction occurs on-chain.

_Arguments_

Name

Type

Description

tokenAddress

address

amount to be harvested

amount

uint256

address of an ERC20 token to be harvested

scaledAmount

uint256

amount of communityToken spent

ERC721Envious

_arrayContains

function _arrayContains(address tokenAddress, address[] memory findFrom) private pure returns (bool shouldAppend, uint256 index)

_arrayContains function checks whether an element exists in the array. If the element is found, the function returns the index of the element. Otherwise, it sets the variable shouldAppend to true.

_arrayContains function returns a tuple of values. The first value indicates whether the element should be added to the array (true if the element is not found in the array, false otherwise). The second value indicates the index of the element in the array if it exists.

_Arguments_

Name

Type

Description

tokenAddress

address

address of an ERC20 token to be added to the collateral

findFrom

address[]

array of available tokenAddresses

_arrayContains

function _arrayContains(uint256 noteId, uint256[] memory findFrom) private pure returns (uint256 index)

_arrayContains function checks whether a noteId exists in the bond index array.

_arrayContains function returns the index of the bond based on the noteId.

_Arguments_

Name

Type

Description

noteId

uint256

unique bond note identifier

_scaledAmount

function _scaledAmount(address tokenAddress) private view returns (uint256)

_scaledAmount function adjusts the decimal alignment of tokens collected in communityBalance to match the decimal places of a communityToken.

_Arguments_

Name

Type

Description

tokenAddress

address

address of an ERC20 token to be harvested

_harvest

function _harvest(uint256 amount, address tokenAddress) private

_harvest function is an internal function for function harvest.

_Arguments_

Name

Type

Description

amount

uint256

amount to an ERC20 token to be harvested

tokenAddress

address

address of an ERC20 token to be harvested

_addTokenCollateral

function _addTokenCollateral(uint256 tokenId, uint256 amount, address tokenAddress, bool claim) private

_addTokenCollateral function is an internal function for function collateralize.

_Arguments_

Name

Type

Description

tokenId

uint256

unique token identifier

amount

uint256

amount to be added to the collateral

tokenAddress

address

address of an ERC20 token to be added to the collateral

claim

bool

true for bond collateral redemption and false for common collateralization process

_removeTokenCollateral

function _removeTokenCollateral(uint256 tokenId, uint256 amount, address tokenAddress) private

_removeTokenCollateral function is an internal function for function uncollateralize.

_Arguments_

Name

Type

Description

tokenId

uint256

unique token identifier

amount

uint256

amount to be redeemed from the collateral

tokenAddress

address

address of an ERC20 token to be redeemed from the collateral

_disperseTokenCollateral

function _disperseTokenCollateral(uint256 amount, address tokenAddress) private

_disperseTokenCollateral function is an internal function for function disperse.

_Arguments_

Name

Type

Description

amount

uint256

amount to an ERC20 token to be dispersed

tokenAddress

address

address of an ERC20 token to be dispersed

_checkValidity

function _checkValidity(address tokenAddress) private view

_checkValidity function determines whether a given address represents a valid ERC20 token by invoking the decimals function.

_Arguments_

Name

Type

Description

tokenAddress

address

address of any ERC20 token

_communityCommission

function _communityCommission(uint256 amount, uint256 percentage, address tokenAddress) private returns (uint256)

_communityCommission computes the amount remaining after deducting the commission.

_communityCommission function returns amount after commission based on the amount before commission, commission percentage charged, and tokenAddress.

_Arguments_

Name

Type

Description

amount

uint256

amount before commission is charged

percentage

uint256

commission fee rate

tokenAddress

address

address of an ERC20 token

_disperse

function _disperse(address collection, address tokenAddress, uint256 tokenId) private

_disperse function enables input of a dispersion value, which is then used to increase the collateralBalances of a particular tokenAddress for the corresponding tokenId.

Hint

_disperse function is required to be implemented by the collection creator.

_Arguments_

Name

Type

Description

collection

address

NFT collection address

tokenAddress

address

address of an ERC20 token to be dispersed

tokenId

uint256

unique token identifier

_changeCommunityAddresses

function _changeCommunityAddresses(address newTokenAddress, address newBlackHole) internal virtual

_changeCommunityAddresses function enables to change the address of the communityToken and the blackHole.

_Arguments_

Name

Type

Description

newTokenAddress

address

new address of an ERC20 communityToken

newBlackHole

address

new address of a blackHole

_changeGhostAddresses

function _changeGhostAddresses(address newGhostTokenAddress, address newGhostBondingAddress) internal virtual

_changeGhostAddresses function enables to change the address of the ghostAddress and the ghostBondingAddress.

_Arguments_

Name

Type

Description

newGhostTokenAddress

address

new address of a ghostAddress

newGhostBondingAddress

address

new address of a ghostBondingAddress

EnviousHouse Contract

Description

EnviousHouse smart contract serves as a middleware between standard ERC721 and ERC721Envious NFT collections.

By integrating EnviousHouse, standard ERC721 collections can become Envious without needing to redeploy their smart contracts. EnviousHouse mirrors the ERC721Envious standard and serves as storage for tokens and native coins. On the other hand, ERC721Envious collections already have all the necessary Envious functionality, and EnviousHouse simply routes the calls.

Hint

Any user has the ability to rescue unregistered collections by either adding collateral (collateralize) to an individual NFT or executing a disperse on the entire collection. Rescued collections have their commission fees set to 0 by default.

Warning

Commissions and communityToken cannot be modified after the standard ERC721 collection has been registered at EnviousHouse.

The GHOST team believes in the principles of decentralization and web3, and therefore, we do not grant or maintain any admin rights over the current contract. The first user to register a collection will have an opportunity to irreversibly set the communityToken.

The GHOST team strongly encourages all users to act in good faith and share communityToken and/or harvested commissions with the collection creators and community.

Hint

The first user to register a collection will have the ability to set the rate for commissions and communityToken. To prevent spam registrations, the registrant is required to make an initial contribution of the minimum dispersion in the native coin to all NFT holders. The minimum required disperse amount was set to approximately $69.00 on all networks at the time of deployment.

IEnviousHouse

totalCollections

function totalCollections() external view returns (uint256)

totalCollections represents the total number of registered collections.

totalCollections function returns the total count of registered collections.

ghostAddress

function ghostAddress(address collection) external view returns (address)

ghostAddress function returns the token address for bond payouts. Following the launch of ghostDAO, ghostAddress will be set to the tokenAddress of the GHST token.

_Arguments_

Name

Type

Description

collection

address

NFT collection address

ghostBondingAddress

function ghostBondingAddress(address collection) external view returns (address)

ghostBondingAddress function returns the smart contract address that facilitates the purchase of bonds using the DeFi 2.0 protocol. Following the launch of ghostDAO, ghostBondingAddress will be set to the bonding smart contract address of ghostDAO.

_Arguments_

Name

Type

Description

collection

address

NFT collection address

blackHole

function blackHole(address collection) external view returns (address)

blackHole is an address that ensures any tokens sent to it cannot be retrieved.

blackHole function returns the address of the blackHole.

_Arguments_

Name

Type

Description

collection

address

NFT collection address

collections

function collections(uint256 index) external view returns (address)

collections is a getter function for registered collection addresses based on the collection index.

collections function returns the collection address based on the collection index input.

_Arguments_

Name

Type

Description

index

uint256

index in array of collections

collectionIds

function collectionIds(address collection) external view returns (uint256)

collectionIds is a getter function for collection index based on the registered collection address.

collectionIds function returns the collection index based on the collection address input.

_Arguments_

Name

Type

Description

collection

address

NFT collection address

specificCollections

function specificCollections(address collection) external view returns (bool)

specificCollections is a getter function for collections that do not follow the ERC721 standard.

specificCollections function returns whether a particular collection follows the ERC721 standard or not.

_Arguments_

Name

Type

Description

collection

address

NFT collection address

commissions

function commissions(address collection, uint256 index) external view returns (uint256)

commissions are defined by an array with two elements as input, each representing a commission percentage charged on collateral. The first element denotes the commission charged for collateralization, while the second element represents the commission for uncollateralization. It is important to note that a 3 decimal buffer should be added to each commission rate. For example, 1% would be represented as 1000.

commissions function returns the value of the respective commission fee.

_Arguments_

Name

Type

Description

collection

address

NFT collection address

index

uint256

index of value in array

communityToken

function communityToken(address collection) external view returns (address)

communityToken is an ERC20 token set by the collection registrant. communityToken can be exchanged to harvest accumulated commissions.

communityToken function returns the address of the communityToken.

_Arguments_

Name

Type

Description

collection

address

NFT collection address

communityPool

function communityPool(address collection, uint256 index) external view returns (address)

communityPool is an array of ERC20 tokens that can be harvested by communityToken holders.

communityPool function returns the address of a specific ERC20 token available for harvesting by communityToken holders.

_Arguments_

Name

Type

Description

collection

address

NFT collection address

index

uint256

index of value in array

communityBalance

function communityBalance(address collection, address tokenAddress) external view returns (uint256)

communityBalance is the amount of ERC20 token available for harvesting.

communityBalance function returns the total balance of a specified ERC20 token that has been accumulated from collected commissions and is currently available for harvesting.

_Arguments_

Name

Type

Description

collection

address

NFT collection address

tokenAddress

address

address of a token available for harvesting

disperseTokens

function disperseTokens(address collection, uint256 index) external view returns (address)

disperseTokens is an array of ERC20 tokens that have already been dispersed.

disperseTokens function returns the address of a specific ERC20 token that has been dispersed.

_Arguments_

Name

Type

Description

collection

address

NFT collection address

index

uint256

index of value in array

disperseBalance

function disperseBalance(address collection, address tokenAddress) external view returns (uint256)

disperseBalance is the total amount of ERC20 tokens that have been distributed to all tokenIds within a particular NFT collection.

disperseBalance function returns the total amount of a particular ERC20 token that has been dispersed to all tokenIds within a particular NFT collection.

_Arguments_

Name

Type

Description

collection

address

NFT collection address

tokenAddress

address

address of a dispersed ERC20 token

disperseTotalTaken

function disperseTotalTaken(address collection, address tokenAddress) external view returns (uint256)

disperseTotalTaken is the quantity of ERC20 tokens that has been already claimed from the disperseBalance.

disperseBalance function returns the number of dispersed ERC20 tokens of a specific tokenAddress from the disperseBalance.

_Arguments_

Name

Type

Description

collection

address

NFT collection address

tokenAddress

address

address of token

disperseTaken

function disperseTaken(address collection, uint256 tokenId, address tokenAddress) external view returns (uint256)

disperseTaken is the quantity of ERC20 tokens that has been already claimed from the disperseBalance, specifically in reference to a particular tokenId.

disperseTaken function returns the quantity of a specific ERC20 token that has been distributed from the disperseBalance to a particular tokenId.

_Arguments_

Name

Type

Description

collection

address

NFT collection address

tokenId

uint256

unique token identifier

tokenAddress

address

address of a dispersed ERC20 token

bondPayouts

function bondPayouts(address collection, uint256 bondId) external view returns (uint256)

bondPayouts is an estimated quantity of the ghostAddress token to be obtained from the bond upon completion of the vesting period.

bondPayouts function returns the approximate payout quantity of the ghostAddress token to be obtained from a particular bondId after the vesting period is over.

_Arguments_

Name

Type

Description

collection

address

NFT collection address

bondId

uint256

unique bond identifier

bondIndexes

function bondIndexes(address collection, uint256 tokenId, uint256 index) external view returns (uint256)

bondIndexes is a mapping that associates each tokenId from a particular NFT collection with an array of bonds.

bondIndexes function returns the index of a bond based on collection address, tokenId, and chronological index position.

_Arguments_

Name

Type

Description

collection

address

NFT collection address

tokenId

uint256

unique token identifier

index

uint256

index in array

collateralTokens

function collateralTokens(address collection, uint256 tokenId, uint256 index) external view returns (address)

collateralTokens represents ERC20 tokens used as a collateral for a particular NFT.

collateralTokens function returns the address of an ERC20 token used as a collateral for a particular tokenId, determined by its chronological index position.

_Arguments_

Name

Type

Description

collection

address

NFT collection address

tokenId

uint256

unique token identifier

index

uint256

index in array

collateralBalances

function collateralBalances(address collection, uint256 tokenId, address tokenAddress) external view returns (uint256)

collateralBalances reflects the total quantity of ERC20 tokens that are currently being held as collateral for a particular tokenId.

collateralBalances function returns the quantity of ERC20 tokens held as collateral for a specific tokenId, based on the provided tokenAddress.

_Arguments_

Name

Type

Description

collection

address

NFT collection address

tokenId

uint256

unique token identifier

tokenAddress

address

address of an ERC20 token being held as collateral

getAmount

function getAmount(address collection, uint256 amount, address tokenAddress) external view returns (uint256)

getAmount is a calculator for estimating the harvesting amount.

getAmount function returns the harvesting amount for a specific ERC20 token based on the amount of communityToken to be exchanged.

_Arguments_

Name

Type

Description

collection

address

NFT collection address

amount

uint256

amount of communityToken

tokenAddress

address

address of an ERC20 harvested token

setGhostAddresses

function setGhostAddresses(address ghostToken, address ghostBonding) external

setGhostAddress function enables the feature of bonding, representing the ability to add discounted collateral.

_Arguments_

Name

Type

Description

ghostToken

address

address of a non-rebasing bonding token

ghostBonding

address

address of a bonding smart contract

setSpecificCollection

function setSpecificCollection(address collection) external

setSpecificCollection function enables the addition of any collection that is not compatible with the ERC721 standard to the list of exceptions.

_Arguments_

Name

Type

Description

collection

address

NFT collection address

registerCollection

function registerCollection(address collection, address token, uint256 incoming, uint256 outcoming) external payable

registerCollection function grants Envious functionality to any ERC721-compatible collection and streamlines the distribution of an initial minimum disbursement to all NFT holders.

_Arguments_

Name

Type

Description

collection

address

NFT collection address

token

address

address of an ERC20 communityToken

incoming

uint256

collateralization fee, incoming / 1e5 * 100%

outcoming

uint256

uncollateralization fee, incoming / 1e5 * 100%

harvest

function harvest(address collection, uint256[] memory amounts, address[] memory tokenAddresses) external

harvest function collects commission fees in exchange for communityToken.

_Arguments_

Name

Type

Description

collection

address

NFT collection address

amounts

uint256[]

array of amounts to be harvested

tokenAddresses

address[]

array of token addresses to be harvested

collateralize

function collateralize(address collection, uint256 tokenId, uint256[] memory amounts, address[] memory tokenAddresses) external payable

collateralize function facilitates the collateralization of a specific tokenId using a specified amount of a designated ERC20 token.

_Arguments_

Name

Type

Description

collection

address

NFT collection address

tokenId

uint256

unique token identifier

amounts

uint256[]

array of amounts to be added to the collateral

tokenAddresses

address[]

array of token addresses to be added to the collateral

uncollateralize

function uncollateralize(address collection, uint256 tokenId, uint256[] memory amounts, address[] memory tokenAddresses) external

uncollateralize function facilitates the redemption of a specific tokenId using a specified amount of a designated ERC20 token.

Hint

Only the owner of the tokenId is able to trigger the uncollateralize function.

_Arguments_

Name

Type

Description

collection

address

NFT collection address

tokenId

uint256

unique token identifier

amounts

uint256[]

array of amounts to be redeemed from the collateral

tokenAddresses

address[]

array of token addresses to be redeemed from the collateral

getDiscountedCollateral

function getDiscountedCollateral(address collection, uint256 bondId, address quoteToken, uint256 tokenId, uint256 amount, uint256 maxPrice) external

getDiscountedCollateral function enables NFT collateralization with a discount determined by the available bonds. The smart contract acts as the temporary owner of the bond during the bond vesting period.

_Arguments_

Name

Type

Description

collection

address

NFT collection address

bondId

uint256

unique bond identifier

quoteToken

address

address of the token that is accepted as a payment for a bond

tokenId

uint256

unique token identifier

amount

uint256

quantity of the quoteToken paid for the bond

maxPrice

uint256

maximum price allowed to pay for the bond

claimDiscountedCollateral

function claimDiscountedCollateral(address collection, uint256 tokenId, uint256[] memory indexes) external

claimDiscountedCollateral function allows for the redemption of the corresponding bond notes for ghostAddress collateral after the bond vesting period has elapsed.

_Arguments_

Name

Type

Description

collection

address

NFT collection address

tokenId

uint256

unique token identifier

indexes

uint256[]

array of note indexes to redeem

disperse

function disperse(address collection, uint256[] memory amounts, address[] memory tokenAddresses) external payable

disperse function logs the amounts of tokenAddresses into disperseBalance.

_Arguments_

Name

Type

Description

collection

address

NFT collection address

amounts

uint256[]

array of amounts to be dispersed

tokenAddresses

address[]

array of token addresses to be dispersed

event Collateralized

event Collateralized is triggered every time a collateral transaction occurs on-chain.

_Arguments_

Name

Type

Description

collection

address

NFT collection address

tokenId

uint256

unique token identifier

amount

uint256

amount to be added to the collateral

tokenAddress

address

address of an ERC20 token to be added to the collateral

event Uncollateralized

event Uncollateralized is triggered every time an uncollateral transaction occurs on-chain.

_Arguments_

Name

Type

Description

collection

address

NFT collection address

tokenId

uint256

unique token identifier

amount

uint256

amount to be redeemed from the collateral

tokenAddress

address

address of an ERC20 token to be redeemed from the collateral

event Dispersed

event Dispersed is triggered every time a disperse transaction occurs on-chain.

_Arguments_

Name

Type

Description

collection

address

NFT collection address

amount

uint256

amount to be dispersed

tokenAddress

address

address of an ERC20 token to be dispersed

event Harvested

event Harvested is triggered every time a harvest transaction occurs on-chain.

_Arguments_

Name

Type

Description

collection

address

NFT collection address

tokenAddress

address

address of an ERC20 token to be harvested

amount

uint256

amount to be harvested

scaledAmount

uint256

amount of communityToken exchanged for commission fees

EnviousHouse

_arrayContains

function _arrayContains(address tokenAddress, address[] memory findFrom) private pure returns (bool shouldAppend, uint256 index)

_arrayContains function checks whether an element exists in the array. If the element is found, the function returns the index of the element. Otherwise, it sets the variable shouldAppend to true.

_arrayContains function returns a tuple of values. The first value indicates whether the element should be added to the array (true if the element is not found in the array, false otherwise). The second value indicates the index of the element in the array if it exists.

_Arguments_

Name

Type

Description

tokenAddress

address

address of an ERC20 token to be added to the collateral

findFrom

address[]

array of available tokenAddresses

_arrayContains

function _arrayContains(uint256 noteId, uint256[] memory findFrom) private pure returns (uint256 index)

_arrayContains function checks whether a noteId exists in the bond index array.

_arrayContains function returns the index of the bond based on the noteId.

_Arguments_

Name

Type

Description

noteId

uint256

unique bond note identifier

_scaledAmount

function _scaledAmount(address collection, address tokenAddress) private view returns (uint256)

_scaledAmount function adjusts the decimal alignment of tokens collected in communityBalance to match the decimal places of a communityToken.

_Arguments_

Name

Type

Description

collection

address

NFT collection address

tokenAddress

address

address of an ERC20 token to be harvested

_harvest

function _harvest(address collection, uint256 amount, address tokenAddress) private

_harvest function is an internal function for function harvest.

_Arguments_

Name

Type

Description

collection

address

NFT collection address

amount

uint256

amount to an ERC20 token to be harvested

tokenAddress

address

address of an ERC20 token to be harvested

_addTokenCollateral

function _addTokenCollateral(address collection, uint256 tokenId, uint256 amount, address tokenAddress, bool claim) private

_addTokenCollateral function is an internal function for function collateralize.

_Arguments_

Name

Type

Description

collection

address

NFT collection address

tokenId

uint256

unique token identifier

amount

uint256

amount to be added to the collateral

tokenAddress

address

address of an ERC20 token to be added to the collateral

claim

bool

true for bond collateral redemption and false for common collateralization process

_removeTokenCollateral

function _removeTokenCollateral(address collection, uint256 tokenId, uint256 amount, address tokenAddress) private

_removeTokenCollateral function is an internal function for function uncollateralize.

_Arguments_

Name

Type

Description

collection

address

NFT collection address

tokenId

uint256

unique token identifier

amount

uint256

amount to be redeemed from the collateral

tokenAddress

address

address of an ERC20 token to be redeemed from the collateral

_disperseTokenCollateral

function _disperseTokenCollateral(address collection, uint256 amount, address tokenAddress) private

_disperseTokenCollateral function is an internal function for function disperse.

_Arguments_

Name

Type

Description

collection

address

NFT collection address

amount

uint256

amount to an ERC20 token to be dispersed

tokenAddress

address

address of an ERC20 token to be dispersed

_checkValidity

function _checkValidity(address tokenAddress) private view

_checkValidity function determines whether a given address represents a valid ERC20 token by invoking the decimals function.

_Arguments_

Name

Type

Description

tokenAddress

address

address of any ERC20 token

_communityCommission

function _communityCommission(address collection, uint256 amount, uint256 percentage, address tokenAddress) private returns (uint256)

_communityCommission computes the amount remaining after deducting the commission.

_communityCommission function returns amount after commission based on the amount before commission, commission percentage charged, and tokenAddress.

_Arguments_

Name

Type

Description

collection

address

NFT collection address

amount

uint256

amount before commission is charged

percentage

uint256

commission fee rate

tokenAddress

address

address of an ERC20 token

_disperse

function _disperse(address collection, address tokenAddress, uint256 tokenId) private

_disperse function enables input of a dispersion value, which is then used to increase the collateralBalances of a particular tokenAddress for the corresponding tokenId.

_Arguments_

Name

Type

Description

collection

address

NFT collection address

tokenAddress

address

address of an ERC20 token to be dispersed

tokenId

uint256

unique token identifier

_rescueCollection

function _rescueCollection(address collection) private

_rescueCollection function sets the commissions to 0% permanently after an individual NFT from an unregistered collection is collateralized.

_Arguments_

Name

Type

Description

collection

address

NFT collection address

_checkEnvious

function _checkEnvious(address collection) private view

_checkEnvious function determines whether a particular address supports IERC721Envious functionality.

_Arguments_

Name

Type

Description

collection

address

NFT collection address

Gas Report

The complete test results can be found in the ./gas reporter/EnviousHouse.txt file. The actual tests are available in the ./tests/EnviousHouse.test.js file.

·-----------------------------------------------------|---------------------------|--------------|----------------------------·
|         Solc version: 0.8.4+commit.c7e474f2         ·  Optimizer enabled: true  ·  Runs: 1337  ·  Block limit: 6718946 gas  │
······················································|···························|··············|·····························
|  Methods                                                                                                                    │
························|·····························|·············|·············|··············|··············|··············
|  Contract             ·  Method                     ·  Min        ·  Max        ·  Avg         ·  # calls     ·  eur (avg)  │
························|·····························|·············|·············|··············|··············|··············
|  BaseToken            ·  approve                    ·      46220  ·      46244  ·       46232  ·         127  ·          -  │
························|·····························|·············|·············|··············|··············|··············
|  BaseToken            ·  mint                       ·          -  ·          -  ·       68285  ·          72  ·          -  │
························|·····························|·············|·············|··············|··············|··············
|  EnviousHouse         ·  claimDiscountedCollateral  ·          -  ·          -  ·      180886  ·           2  ·          -  │
························|·····························|·············|·············|··············|··············|··············
|  EnviousHouse         ·  collateralize              ·     157311  ·     328704  ·      189772  ·          42  ·          -  │
························|·····························|·············|·············|··············|··············|··············
|  EnviousHouse         ·  disperse                   ·      42280  ·     131304  ·      108063  ·          10  ·          -  │
························|·····························|·············|·············|··············|··············|··············
|  EnviousHouse         ·  getDiscountedCollateral    ·     206118  ·     206130  ·      206128  ·           6  ·          -  │
························|·····························|·············|·············|··············|··············|··············
|  EnviousHouse         ·  harvest                    ·     115467  ·     134801  ·      122870  ·           8  ·          -  │
························|·····························|·············|·············|··············|··············|··············
|  EnviousHouse         ·  registerCollection         ·      80192  ·     213650  ·      128844  ·         116  ·          -  │
························|·····························|·············|·············|··············|··············|··············
|  EnviousHouse         ·  setGhostAddresses          ·      68807  ·      68819  ·       68818  ·          11  ·          -  │
························|·····························|·············|·············|··············|··············|··············
|  EnviousHouse         ·  uncollateralize            ·     153272  ·     269507  ·      188441  ·           8  ·          -  │
························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousPreset  ·  claimDiscountedCollateral  ·          -  ·          -  ·      171087  ·           1  ·          -  │
························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousPreset  ·  collateralize              ·     144540  ·     149340  ·      145189  ·          15  ·          -  │
························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousPreset  ·  disperse                   ·          -  ·          -  ·      130087  ·           2  ·          -  │
························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousPreset  ·  getDiscountedCollateral    ·     183430  ·     201799  ·      189558  ·           6  ·          -  │
························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousPreset  ·  mint                       ·          -  ·          -  ·      167530  ·          59  ·          -  │
························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousPreset  ·  setGhostAddresses          ·      69177  ·      69189  ·       69188  ·          12  ·          -  │
························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousPreset  ·  uncollateralize            ·          -  ·          -  ·       76840  ·           2  ·          -  │
························|·····························|·············|·············|··············|··············|··············
|  ERC721Mock           ·  mint                       ·          -  ·          -  ·       91012  ·          66  ·          -  │
························|·····························|·············|·············|··············|··············|··············
|  Deployments                                        ·                                          ·  % of limit  ·             │
······················································|·············|·············|··············|··············|··············
|  BaseToken                                          ·     775391  ·     775451  ·      775414  ·      11.5 %  ·          -  │
······················································|·············|·············|··············|··············|··············
|  BlackHole                                          ·     321380  ·     321452  ·      321416  ·       4.8 %  ·          -  │
······················································|·············|·············|··············|··············|··············
|  BondingMock                                        ·    1114846  ·    1114870  ·     1114868  ·      16.6 %  ·          -  │
······················································|·············|·············|··············|··············|··············
|  EnviousHouse                                       ·    4266540  ·    4266552  ·     4266551  ·      63.5 %  ·          -  │
······················································|·············|·············|··············|··············|··············
|  ERC721EnviousPreset                                ·          -  ·          -  ·     5433128  ·      80.9 %  ·          -  │
······················································|·············|·············|··············|··············|··············
|  ERC721Mock                                         ·    1477822  ·    1477834  ·     1477827  ·        22 %  ·          -  │
·-----------------------------------------------------|-------------|-------------|--------------|--------------|-------------·

BlackHole Contract

Description

Since some ERC20 tokens forbid transfers to the zero address and/or lack implementation of the burn functionality, it is necessary to have a reliable burning mechanism in the harvest transactions. blackHole smart contract removes ERC20 communityTokens from the circulating supply in exchange for commission fees withdrawn.

blackHole has been designed to prevent the transfer of any tokens from itself and can only perform read operations. It is intended to be used with the ERC721Envious extension in implementations related to commission harvesting.

IBlackHole

function whoAmI

function whoAmI() external view returns (string memory)

whoAmI function returns the name of the BlackHole instance. For instance, the function could be set to return the name IC 1011, which would serve as a unique identifier for the blackHole instance.

absorbedBalance

function absorbedBalance(address token) external view returns (uint256)

absorbedBalance function returns the balance of an ERC20 token that was harvested and subsequently forwarded to the blackHole smart contract.

_Arguments_

Name

Type

Description

token

address

address of an ERC20 token

availableSupply

function availableSupply(address token) external view returns (uint256)

availableSupply function returns the remaining balance of an ERC20 token that has not yet been harvested and is still considered as part of the actual circulating supply.

_Arguments_

Name

Type

Description

token

address

address of an ERC20 token

Gas Report

The complete test results can be found in the ./gas reporter/BlackHole.txt file. The actual tests are available in the ./tests/BlackHole.test.js file.

·---------------------------------------|---------------------------|--------------|----------------------------·
|  Solc version: 0.8.4+commit.c7e474f2  ·  Optimizer enabled: true  ·  Runs: 1337  ·  Block limit: 6718946 gas  │
········································|···························|··············|·····························
|  Methods                                                                                                      │
·····················|··················|·············|·············|··············|··············|··············
|  Contract          ·  Method          ·  Min        ·  Max        ·  Avg         ·  # calls     ·  eur (avg)  │
·····················|··················|·············|·············|··············|··············|··············
|  BaseToken         ·  mint            ·          -  ·          -  ·       68285  ·           8  ·          -  │
·····················|··················|·············|·············|··············|··············|··············
|  BaseToken         ·  transfer        ·          -  ·          -  ·       51396  ·           3  ·          -  │
·····················|··················|·············|·············|··············|··············|··············
|  Deployments                          ·                                          ·  % of limit  ·             │
········································|·············|·············|··············|··············|··············
|  BaseToken                            ·          -  ·          -  ·      775367  ·      11.5 %  ·          -  │
········································|·············|·············|··············|··············|··············
|  BlackHole                            ·          -  ·          -  ·      321380  ·       4.8 %  ·          -  │
·---------------------------------------|-------------|-------------|--------------|--------------|-------------·

Basic Envious Preset

Description

This preset provides a basic implementation of ERC721Envious with the added functionality of utilizing IBondDepository and INoteKeeper. The ERC721Enumerable extension is used in this example, so the _disperse function is based on the totalSupply of this extension. Although the current smart contract will implement five extensions, its resulting size is approximately 23.59 KiB as determined by 1337 optimization runs.

Hint

During the development process, Debian and truffle were utilized.

ERC721EnviousPreset

ERC721EnviousPreset is a combination of AccessControlEnumerable, ERC721Burnable, ERC721Pausable, ERC721Enumerable, ERC721Envious.

Implemented roles:

  • Minter_Role allows for token minting

  • Pauser_Role grants permissions to pauseNFT transfers

  • Ghosty_Role is capable of modifying modify Envious-specific variables

Hint

By default, the smart contract deployer will be assigned the Minter_Role, Pauser_Role, and Ghosty_Role.

receive

receive() external payable

receive function routes incoming transfers of the native coin towards dispersing the value of msg.value.

baseURI

function baseURI() external view virtual returns (string memory)

baseURI is a getter function for the baseURI.

baseURI function returns baseURI for the entire collection.

tokenURI

function tokenURI(uint256 tokenId) public view virtual override returns (string memory)

tokenURI is a getter function for a particular tokenURI.

tokenURI function returns tokenURI for a specific NFT.

_Arguments_

Name

Type

Description

tokenId

uint256

unique token identifier

mint

function mint(address to) public virtual override

mint function generates a new token. mint function can be triggered by the account with Minter_Role only.

_Arguments_

Name

Type

Description

to

address

receiver of new NFT

pause

function pause() external virtual

pause function halts all transfers of NFTs in the collection. pause function can be activated by the account with the Pauser_Role only.

unpause

function unpause() external virtual

unpause function resumes all NFT transfers in the collection. unpause function can be triggered by the account with the Pauser_Role only.

setGhostAddresses

function setGhostAddresses(address ghostToken, address ghostBonding) public virtual

setGhostAddresses function modifies the underlying ghost-related addresses. setGhostAddresses function can be triggered by the account with the Ghosty_Role only.

_Arguments_

Name

Type

Description

ghostToken

address

address of a non-rebasing bonding token

ghostBonding

address

address of a bonding smart contract

Gas Report

The complete test results can be found in the ./gas reporter/ERC721EnviouspPreset.txt file. The actual tests are available in the ./tests/ERC721EnviousPreset.test.js file.

·-----------------------------------------------------|---------------------------|--------------|----------------------------·
|         Solc version: 0.8.4+commit.c7e474f2         ·  Optimizer enabled: true  ·  Runs: 1337  ·  Block limit: 6718946 gas  │
······················································|···························|··············|·····························
|  Methods                                                                                                                    │
························|·····························|·············|·············|··············|··············|··············
|  Contract             ·  Method                     ·  Min        ·  Max        ·  Avg         ·  # calls     ·  eur (avg)  │
························|·····························|·············|·············|··············|··············|··············
|  BadToken             ·  approve                    ·      46201  ·      46213  ·       46211  ·          12  ·          -  │
························|·····························|·············|·············|··············|··············|··············
|  BadToken             ·  mint                       ·          -  ·          -  ·       70691  ·           6  ·          -  │
························|·····························|·············|·············|··············|··············|··············
|  BaseToken            ·  approve                    ·      29180  ·      46244  ·       46079  ·         104  ·          -  │
························|·····························|·············|·············|··············|··············|··············
|  BaseToken            ·  burn                       ·          -  ·          -  ·       26889  ·           1  ·          -  │
························|·····························|·············|·············|··············|··············|··············
|  BaseToken            ·  mint                       ·      51185  ·      68321  ·       67972  ·         109  ·          -  │
························|·····························|·············|·············|··············|··············|··············
|  BaseToken            ·  transfer                   ·          -  ·          -  ·       46608  ·           1  ·          -  │
························|·····························|·············|·············|··············|··············|··············
|  DAI                  ·  approve                    ·      29149  ·      46213  ·       45965  ·          69  ·          -  │
························|·····························|·············|·············|··············|··············|··············
|  DAI                  ·  burn                       ·          -  ·          -  ·       27704  ·           1  ·          -  │
························|·····························|·············|·············|··············|··············|··············
|  DAI                  ·  mint                       ·      70713  ·      70749  ·       70714  ·          69  ·          -  │
························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousPreset  ·  approve                    ·      26628  ·      51081  ·       44728  ·         216  ·          -  │
························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousPreset  ·  burn                       ·      48532  ·      66848  ·       62738  ·          21  ·          -  │
························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousPreset  ·  changeCommissions          ·      28680  ·      68480  ·       47782  ·         748  ·          -  │
························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousPreset  ·  changeCommunityAddresses   ·      29310  ·      69134  ·       49192  ·         720  ·          -  │
························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousPreset  ·  claimDiscountedCollateral  ·      55765  ·     244786  ·      209562  ·          14  ·          -  │
························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousPreset  ·  collateralize              ·      74616  ·     682712  ·      193841  ·         101  ·          -  │
························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousPreset  ·  disperse                   ·      72718  ·     403232  ·      150497  ·          27  ·          -  │
························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousPreset  ·  getDiscountedCollateral    ·     158329  ·     206611  ·      187426  ·          23  ·          -  │
························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousPreset  ·  grantRole                  ·      31608  ·     101218  ·       90625  ·          46  ·          -  │
························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousPreset  ·  harvest                    ·      81301  ·     312987  ·      132263  ·          14  ·          -  │
························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousPreset  ·  mint                       ·     155730  ·     167530  ·      162693  ·         571  ·          -  │
························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousPreset  ·  pause                      ·          -  ·          -  ·       47048  ·          20  ·          -  │
························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousPreset  ·  renounceRole               ·      27123  ·      36464  ·       32906  ·          21  ·          -  │
························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousPreset  ·  revokeRole                 ·      31643  ·      48470  ·       39263  ·          21  ·          -  │
························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousPreset  ·  safeTransferFrom           ·      33631  ·     103781  ·       86934  ·         104  ·          -  │
························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousPreset  ·  safeTransferFrom           ·      34307  ·     104899  ·       87796  ·         104  ·          -  │
························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousPreset  ·  setApprovalForAll          ·      26408  ·      46320  ·       45372  ·         189  ·          -  │
························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousPreset  ·  setGhostAddresses          ·      69177  ·      69189  ·       69188  ·          24  ·          -  │
························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousPreset  ·  transferFrom               ·      33274  ·      96376  ·       82939  ·          56  ·          -  │
························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousPreset  ·  uncollateralize            ·      61761  ·     298701  ·      111653  ·          42  ·          -  │
························|·····························|·············|·············|··············|··············|··············
|  RebaseToken          ·  approve                    ·      29135  ·      46235  ·       45986  ·          69  ·          -  │
························|·····························|·············|·············|··············|··············|··············
|  RebaseToken          ·  initialize                 ·      94307  ·      94319  ·       94318  ·          68  ·          -  │
························|·····························|·············|·············|··············|··············|··············
|  RebaseToken          ·  transfer                   ·          -  ·          -  ·       34665  ·           1  ·          -  │
························|·····························|·············|·············|··············|··············|··············
|  StakingMock          ·  fund                       ·          -  ·          -  ·       61607  ·          69  ·          -  │
························|·····························|·············|·············|··············|··············|··············
|  TetherToken          ·  approve                    ·      26344  ·      46244  ·       45955  ·          69  ·          -  │
························|·····························|·············|·············|··············|··············|··············
|  TetherToken          ·  burn                       ·          -  ·          -  ·       26907  ·           1  ·          -  │
························|·····························|·············|·············|··············|··············|··············
|  TetherToken          ·  mint                       ·          -  ·          -  ·       68219  ·          69  ·          -  │
························|·····························|·············|·············|··············|··············|··············
|  Deployments                                        ·                                          ·  % of limit  ·             │
······················································|·············|·············|··············|··············|··············
|  BadToken                                           ·          -  ·          -  ·     1140859  ·        17 %  ·          -  │
······················································|·············|·············|··············|··············|··············
|  BaseToken                                          ·     775391  ·     775475  ·      775423  ·      11.5 %  ·          -  │
······················································|·············|·············|··············|··············|··············
|  BlackHole                                          ·          -  ·          -  ·      321368  ·       4.8 %  ·          -  │
······················································|·············|·············|··············|··············|··············
|  BondingMock                                        ·    1114858  ·    1114870  ·     1114868  ·      16.6 %  ·          -  │
······················································|·············|·············|··············|··············|··············
|  DAI                                                ·          -  ·          -  ·     1148998  ·      17.1 %  ·          -  │
······················································|·············|·············|··············|··············|··············
|  ERC721EnviousPreset                                ·          -  ·          -  ·     5478148  ·      81.5 %  ·          -  │
······················································|·············|·············|··············|··············|··············
|  ERC721ReceiverMock                                 ·     285979  ·     286027  ·      286014  ·       4.3 %  ·          -  │
······················································|·············|·············|··············|··············|··············
|  RebaseToken                                        ·          -  ·          -  ·     1711816  ·      25.5 %  ·          -  │
······················································|·············|·············|··············|··············|··············
|  StakingMock                                        ·     246573  ·     246585  ·      246585  ·       3.7 %  ·          -  │
······················································|·············|·············|··············|··············|··············
|  TetherToken                                        ·          -  ·          -  ·      758083  ·      11.3 %  ·          -  │
·-----------------------------------------------------|-------------|-------------|--------------|--------------|-------------·

Dynamic Envious Preset

Description

In the specification of the ERC721 standard, the tokenId maps to a unique URI using the tokenURI function. This mapping is possible since the tokenURI function is bijective.

In ERC721Envious and EnviousHouse, a new parameter collateral is added to represent the power of the NFT. The tokenURI function is modified to include this new parameter and to update the result of the function on every collateral, uncollateral, and disperse function call. These functions are overridden with additional logic to include the new collateral parameter. This allows for more flexibility and customization in how the NFTs are used and represented.

Hint

Currently, collateral is only measured for the measurementToken, but an upgrade is possible to enable checking of all collateral and achieve a dynamic tokenURI.

The tokenURI function in the template implementation appears as follows:

function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
  _requireMinted(tokenId);

  string memory currentURI = _baseURI();
  return string(abi.encodePacked(currentURI, tokenId.toString()));
}

The results are likely recognizable to most readers and take the form of ipfs://QmeSjSinHpPnmXmspMjwiXyN6zS4E9zccariGR3jxcaWtq/1337 for a specific Bored Ape Yacht Club NFT (in this case, number 1337). This link points to the metadata for the given NFT and consists of two components:

  • Basic URI (in the example, an IPFS hash)

  • tokenId for an existing NFT

To make the collection dynamic, it’s only necessary to update the tokenURI function with the following:

function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
  _requireMinted(tokenId);

  string memory currentURI = _baseURI();
  uint256 tokenPointer = getTokenPointer(tokenId);
  return string(abi.encodePacked(currentURI, tokenPointer.toString()));
}

The tokenPointer refers to the proportional quantity of the measurementToken.

Hint

Although the GHOST team favors appending .json to every tokenURI, any preferred method will suffice.

To implement the getTokenPointer function, it is necessary to define the edges that correspond to specific groups of URIs. The keccak256 hashing function can then be applied to merge different parameters into one, resulting in the final tokenPointer. An example of the getTokenPointer function is provided below:

function getTokenPointer(uint256 tokenId) public view virtual override returns (uint256) {
  uint256 collateral = collateralBalances[tokenId][measurmentTokenAddress];
  uint256 totalDisperse = disperseBalance[measurmentTokenAddress] / totalSupply();
  uint256     takenDisperse = disperseTaken[tokenId][measurmentTokenAddress];
  uint256 value = collateral + totalDisperse - takenDisperse;

  uint256 range = 1;
  uint256 offset = 0;

  for (uint256 i = edges.length; i > 0; i--) {
    if (value >= edges[i-1].value) {
      range = edges[i-1].range;
      offset = edges[i-1].offset;
      break;
    }
  }

  uint256 seed = uint256(keccak256(abi.encodePacked(tokenId, collateral, totalDisperse))) % range;
  return seed + offset;
}

The initial step is to obtain the amount of full collateral in the measurementToken for a specific tokenId. Subsequently, the iteration through predetermined edges takes place to determine the level at which the collateral amount falls into. Finally, the keccak256 is applied to retrieve a specific value within a predefined range.

John McAfee Legacy (JML) NFT Collection is the first implementation of the ERC721EnviousDynamic preset.

IERC721EnviousDynamic

struct Edge

struct Edge stores the required data for enabling dynamic behavior in the collection, which can be compared to levels in gaming.

_Arguments_

Name

Type

Description

value

uint256

minimal measurementToken collateral in edge

offset

uint256

minimum tokenId in edge

range

uint256

maximum tokenId range between the edges

getTokenPointer

function getTokenPointer(uint256 tokenId) external view returns (uint256)

getTokenPointer serves as a tokenURI getter for a specific tokenId, with the edge being determined by the collateral.

getTokenPointer function returns a pseudo pointer to the metadata.

_Arguments_

Name

Type

Description

tokenId

uint256

unique token identifier

ERC721EnviousDynamic

baseURI

function baseURI() external view virtual returns (string memory)

baseURI is a getter function for the baseURI, typically represented by an IPFS hash.

baseURI function returns the prefix for the URI with metadata.

setGhostAddresses

function setGhostAddresses(address ghostToken, address ghostBonding) public virtual

setGhostAddresses function modifies the underlying ghost-related addresses.

_Arguments_

Name

Type

Description

ghostToken

address

address of a non-rebasing bonding token

ghostBonding

address

address of a bonding smart contract

changeCommunityAddresses

function changeCommunityAddresses(address newTokenAddress, address newBlackHole) public virtual

changeCommunityAddresses function enables to change the address of the communityToken and the blackHole.

_Arguments_

Name

Type

Description

newTokenAddress

address

new address of an ERC20 communityToken

newBlackHole

address

new address of a blackHole

_changeBaseURI

function _changeBaseURI(string memory newBaseURI) internal virtual

_changeBaseURI function enables to change baseURI.

_Arguments_

Name

Type

Description

newBaseURI

string

new link prefix

Gas Report

The complete test results can be found in the ./gas reporter/ERC721EnviousDynamicPreset.txt file. The actual tests are available in the ./tests/ERC721EnviousDynamicPreset.test.js file.

·------------------------------------------------------------|---------------------------|--------------|----------------------------·
|            Solc version: 0.8.4+commit.c7e474f2             ·  Optimizer enabled: true  ·  Runs: 1337  ·  Block limit: 6718946 gas  │
·····························································|···························|··············|·····························
|  Methods                                                                                                                           │
·······························|·····························|·············|·············|··············|··············|··············
|  Contract                    ·  Method                     ·  Min        ·  Max        ·  Avg         ·  # calls     ·  eur (avg)  │
·······························|·····························|·············|·············|··············|··············|··············
|  BadToken                    ·  approve                    ·          -  ·          -  ·       46213  ·          12  ·          -  │
·······························|·····························|·············|·············|··············|··············|··············
|  BadToken                    ·  mint                       ·          -  ·          -  ·       70691  ·           6  ·          -  │
·······························|·····························|·············|·············|··············|··············|··············
|  BaseToken                   ·  approve                    ·      46220  ·      46244  ·       46241  ·         109  ·          -  │
·······························|·····························|·············|·············|··············|··············|··············
|  BaseToken                   ·  mint                       ·      51185  ·      68285  ·       67982  ·         114  ·          -  │
·······························|·····························|·············|·············|··············|··············|··············
|  BaseToken                   ·  transfer                   ·          -  ·          -  ·       46608  ·           1  ·          -  │
·······························|·····························|·············|·············|··············|··············|··············
|  DAI                         ·  approve                    ·      46201  ·      46213  ·       46212  ·          59  ·          -  │
·······························|·····························|·············|·············|··············|··············|··············
|  DAI                         ·  mint                       ·          -  ·          -  ·       70713  ·          59  ·          -  │
·······························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousDynamicPreset  ·  approve                    ·      26672  ·      51125  ·       44754  ·         215  ·          -  │
·······························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousDynamicPreset  ·  burn                       ·      46412  ·      62487  ·       59571  ·          15  ·          -  │
·······························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousDynamicPreset  ·  changeCommunityAddresses   ·          -  ·          -  ·       66687  ·           2  ·          -  │
·······························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousDynamicPreset  ·  claimDiscountedCollateral  ·      55765  ·     182596  ·      156257  ·          14  ·          -  │
·······························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousDynamicPreset  ·  collateralize              ·      69447  ·     466833  ·      137521  ·         105  ·          -  │
·······························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousDynamicPreset  ·  disperse                   ·      72718  ·     403232  ·      148481  ·          31  ·          -  │
·······························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousDynamicPreset  ·  getDiscountedCollateral    ·     158312  ·     206589  ·      187408  ·          23  ·          -  │
·······························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousDynamicPreset  ·  mint                       ·     151053  ·     162853  ·      158041  ·         562  ·          -  │
·······························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousDynamicPreset  ·  safeTransferFrom           ·      31313  ·     101463  ·       84615  ·         104  ·          -  │
·······························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousDynamicPreset  ·  safeTransferFrom           ·      32033  ·     102625  ·       85522  ·         104  ·          -  │
·······························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousDynamicPreset  ·  setApprovalForAll          ·      26386  ·      46298  ·       45350  ·         189  ·          -  │
·······························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousDynamicPreset  ·  setGhostAddresses          ·      66774  ·      66786  ·       66784  ·          26  ·          -  │
·······························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousDynamicPreset  ·  transferFrom               ·      30954  ·      94056  ·       80619  ·          56  ·          -  │
·······························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousDynamicPreset  ·  uncollateralize            ·      56897  ·     138116  ·       90793  ·          39  ·          -  │
·······························|·····························|·············|·············|··············|··············|··············
|  RebaseToken                 ·  approve                    ·      46223  ·      46235  ·       46234  ·          59  ·          -  │
·······························|·····························|·············|·············|··············|··············|··············
|  RebaseToken                 ·  initialize                 ·      94307  ·      94319  ·       94317  ·          59  ·          -  │
·······························|·····························|·············|·············|··············|··············|··············
|  StakingMock                 ·  fund                       ·          -  ·          -  ·       61607  ·          59  ·          -  │
·······························|·····························|·············|·············|··············|··············|··············
|  TetherToken                 ·  approve                    ·      46232  ·      46244  ·       46243  ·          59  ·          -  │
·······························|·····························|·············|·············|··············|··············|··············
|  TetherToken                 ·  mint                       ·          -  ·          -  ·       68219  ·          59  ·          -  │
·······························|·····························|·············|·············|··············|··············|··············
|  Deployments                                               ·                                          ·  % of limit  ·             │
·····························································|·············|·············|··············|··············|··············
|  BadToken                                                  ·          -  ·          -  ·     1140859  ·        17 %  ·          -  │
·····························································|·············|·············|··············|··············|··············
|  BaseToken                                                 ·     775391  ·     775475  ·      775422  ·      11.5 %  ·          -  │
·····························································|·············|·············|··············|··············|··············
|  BondingMock                                               ·    1114846  ·    1114870  ·     1114867  ·      16.6 %  ·          -  │
·····························································|·············|·············|··············|··············|··············
|  DAI                                                       ·          -  ·          -  ·     1148998  ·      17.1 %  ·          -  │
·····························································|·············|·············|··············|··············|··············
|  ERC721EnviousDynamicPreset                                ·    4701295  ·    4701307  ·     4701306  ·        70 %  ·          -  │
·····························································|·············|·············|··············|··············|··············
|  ERC721ReceiverMock                                        ·     285979  ·     286027  ·      286014  ·       4.3 %  ·          -  │
·····························································|·············|·············|··············|··············|··············
|  RebaseToken                                               ·          -  ·          -  ·     1711816  ·      25.5 %  ·          -  │
·····························································|·············|·············|··············|··············|··············
|  StakingMock                                               ·     246573  ·     246585  ·      246584  ·       3.7 %  ·          -  │
·····························································|·············|·············|··············|··············|··············
|  TetherToken                                               ·          -  ·          -  ·      758083  ·      11.3 %  ·          -  │
·------------------------------------------------------------|-------------|-------------|--------------|--------------|-------------·

Royalty Envious Preset

Description

The possibility for creators of an ERC721Envious Collection to receive royalty payments on every transaction between different addresses is due to the fact that the tokenId can hold actual collateral in ERC20 tokens and native coin.

Hint

By default, all ERC20 tokens that collateralize an NFT will be included in the royalty payments. However, there is an option to customize the list and include only specific tokens if needed.

Commission fees can be collected during the collateralization and uncollateralization processes, which creates an additional revenue stream for creators that is triggered during transferFrom. It’s worth noting that there are two types of addresses:

  • Externally Owned Accounts (EOA) that are controlled by private keys and are typically used by humans

  • Contract Accounts that represent smart contracts deployed on the EVM network

Hint

It is possible for transfers between different accounts to have varying commission fees, which can be customized by the collection developer.

More detailed information on potential use cases for the Royalty Envious Preset can be found here.

IERC721RoyaltyPreset

royalties

function royalties(uint256 id) external view returns (uint256)

royalties function represents royalties that can be assigned to both user addresses and smart contracts. When a transfer occurs between a user address and another user address or smart contract, the first element of the royalty array will be used. Conversely, when a transfer occurs between two smart contracts, the second element of the array will be used.

royalties function returns royalty percentage with a 3 decimal point buffer, meaning that a value of 1,000 represents a royalty percentage of 1%.

_Arguments_

Name

Type

Description

id

uint256

index position of an element in an array with a length of 2

changeRoyalties

function changeRoyalties(uint256 user, uint256 smart) external

_changeRoyalties function enables to change royalties.

_Arguments_

Name

Type

Description

user

uint256

royalty percentage between EOA addresses

smart

uint256

royalty percentage between smart contracts

ERC721RoyaltyPreset

baseURI

function baseURI() external view virtual returns (string memory)

baseURI is a getter function for the baseURI, typically represented by an IPFS hash.

baseURI function returns the prefix for the URI with metadata.

setGhostAddresses

function setGhostAddresses(address ghostToken, address ghostBonding) public virtual

setGhostAddresses function modifies the underlying ghost-related addresses.

Hint

OpenZeppelin’s Ownable provides the onlyOwner modifier by default.

_Arguments_

Name

Type

Description

ghostToken

address

address of a non-rebasing bonding token

ghostBonding

address

address of a bonding smart contract

changeCommunityAddresses

function changeCommunityAddresses(address newTokenAddress, address newBlackHole) public virtual

changeCommunityAddresses function enables to change the address of the communityToken and the blackHole.

_Arguments_

Name

Type

Description

newTokenAddress

address

new address of an ERC20 communityToken

newBlackHole

address

new address of a blackHole

_changeBaseURI

function _changeBaseURI(string memory newBaseURI) internal virtual

_changeBaseURI function enables to change baseURI.

_Arguments_

Name

Type

Description

newBaseURI

string

new link prefix

changeCommissions

function changeCommissions(uint256 incoming, uint256 outcoming) public virtual

changeCommissions function enables to change the rates of commission fees.

Hint

OpenZeppelin’s Ownable provides onlyOwner as the default availability.

_Arguments_

Name

Type

Description

incoming

uint256

updated collateralization fee

outcoming

uint256

updated uncollateralization fee

changeRoyalties

function changeRoyalties(uint256 user, uint256 smart) public virtual override onlyOwner

changeRoyalties function enables to change royalties.

Hint

OpenZeppelin’s Ownable provides onlyOwner as the default availability.

_Arguments_

Name

Type

Description

user

uint256

royalty percentage between EOA addresses

smart

uint256

royalty percentage between smart contracts

_getRoyaltyFromCollateral

function _getRoyaltyFromCollateral(uint256 tokenId, uint256 royalty) internal virtual

_getRoyaltyFromCollateral function calculates and stores royalty payments.

Warning

The collection owner can withdraw collected royalties only in the same manner as other commissions were collected.

_Arguments_

Name

Type

Description

tokenId

uint256

unique token identifier

royalty

uint256

royalty percentage

Gas Report

The complete test results can be found in the ./gas reporter/ERC721EnviousRoyaltyPreset.txt file. The actual tests are available in the ./tests/ERC721EnviousRoyaltyPreset.test.js file.

·------------------------------------------------------------|---------------------------|--------------|----------------------------·
|            Solc version: 0.8.4+commit.c7e474f2             ·  Optimizer enabled: true  ·  Runs: 1337  ·  Block limit: 6718946 gas  │
·····························································|···························|··············|·····························
|  Methods                                                                                                                           │
·······························|·····························|·············|·············|··············|··············|··············
|  Contract                    ·  Method                     ·  Min        ·  Max        ·  Avg         ·  # calls     ·  eur (avg)  │
·······························|·····························|·············|·············|··············|··············|··············
|  BadToken                    ·  approve                    ·          -  ·          -  ·       46213  ·          12  ·          -  │
·······························|·····························|·············|·············|··············|··············|··············
|  BadToken                    ·  mint                       ·          -  ·          -  ·       70691  ·           6  ·          -  │
·······························|·····························|·············|·············|··············|··············|··············
|  BaseToken                   ·  approve                    ·      29180  ·      46244  ·       46115  ·         133  ·          -  │
·······························|·····························|·············|·············|··············|··············|··············
|  BaseToken                   ·  burn                       ·          -  ·          -  ·       26889  ·           1  ·          -  │
·······························|·····························|·············|·············|··············|··············|··············
|  BaseToken                   ·  mint                       ·      51185  ·      68321  ·       67929  ·         144  ·          -  │
·······························|·····························|·············|·············|··············|··············|··············
|  BaseToken                   ·  transfer                   ·          -  ·          -  ·       46608  ·           1  ·          -  │
·······························|·····························|·············|·············|··············|··············|··············
|  DAI                         ·  approve                    ·      29149  ·      46213  ·       45966  ·          69  ·          -  │
·······························|·····························|·············|·············|··············|··············|··············
|  DAI                         ·  burn                       ·          -  ·          -  ·       27704  ·           1  ·          -  │
·······························|·····························|·············|·············|··············|··············|··············
|  DAI                         ·  mint                       ·      70713  ·      70749  ·       70714  ·          69  ·          -  │
·······························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousRoyaltyPreset  ·  approve                    ·      26628  ·      51081  ·       44710  ·         215  ·          -  │
·······························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousRoyaltyPreset  ·  burn                       ·      52199  ·      68274  ·       65358  ·          15  ·          -  │
·······························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousRoyaltyPreset  ·  changeCommissions          ·      27230  ·      68285  ·       68074  ·         389  ·          -  │
·······························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousRoyaltyPreset  ·  changeCommunityAddresses   ·      34651  ·      68851  ·       68659  ·         360  ·          -  │
·······························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousRoyaltyPreset  ·  changeRoyalties            ·          -  ·          -  ·       28271  ·           6  ·          -  │
·······························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousRoyaltyPreset  ·  claimDiscountedCollateral  ·      55765  ·     244786  ·      209562  ·          28  ·          -  │
·······························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousRoyaltyPreset  ·  collateralize              ·      74616  ·     682724  ·      194172  ·         106  ·          -  │
·······························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousRoyaltyPreset  ·  disperse                   ·      72718  ·     403232  ·      150496  ·          27  ·          -  │
·······························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousRoyaltyPreset  ·  getDiscountedCollateral    ·     158329  ·     206611  ·      187426  ·          46  ·          -  │
·······························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousRoyaltyPreset  ·  harvest                    ·      81301  ·     312999  ·      132266  ·          14  ·          -  │
·······························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousRoyaltyPreset  ·  mint                       ·     160493  ·     172293  ·      167614  ·         578  ·          -  │
·······························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousRoyaltyPreset  ·  renounceOwnership          ·          -  ·          -  ·       23269  ·           2  ·          -  │
·······························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousRoyaltyPreset  ·  safeTransferFrom           ·      36109  ·     106120  ·       90073  ·         104  ·          -  │
·······························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousRoyaltyPreset  ·  safeTransferFrom           ·      36783  ·     107239  ·       90936  ·         104  ·          -  │
·······························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousRoyaltyPreset  ·  setApprovalForAll          ·      26386  ·      46298  ·       45350  ·         189  ·          -  │
·······························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousRoyaltyPreset  ·  setGhostAddresses          ·      68948  ·      68972  ·       68970  ·          50  ·          -  │
·······························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousRoyaltyPreset  ·  transferFrom               ·      35755  ·     139697  ·       92096  ·          64  ·          -  │
·······························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousRoyaltyPreset  ·  transferOwnership          ·          -  ·          -  ·       28654  ·           2  ·          -  │
·······························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousRoyaltyPreset  ·  uncollateralize            ·      61717  ·     298705  ·      111035  ·          43  ·          -  │
·······························|·····························|·············|·············|··············|··············|··············
|  RebaseToken                 ·  approve                    ·      29135  ·      46235  ·       45987  ·          69  ·          -  │
·······························|·····························|·············|·············|··············|··············|··············
|  RebaseToken                 ·  initialize                 ·      94307  ·      94319  ·       94318  ·          68  ·          -  │
·······························|·····························|·············|·············|··············|··············|··············
|  RebaseToken                 ·  transfer                   ·          -  ·          -  ·       34665  ·           1  ·          -  │
·······························|·····························|·············|·············|··············|··············|··············
|  StakingMock                 ·  fund                       ·          -  ·          -  ·       61607  ·          69  ·          -  │
·······························|·····························|·············|·············|··············|··············|··············
|  TetherToken                 ·  approve                    ·      26344  ·      46244  ·       45955  ·          69  ·          -  │
·······························|·····························|·············|·············|··············|··············|··············
|  TetherToken                 ·  burn                       ·          -  ·          -  ·       26907  ·           1  ·          -  │
·······························|·····························|·············|·············|··············|··············|··············
|  TetherToken                 ·  mint                       ·          -  ·          -  ·       68219  ·          69  ·          -  │
·······························|·····························|·············|·············|··············|··············|··············
|  Deployments                                               ·                                          ·  % of limit  ·             │
·····························································|·············|·············|··············|··············|··············
|  BadToken                                                  ·          -  ·          -  ·     1140859  ·        17 %  ·          -  │
·····························································|·············|·············|··············|··············|··············
|  BaseToken                                                 ·     775391  ·     775475  ·      775424  ·      11.5 %  ·          -  │
·····························································|·············|·············|··············|··············|··············
|  BlackHole                                                 ·          -  ·          -  ·      321368  ·       4.8 %  ·          -  │
·····························································|·············|·············|··············|··············|··············
|  BondingMock                                               ·    1114846  ·    1114870  ·     1114868  ·      16.6 %  ·          -  │
·····························································|·············|·············|··············|··············|··············
|  DAI                                                       ·          -  ·          -  ·     1148998  ·      17.1 %  ·          -  │
·····························································|·············|·············|··············|··············|··············
|  ERC721EnviousRoyaltyPreset                                ·          -  ·          -  ·     4539709  ·      67.6 %  ·          -  │
·····························································|·············|·············|··············|··············|··············
|  ERC721ReceiverMock                                        ·     285979  ·     286027  ·      286014  ·       4.3 %  ·          -  │
·····························································|·············|·············|··············|··············|··············
|  RebaseToken                                               ·          -  ·          -  ·     1711816  ·      25.5 %  ·          -  │
·····························································|·············|·············|··············|··············|··············
|  StakingMock                                               ·     246573  ·     246585  ·      246584  ·       3.7 %  ·          -  │
·····························································|·············|·············|··············|··············|··············
|  TetherToken                                               ·          -  ·          -  ·      758083  ·      11.3 %  ·          -  │
·------------------------------------------------------------|-------------|-------------|--------------|--------------|-------------·

VRF Envious Preset

Description

The Chainlink VRF (Verifiable Random Function) is a secure and trustworthy method of generating random numbers that enables smart contracts to access unpredictable values while maintaining the integrity and usability of the system. Upon receiving a request, the Chainlink VRF produces one or multiple random values, along with cryptographic evidence of how these values were generated. The evidence is then recorded on the blockchain and validated before being available for consumption by applications. This approach guarantees that the outcomes cannot be altered or controlled by any single party, including oracle operators, miners, users, or smart contract developers. For further details, please refer to the ChainLink documentation <https://docs.chain.link/vrf/v2/introduction/>`_.

The Envious standard offers a variety of functions, but in certain circumstances, they may not suffice. Consider a gaming NFT platform that requires a reward system that disperses a particular amount of specific tokenIds chosen at random. In such situations, the VRF Envious Preset is an exceptional solution.

IERC721EnviousVrfPreset

vrfCoordinatorAddress

function vrfCoordinatorAddress() external view returns (address)

vrfCoordinatorAddress function is the coordinator address, which is unique and immutable for each network. Read more here.

sSubscriptionId

function sSubscriptionId() external view returns (uint64)

sSubscriptionId function returns the ChainLink VRF v2 subscription ID.

sKeyHash

function sKeyHash() external view returns (bytes32)

sKeyHash function returns the gas lane that determines the upper limit for gas prices that can be increased. To view the available gas lanes for each network, please refer to the following link.

callbackGasLimit

function callbackGasLimit() external view returns (uint32)

callbackGasLimit function depends on the number of requested values to be forwarded to the fulfillRandomWords() function. Since storing each word requires about 20,000 gas, a safe default value for this example contract is 40,000 gas. However, it is recommended to test and adjust this limit based on the selected network, the request’s size, and the processing of the callback request in the fulfillRandomWords() function.

numWords

function numWords() external view returns (uint32)

numWords function returns the word count. It should be noted that numWords cannot exceed the value defined in VRFCoordinatorV2.MAX_NUM_WORDS.

requestConfirmations

function requestConfirmations() external view returns (uint16)

requestConfirmations function returns the required number of block confirmations, with a default value of 3 confirmations.

prepareRandomness

function prepareRandomness() external returns (uint256)

prepareRandomness function returns on-chain randomness from Chainlink VRF v2.

extraDisperseAmount

function extraDisperseAmount(address tokenAddress) external view returns (uint256)

extraDisperseAmount is an extra quantity of a particular tokenAddress to be randomly distributed.

extraDisperseAmount function returns the additional quantity of a specific tokenAddress to be randomly dispersed.

_Arguments_

Name

Type

Description

tokenAddress

address

address of a dispersed ERC20 token

extraDisperseTaken

function extraDisperseTaken(address tokenAddress) external view returns (uint256)

extraDisperseTaken is a quantity of an ERC20 token that has been already claimed from the extraDisperseAmount.

extraDisperseTaken function returns the amount of a specific tokenAddress that has been distributed from the extraDisperseAmount.

_Arguments_

Name

Type

Description

tokenAddress

address

address of a dispersed ERC20 token

extraDisperseTokenId

function extraDisperseTokenId(address tokenAddress) external view returns (uint256)

extraDisperseTokenId function selects all tokenIds that are divisible by a specified number, without leaving a remainder, for random distribution.

extraDisperseTokenId function returns divisor used to determine which tokenIds are eligible for random distribution.

_Arguments_

Name

Type

Description

tokenAddress

address

address of a dispersed ERC20 token

randomAmountsDisperse

function randomAmountsDisperse(address tokenAddress, uint256 tokenId) external view returns(uint256)

randomAmountsDisperse generates an additional random amount of tokens to be distributed.

randomAmountsDisperse returns an additional random quantity of tokens for distribution.

_Arguments_

Name

Type

Description

tokenAddress

address

address of a dispersed ERC20 token

tokenId

uint256

unique token identifier

collateralRandomTokens

function collateralRandomTokens(uint256[] memory amounts, address[] memory tokenAddresses) external payable;

collateralRandomTokens function collateralizes randomly selected tokenIds with predetermined amount of tokenAddresses.

_Arguments_

Name

Type

Description

amounts

uint256[]

array of amounts to be added to the collateral

tokenAddresses

address[]

array of token addresses to be added to the collateral

collateralRandomAmounts

function collateralRandomAmounts(uint256[] memory tokenIds, uint256 amount, address tokenAddress) external payable

collateralRandomAmounts function collateralizes specific tokenIds with randomly generated amounts.

Warning

If ETH is used, the amount of collateral required should match the value of the msg.value parameter.

_Arguments_

Name

Type

Description

tokenIds

uint256[]

unique token identifiers

amounts

uint256[]

array of amounts to be added to the collateral

tokenAddresses

address[]

array of token addresses to be added to the collateral

function initializeVRF

function initializeVRF(uint64 newSSubscriptionId, bytes32 newSKeyHash, uint32 newNumWords, uint32 newCallbackGasLimit, uint16 newRequestConfirmations) external

initializeVRF function is used to initialize all the necessary information related to ChainlinkVRF.

_Arguments_

Name

Type

Description

newSSubscriptionId

uint64

Chainlink subscription id

newSKeyHash

bytes32

gas lane used to specify the maximum gas price to increase to

newNumWords

uint32

number of random values to retrieve

newCallbackGasLimit

uint32

required gas limit for the fulfillRandomWords() function

newRequestConfirmations

uint16

number of confirmations required

event VrfChanged

event VrfChanged(uint64 newSSubscriptionId, bytes32 newSKeyHash, uint32 newNumWords, uint32 newCallbackGasLimit, uint16 newRequestConfirmations);

event vrfChanged is triggered after the parameters related to Chainlink VRF v2 have been changed.

_Arguments_

Name

Type

Description

newSSubscriptionId

uint64

Chainlink subscription id

newSKeyHash

bytes32

gas lane used to specify the maximum gas price to increase to

newNumWords

uint32

number of random values to retrieve

newCallbackGasLimit

uint32

required gas limit for the fulfillRandomWords() function

newRequestConfirmations

uint16

number of confirmations required

ERC721EnviousVrfPreset

baseURI

function baseURI() external view virtual returns (string memory)

baseURI is a getter function for the baseURI.

baseURI function returns baseURI for the entire collection.

tokenURI

function tokenURI(uint256 tokenId) public view virtual override returns (string memory)

tokenURI is a getter function for a particular tokenURI.

tokenURI function returns tokenURI for a specific NFT.

_Arguments_

Name

Type

Description

tokenId

uint256

unique token identifier

totalSupply

function totalSupply() public view virtual returns (uint256)

totalSupply is a getter function for the total count of NFTs in the collection.

totalSupply function returns the overall count of NFTs within the collection.

setGhostAddresses

function setGhostAddresses(address ghostToken, address ghostBonding) public virtual

setGhostAddress function enables the feature of bonding, representing the ability to add discounted collateral.

_Arguments_

Name

Type

Description

ghostToken

address

address of a non-rebasing bonding token

ghostBonding

address

address of a bonding smart contract

changeCommunityAddresses

function changeCommunityAddresses(address newTokenAddress, address newBlackHole) public virtual

changeCommunityAddresses function enables to change the address of the communityToken and the blackHole.

_Arguments_

Name

Type

Description

newTokenAddress

address

new address of an ERC20 communityToken

newBlackHole

address

new address of a blackHole

_nullifyRandomness

function _nullifyRandomness(address who) internal virtual

_nullifyRandomness function invalidates mappings after their use.

_Arguments_

Name

Type

Description

who

address

address that requires nullification

Gas Report

The complete test results can be found in the ./gas reporter/ERC721VRFRoyaltyPreset.txt file. The actual tests are available in the ./tests/ERC721VRFRoyaltyPreset.test.js file.

·--------------------------------------------------------|---------------------------|--------------|----------------------------·
|          Solc version: 0.8.4+commit.c7e474f2           ·  Optimizer enabled: true  ·  Runs: 1337  ·  Block limit: 6718946 gas  │
·························································|···························|··············|·····························
|  Methods                                                                                                                       │
···························|·····························|·············|·············|··············|··············|··············
|  Contract                ·  Method                     ·  Min        ·  Max        ·  Avg         ·  # calls     ·  eur (avg)  │
···························|·····························|·············|·············|··············|··············|··············
|  BadToken                ·  approve                    ·      46201  ·      46213  ·       46211  ·          25  ·          -  │
···························|·····························|·············|·············|··············|··············|··············
|  BadToken                ·  mint                       ·          -  ·          -  ·       70691  ·          15  ·          -  │
···························|·····························|·············|·············|··············|··············|··············
|  BaseToken               ·  approve                    ·      29180  ·      46244  ·       46094  ·         115  ·          -  │
···························|·····························|·············|·············|··············|··············|··············
|  BaseToken               ·  burn                       ·          -  ·          -  ·       26889  ·           1  ·          -  │
···························|·····························|·············|·············|··············|··············|··············
|  BaseToken               ·  mint                       ·      51185  ·      68321  ·       68000  ·         120  ·          -  │
···························|·····························|·············|·············|··············|··············|··············
|  BaseToken               ·  transfer                   ·          -  ·          -  ·       46608  ·           1  ·          -  │
···························|·····························|·············|·············|··············|··············|··············
|  DAI                     ·  approve                    ·      29149  ·      46213  ·       45964  ·          69  ·          -  │
···························|·····························|·············|·············|··············|··············|··············
|  DAI                     ·  burn                       ·          -  ·          -  ·       27704  ·           1  ·          -  │
···························|·····························|·············|·············|··············|··············|··············
|  DAI                     ·  mint                       ·      70713  ·      70749  ·       70714  ·          69  ·          -  │
···························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousVRFPreset  ·  approve                    ·      26650  ·      51103  ·       44732  ·         215  ·          -  │
···························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousVRFPreset  ·  burn                       ·          -  ·          -  ·       31690  ·           6  ·          -  │
···························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousVRFPreset  ·  changeCommissions          ·          -  ·          -  ·       46175  ·         343  ·          -  │
···························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousVRFPreset  ·  changeCommunityAddresses   ·      32553  ·      66753  ·       66541  ·         326  ·          -  │
···························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousVRFPreset  ·  claimDiscountedCollateral  ·      55787  ·     187261  ·      160258  ·          14  ·          -  │
···························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousVRFPreset  ·  collateralize              ·      74112  ·     490178  ·      143443  ·         101  ·          -  │
···························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousVRFPreset  ·  collateralRandomAmounts    ·          -  ·          -  ·       79304  ·           3  ·          -  │
···························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousVRFPreset  ·  collateralRandomTokens     ·      69452  ·     102238  ·       94950  ·           9  ·          -  │
···························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousVRFPreset  ·  disperse                   ·      72740  ·     403254  ·      150519  ·          27  ·          -  │
···························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousVRFPreset  ·  getDiscountedCollateral    ·     158294  ·     206567  ·      187390  ·          23  ·          -  │
···························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousVRFPreset  ·  harvest                    ·      81301  ·     312999  ·      132266  ·          14  ·          -  │
···························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousVRFPreset  ·  initializeVRF              ·      36246  ·      56182  ·       54796  ·          29  ·          -  │
···························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousVRFPreset  ·  mint                       ·      59205  ·      76305  ·       69393  ·         522  ·          -  │
···························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousVRFPreset  ·  prepareRandomness          ·          -  ·          -  ·       98895  ·          12  ·          -  │
···························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousVRFPreset  ·  renounceOwnership          ·          -  ·          -  ·       23335  ·           2  ·          -  │
···························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousVRFPreset  ·  safeTransferFrom           ·      31028  ·      69852  ·       59029  ·         104  ·          -  │
···························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousVRFPreset  ·  safeTransferFrom           ·      31704  ·      70970  ·       59892  ·         104  ·          -  │
···························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousVRFPreset  ·  setApprovalForAll          ·      26364  ·      46276  ·       45328  ·         189  ·          -  │
···························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousVRFPreset  ·  setGhostAddresses          ·      66642  ·      66654  ·       66653  ·          24  ·          -  │
···························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousVRFPreset  ·  transferFrom               ·      30714  ·      62490  ·       54579  ·          50  ·          -  │
···························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousVRFPreset  ·  transferOwnership          ·          -  ·          -  ·       28676  ·           2  ·          -  │
···························|·····························|·············|·············|··············|··············|··············
|  ERC721EnviousVRFPreset  ·  uncollateralize            ·      89204  ·     506027  ·      153918  ·          45  ·          -  │
···························|·····························|·············|·············|··············|··············|··············
|  RebaseToken             ·  approve                    ·      29135  ·      46235  ·       45986  ·          69  ·          -  │
···························|·····························|·············|·············|··············|··············|··············
|  RebaseToken             ·  initialize                 ·      94307  ·      94319  ·       94319  ·          68  ·          -  │
···························|·····························|·············|·············|··············|··············|··············
|  RebaseToken             ·  transfer                   ·          -  ·          -  ·       34665  ·           1  ·          -  │
···························|·····························|·············|·············|··············|··············|··············
|  StakingMock             ·  fund                       ·          -  ·          -  ·       61607  ·          69  ·          -  │
···························|·····························|·············|·············|··············|··············|··············
|  TetherToken             ·  approve                    ·      26344  ·      46244  ·       45954  ·          69  ·          -  │
···························|·····························|·············|·············|··············|··············|··············
|  TetherToken             ·  burn                       ·          -  ·          -  ·       26907  ·           1  ·          -  │
···························|·····························|·············|·············|··············|··············|··············
|  TetherToken             ·  mint                       ·          -  ·          -  ·       68219  ·          69  ·          -  │
···························|·····························|·············|·············|··············|··············|··············
|  VRFCoordinatorV2Mock    ·  addConsumer                ·      70732  ·      70744  ·       70740  ·          13  ·          -  │
···························|·····························|·············|·············|··············|··············|··············
|  VRFCoordinatorV2Mock    ·  createSubscription         ·          -  ·          -  ·       67774  ·          13  ·          -  │
···························|·····························|·············|·············|··············|··············|··············
|  VRFCoordinatorV2Mock    ·  fulfillRandomWords         ·      82435  ·      82447  ·       82443  ·          13  ·          -  │
···························|·····························|·············|·············|··············|··············|··············
|  VRFCoordinatorV2Mock    ·  fundSubscription           ·          -  ·          -  ·       29385  ·          12  ·          -  │
···························|·····························|·············|·············|··············|··············|··············
|  Deployments                                           ·                                          ·  % of limit  ·             │
·························································|·············|·············|··············|··············|··············
|  BadToken                                              ·          -  ·          -  ·     1140859  ·        17 %  ·          -  │
·························································|·············|·············|··············|··············|··············
|  BaseToken                                             ·     775391  ·     775475  ·      775422  ·      11.5 %  ·          -  │
·························································|·············|·············|··············|··············|··············
|  BlackHole                                             ·          -  ·          -  ·      321368  ·       4.8 %  ·          -  │
·························································|·············|·············|··············|··············|··············
|  BondingMock                                           ·    1114858  ·    1114870  ·     1114868  ·      16.6 %  ·          -  │
·························································|·············|·············|··············|··············|··············
|  DAI                                                   ·          -  ·          -  ·     1148998  ·      17.1 %  ·          -  │
·························································|·············|·············|··············|··············|··············
|  ERC721EnviousVRFPreset                                ·    4949552  ·    4949564  ·     4949563  ·      73.7 %  ·          -  │
·························································|·············|·············|··············|··············|··············
|  ERC721ReceiverMock                                    ·     285979  ·     286027  ·      286014  ·       4.3 %  ·          -  │
·························································|·············|·············|··············|··············|··············
|  RebaseToken                                           ·          -  ·          -  ·     1711816  ·      25.5 %  ·          -  │
·························································|·············|·············|··············|··············|··············
|  StakingMock                                           ·     246573  ·     246585  ·      246585  ·       3.7 %  ·          -  │
·························································|·············|·············|··············|··············|··············
|  TetherToken                                           ·          -  ·          -  ·      758083  ·      11.3 %  ·          -  │
·························································|·············|·············|··············|··············|··············
|  VRFCoordinatorV2Mock                                  ·          -  ·          -  ·     1448986  ·      21.6 %  ·          -  │
·--------------------------------------------------------|-------------|-------------|--------------|--------------|-------------·

Multi-Chain

The following list of actual deployments and implementations that has been conducted by the GHOST team.

All products outlined below have been deployed on the following 16 networks, including 14 MainNets and 2 TestNets:

GHOST team is planning to deploy the products on more EVM-compatible chains based on demand. GHOST team is also planning to deploy all products on non-EVM-compatible blockchain networks depending on grants, co-marketing opportunities, and collaboration available.

GHOST team went an extra mile to deploy all smart contracts on multiple chains under the same smart contract address to make it more convenient for developers and users.

ghostHouse

ghostHouse is the first implementation of the EnviousHouse standard. With ghostHouse, existing ERC721 collections or custom NFT collections on any EVM network can utilize the collateral feature.

Check out ghostNFT DApp to try ghostHouse on 16 EVM-compatible networks.

Discover the advantages of collateralizing your collections by visiting the provided link.

Blockchain

ghostHouse Smart Contract Address

Ethereum

0x136E29d881DD91349d660B452aFb206e09C94268

Astar

0x136E29d881DD91349d660B452aFb206e09C94268

Aurora

0x136E29d881DD91349d660B452aFb206e09C94268

Avalanche

0x136E29d881DD91349d660B452aFb206e09C94268

Binance

0x136E29d881DD91349d660B452aFb206e09C94268

Celo

0x136E29d881DD91349d660B452aFb206e09C94268

Classic

0x136E29d881DD91349d660B452aFb206e09C94268

Fantom

0x136E29d881DD91349d660B452aFb206e09C94268

Fuse

0x136E29d881DD91349d660B452aFb206e09C94268

Gnosis

0x136E29d881DD91349d660B452aFb206e09C94268

Harmony

0x136E29d881DD91349d660B452aFb206e09C94268

Metis

0x136E29d881DD91349d660B452aFb206e09C94268

Moonbeam

0x136E29d881DD91349d660B452aFb206e09C94268

Polygon

0x136E29d881DD91349d660B452aFb206e09C94268

Goerli

0x136E29d881DD91349d660B452aFb206e09C94268

zkEVM

0x136E29d881DD91349d660B452aFb206e09C94268

JML NFT Collection

John McAfee Legacy (JML) NFT Collection is the first ER721EnviousDynamic collection consisting of 71,202 unique NFTs.

JML gNFTs get dynamically upgraded towards a higher level of rarity as the collateral in GMV token increases. GMV is a utility token that serves as a measurementToken for the JML Collection.

Check out JML Wiki to learn more about JML NFT Collection.

Blockchain

JML Collection Address

Ethereum

0x91ba8A14D2CC851aBb69212c09f59e06e1e7f0a5

Astar

0x91ba8A14D2CC851aBb69212c09f59e06e1e7f0a5

Aurora

0x91ba8A14D2CC851aBb69212c09f59e06e1e7f0a5

Avalanche

0x91ba8A14D2CC851aBb69212c09f59e06e1e7f0a5

Binance

0x91ba8A14D2CC851aBb69212c09f59e06e1e7f0a5

Celo

0x91ba8A14D2CC851aBb69212c09f59e06e1e7f0a5

Classic

0x91ba8A14D2CC851aBb69212c09f59e06e1e7f0a5

Fantom

0x91ba8A14D2CC851aBb69212c09f59e06e1e7f0a5

Fuse

0x91ba8A14D2CC851aBb69212c09f59e06e1e7f0a5

Gnosis

0x91ba8A14D2CC851aBb69212c09f59e06e1e7f0a5

Harmony

0x91ba8A14D2CC851aBb69212c09f59e06e1e7f0a5

Metis

0x91ba8A14D2CC851aBb69212c09f59e06e1e7f0a5

Moonbeam

0x91ba8A14D2CC851aBb69212c09f59e06e1e7f0a5

Polygon

0x91ba8A14D2CC851aBb69212c09f59e06e1e7f0a5

Goerli

0x91ba8A14D2CC851aBb69212c09f59e06e1e7f0a5

zkEVM

0x91ba8A14D2CC851aBb69212c09f59e06e1e7f0a5

GMV Token

GMV is an ERC20 utility token that serves as a measurementToken for the John McAfee Legacy (JML) NFT Collection.

Quantity of GMV token used as collateral increases rarity for JML gNFT. To learn about JML edges in relevance to GMV token quantity, learn here.

Blockchain

GMV Token Address

Ethereum

0x7EF911f8ef130F73D166468c0068753932357B17

Astar

0x7EF911f8ef130F73D166468c0068753932357B17

Aurora

0x7EF911f8ef130F73D166468c0068753932357B17

Avalanche

0x7EF911f8ef130F73D166468c0068753932357B17

Binance

0x7EF911f8ef130F73D166468c0068753932357B17

Celo

0x7EF911f8ef130F73D166468c0068753932357B17

Classic

0x7EF911f8ef130F73D166468c0068753932357B17

Fantom

0x7EF911f8ef130F73D166468c0068753932357B17

Fuse

0x7EF911f8ef130F73D166468c0068753932357B17

Gnosis

0x7EF911f8ef130F73D166468c0068753932357B17

Harmony

0x7EF911f8ef130F73D166468c0068753932357B17

Metis

0x7EF911f8ef130F73D166468c0068753932357B17

Moonbeam

0x7EF911f8ef130F73D166468c0068753932357B17

Polygon

0x7EF911f8ef130F73D166468c0068753932357B17

Goerli

0x7EF911f8ef130F73D166468c0068753932357B17

zkEVM

0x7EF911f8ef130F73D166468c0068753932357B17

ghostAirdrop

ghostAirdrop DApp is the first implementation of the Initial NFT Offering (INO) where token allocation is stored in JML gNFT collateral and every user has to claim their GMV token collateral.

After claiming free gNFT every user starts having access to a personal affiliate url comprised of user’s public key.

The GMV rewards increase in proportion to the number of referrals, following a sigmoid function.

To claim a free gNFT or learn more about ghostAirdop follow this link.

Blockchain

ghostFaucet Smart Contract Addresses

Ethereum

0x9C4c49C3c3bd7ab49D91576d0103A25514CaD1D6

Astar

0x9C4c49C3c3bd7ab49D91576d0103A25514CaD1D6

Aurora

0x9C4c49C3c3bd7ab49D91576d0103A25514CaD1D6

Avalanche

0x9C4c49C3c3bd7ab49D91576d0103A25514CaD1D6

Binance

0x9C4c49C3c3bd7ab49D91576d0103A25514CaD1D6

Celo

0x9C4c49C3c3bd7ab49D91576d0103A25514CaD1D6

Classic

0x9C4c49C3c3bd7ab49D91576d0103A25514CaD1D6

Fantom

0x9C4c49C3c3bd7ab49D91576d0103A25514CaD1D6

Fuse

0x9C4c49C3c3bd7ab49D91576d0103A25514CaD1D6

Gnosis

0x9C4c49C3c3bd7ab49D91576d0103A25514CaD1D6

Harmony

0x9C4c49C3c3bd7ab49D91576d0103A25514CaD1D6

Metis

0x9C4c49C3c3bd7ab49D91576d0103A25514CaD1D6

Moonbeam

0x9C4c49C3c3bd7ab49D91576d0103A25514CaD1D6

Polygon

0x9C4c49C3c3bd7ab49D91576d0103A25514CaD1D6

Goerli

0x9C4c49C3c3bd7ab49D91576d0103A25514CaD1D6

zkEVM

0x9C4c49C3c3bd7ab49D91576d0103A25514CaD1D6

NFT 2.0 == Promises of NFT 1.0

NFT 2.0 is a new concept with a number of features and use cases. The list of features and use cases is ever expanding as NFT 2.0 gets more adoption.

A number of promises of NFT 1.0 are just not feasible given NFT 1.0 limitations. However, NFT 2.0 extends these limitations.

On-chain verifiable price floor

NFT 1.0 attempts to bring ‘big data’ and statistical methods to estimate the price floor. There are many problems with such an approach. First of all, the data is easily manipulated to inflate the prices of NFTs through inside wash sale, which gives a very inaccurate picture on the real liquidity deposited into a given NFT collection. Secondly, many NFT marketplaces are powered by off-chain NFT storage and operations resulting in even more obscure datapoints. Finally, there is simply not enough data to make any statistically significant forecasts let alone fair ‘big data’ predictions.

NFT 2.0 easily solves the problem of on-chain verifiable price floors since every gNFT has an on-chain collateral attached to it.

Sustainable NFT royalties

Since its origination, the concept of NFT staking was always desirable. Many NFT and Play2Earn projects were offering the yield on their NFTs. However, the yield was often in the form of a native token with unlimited supply where inflated supply was not backed appropriately creating all types of busts in bank-run scenario.

Appropriate collateral enables a gNFT to generate sustainable and sometimes consistently sustainable royalties. As it was already mentioned throughout this lightpaper, collateralizing a gNFT with DeFi 2.0 tokens or LP tokens could result in sustainable appreciation of gNFT value.

Further integration with DeFi 2.0 protocols such as ghostDAO enables discounted collateral and additional appreciation of the value of gNFT.

New Monetization Streams

NFT 2.0 enables additional monetization of NFT collections through the following fees:

  • Collateralization Fee

  • Uncollateralization Fee

  • NFT Transfer Fee

Additional NFT collection gamification can be implemented by utilizing VRFPreset and DynamicPreset described earlier

NFT 2.0 Powers DAOs

As DAOs are getting more traction in Web 3.0, NFT 2.0 offers novel ways to realize governance mechanisms. NFTs representing DAO decision makers was receiving more and more popularization in 2020-2021. gNFTs can significantly improve governance mechanisms by aligning incentives more appropriately.

For example, the voting power can be correlated to the amount of collateral behind a voting gNFT. Council members with more belief in the protocol will have to provide a larger collateral to achieve a higher voting power. Similarly, all gNFT collection holders can have an equivalent amount of native token distributed behind every gNFT; those holders to redeem gNFT collateral partial or in-full will lose a proportional amount of voting power.

Another way to utilize gNFT for voting is by rewarding Council members who dispersed larger amounts of collateral to other members of the gNFT collection with a higher voting power. All gNFT collateral activities are on-chain verifiable making it easy for DAOs to construct various mechanisms and incentive structures.

NFT 2.0 Powers DeFi

Utility NFTs that the world was expecting for a very long time are somewhat difficult with NFT 1.0 and super achievable with NFT 2.0.

On-chain portfolio management applications can be designed with gNFTs. gNFT can be collateralized by any combinations of underlying tokens.

For example, let’s assume that a given gNFT was collateralized by:

  • 10 ETH

  • 1,000 DAI

  • 5,000 eGHST

  • 30 LP

The owner of the gNFT has the claim for all 4 tokens: ETH, DAI, eGHST, LP. Transfer of this gNFT to another user would give that user the claim for the 4 tokens. Thus, the gNFT serves as a receipt for the underlying tokens in the collateralized digital asset basket.

Initial NFT Offering (INO)

NFT 2.0 empowers a new crowdfunding standard of the Initial NFT Offering (INO). The following example will illustrate how INOs work.

Let’s assume there is a new gNFT collection based on ERC721Envious | DynamicPreset. Let’s assume there are 5 levels of gNFTs based on the amount of collateral attached where Level 1 has the lowest amount of collateral and Level 5 is achieved by depositing the largest amount of collateral. The visual associated with gNFT changes dynamically and becomes rarer with larger amounts of tokens and/or capital contributed.

Users place respective NFT visuals on their avatars to reflect their status. Users with Level 1 gNFT have common NFT visuals. They would need to acquire the native token and collateralize Level 1 gNFT to get to Level 5 gNFT with more status-rich NFT visuals.

Cross-Chain Interoperability

ghostNFT has natural integration with the GHOST protocol, which is responsible for decentralized cross-chain interoperability. GHOST protocol powers cross-chain interoperability of both NFTs and gNFTs. To reiterate, both NFTs and NFTs with attached collateral can move between EVM-compatible blockchains powered by the GHOST protocol. Please read the GHOST Lightpaper for a more in-depth explanation.