지분 없는 청구

12984 단어
우리가 DeFi 2.0이라고 부르는 것(autocompund, reflections 등)은 NFT에도 적용될 수 있습니다. 이 비디오에서 우리는 단순한 보유 행위에 대해 보유자에게 보상하는 NFT에 의해 인플레이션이 제어되는 토큰을 출시할 것입니다. 이 생태계에서는 계약에 NFT를 입금할 필요가 없으며 직접 청구하면 토큰이 지갑에 직접 발행됩니다.

시작하기 전에



이 튜토리얼에서는 Metamask 또는 faucet에서 얻을 수 있는 Goerli 자금이 포함된 다른 EVM 호환 지갑이 필요합니다.

NFT



먼저 NFT 계약을 시작하고 이 마법을 가능하게 하는 register 기능에 주목합니다.

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


토큰



토큰 컨트랙트를 실행할 때 NFT 컨트랙트에 연결하여 함수setTokenContract를 실행해야 합니다. 이렇게 하면 보상이 시작됩니다.

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


이 비디오를 시청해 주셔서 감사합니다!

블록체인 개발과 관련된 모든 것을 보려면 dev.to 및 in에서 우리를 팔로우하세요.

좋은 웹페이지 즐겨찾기