Claim without stake
Published: 2022-09-12 17:52:55

---
title: Claim without stake
published: true
description: 
tags: 
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l2xk8lfubrqn4s8fbaxj.png
---

What we call DeFi 2.0 (autocompund, reflections, etc) can also be applied to NFTs. In this video we will launch a token whose inflation is controlled by NFTs that rewards the holders just for the simple act of holding. In this ecosystem there is no need to deposit the NFT in any contract we just do a direct claim, and the tokens will be minted directly to our wallet.

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

## Before we start

For this tutorial you will need [Metamask](https://metamask.io/) or another EVM compatible wallet with Goerli funds that you can get from a [faucet](https://goerlifaucet.com/).

## The NFTs

First, we launch the NFT contract, notice the `register` function that makes this magic possible.

```solidity
// 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);
    }
}
```

## The Token

When you launch the token contract, make sure to connect it to the NFT contract, executing the function `setTokenContract`. This will kickstart the rewards.

```solidity
// 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);
    }
}
```

**Thanks for watching this video!**

Follows us on dev.to and in [Youtube]( https://www.youtube.com/channel/UCbF5CFuXv2vTkcGfepWV2nA) for everything related to Blockchain development.