Staking de NFTs en Solidity
Tags: blockchain, solidity, nfts, defi
Published: 2021-10-12 13:02:54

---
title: Staking de NFTs en Solidity
published: true
description: 
tags: blockchain, solidity, nfts, defi
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3clnp54oejfnbza2fsyh.png
---

El Staking de NFTs es un trend que está conectando los nuevos proyectos de NFTs con el resto del ecosistema DeFi. El staking ha demostrado ser un mecanismo que incentiva comprar y holdear por lo que pienso que es bastante prometedor combinarlo con mundo de los NFTs.

## Qué necesitas para este tutorial

Para este tutorial necetias tener instalado [Metamask](https://metamask.io/) y tener fondos en Rinkeby que puedes conseguir desde el [faucet](https://faucet.rinkeby.io/).

## 1. Lanzamos un contrato de NFTs

Este es un ejemplo mínimo de colección de ERC-721 solo con fines únicamente educativos.

```solidity
// SPDX-License-Identifier: MIT
pragma solidity 0.8.9;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";

contract MyNFTCollection is ERC721 {
    uint256 token_count;

    constructor() ERC721("My NFT", "MYNFT") {}
    
    function mintNFT(address to) public
    {
        _mint(to, token_count);
        token_count  += 1;
    }
}
```

## 2. Lanzamos el toquen que premia por Stakear

Asegurate de reemplazar `0x0000000000000000000000000000000000000000` por el address del contrato ERC-721.

```solidity
// SPDX-License-Identifier: MIT
pragma solidity 0.8.9;
import '@openzeppelin/contracts/token/ERC20/ERC20.sol';
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";

contract MyNFTLiquidityPool is ERC20
{
    mapping(address => uint256) public checkpoints;
    mapping(address => uint256) public deposited_tokens;
    mapping(address => bool) public has_deposited;
    ERC721 public my_token;
    
    uint public REWARD_PER_BLOCK = 0.1 ether;
    
    constructor() ERC20("My Staking Token", "MYST"){
        my_token = ERC721(0x0000000000000000000000000000000000000000);
    }
    
    function deposit(uint256 tokenId) external
    {
        require (msg.sender == my_token.ownerOf(tokenId), 'Sender must be owner');
        require (!has_deposited[msg.sender], 'Sender already deposited');
        if(checkpoints[msg.sender] == 0){
            checkpoints[msg.sender] = block.number;
        }
        collect(msg.sender);
        my_token.transferFrom(msg.sender, address(this), tokenId);
        deposited_tokens[msg.sender] = tokenId;
        has_deposited[msg.sender] = true;
   }

    function withdraw() external
    {
        require(has_deposited[msg.sender], 'No tokens to withdarw');
        collect(msg.sender);
        my_token.transferFrom(address(this), msg.sender, deposited_tokens[msg.sender]);
        has_deposited[msg.sender] = false;
    }

    function collect(address beneficiary) public
    {
        uint256 reward = calculateReward(beneficiary);
        checkpoints[beneficiary] = block.number;      
        _mint(msg.sender, reward);
    }
    
    function calculateReward(address beneficiary) public view returns(uint256)
    {
        if(!has_deposited[beneficiary])
        {
            return 0;
        }
        uint256 checkpoint = checkpoints[beneficiary];
        return REWARD_PER_BLOCK * (block.number-checkpoint);
    }
}
```



**¡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.

**Updates**
23/06/2022 Gracias a Yerson corregimos la función calculateReward