Address
0x0c99b3101e2a06bc85eee5ad43d299e3ecf4e7e7Current Holdings
$0.00
TXs sent
not counted
First Active
2023-06-16
block 17,541,751
Last Active
1,187 days ago
block 17,541,751
Funded By
not identified
Net worth historyi
2 snapshots · to block 27,455,284coverage change 26 Augcoverage change 27 Augcoverage change 27 Augcoverage change 27 Augcoverage change 27 Aug
partial matchEcoNFTsolc 0.8.3+commit.8d00100cruntime partial · creation partial
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; // ERC20 interface
import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; // ERC721
import "@openzeppelin/contracts/access/Ownable.sol"; // OZ: Ownable
import "@openzeppelin/contracts/utils/math/SafeMath.sol"; // OZ: SafeMath
import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; // OZ: ReentrancyGuard
import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; // OZ: EnumerableSet
contract EcoNFT is ERC721, ReentrancyGuard, Ownable {
using SafeMath for uint256;
using Strings for string;
using Strings for uint256;
using EnumerableSet for EnumerableSet.UintSet;
uint256 public constant PINO_NFT_SIZE = 1080;
uint256 public constant TERU_NFT_LEVEL_LEN = 5;
bool public is_synthetic; // synthetics opened
EnumerableSet.UintSet internal mintedTokenIds;
uint256 internal fee;
uint256 public mintSize;
uint256 public startIndex; //inclusive
uint256 public endIndex; //exclusive
uint256 public pinoStartIndex; //inclusive
uint256 public pinoEndIndex; //exclusive
uint256 public airdropStartIndex; //inclusive
uint256 public syntheticStartIndex; //inclusive
uint256 public boxSold;
uint256 public nftMinted;
uint256 public pinoNftMinted;
uint256 public airdropNftMinted;
uint256 public mintFeeETH;
uint256 public mintFeeToken;
uint256 public pinoMintFeeETH;
uint256 public pinoMintFeeToken;
address public teamWallet;
IERC20 public immutable EsgToken;
mapping(uint256 => uint256) public levels;
mapping(bytes32 => address) requestToSender;
mapping (uint256 => address) internal depositOf;
/**
* Events
*/
event BuyLuckyBoxETH(address indexed account, uint256 tokenId, uint256 cost);
event BuyLuckyBoxESG(address indexed account, uint256 tokenId, uint256 cost);
event NFTSyntheticed(address indexed pinoNftOwner, uint256 indexed pinoTokenId, uint256 indexed teruTokenId, uint256 tokenId, uint256 teruNftLevel);
/**
*
*/
constructor(address _esgToken)
ERC721("TeTeru NFT", "TeTeru NFT")
{
EsgToken = IERC20(_esgToken);
fee = 0.1 * 10**18; // 0.1 LINK
mintSize = 1000;
startIndex = 0;
endIndex = 1000;
pinoStartIndex = 10000;
pinoEndIndex = 11000;
airdropStartIndex = 20000;
syntheticStartIndex = 30000;
airdropNftMinted = 0;
pinoNftMinted = 0;
mintFeeETH = 0.3 * 10**18; //0.3 ETH
mintFeeToken = 476 * 10**18; //320 ESG
pinoMintFeeETH = 0.08 * 10**18; //0.1 ETH
pinoMintFeeToken = 158 * 10**18; //120 ESG
teamWallet = 0x9e3ee009c2E8103Fb2D358d64C80249eF108e33B;
is_synthetic = false;
}
function getLevelById(uint256 id) internal pure returns(uint256){
if(id<410)
return 1;
if(id<740)
return 2;
if(id<910)
return 3;
if(id<990)
return 4;
if(id<1000)
return 5;
return 0;
}
//buy a lucky box
function requestNewRandomNFTETH(address referrer) public payable nonReentrant returns (uint256) {
require(
referrer != address(0),
"Invalid referrer"
);
require(msg.value >= mintFeeETH, "INSUFFICIENT MINT COST ETH");
uint256 newId = random(1000);
boxSold = boxSold.add(1);
if(_exists(newId))
{
for(uint256 i=startIndex; i < endIndex; i++)
{
if(!_exists(i))
{
newId = i;
break;
}
}
require(!_exists(newId), "BOX SOLD OUT");
}
nftMinted = nftMinted.add(1);
levels[newId] = getLevelById(newId);
payable(referrer).transfer(msg.value.div(20));
payable(teamWallet).transfer(msg.value.mul(19).div(20));
_safeMint(msg.sender, newId);
EnumerableSet.add(mintedTokenIds, newId);
emit BuyLuckyBoxETH(msg.sender, newId, msg.value);
return newId;
}
function requestNewRandomNFTToken(address referrer) public nonReentrant returns (uint256) {
require(
referrer != address(0),
"Invalid referrer"
);
require(EsgToken.balanceOf(msg.sender) >= mintFeeToken, "INSUFFICIENT MINT COST TOKEN");
EsgToken.transferFrom(msg.sender, address(this), mintFeeToken);
uint256 newId = random(1000);
boxSold = boxSold.add(1);
if(_exists(newId))
{
for(uint256 i=startIndex; i < endIndex; i++)
{
if(!_exists(i))
{
newId = i;
break;
}
}
require(!_exists(newId), "BOX SOLD OUT");
}
nftMinted = nftMinted.add(1);
levels[newId] = getLevelById(newId);
EsgToken.transfer(referrer, mintFeeToken.div(20));
EsgToken.transfer(teamWallet, mintFeeToken.mul(19).div(20));
_safeMint(msg.sender, newId);
EnumerableSet.add(mintedTokenIds, newId);
emit BuyLuckyBoxESG(msg.sender, newId, mintFeeToken);
return newId;
}
/**
* @notice Synthetic two kinds of NFT to one Gold NFT(Teru and Pino)
* @param pinoTokenId The tokenId of Pino NFT to be deposited
* @param teruTokenId The tokenId of Teru NFT to be deposited
* @return Success indicator for success
*/
function synthetic(uint256 pinoTokenId, uint256 teruTokenId) external nonReentrant returns (bool) {
require(is_synthetic == true, "sythentic is not open.");
uint256 pinoNftLevel = EcoNFT(address(this)).getLevel(pinoTokenId);
require(pinoNftLevel == 0, "Pino NFT accepted.");
require(depositOf[pinoTokenId] == address(0), "Pino token already sythenticed");
address pinoNftOwner = EcoNFT(address(this)).ownerOf(pinoTokenId);
EcoNFT(address(this)).safeTransferFrom(pinoNftOwner, address(this), pinoTokenId);
depositOf[pinoTokenId] = pinoNftOwner;
uint256 teruNftLevel = EcoNFT(address(this)).getLevel(teruTokenId);
require(teruNftLevel > 0, "Teru NFT accepted.");
require(depositOf[teruTokenId] == address(0), "Teru token already sythenticed");
address teruNftOwner = EcoNFT(address(this)).ownerOf(teruTokenId);
EcoNFT(address(this)).safeTransferFrom(teruNftOwner, address(this), teruTokenId);
depositOf[teruTokenId] = teruNftOwner;
uint256 aStartIndex = syntheticStartIndex;
uint256 newId = aStartIndex.add(1);
require(!_exists(newId), "NFT minted.");
nftMinted = nftMinted.add(1);
_safeMint(msg.sender, newId);
EnumerableSet.add(mintedTokenIds, newId);
levels[newId] = teruNftLevel.add(TERU_NFT_LEVEL_LEN);
emit NFTSyntheticed(pinoNftOwner, pinoTokenId, teruTokenId, newId, teruNftLevel);
return true;
}
function airdropMint(address receipient)
external
onlyOwner
{
uint256 aStartIndex = airdropStartIndex.add(airdropNftMinted);
for(uint256 i=0; i < 20; i++)
{
uint256 newId = aStartIndex.add(i);
require(!_exists(newId), "NFT minted.");
nftMinted = nftMinted.add(1);
airdropNftMinted = airdropNftMinted.add(1);
levels[newId] = 0;
_safeMint(receipient, newId);
EnumerableSet.add(mintedTokenIds, newId);
}
}
function pinoMintETH(address referrer, address receipient) public payable nonReentrant
{
require(referrer != address(0), "invalid address");
require(receipient != address(0), "invalid address");
require(msg.value >= pinoMintFeeETH, "INSUFFICIENT MINT COST ETH");
uint256 newId = pinoStartIndex.add(pinoNftMinted);
require(newId < pinoEndIndex, "tokenId exceeds limit");
require(!_exists(newId), "NFT minted.");
nftMinted = nftMinted.add(1);
pinoNftMinted = pinoNftMinted.add(1);
payable(referrer).transfer(msg.value.div(20));
payable(teamWallet).transfer(msg.value.mul(19).div(20));
levels[newId] = 0;
_safeMint(receipient, newId);
EnumerableSet.add(mintedTokenIds, newId);
}
function pinoMintToken(address referrer, address receipient) public nonReentrant
{
require(referrer != address(0), "invalid address");
require(receipient != address(0), "invalid address");
require(EsgToken.balanceOf(msg.sender) >= pinoMintFeeToken, "INSUFFICIENT MINT COST TOKEN");
EsgToken.transferFrom(msg.sender, address(this), pinoMintFeeToken);
uint256 newId = pinoStartIndex.add(pinoNftMinted);
require(newId < pinoEndIndex, "tokenId exceeds limit");
require(!_exists(newId), "NFT minted.");
nftMinted = nftMinted.add(1);
pinoNftMinted = pinoNftMinted.add(1);
EsgToken.transfer(referrer, pinoMintFeeToken.div(20));
EsgToken.transfer(teamWallet, pinoMintFeeToken.mul(19).div(20));
levels[newId] = 0;
_safeMint(receipient, newId);
EnumerableSet.add(mintedTokenIds, newId);
}
function random(uint number) internal view returns(uint) {
return uint(keccak256(abi.encodePacked(block.timestamp,block.difficulty,msg.sender))) % number;
}
function getLevel(uint256 tokenId) public view returns (uint256) {
return levels[tokenId];
}
function getNumberOfBoxSold() external view returns (uint256) {
return boxSold;
}
function getMintedNFTLength() external view returns (uint256) {
return EnumerableSet.length(mintedTokenIds);
}
function getMintedNFT(uint256 index) external view returns (uint256) {
return EnumerableSet.at(mintedTokenIds, index);
}
/// @notice Returns metadata about a token (depending on randomness reveal status)
/// @dev Partially implemented, returns only example string of randomness-dependent content
function tokenURI(uint256 tokenId) override public pure returns (string memory) {
string[2] memory parts;
parts[0] = 'https://econft.market/service/meta.php?id=';
parts[1] = string(tokenId.toString());
string memory output = string(abi.encodePacked(parts[0], parts[1]));
return output;
}
function tokenURIExtend(uint256 tokenId) public pure returns (string memory, string memory) {
string[3] memory parts;
parts[0] = 'https://econft.market';
parts[1] = '/service/meta.php?id=';
parts[2] = string(tokenId.toString());
string memory api = string(abi.encodePacked(parts[1], parts[2]));
return (parts[0], api);
}
// admin functions
function _setMintSize(uint256 size) public onlyOwner {
require(size != 0);
mintSize = size;
}
function _setStartIndex(uint256 startId) public onlyOwner {
startIndex = startId;
}
function _setEndIndex(uint256 endId) public onlyOwner {
require(endId != 0);
endIndex = endId;
}
function _setLevelsMap(uint256[] memory ids, uint256[] memory lvs) public onlyOwner {
require(ids.length != 0 && ids.length == lvs.length);
for(uint256 i=0; i< ids.length; i++)
levels[ids[i]] = lvs[i];
}
function _setMintFeeETH(uint256 _mintFee) public onlyOwner {
require(_mintFee != 0);
mintFeeETH = _mintFee;
}
function _setMintFeeToken(uint256 _mintFee) public onlyOwner {
require(_mintFee != 0);
mintFeeToken = _mintFee;
}
function _setPinoMintFeeETH(uint256 _mintFee) public onlyOwner {
require(_mintFee != 0);
pinoMintFeeETH = _mintFee;
}
function _setPinoMintFeeToken(uint256 _mintFee) public onlyOwner {
require(_mintFee != 0);
pinoMintFeeToken = _mintFee;
}
function _setTeamWallet(address _wallet) public onlyOwner {
require(_wallet != address(0));
teamWallet = _wallet;
}
function _withdrawERC20Token(address token) public onlyOwner {
uint256 amount = IERC20(token).balanceOf(address(this));
if(amount > 0)
IERC20(token).transfer(teamWallet, amount);
}
function _withdrawETH() public onlyOwner {
uint256 amount = address(this).balance;
if(amount > 0)
payable(teamWallet).transfer(amount);
}
/**
* @notice Update synthetic status
* @param flag If synthetic should be opened.
*/
function _updateIsSynthetic(bool flag) external onlyOwner {
is_synthetic = flag;
}
function _setPinoEndIndex(uint256 endId) public onlyOwner {
pinoEndIndex = endId;
}
}