Mints random verificables de NFTs
Tags: blockchain, soldity, nfts, chainlink
Published: 2021-10-26 18:51:58

---
title: Mints random verificables de NFTs
published: true
description: 
tags: blockchain, soldity, nfts, chainlink
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ts6ttdbrxp07m8ey1cis.png
---

Muchos usuarios no saben que la mayoría de NFTs en el mercado de hoy tienen fuertes componentes centralizados. La buena noticia es que poco a poco nuevos proyectos están integrando componentes que [ayudan a decentralizar](https://www.chainlinkecosystem.com/ecosystem/). En este video exploramos cómo hacer mints random verificables y porqué quisiéramos hacerlo o no.

{% youtube uu3jiS2okzA %}

## 1. La metadata

Subimos la metadata a cualquier servidor web siguiendo los estándares de los ERC-1155.

Recuerda llamar a los archivos de metadata siguiendo la sequencia `0000000000000000000000000000000000000000000000000000000000000000.json`.

```json
{
    "name": "Zanahoria",
    "description": "Tiene muchas vitaminas",
    "image": "https://TUURL/Zanahoria.png"
}
```

## 2. El contrato

Este contrato funciona únicamente en Polygon Ethereum Plasma y está compuesto de los siguientes elementos:

* Router de [Quickswap](https://quickswap.exchange/): Nos permite comprar el token LINK que ocupamos como fee para recibir un número random del oráculo. En el caso de polygon el fee es de `0.0001` LINK.
* [PegSwap](https://pegswap.chain.link/): Los tokens que obtenemos a través de Quickswap (o a través del Polygon Bridge) no son compatibles con el oráculo. Por eso debemos swapearlos via PegSwap donde cambiamos nuestros LINKS normales con los LINKS ERC-677 que sí son compatibles con el oráculo.
* [Chainlink VRF](https://docs.chain.link/docs/chainlink-vrf/): Es oráculo de chainlink que nos devuelve un número random
* Los [Price Feeds](https://docs.chain.link/docs/get-the-latest-price/): Nos ayudan a calcular el precio de mercado al momento de comprar el fee de los oráculos.

En este contrato, cuando compramos un NFT vía `mintNFT` destinamos un poco del `MATIC` del precio de compra para comprar `0.0001` LINK en Quickswap. Luego cambiamos ese `0.0001` LINK por LINK ERC-677 que usamos para pagar el fee cuando solicitamos un número random por medio de `requestRandomness`. Obtenemos ese valor en el callback `fulfillRandomness` y es ahí donde seleccionamos un id del token ERC-1155 de manera aleatoria.

Recuerda modificar `CREATOR`, `BASE_URI` y `PRICE` antes de lanzar.

```solidity
// SPDX-License-Identifier: MIT
pragma solidity 0.8.9;

import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@chainlink/contracts/src/v0.8/VRFConsumerBase.sol";
import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";

contract Router {
    function swapETHForExactTokens(
        uint amountOut,
        address[] calldata path,
        address to,
        uint deadline
    ) external payable returns (uint[] memory amounts) {}
}

contract PegSwap {
    function swap(
        uint256 amount,
        address source,
        address target
    ) external {}
}

contract MyNFT is ERC1155, VRFConsumerBase {
    address CREATOR = 0x0000000000000000000000000000000000000000;
    string BASE_URI = "https://MIURL{id}.json";

    uint256 public PRICE = 0.1 ether;
    uint256 SLIPPAGE_PERCENTAGE = 20;

    bytes32 VRF_KEYHASH = 0xf86195cf7690c55907b2b611ebb7343a6f649bff128701cc542f0569e2c549da;
    uint256 VRF_FEE = 0.0001 ether;
    address VRF_COORDINATOR = 0x3d2341ADb2D31f1c5530cDC622016af293177AE0;

    Router quickswap = Router(0xa5E0829CaCEd8fFDD4De3c43696c57F7D7A678ff);
    PegSwap peg_swap = PegSwap(0xAA1DC356dc4B18f30C347798FD5379F3D77ABC5b);
    ERC20 WMATIC_token  = ERC20(0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270);
    ERC20 LINK_token  = ERC20(0x53E0bca35eC356BD5ddDFebbD1Fc0fD03FaBad39);
    ERC20 LINK_ERC677_token  = ERC20(0xb0897686c545045aFc77CF20eC7A532E3120E0F1);
    AggregatorV3Interface MATIC_LINK_price_feed = AggregatorV3Interface(0x5787BefDc0ECd210Dfa948264631CD53E68F7802);

    mapping(bytes32  => address) public sender_request_ids;

    constructor()
        ERC1155(BASE_URI)
        VRFConsumerBase(
            VRF_COORDINATOR,
            address(LINK_ERC677_token)
        )
    {
    }

    function mintNFT(address to) public payable
    {
        require(msg.value >= PRICE, "Value below price");
        swapMATICToLINK();
        sender_request_ids[requestRandomness(VRF_KEYHASH, VRF_FEE)] = to;
    }

    function swapMATICToLINK() public payable
    {
        address[] memory path = new address[](2);
        path[0] = address(WMATIC_token);
        path[1] = address(LINK_token);

        quickswap.swapETHForExactTokens{value: ((getMaticPrice() * VRF_FEE) / 1 ether) * (100 + SLIPPAGE_PERCENTAGE) / 100}(
            VRF_FEE,
            path,
            address(this),
            block.timestamp
        );
        LINK_token.approve(address(peg_swap), VRF_FEE);
        peg_swap.swap(
            VRF_FEE,
            address(LINK_token),
            address(LINK_ERC677_token)
        );
    }

    function getMaticPrice() public view returns (uint)
    {
        (
            uint80 roundID, 
            int price,
            uint startedAt,
            uint timeStamp,
            uint80 answeredInRound
        ) = MATIC_LINK_price_feed.latestRoundData();
        roundID;
        startedAt;
        timeStamp;
        answeredInRound;
        return uint(price);
    }

    function fulfillRandomness(bytes32 requestId, uint256 randomness) internal override {
        uint token_id = randomness % 3;
        uint amount = 1;
        _mint(sender_request_ids[requestId], token_id, amount, "");
    }

    function withdraw() public
    {
        payable(CREATOR).transfer(address(this).balance);
        LINK_token.transfer(payable(CREATOR), LINK_token.balanceOf(address(this)));
        LINK_ERC677_token.transfer(payable(CREATOR), LINK_ERC677_token.balanceOf(address(this)));
    }

    fallback() external payable {}
    receive() external payable {}
}
```

**¡Gracias por ver este tutorial!**

Sígueme en dev.to y en [Youtube](https://www.youtube.com/channel/UCNRB4tgwp09z4391JRjEsRA) para todo lo relacionado al desarrollo en Blockchain en Español.