DEV Community

Cover image for Staking de NFTs en Solidity
Ahmed Castro
Ahmed Castro

Posted on • Edited on

Staking de NFTs en Solidity

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 y tener fondos en Rinkeby que puedes conseguir desde el faucet.

1. Lanzamos un contrato de NFTs

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

// 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;
    }
}
Enter fullscreen mode Exit fullscreen mode

2. Lanzamos el toquen que premia por Stakear

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

// 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);
    }
}
Enter fullscreen mode Exit fullscreen mode

¡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

Top comments (5)

Collapse
 
unknowncoder05 profile image
Yerson

encontre un problema con el contrato, en la funcion calculateReward
en la condicional if(!has_deposited[msg.sender])
deberia ser if(!has_deposited[beneficiary])

Collapse
 
turupawn profile image
Ahmed Castro

Tenes razón, ya lo corregí, muchas gracias.

Collapse
 
draco profile image
john carlos

Como se puede hacer para que un nft tenga un periodo de vida. Para hacer staking. Y despues como hacer para devolverle su poder de staking

Collapse
 
turupawn profile image
Ahmed Castro

Muy buena pregunta, no tengo un video al respecto pero combinando este video con un poco de extra solidity lo podes lograr.

Collapse
 
wailancrypto profile image
Wailancrypto

amigo me interesa mucho tu trabajo, tengo varias artes para trabajar juntos en un proyecto, contactame gaminglancry@gmail.com o por twitter @wailancrypto