0%

thlm | THLMNFT

相关合约

  • GAMENFT
  • 质押合约

GAMENFT

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import {Pausable} from "@openzeppelin/contracts/security/Pausable.sol";
import {ReentrancyGuard} from "@openzeppelin/contracts/security/ReentrancyGuard.sol";


interface GameNFTStake {
function stakeFromMint(address user, uint256 tokenId) external;
}

contract GameNFT is ERC1155, Ownable, Pausable, ReentrancyGuard {
IERC20 public gameToken; // Game币的合约接口
GameNFTStake public stakeContract; // 质押合约
address public daoAddress = 0xbA97a5F7b8B662Dc5B34a283faD741dDc615E690; // 国库地址
address public burnAddress = 0x000000000000000000000000000000000000dEaD;//销毁地址
address public preMintOwner;


uint256 public burnPercentage = 5; // 销毁比例
uint256 public daoPercentage = 90; // 国库比例
uint256 public premiumPercentage = 10; // 10%的溢价

struct NFTType {
uint256 price;
bool pause;
bool exist;
}

mapping(uint256 => NFTType) public nftTypes; // 存储每种NFT的信息
uint256 public nftTypeCount; // NFT种类的计数器

event NFTMinted(address minter, address refer,uint256 tokenId, uint256 amount,uint256 price);
event NewNFTTypeAdded(uint256 tokenId, uint256 price);

modifier onlyPreMintOwner() {
require(msg.sender == preMintOwner, "only PreMintOwner");
_;
}

constructor(address ownerAddress,address _gameToken) ERC1155("") Ownable(ownerAddress) {
gameToken = IERC20(_gameToken);
preMintOwner = ownerAddress;
}

function renouncePreMintOwner() public onlyPreMintOwner {
preMintOwner = address(0);
}

function changeNFTPause(uint256 _tokenId,bool _pause) external onlyOwner{
NFTType storage nftType = nftTypes[_tokenId];
nftType.pause = _pause;
}

function updateDaoAddress(address _daoAddress) external onlyOwner{
daoAddress = _daoAddress;
}

function updateBurnPercentage(uint _burnPercentage) external onlyOwner{
burnPercentage = _burnPercentage;
}

function updateDaoPercentage(uint _daoPercentage) external onlyOwner{
daoPercentage = _daoPercentage;
}

function updatePremiumPercentage(uint _premiumPercentage) external onlyOwner{
premiumPercentage = _premiumPercentage;
}

function addNFTType(uint256 _price) external onlyOwner {
nftTypeCount++;
nftTypes[nftTypeCount] = NFTType(_price, false,true);
emit NewNFTTypeAdded(nftTypeCount, _price);
}

function setStakingContract(address _stakingContract) external onlyOwner {
stakeContract = GameNFTStake(_stakingContract);
}

function mintPreNFT(uint256 _tokenId) external nonReentrant onlyPreMintOwner{
require(!nftTypes[_tokenId].pause, "NFT is paused");
require(nftTypes[_tokenId].exist, "NFT is not exist");
uint256 totalPrice = 0;

_mintNFT(totalPrice, burnAddress);
_mint(msg.sender, _tokenId, 1, ""); // 直接 mint

emit NFTMinted(msg.sender,burnAddress, _tokenId, 1,totalPrice);
}

function mintOriginNFT(uint256 _tokenId,address _referrer) external nonReentrant whenNotPaused{
require(!nftTypes[_tokenId].pause, "NFT is paused");
require(nftTypes[_tokenId].exist, "NFT is not exist");
uint256 totalPrice = nftTypes[_tokenId].price;

_mintNFT(totalPrice, _referrer);

_mint(msg.sender, _tokenId, 1, ""); // 质押

emit NFTMinted(msg.sender,_referrer, _tokenId, 1,totalPrice);
}

function mintPremiumNFT(uint256 _tokenId,address _referrer) external nonReentrant whenNotPaused{
require(!nftTypes[_tokenId].pause, "NFT is paused");
require(nftTypes[_tokenId].exist, "NFT is not exist");
uint256 totalPrice = nftTypes[_tokenId].price * (100 + premiumPercentage) / 100;

_mintNFT(totalPrice, _referrer);
_mint(address(stakeContract), _tokenId, 1, ""); // mint 到质押合约中
stakeContract.stakeFromMint(msg.sender,_tokenId);

emit NFTMinted(msg.sender,_referrer, _tokenId, 1,totalPrice);
}



function _mintNFT(uint totalPrice,address _referrer) internal {
require(gameToken.balanceOf(msg.sender) >= totalPrice, "Game is not enough");
require(gameToken.allowance(msg.sender, address(this)) >= totalPrice, "Game approve is not enough");

// 转移 GAME 代币到合约
require(gameToken.transferFrom(msg.sender, address(this), totalPrice), "transfer fail");
// 计算各部分金额
uint256 burnAmount = (totalPrice * burnPercentage) / 100; // 销毁
uint256 daoAmount = (totalPrice * daoPercentage) / 100; // 进国库
uint256 referralAmount = totalPrice - burnAmount - daoAmount; // 返佣

// 销毁部分GAME代币
gameToken.transfer(burnAddress, burnAmount);

// 转移到国库
gameToken.transfer(daoAddress, daoAmount);

// 处理返佣(如果有推荐人)
if (_referrer != address(0) && _referrer != msg.sender) {
gameToken.transfer(_referrer, referralAmount);
} else {
// 如果没有有效的推荐人,将返佣部分也转入国库
gameToken.transfer(daoAddress, referralAmount);
}
}

function setURI(string memory newuri) external onlyOwner {
_setURI(newuri);
}
}

质押合约

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC1155/IERC1155.sol";
import "@openzeppelin/contracts/token/ERC1155/utils/ERC1155Holder.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

contract GameNFTStake is ERC1155Holder, Ownable {

IERC1155 public nftContract;

struct StakedNFT {
uint256 tokenId;
uint256 amount;
uint256 stakedAt;
uint256 unlockTime;
}

mapping(address => StakedNFT[]) public stakedNFTs;

event NFTStaked(address user, uint256 tokenId, uint256 amount, uint256 unlockTime);
event NFTUnstaked(address user, uint256 tokenId, uint256 amount);

constructor() Ownable(msg.sender) {
}

function setNftContract(address _nftContract) external onlyOwner {
nftContract = IERC1155(_nftContract);
}

function stakeFromMint(address user, uint256 tokenId) external {
require(msg.sender == address(nftContract), "Only NFT contract can call this function");
_stake(user,tokenId);
}

function stake(uint256 tokenId) external {
require(nftContract.balanceOf(msg.sender, tokenId) >= 1, "Insufficient balance");
nftContract.safeTransferFrom(msg.sender, address(this), tokenId, 1, "");
_stake(msg.sender,tokenId);
}

function _stake(address user,uint256 tokenId) internal {
uint256 unlockTime = block.timestamp + 30 seconds;
stakedNFTs[user].push(StakedNFT(tokenId, 1, block.timestamp, unlockTime));
emit NFTStaked(user, tokenId, 1, unlockTime);
}

function unstake(uint256 index) external {
require(index < stakedNFTs[msg.sender].length, "Invalid index");
StakedNFT storage stakedNFT = stakedNFTs[msg.sender][index];
require(block.timestamp >= stakedNFT.unlockTime, "Staking period not finished");

uint256 tokenId = stakedNFT.tokenId;
uint256 amount = stakedNFT.amount;

nftContract.safeTransferFrom(address(this), msg.sender, tokenId, amount, "");

// Remove the unstaked NFT from the array
stakedNFTs[msg.sender][index] = stakedNFTs[msg.sender][stakedNFTs[msg.sender].length - 1];
stakedNFTs[msg.sender].pop();

emit NFTUnstaked(msg.sender, tokenId, amount);
}

function getStakedNFTs(address user) external view returns (StakedNFT[] memory) {
return stakedNFTs[user];
}
}
请我喝杯咖啡吧~