Remix directory structure for NFT ERC721 contract that supports secondary sales royalties

Crypto Market Pool: contrato ERC721 que respalda las regalías de ventas

Publicado por
Comparte en redes sociales

En este tutorial, crearemos un contrato Solidity ERC721 que admita regalías de ventas secundarias. Este contrato le permitirá crear tokens NFT, publicarlos para la venta en diferentes intercambios y permitir que el propietario del contrato reclame una regalía de creador en cada venta secundaria. Este contrato respalda las regalías de ventas secundarias en las plataformas comerciales Open Sea, Rarible y Mintable.

Este es un contrato avanzado y si es la primera vez que crea un NFT, le recomendaría leer «Cómo crear un contrato inteligente ERC721 Solidity». Luego regrese a este tutorial para aprender cómo implementar funciones avanzadas en un contrato ERC721.

Primeros pasos con un contrato de Solidity

En este momento, asegúrese de configurar su entorno de desarrollo. Puede utilizar cualquier IDE de Solidity con el que esté familiarizado. Para este tutorial usaremos remezclar ya que es simple, está basado en la web y hay mucho material de capacitación en la web para aprender cómo comenzar.

Dependencias del contrato ERC721

Cabe señalar que el contrato inteligente que crearemos requiere varios archivos de dependencia. Estos archivos de dependencia son fundamentales para que el contrato NFT respalde las regalías de ventas secundarias para el propietario del contrato. Las dependencias del contrato son las siguientes:

  1. Métodos de propiedad necesarios para Open Sea
  2. Métodos de regalías para Rarible
  3. Métodos de regalías ERC2981 NFT para Mintable

Agregaremos cada uno de los archivos de dependencia a Remix y los importaremos a nuestro contrato ERC721. Como alternativa, puede guardarlos en su repositorio de Github e importarlos a su contrato.

Configurar dependencias de regalías de ventas de contratos ERC721 en Remix

Primero cree los siguientes directorios en Remix en el explorador de archivos. Es importante que siga esta estructura de carpetas y archivos en Remix con las mismas convenciones de nomenclatura. Siempre puede cambiar la estructura y los nombres en una fecha posterior.

Cree los siguientes directorios:

  1. rarezas/regalías/contratos
  2. rarezas/royalties/contratos/impl

En estas dos carpetas pondremos 5 de los contratos de dependencia que necesitamos para este contrato NFT.

Estructura de directorio de remezclas para el contrato NFT ERC721 que admite regalías de ventas secundarias

Directorio – objetos raros/regalías/contratos

En segundo lugar, coloque los siguientes archivos de dependencia en el directorio raribles/royalties/contracts

  1. LibPart
  2. LibRoyaltiesV2
  3. RegalíasV2
Estructura de directorio de remezclas para el contrato NFT ERC721 que admite el explorador de archivos de regalías de ventas secundarias en remezclas

LibPart – Necesario para las regalías de ventas secundarias de Rarible

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

library LibPart {
    bytes32 public constant TYPE_HASH = keccak256("Part(address account,uint96 value)");

    struct Part {
        address payable account;
        uint96 value;
    }

    function hash(Part memory part) internal pure returns (bytes32) {
        return keccak256(abi.encode(TYPE_HASH, part.account, part.value));
    }
}

Pruébalo en remezclar

LibRoyaltiesV2 – Necesario para las regalías de ventas secundarias de Rarible

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

library LibRoyaltiesV2 {
    /*
     * bytes4(keccak256('getRaribleV2Royalties(uint256)')) == 0xcad96cca
     */
    bytes4 constant _INTERFACE_ID_ROYALTIES = 0xcad96cca;
}

Pruébalo en remezclar

Leer también  Aprende a invertir en criptomonedas con estos 4 libros

RegalíasV2 – Necesario para las regalías de ventas secundarias de Rarible

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;


import "./LibPart.sol";

interface RoyaltiesV2 {
    event RoyaltiesSet(uint256 tokenId, LibPart.Part[] royalties);

    function getRaribleV2Royalties(uint256 id) external view returns (LibPart.Part[] memory);
}

Pruébalo en remezclar

Directorio – rarezas/royalties/contratos/impl

Tercero, coloque los siguientes archivos de dependencia en el directorio raribles/royalties/contracts/impl

  1. ResumenRealezas
  2. RegalíasV2Impl
Estructura de directorio de remezclas para el contrato NFT ERC721 que admite el explorador de archivos de regalías de ventas secundarias en remezclas. dependencias

ResumenRealezas – Necesario para las regalías de ventas secundarias de Rarible

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "../LibPart.sol";

abstract contract AbstractRoyalties {
    mapping (uint256 => LibPart.Part[]) internal royalties;

    function _saveRoyalties(uint256 id, LibPart.Part[] memory _royalties) internal {
        uint256 totalValue;
        for (uint i = 0; i < _royalties.length; i++) {
            require(_royalties[i].account != address(0x0), "Recipient should be present");
            require(_royalties[i].value != 0, "Royalty value should be positive");
            totalValue += _royalties[i].value;
            royalties[id].push(_royalties[i]);
        }
        require(totalValue < 10000, "Royalty total value should be < 10000");
        _onRoyaltiesSet(id, _royalties);
    }

    function _updateAccount(uint256 _id, address _from, address _to) internal {
        uint length = royalties[_id].length;
        for(uint i = 0; i < length; i++) {
            if (royalties[_id][i].account == _from) {
                royalties[_id][i].account = payable(address(uint160(_to)));
            }
        }
    }

    function _onRoyaltiesSet(uint256 id, LibPart.Part[] memory _royalties) virtual internal;
}

Pruébalo en remezclar

RegalíasV2Impl – Necesario para las regalías de ventas secundarias de Rarible

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./AbstractRoyalties.sol";
import "../RoyaltiesV2.sol";

contract RoyaltiesV2Impl is AbstractRoyalties, RoyaltiesV2 {

    function getRaribleV2Royalties(uint256 id) override external view returns (LibPart.Part[] memory) {
        return royalties[id];
    }

    function _onRoyaltiesSet(uint256 id, LibPart.Part[] memory _royalties) override internal {
        emit RoyaltiesSet(id, _royalties);
    }
}

Pruébalo en remezclar

Crear un contrato inteligente ERC721

Ahora que todos nuestros archivos dependientes se han configurado y creado, creemos el contrato inteligente ERC721. En la raíz del explorador de archivos Remix, cree un nuevo archivo para nuestro contrato ERC721. Cabe señalar que si no se sigue la estructura de carpetas y archivos ilustrada arriba y abajo, los contratos dependientes no se importarán a su contrato inteligente correctamente.

Estructura de directorio de remezclas para el contrato NFT ERC721 que admite el explorador de archivos de regalías de ventas secundarias en remezclas

Ahora copie el contrato a continuación y péguelo en Remix. Este contrato contiene las declaraciones de importación necesarias para Open Zeppelin y los archivos dependientes enumerados anteriormente. El contrato admite:

  1. acuñación de nuevos NFT
  2. revelando el proyecto NFT
  3. pausar la capacidad de acuñar NFT
  4. regalías de ventas secundarias en múltiples plataformas
  5. etc

Además, lea los comentarios en el código de contrato inteligente de Solidity para comprender cómo funcionan las diferentes funciones. Obtendrá una comprensión de todo el proceso de NFT, incluido cómo funcionan las regalías comerciales secundarias.

// SPDX-License-Identifier: MIT

pragma solidity &gt;=0.7.0 <0.9.0;

import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
//Ownable is needed to setup sales royalties on Open Sea
//if you are the owner of the contract you can configure sales Royalties in the Open Sea website
import "@openzeppelin/contracts/access/Ownable.sol";
//the rarible dependency files are needed to setup sales royalties on Rarible 
import "rarible/royalties/contracts/impl/RoyaltiesV2Impl.sol";
import "rarible/royalties/contracts/LibPart.sol";
import "rarible/royalties/contracts/LibRoyaltiesV2.sol";

//give your contract a name
contract NAMEYOURCONTRACT is ERC721Enumerable, Ownable, RoyaltiesV2Impl {
  using Strings for uint256;

//configuration
  string baseURI;
  string public baseExtension = ".json";

//set the cost to mint each NFT
  uint256 public cost = 0.00 ether;

//set the max supply of NFT's
  uint256 public maxSupply = 100;

//set the maximum number an address can mint at a time
  uint256 public maxMintAmount = 1;

//is the contract paused from minting an NFT
  bool public paused = false;

//are the NFT's revealed (viewable)? If true users can see the NFTs. 
//if false everyone sees a reveal picture
  bool public revealed = true;

//the uri of the not revealed picture
  string public notRevealedUri;

  bytes4 private constant _INTERFACE_ID_ERC2981 = 0x2a55205a;

  constructor(
    string memory _name,
    string memory _symbol,
    string memory _initBaseURI,
    string memory _initNotRevealedUri
  ) ERC721(_name, _symbol) {
    setBaseURI(_initBaseURI);
    setNotRevealedURI(_initNotRevealedUri);
  }


  //internal function for base uri
  function _baseURI() internal view virtual override returns (string memory) {
    return baseURI;
  }

  //function allows you to mint an NFT token
  function mint(uint256 _mintAmount) public payable {
    uint256 supply = totalSupply();
    require(!paused);
    require(_mintAmount > 0);
    require(_mintAmount <= maxMintAmount);
    require(supply + _mintAmount <= maxSupply);

    if (msg.sender != owner()) {
      require(msg.value >= cost * _mintAmount);
    }

    for (uint256 i = 1; i <= _mintAmount; i++) {
      _safeMint(msg.sender, supply + i);
    }
  }

//function returns the owner
  function walletOfOwner(address _owner)
    public
    view
    returns (uint256[] memory)
  {
    uint256 ownerTokenCount = balanceOf(_owner);
    uint256[] memory tokenIds = new uint256[](ownerTokenCount);
    for (uint256 i; i < ownerTokenCount; i++) {
      tokenIds[i] = tokenOfOwnerByIndex(_owner, i);
    }
    return tokenIds;
  }

//input a NFT token ID and get the IPFS URI
  function tokenURI(uint256 tokenId)
    public
    view
    virtual
    override
    returns (string memory)
  {
    require(
      _exists(tokenId),
      "ERC721Metadata: URI query for nonexistent token"
    );
    
    if(revealed == false) {
        return notRevealedUri;
    }

    string memory currentBaseURI = _baseURI();
    return bytes(currentBaseURI).length > 0
        ? string(abi.encodePacked(currentBaseURI, tokenId.toString(), baseExtension))
        : "";
  }


  //only owner
  function reveal() public onlyOwner {
      revealed = true;
  }
  
//set the cost of an NFT
  function setCost(uint256 _newCost) public onlyOwner {
    cost = _newCost;
  }

//set the max amount an address can mint
  function setmaxMintAmount(uint256 _newmaxMintAmount) public onlyOwner {
    maxMintAmount = _newmaxMintAmount;
  }
  
//set the not revealed URI on IPFS
  function setNotRevealedURI(string memory _notRevealedURI) public onlyOwner {
    notRevealedUri = _notRevealedURI;
  }

//set the base URI on IPFS
  function setBaseURI(string memory _newBaseURI) public onlyOwner {
    baseURI = _newBaseURI;
  }


  function setBaseExtension(string memory _newBaseExtension) public onlyOwner {
    baseExtension = _newBaseExtension;
  }

//pause the contract and do not allow any more minting
  function pause(bool _state) public onlyOwner {
    paused = _state;
  }
 

  function withdraw() public payable onlyOwner {
   
    (bool success, ) = payable(msg.sender).call{value: address(this).balance}("");
    require(success);
  }


    

    //configure royalties for Rariable
    function setRoyalties(uint _tokenId, address payable _royaltiesRecipientAddress, uint96 _percentageBasisPoints) public onlyOwner {
        LibPart.Part[] memory _royalties = new LibPart.Part[](1);
        _royalties[0].value = _percentageBasisPoints;
        _royalties[0].account = _royaltiesRecipientAddress;
        _saveRoyalties(_tokenId, _royalties);
    }


    //configure royalties for Mintable using the ERC2981 standard
    function royaltyInfo(uint256 _tokenId, uint256 _salePrice) external view returns (address receiver, uint256 royaltyAmount) {
      //use the same royalties that were saved for Rar
      LibPart.Part[] memory _royalties = royalties[_tokenId];
      if(_royalties.length > 0) {
        return (_royalties[0].account, (_salePrice * _royalties[0].value) / 10000);
      }
      return (address(0), 0);
    }


    function supportsInterface(bytes4 interfaceId) public view virtual override(ERC721Enumerable) returns (bool) {
        if(interfaceId == LibRoyaltiesV2._INTERFACE_ID_ROYALTIES) {
            return true;
        }

        if(interfaceId == _INTERFACE_ID_ERC2981) {
          return true;
        }

        return super.supportsInterface(interfaceId);
    }

}

Pruébalo en remezclar

Leer también  H2ODao (H2O) Token ¿Qué es, cómo comprar y precio?

Finalmente, modifique el contrato anterior para satisfacer sus necesidades de NFT. Puede usar el tutorial Cómo crear e implementar una colección NFT + el contrato de arriba para construir un gran proyecto NFT.

Después de crear un contrato ERC721, asegúrese de implementarlo en el entorno Goerli y probarlo con Open Sea, Rarible y Mintable. Asegúrese de probar la acuñación de tokens, cambiar los parámetros en el contrato y establecer regalías de ventas. El entorno de prueba de mar abierto en https://testnets.opensea.io/ permite a los propietarios de contratos conectar sus billeteras y establecer porcentajes de regalías de ventas.

Por último, pero no menos importante, no olvide revisar su código, auditar su contrato y escribir casos de prueba de unidad. Además, es importante realizar su propia investigación, auditoría y pruebas antes de implementar un contrato inteligente en la cadena de bloques. Este contrato ERC721 que respalda las regalías de ventas secundarias y otros contratos en este sitio son solo para fines educativos.

Si quiere puede hacernos una donación por el trabajo que hacemos, lo apreciaremos mucho.

Direcciones de Billetera:

- BTC: 14xsuQRtT3Abek4zgDWZxJXs9VRdwxyPUS 

- USDT: TQmV9FyrcpeaZMro3M1yeEHnNjv7xKZDNe 

- BNB: 0x2fdb9034507b6d505d351a6f59d877040d0edb0f

- DOGE: D5SZesmFQGYVkE5trYYLF8hNPBgXgYcmrx 

También puede seguirnos en nuestras Redes sociales para mantenerse al tanto de los últimos post de la web:

-Twitter

- Telegram

Disclaimer: En Cryptoshitcompra.com no nos hacemos responsables de ninguna inversión de ningún visitante, nosotros simplemente damos información sobre Tokens, juegos NFT y criptomonedas, no recomendamos inversiones

Dejar un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *