DCIPs/assets/eip-5725/contracts/ERC5725.sol

164 lines
4.6 KiB
Solidity

// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.17;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
import "./IERC5725.sol";
abstract contract ERC5725 is IERC5725, ERC721 {
using SafeERC20 for IERC20;
/// @dev mapping for claimed payouts
mapping(uint256 => uint256) /*tokenId*/ /*claimed*/
internal _payoutClaimed;
/**
* @notice Checks if the tokenId exists and its valid
* @param tokenId The NFT token id
*/
modifier validToken(uint256 tokenId) {
require(_exists(tokenId), "ERC5725: invalid token ID");
_;
}
/**
* @dev See {IERC5725}.
*/
function claim(uint256 tokenId) external override(IERC5725) validToken(tokenId) {
require(ownerOf(tokenId) == msg.sender, "Not owner of NFT");
uint256 amountClaimed = claimablePayout(tokenId);
require(amountClaimed > 0, "ERC5725: No pending payout");
emit PayoutClaimed(tokenId, msg.sender, amountClaimed);
_payoutClaimed[tokenId] += amountClaimed;
IERC20(payoutToken(tokenId)).safeTransfer(msg.sender, amountClaimed);
}
/**
* @dev See {IERC5725}.
*/
function vestedPayout(uint256 tokenId) public view override(IERC5725) returns (uint256 payout) {
return vestedPayoutAtTime(tokenId, block.timestamp);
}
/**
* @dev See {IERC5725}.
*/
function vestedPayoutAtTime(uint256 tokenId, uint256 timestamp)
public
view
virtual
override(IERC5725)
returns (uint256 payout);
/**
* @dev See {IERC5725}.
*/
function vestingPayout(uint256 tokenId)
public
view
override(IERC5725)
validToken(tokenId)
returns (uint256 payout)
{
return _payout(tokenId) - vestedPayout(tokenId);
}
/**
* @dev See {IERC5725}.
*/
function claimablePayout(uint256 tokenId)
public
view
override(IERC5725)
validToken(tokenId)
returns (uint256 payout)
{
return vestedPayout(tokenId) - _payoutClaimed[tokenId];
}
/**
* @dev See {IERC5725}.
*/
function claimedPayout(uint256 tokenId)
public
view
override(IERC5725)
validToken(tokenId)
returns (uint256 payout)
{
return _payoutClaimed[tokenId];
}
/**
* @dev See {IERC5725}.
*/
function vestingPeriod(uint256 tokenId)
public
view
override(IERC5725)
validToken(tokenId)
returns (uint256 vestingStart, uint256 vestingEnd)
{
return (_startTime(tokenId), _endTime(tokenId));
}
/**
* @dev See {IERC5725}.
*/
function payoutToken(uint256 tokenId) public view override(IERC5725) validToken(tokenId) returns (address token) {
return _payoutToken(tokenId);
}
/**
* @dev See {IERC165-supportsInterface}.
* IERC5725 interfaceId = 0x7c89676d
*/
function supportsInterface(bytes4 interfaceId)
public
view
virtual
override(ERC721, IERC165)
returns (bool supported)
{
return interfaceId == type(IERC5725).interfaceId || super.supportsInterface(interfaceId);
}
/**
* @dev Internal function to get the payout token of a given vesting NFT
*
* @param tokenId on which to check the payout token address
* @return address payout token address
*/
function _payoutToken(uint256 tokenId) internal view virtual returns (address);
/**
* @dev Internal function to get the total payout of a given vesting NFT.
* @dev This is the total that will be paid out to the NFT owner, including historical tokens.
*
* @param tokenId to check
* @return uint256 the total payout of a given vesting NFT
*/
function _payout(uint256 tokenId) internal view virtual returns (uint256);
/**
* @dev Internal function to get the start time of a given vesting NFT
*
* @param tokenId to check
* @return uint256 the start time in epoch timestamp
*/
function _startTime(uint256 tokenId) internal view virtual returns (uint256);
/**
* @dev Internal function to get the end time of a given vesting NFT
*
* @param tokenId to check
* @return uint256 the end time in epoch timestamp
*/
function _endTime(uint256 tokenId) internal view virtual returns (uint256);
}