DEV Community

Cover image for Claimea sin Stakear
Ahmed Castro
Ahmed Castro

Posted on

Claimea sin Stakear

Lo que llamábamos DeFi 2.0 con autocompund y reflexiones también se puede aplicar a los NFTs. En este video lanzaremos un Token cuya inflación está controlada por NFTs que premian a los holders por el simple hecho de holdear. En este ecosistema no hay necesidad de depositar el NFT en ningún contrato solo se hace un claimeo directo y los tokens serán minteados directo a nuestra wallet.

https://www.youtube.com/watch?v=dkUjpXAkdmY

Antes de comenzar

Para este tutorial ocuparás Metamask u otra wallet compatible con fondos en Goerli que puedes obtener desde un faucet.

Los NFTs

Primero lanzamos el contrato de NFTs, toma nota de la función register que hace posible esta magia.

// SPDX-License-Identifier: MIT
pragma solidity 0.8.16;

import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

interface ITokenContract
{
    function register(uint tokenId) external;
}

contract NFTContract is ERC721, Ownable {  
    ITokenContract tokenContract;

    uint public price = 0.001 ether;
    uint public constant MAX_SUPPLY = 10000;
    uint public supply;

    constructor () ERC721 ("My NFT", "MNFT") {
    }

    function mint(uint _amount) public payable {
        require( supply + _amount <= MAX_SUPPLY, "Can't mint more than max supply" );
        require( msg.value == price * _amount, "Wrong amount of ETH sent" );
        require( _amount >= 1, "Must mint at least one" );
        for(uint i; i < _amount; i++){
            _safeMint( msg.sender, supply + i );
            tokenContract.register(supply + i);
        }
    }

    function withdrawETH() public onlyOwner
    {
        (bool sent, bytes memory data) = address(owner()).call{value: address(this).balance}("");
        require(sent, "Failed to send Ether");
        data;
    }

    function setTokenContract(address tokenContractAddress) public onlyOwner {
        tokenContract = ITokenContract(tokenContractAddress);
    }
}
Enter fullscreen mode Exit fullscreen mode

Los Tokens

El mismo contrato de tokens se encarga de distribuir las recompenzas a los holders. Luego de lanzarlo el contrato de tokens, asegurate de conectarlo con el contrato de NFTs ejecutando la función setTokenContract. Esto permitirá a quienes minteen los nfts empezar a mintear y recibir recompenzas.

// SPDX-License-Identifier: MIT
pragma solidity 0.8.16;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

interface INFTContract
{
    function ownerOf(uint tokenId) external view returns (address owner);
}

contract TokenContract is ERC20, Ownable {
    uint public REWARD_PER_BLOCK = 0.1 ether;

    INFTContract public myERC721Contract;

    mapping(uint => uint) public checkpoints;
    mapping(uint => bool) public isRegistered;

    constructor(address nftContractAddress) ERC20("My Token", "TKN") {
        myERC721Contract = INFTContract(nftContractAddress);
    }

    function register(uint tokenId) public
    {
        require(msg.sender == address(myERC721Contract));
        isRegistered[tokenId] = true;
        checkpoints[tokenId] = block.number;
    }

    function claim(uint tokenId) public
    {
        require(myERC721Contract.ownerOf(tokenId) == msg.sender, "Must be token owner");
        uint256 reward = calculateReward(tokenId);
        _mint(msg.sender, reward);
        checkpoints[tokenId] = block.number;
    }

    function calculateReward(uint tokenId) public view returns(uint256)
    {
        if(!isRegistered[tokenId])
        {
            return 0;
        }
        uint256 checkpoint = checkpoints[tokenId];
        return REWARD_PER_BLOCK * (block.number-checkpoint);
    }
}
Enter fullscreen mode Exit fullscreen mode

Gracias por ver este video!

Sígannos en dev.to y en Youtube para todo lo relacionado al desarrollo en Blockchain en Español.

Top comments (0)