Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ERC: Sustainable collaborative NFT collections #752

Open
wants to merge 36 commits into
base: master
Choose a base branch
from

Conversation

gfLobo
Copy link

@gfLobo gfLobo commented Dec 4, 2024


eip: 7832
title: Sustainable collaborative NFT collections
description: Economically sustainable collaborative NFT collections with dynamic fees and donation-based engagement.
author: Gustavo Lobo (@gfLobo)
discussions-to: https://ethereum-magicians.org/t/erc-7832-sustainable-nft-collections/22201
status: Review
type: Standards Track
category: ERC
created: 2024-12-04
requires: 721

Abstract

This EIP proposes a standard for creating economically sustainable NFT governance for collections built on collaborative models based on ERC-721. It introduces dynamic minting fees, role-based access control, and a donation-based engagement model to enhance creator-community interactions. These mechanisms aim to balance scarcity, incentivize meaningful participation, and ensure sustainable growth for both creators and contributors.

The model defines "economically sustainable" as tokens whose minting value, creator subscription fees, and token quantity within each progressive discount cycle can only be adjusted once every 30 days from the last update by an ADMIN user. These mechanisms prevent excessive administrative modifications that could disrupt market stability, ensuring consistent price discovery and maintaining participant confidence. By aligning incentives and fostering predictability, the model creates a robust framework for engagement and value creation.

Motivation


As the NFT market matures, one of the recurring challenges faced by both creators and users is the inflationary nature of supply and the lack of effective mechanisms to engage the community meaningfully. NFT collections built on collaborative models require governance systems that empower all stakeholders—creators, contributors, and collectors—while also maintaining long-term economic sustainability. The introduction of this proposal aims to solve these issues by fostering a more dynamic, flexible, and transparent system for NFT collections. This EIP addresses these gaps by introducing:

  • Role-Based Access: Empowering creators while ensuring transparent governance by admins.
  • Dynamic Minting Fees: To align token costs with user activity and ownership.
  • Donation-Based Engagement: Encouraging contributions to creators.

Specification

The keywords "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119.

The following interface MUST be implemented.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;


interface IERC7832 is IERC721 {
    
    // Events
    event CreatorTermsUpdated(
        uint256 mintBaseFee,
        uint256 creatorSignatureFee,
        uint256 maxMintsPerUserInCycle);

    event DonationReceived(address from, address to, uint256 amount);

    // Function to get the current token ID
    function currentTokenId() external view returns (uint256);

    // Function to get the current mint base fee
    function mintBaseFee() external view returns (uint256);
    
    // Function to get the creator signature fee
    function creatorSignatureFee() external view returns (uint256);
    
    // Function to get the maximum mints a user can perform during his progressive discount cycle per mint
    function maxMintsPerUserInCycle() external view returns (uint256);

    // Function to get the last update timestamp
    function lastUpdateTimestamp() external view returns (uint256);

    // Function to get the update interval constant (30 days)
    function UPDATE_INTERVAL() external pure returns (uint256);

    // Function to get the CREATOR_ROLE
    function getCreatorSignature() external payable;

    // Function to get the CONTRIBUTOR_ROLE identifier
    function CONTRIBUTOR_ROLE() external pure returns (bytes32);

    // Function to get CREATOR_ROLE identifier
    function CREATOR_ROLE() external pure returns (bytes32);

    // Function to get ADMIN_ROLE identifier
    function ADMIN_ROLE() external pure returns (bytes32);

    // Function to check the number of mints a user has performed in their current cycle of progressive discounts
    function mintsPerUserInCycle(address user) external view returns (uint256);

    // Allow users to donate ETH to a specific creator in the system.
    function donate(address creator) external payable;

    // Allow users to check their mint fee
    function mintFee() external view returns (uint256);

    // Allow token owners to burn their tokens
    function burn(uint256 tokenId) external;

    // Allow ADMIN_ROLE pause the contract
    function pause() external;

    // Allow ADMIN_ROLE unpause the contract
    function unpause() external;

    // Allow CREATOR_ROLE to mint
    function safeMint(string memory uri) external payable;

    // Allow ADMIN_ROLE to update contract terms
    function updateTerms(
        uint256 mintBaseFee,
        uint256 creatorSignatureFee,
        uint256 maxMintsPerUserInCycle
    ) external;

    // Allow ADMIN_ROLE to withdraw funds from the contract
    function withdraw(uint256 amount) external;

}

currentTokenId()

Description:

Tracks the current token ID in the system. Can also be used to determine how many tokens have been minted in the system.

mintBaseFee()

Description:
The base fee for minting a token, paid by the user to create a new token.

creatorSignatureFee()

Description:
The fee required for a user to acquire a creator's signature, allowing them to become a creator in the system.

maxMintsPerUserInCycle()

Description:
The maximum number of mints a user can perform during their current cycle of progressive discounts. Once the limit is exceeded, the user's minting count is reset to zero.

lastUpdateTimestamp()

Description:
Timestamp of the last time the contract terms were updated (e.g., minting fees and creator signature fees). It is used to determine when the contract's terms can be updated again.

UPDATE_INTERVAL()

Description:
The time interval between contract terms updates. MUST be fixed to 30 days.

ADMIN_ROLE()

Description:
The role identifier for admins in the system.

Requirements:

  • MUST be assigned inside the constructor to the msg.sender.

CREATOR_ROLE()

Description:
The role identifier for creators in the system.

Requirements:

  • MUST be assigned inside the constructor to the msg.sender.

CONTRIBUTOR_ROLE()

Description:
The role identifier for contributors in the system.

mintsPerUserInCycle(address user)

Description:
Tracks the number of mints a user has performed in their current cycle of progressive discounts. It is used to enforce the maximum minting limit per user.

CreatorTermsUpdated(uint256 mintBaseFee, uint256 creatorSignatureFee, uint256 maxMintsPerUserInCycle)

Description:
Emitted when the contract terms related to minting are updated by the ADMIN_ROLE.

DonationReceived(address from, address to, uint256 amount)

Description:
Emitted when a user donates ETH to a creator. This event tracks the details of the donation, including the donor's address, the recipient's address, and the donation amount.

Parameters:

  • from: The address of the user making the donation.
  • to: The address of the creator receiving the donation.
  • amount: The amount of ETH donated.

safeMint(string memory uri)

Description:
Allows the caller to mint a new token to their address with a provided URI.

Requirements:

  • The caller MUST have the CREATOR_ROLE.
  • The user MUST pay the minting fee, which is dynamic based on their previous minting activity.
  • If the minting limit is exceeded, the user's mint count SHALL be reset to zero.
  • Is RECOMMENDED to require that the contract is not paused before using this function.

mintFee()

Description:
Calculates and returns the current minting fee that the caller MUST pay, based on the number of mints performed during his current discount per mint cycle. Is RECOMMENDED that the fee use a logarithmic reduction to adjust the fee smoothly.

Formula:

$$\text{mintFee} = \begin{cases} 0, & \text{if msg.sender has the ADMIN\_ROLE} \\ \frac{\text{mintBaseFee}}{\log_x(\text{userMints})}, & \text{if } \text{userMints} > 1 \\ \frac{\text{mintBaseFee}}{1}, & \text{if } \text{userMints} <= 1 \end{cases}$$

Note: Please note that the returned logarithm is always rounded to integers due to the characteristics of Solidity with floating-point numbers.

Requirements:

  • The minting fee MUST be paid by the caller.

donate(address creator)

Description:
Allows users to donate ETH to a creator, helping fund their activities. After making a donation, the donor SHALL receive the CONTRIBUTOR_ROLE.

Requirements:

  • The provided address MUST be a valid creator (having the CREATOR_ROLE).
  • The msg.sender MUST NOT be the same as the creator.
  • The donation amount MUST be greater than zero.
  • MUST emit a DonationReceived event after the donation is processed.

getCreatorSignature()

Description:
Allows a user to acquire a creator's signature by paying the required fee.

Requirements:

  • The caller MUST pay the creator signature fee.
  • After the payment, the caller SHALL be granted the CREATOR_ROLE.
  • Is RECOMMENDED to require that the contract is not paused before using this function.

updateTerms(uint256 mintBaseFee, uint256 creatorSignatureFee, uint256 maxMintsPerUserInCycle)

Description:
Allows the admin to update the minting fee, creator signature fee, and the maximum mints per user in a cycle of progressive discounts.

Requirements:

  • Only the ADMIN_ROLE MUST call this function.
  • MUST be called in the contract constructor as the first update of the contract terms.
  • The update interval period SHALL be respected before another update can occur.
  • MUST emit a CreatorTermsUpdated event after the contract terms are updated.

withdraw(uint256 amount)

Description:
Allows the ADMIN_ROLE to withdraw ETH from the contract.

Requirements:

  • Only the ADMIN_ROLE MUST call this function.

burn(uint256 tokenId)

Description:
Allows the owner of a token to burn (destroy) the token specified by tokenId.

Requirements:

  • The caller MUST be the owner of the token.

pause()

Description:
Allows the ADMIN_ROLE to pause the contract, disabling certain functions.

Requirements:

  • Only the ADMIN_ROLE SHOULD call this function to pause the contract.

unpause()

Description:
Allows the ADMIN_ROLE to unpause the contract, re-enabling functionality.

Requirements:

  • Only the ADMIN_ROLE SHOULD call this function to unpause the contract.

Rationale

Below are the key considerations and justifications for the design choices:

  1. Access Control

    • Problem: In collaborative NFT systems, it is essential to ensure that critical contract functions are executed only by authorized users to prevent misuse or manipulation. Without proper access control, there is a risk that anyone could modify key parameters, such as minting fees, terms, or contract pauses, which could lead to instability or unfair advantages for certain users.
    • Solution: By introducing role-based access control, this standard ensures that only trusted actors can perform sensitive actions. Admins are responsible for updating contract terms, pausing or unpausing the contract, and withdrawing funds, while creators can manage their own collections and get donations. This prevents arbitrary changes that might harm market stability or erode community trust.
  2. Dynamic Minting Fees

    • Problem: Fixed minting fees often lead to hoarding and disproportionate ownership, limiting equitable access to NFTs.
    • Solution: By dynamically adjusting minting fees based on user activity within defined minting cycles, we ensure that users are incentivized to engage with the platform by receiving gradual discounts as they mint. Using a logarithmic reduction in minting fees ensures that the process is gradual, preventing market manipulation and maintaining scarcity over time.
  3. Donation-Based Engagement

    • Problem: Creators often lack sustainable models for fostering community engagement and receiving contributions.
    • Solution: The donation system provides a transparent way for contributors to support their favorite creators directly. This can be used to attribute benefits in future trades, for example. This encourages deeper engagement and strengthens the relationship between creators and their communities.

Backwards Compatibility

This EIP is fully compatible with ERC-721. Extensions like dynamic minting fees, donation systems are modular and do not impact existing NFT token functionalities.


Reference Implementation

mintFee()

function mintFee() public view returns (uint256) {
    if (hasRole(ADMIN_ROLE, msg.sender)) return 0;
    uint256 userMints = mintsPerUserInCycle(msg.sender);
    uint256 divisor = userMints <= 1 ? 1 : Math.log2(userMints);
    return mintBaseFee / divisor;
}

safeMint(string memory uri)

function safeMint(string memory uri)
public
payable
override 
onlyIfNotPaused
nonReentrant
onlyRole(CREATOR_ROLE)
{
    bool userMintsExceeded = mintsPerUserInCycle(msg.sender) + 1 > maxMintsPerUserInCycle;

    require(msg.value >= mintFee(), "Not enough ETH!");

    uint256 tokenId = currentTokenId++;
    _safeMint(msg.sender, tokenId);
    _setTokenURI(tokenId, uri);

    if(userMintsExceeded){
        mintsPerUserInCycle(msg.sender) = 0;
    }
    mintsPerUserInCycle(msg.sender)++;
}

Security Considerations

  • Reentrancy Protection:
    Is RECOMMENDED to make sure the functions safeMint, withdraw and donate are protected against reentrancy attacks.
  • Paused State:
    The Administrators MUST be able to pause the contract during emergencies to prevent unwanted operations and mitigate risks during uncertain times.
  • Burning Security:
    Ensure that only the owner of a token can burn it, reducing the risk of malicious contracts or unauthorized users destroying tokens belonging to others. The burn behavior is restricted to the ownership function, enhancing security by preventing accidental or abusive token destruction.

Copyright

Copyright and related rights waived via CC0.

@eip-review-bot
Copy link
Collaborator

eip-review-bot commented Dec 4, 2024

File ERCS/erc-7832.md

Requires 1 more reviewers from @g11tech, @SamWilsn, @xinbenlv

ERCS/erc-xxxx.md Outdated Show resolved Hide resolved
ERCS/erc-xxxx.md Outdated Show resolved Hide resolved
ERCS/erc-xxxx.md Outdated Show resolved Hide resolved
ERCS/erc-xxxx.md Outdated Show resolved Hide resolved
ERCS/erc-xxxx.md Outdated Show resolved Hide resolved
gfLobo and others added 2 commits December 4, 2024 21:57
Co-authored-by: Andrew B Coathup <28278242+abcoathup@users.noreply.github.com>
@github-actions github-actions bot added w-ci and removed w-ci labels Dec 5, 2024
@eip-review-bot eip-review-bot changed the title Add ERC: Sustainable Collections Add ERC: Sustainable NFT Collections Dec 5, 2024
@github-actions github-actions bot added w-ci and removed w-ci labels Dec 5, 2024
@github-actions github-actions bot removed the w-ci label Dec 11, 2024
@github-actions github-actions bot added the w-ci label Dec 11, 2024
@gfLobo gfLobo changed the title Add ERC: Sustainable NFT Collections Add ERC-7832: Sustainable NFT Collections Dec 13, 2024
ERCS/erc-7832.md Outdated Show resolved Hide resolved
ERCS/erc-7832.md Outdated Show resolved Hide resolved
ERCS/erc-7832.md Show resolved Hide resolved
ERCS/erc-7832.md Show resolved Hide resolved
ERCS/erc-7832.md Outdated Show resolved Hide resolved
ERCS/erc-7832.md Outdated Show resolved Hide resolved
ERCS/erc-7832.md Outdated Show resolved Hide resolved
ERCS/erc-7832.md Outdated Show resolved Hide resolved
ERCS/erc-7832.md Outdated Show resolved Hide resolved
ERCS/erc-7832.md Outdated Show resolved Hide resolved
gfLobo and others added 4 commits January 18, 2025 15:18
Co-authored-by: Sam Wilson <57262657+SamWilsn@users.noreply.github.com>
Co-authored-by: Sam Wilson <57262657+SamWilsn@users.noreply.github.com>
Co-authored-by: Sam Wilson <57262657+SamWilsn@users.noreply.github.com>
@eip-review-bot eip-review-bot changed the title Add ERC: Sustainable NFT Collections Add ERC: Sustainable collaborative NFT collections Jan 20, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants