Skip to main content
PulseScanner.io

Address

0x3c8d2fce49906e11e71cb16fa0ffeb2b16c29638
Current Holdings
$0.00
TXs sent
not counted
First Active
2023-05-16
block 17,280,866
Last Active
14 days ago
block 27,435,021
Funded By
not identified

Net worth historyi

2 snapshots · to block 27,488,864coverage change 26 Augcoverage change 27 Augcoverage change 27 Augcoverage change 27 Augcoverage change 27 Aug
exact matchNFTLTokensolc 0.8.4+commit.c7e474f2runtime exact · creation exact
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC20/presets/ERC20PresetMinterPauser.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";

/**
 * @title NFTL Token (The native ecosystem token of Nifty League)
 * @dev Extends standard ERC20 contract from OpenZeppelin
 */
contract NFTLToken is ERC20PresetMinterPauser("Nifty League", "NFTL") {
    /// @notice NFTL tokens calaimable per day for each DEGEN NFT holder
    uint256 public constant EMISSION_PER_DAY = 68.49315e18; // ~68.5 NFTL

    /// @notice Start timestamp from contract deployment
    uint256 public immutable emissionStart;

    /// @notice End date for NFTL emissions to DEGEN NFT holders
    uint256 public immutable emissionEnd;

    /// @dev A record of last claimed timestamp for DEGEN NFTs
    mapping(uint256 => uint256) private _lastClaim;

    /// @dev Contract address for DEGEN NFT
    address private _nftAddress;

    /**
     * @notice Construct the NFTL token
     * @param emissionStartTimestamp Timestamp of deployment
     */
    constructor(uint256 emissionStartTimestamp) {
        emissionStart = emissionStartTimestamp;
        emissionEnd = emissionStartTimestamp + (1 days * 365 * 3);
    }

    // External functions

    /**
     * @notice Sets the contract address to Nifty League DEGEN NFTs upon deployment
     * @param nftAddress Address of verified DEGEN NFT contract
     * @dev Only callable once
     */
    function setNFTAddress(address nftAddress) external onlyRole(DEFAULT_ADMIN_ROLE) {
        require(_nftAddress == address(0), "Already set");
        _nftAddress = nftAddress;
    }

    // Public functions

    /**
     * @notice Check last claim timestamp of accumulated NFTL for given DEGEN NFT
     * @param tokenIndex Index of DEGEN NFT to check
     * @return Last claim timestamp
     */
    function getLastClaim(uint256 tokenIndex) public view returns (uint256) {
        require(tokenIndex <= ERC721Enumerable(_nftAddress).totalSupply(), "NFT at index not been minted");
        require(ERC721Enumerable(_nftAddress).ownerOf(tokenIndex) != address(0), "Owner cannot be 0 address");
        uint256 lastClaimed = uint256(_lastClaim[tokenIndex]) != 0 ? uint256(_lastClaim[tokenIndex]) : emissionStart;
        return lastClaimed;
    }

    /**
     * @notice Check accumulated NFTL tokens for a DEGEN NFT
     * @param tokenIndex Index of DEGEN NFT to check balance
     * @return Total NFTL accumulated and ready to claim
     */
    function accumulated(uint256 tokenIndex) public view returns (uint256) {
        require(block.timestamp > emissionStart, "Emission has not started yet");

        uint256 lastClaimed = getLastClaim(tokenIndex);
        // Sanity check if last claim was on or after emission end
        if (lastClaimed >= emissionEnd) return 0;

        uint256 accumulationPeriod = block.timestamp < emissionEnd ? block.timestamp : emissionEnd; // Getting the min value of both
        uint256 totalAccumulated = ((accumulationPeriod - lastClaimed) * EMISSION_PER_DAY) / 1 days;

        // If claim hasn't been done before for the index, add initial allotment
        if (lastClaimed == emissionStart) {
            if (tokenIndex > 9500 && tokenIndex < 9901)
                totalAccumulated = totalAccumulated + 21500e18; // 21500 NFTL
            else if (tokenIndex > 8500)
                totalAccumulated = totalAccumulated + 15000e18; // 15000 NFTL
            else if (tokenIndex > 6500)
                totalAccumulated = totalAccumulated + 10000e18; // 10000 NFTL
            else if (tokenIndex > 4500)
                totalAccumulated = totalAccumulated + 8000e18; // 8000 NFTL
            else if (tokenIndex > 2500)
                totalAccumulated = totalAccumulated + 6000e18; // 6000 NFTL
            else if (tokenIndex > 1000)
                totalAccumulated = totalAccumulated + 4000e18; // 4000 NFTL
            else totalAccumulated = totalAccumulated + 2000e18; // 2000 NFTL
        }
        return totalAccumulated;
    }

    /**
     * @notice Check total accumulated NFTL tokens for all DEGEN NFTs
     * @param tokenIndices Indexes of NFTs to check balance
     * @return Total NFTL accumulated and ready to claim
     */
    function accumulatedMultiCheck(uint256[] memory tokenIndices) public view returns (uint256) {
        require(block.timestamp > emissionStart, "Emission has not started yet");
        uint256 totalClaimableQty = 0;
        for (uint256 i = 0; i < tokenIndices.length; i++) {
            uint256 tokenIndex = tokenIndices[i];
            // Sanity check for non-minted index
            require(tokenIndex <= ERC721Enumerable(_nftAddress).totalSupply(), "NFT at index not been minted");
            uint256 claimableQty = accumulated(tokenIndex);
            totalClaimableQty = totalClaimableQty + claimableQty;
        }
        return totalClaimableQty;
    }

    /**
     * @notice Mint and claim available NFTL for each DEGEN NFT
     * @param tokenIndices Indexes of NFTs to claim for
     * @return Total NFTL claimed
     */
    function claim(uint256[] memory tokenIndices) public returns (uint256) {
        require(block.timestamp > emissionStart, "Emission has not started yet");

        uint256 totalClaimQty = 0;
        for (uint256 i = 0; i < tokenIndices.length; i++) {
            // Sanity check for non-minted index
            require(tokenIndices[i] <= ERC721Enumerable(_nftAddress).totalSupply(), "NFT at index not been minted");
            // Duplicate token index check
            for (uint256 j = i + 1; j < tokenIndices.length; j++) {
                require(tokenIndices[i] != tokenIndices[j], "Duplicate token index");
            }

            uint256 tokenIndex = tokenIndices[i];
            require(ERC721Enumerable(_nftAddress).ownerOf(tokenIndex) == _msgSender(), "Sender is not the owner");

            uint256 claimQty = accumulated(tokenIndex);
            if (claimQty != 0) {
                totalClaimQty = totalClaimQty + claimQty;
                _lastClaim[tokenIndex] = block.timestamp;
            }
        }

        require(totalClaimQty != 0, "No accumulated NFTL");
        _mint(_msgSender(), totalClaimQty);
        return totalClaimQty;
    }
}