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;
}
}
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);
}
}
¡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