Staking de NFTs en Solidity

Ahmed Castro - Oct 12 '21 - - Dev Community

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

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Terabox Video Player