update
This commit is contained in:
parent
b8793df4f8
commit
cd02184d35
@ -3,5 +3,17 @@
|
||||
pragma solidity ^0.8.14;
|
||||
|
||||
interface INFT {
|
||||
struct TokenInfo {
|
||||
string image;
|
||||
address[] tokens;
|
||||
uint256 rate;
|
||||
uint256 attack;
|
||||
uint256 defense;
|
||||
uint256 health;
|
||||
uint256 critChance;
|
||||
uint256 critDmg;
|
||||
uint256 recover;
|
||||
}
|
||||
|
||||
function raiseRewardPool(uint256 amount) external;
|
||||
}
|
9
contracts/interfaces/INFTMetadata.sol
Normal file
9
contracts/interfaces/INFTMetadata.sol
Normal file
@ -0,0 +1,9 @@
|
||||
// SPDX-License-Identifier: MIT OR Apache-2.0
|
||||
|
||||
pragma solidity ^0.8.14;
|
||||
|
||||
import "./INFT.sol";
|
||||
|
||||
interface INFTMetadata {
|
||||
function tokenURI(uint256 tokenId, INFT.TokenInfo memory token) external view returns (string memory);
|
||||
}
|
@ -11,8 +11,10 @@ import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
||||
import "./interfaces/ITreasury.sol";
|
||||
import "./interfaces/IPancakeSwapPair.sol";
|
||||
import "./mixins/signature-control.sol";
|
||||
import "./interfaces/INFT.sol";
|
||||
import "./interfaces/INFTMetadata.sol";
|
||||
|
||||
contract NFT is ERC721EnumerableUpgradeable, SignatureControl {
|
||||
contract NFT is ERC721EnumerableUpgradeable, SignatureControl, INFT {
|
||||
using EnumerableSetUpgradeable for EnumerableSetUpgradeable.AddressSet;
|
||||
using SafeERC20Upgradeable for IERC20Upgradeable;
|
||||
|
||||
@ -42,11 +44,15 @@ contract NFT is ERC721EnumerableUpgradeable, SignatureControl {
|
||||
//mint prices, caps, addresses of reward tokens(shiba,floki,doggy,doge)
|
||||
uint256[4] prices = [
|
||||
.001 ether,
|
||||
.0008 ether,
|
||||
.0006 ether,
|
||||
.0004 ether
|
||||
// 300 * 10**18,
|
||||
250 * 10**18,
|
||||
200 * 10**18,
|
||||
250 * 10**18
|
||||
// 250 * 10**18,
|
||||
// 200 * 10**18,
|
||||
// 250 * 10**18
|
||||
];
|
||||
INFTMetadata metadata;
|
||||
IERC20Upgradeable BUSD;
|
||||
IERC20Upgradeable WETH;
|
||||
mapping(address => uint256) tokenToPrices;
|
||||
@ -69,7 +75,6 @@ contract NFT is ERC721EnumerableUpgradeable, SignatureControl {
|
||||
mapping(address => mapping(uint256 => uint256)) accountRewards;
|
||||
mapping(address => mapping(uint256 => uint256)) accountRewardsPerTokenPaid;
|
||||
|
||||
//whitelist shit
|
||||
bool public isPresale = true;
|
||||
uint256 whitelistPrice = 200 ether;
|
||||
uint256 maxMintPerAddressDuringWhitelist = 5;
|
||||
@ -82,17 +87,6 @@ contract NFT is ERC721EnumerableUpgradeable, SignatureControl {
|
||||
|
||||
uint256 statMultiplier = 100000;
|
||||
mapping(uint256 => TokenInfo) tokenIdToInfo;
|
||||
struct TokenInfo {
|
||||
string image;
|
||||
address[] tokens;
|
||||
uint256 rate;
|
||||
uint256 attack;
|
||||
uint256 defense;
|
||||
uint256 health;
|
||||
uint256 critChance;
|
||||
uint256 critDmg;
|
||||
uint256 recover;
|
||||
}
|
||||
|
||||
mapping(address => Tokenomic) addressToToken;
|
||||
struct Tokenomic {
|
||||
@ -150,7 +144,7 @@ contract NFT is ERC721EnumerableUpgradeable, SignatureControl {
|
||||
}
|
||||
|
||||
modifier isValidMint(uint256 amount, uint256 tokenType) {
|
||||
require(!isPresale, "(mint) presale");
|
||||
require(!isPresale, "presale");
|
||||
require(tokenType <= 3, "!tokenType");
|
||||
require(mintCapOfToken[tokenType] + amount <= nftCaps[tokenType]);
|
||||
_;
|
||||
@ -485,68 +479,8 @@ contract NFT is ERC721EnumerableUpgradeable, SignatureControl {
|
||||
address(this),
|
||||
block.timestamp
|
||||
);
|
||||
// return
|
||||
// swapRouter.swapTokensForExactETH(
|
||||
// price,
|
||||
// amount,
|
||||
// path,
|
||||
// address(this),
|
||||
// block.timestamp
|
||||
// );
|
||||
}
|
||||
|
||||
// function isValidClaim(
|
||||
// uint256[] memory tokenAmounts,
|
||||
// bytes memory signature,
|
||||
// uint256 userNonce,
|
||||
// uint256 timestamp
|
||||
// ) internal returns (bool) {
|
||||
// bytes memory data = abi.encodePacked(
|
||||
// _toAsciiString(msg.sender),
|
||||
// " is authorized to claim ",
|
||||
// StringsUpgradeable.toString(tokenAmounts[0]),
|
||||
// " shiba, ",
|
||||
// StringsUpgradeable.toString(tokenAmounts[1]),
|
||||
// " floki, ",
|
||||
// StringsUpgradeable.toString(tokenAmounts[2]),
|
||||
// " doggy, ",
|
||||
// StringsUpgradeable.toString(tokenAmounts[3]),
|
||||
// " doge before ",
|
||||
// StringsUpgradeable.toString(timestamp),
|
||||
// ", ",
|
||||
// StringsUpgradeable.toString(userNonce)
|
||||
// );
|
||||
// bytes32 hash = _toEthSignedMessage(data);
|
||||
// address signer = ECDSAUpgradeable.recover(hash, signature);
|
||||
// require(treasury.isOperator(signer), "Mint not verified by operator");
|
||||
// require(block.timestamp <= timestamp, "Outdated signed message");
|
||||
// require(!usedNonces[userNonce], "Used nonce");
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// function claimRewards(
|
||||
// uint256[] memory amounts,
|
||||
// bytes memory signature,
|
||||
// uint256 userNonce,
|
||||
// uint256 timestamp
|
||||
// ) public {
|
||||
// require(isValidClaim(amounts, signature, userNonce, timestamp), "");
|
||||
// for (uint256 i = 0; i < 4; i++) {
|
||||
// if (amounts[i] > 0) {
|
||||
// address[] memory path;
|
||||
// path[0] = address(WETH);
|
||||
// path[1] = rewardTokens[i];
|
||||
// swapRouter.swapExactTokensForTokens(
|
||||
// amounts[i],
|
||||
// 1,
|
||||
// path,
|
||||
// msg.sender,
|
||||
// block.timestamp
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
function walletOfOwner(address _owner)
|
||||
public
|
||||
view
|
||||
@ -566,39 +500,9 @@ contract NFT is ERC721EnumerableUpgradeable, SignatureControl {
|
||||
override
|
||||
returns (string memory)
|
||||
{
|
||||
require(_exists(tokenId), "Non-existant token");
|
||||
TokenInfo storage token = tokenIdToInfo[tokenId];
|
||||
return
|
||||
string(
|
||||
abi.encodePacked(
|
||||
"data:application/json;base64,",
|
||||
Base64Upgradeable.encode(
|
||||
bytes(
|
||||
abi.encodePacked(
|
||||
'{"name": Babies of Mars #',
|
||||
tokenId,
|
||||
', "description": "adasdasdasd", "image": ',
|
||||
token.image,
|
||||
',{ "attributes": [ {"trait_type": "tokens", "value": ',
|
||||
token.tokens,
|
||||
'}, { "trait_type": "attack", "value": ',
|
||||
token.attack,
|
||||
'}, { "trait_type": "defense", "value": ',
|
||||
token.defense,
|
||||
'}, { "trait_type": "health", "value": ',
|
||||
token.health,
|
||||
'}, { "trait_type": "critical rate", "value": ',
|
||||
token.critChance,
|
||||
'}, { "trait_type": "critical damage", "value": ',
|
||||
token.critDmg,
|
||||
'}, { "trait_type": "recovery", "value": ',
|
||||
token.recover,
|
||||
"} ] }"
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
require(_exists(tokenId), "Non-existent token");
|
||||
TokenInfo memory token = tokenIdToInfo[tokenId];
|
||||
return metadata.tokenURI(tokenId, token);
|
||||
}
|
||||
|
||||
function raiseRewardPool(uint256 amount) public {
|
||||
@ -645,38 +549,38 @@ contract NFT is ERC721EnumerableUpgradeable, SignatureControl {
|
||||
emit RewardPoolRaised(swappedFor);
|
||||
}
|
||||
|
||||
// function _afterTokenTransfer(
|
||||
// address from,
|
||||
// address to,
|
||||
// uint256 tokenId
|
||||
// ) internal virtual override {
|
||||
// super._afterTokenTransfer(from, to, tokenId);
|
||||
// TokenInfo memory info = tokenIdToInfo[tokenId];
|
||||
// if (from != address(0)) {
|
||||
// if (ERC721Upgradeable.balanceOf(from) == 0) {
|
||||
// _holders.remove(from);
|
||||
// }
|
||||
// if (info.tokens.length > 1) {
|
||||
// totalShares[4] -= info.rate;
|
||||
// accountShares[from][4] -= info.rate;
|
||||
// } else {
|
||||
// uint256 idx = addressToType[info.tokens[0]];
|
||||
// totalShares[idx] -= info.rate;
|
||||
// accountShares[from][idx] -= info.rate;
|
||||
// }
|
||||
// }
|
||||
// if (to != address(0)) {
|
||||
// _holders.add(to);
|
||||
// if (info.tokens.length > 1) {
|
||||
//// totalShares[4] += info.rate;
|
||||
//// accountShares[to][4] += info.rate;
|
||||
// } else {
|
||||
//// uint256 idx = addressToType[info.tokens[0]];
|
||||
//// totalShares[idx] += info.rate;
|
||||
//// accountShares[to][idx] += info.rate;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
function _afterTokenTransfer(
|
||||
address from,
|
||||
address to,
|
||||
uint256 tokenId
|
||||
) internal virtual override {
|
||||
super._afterTokenTransfer(from, to, tokenId);
|
||||
TokenInfo memory info = tokenIdToInfo[tokenId];
|
||||
if (from != address(0)) {
|
||||
if (balanceOf(from) == 0) {
|
||||
_holders.remove(from);
|
||||
}
|
||||
if (info.tokens.length > 1) {
|
||||
totalShares[4] -= info.rate;
|
||||
accountShares[from][4] -= info.rate;
|
||||
} else {
|
||||
uint256 idx = addressToType[info.tokens[0]];
|
||||
totalShares[idx] -= info.rate;
|
||||
accountShares[from][idx] -= info.rate;
|
||||
}
|
||||
}
|
||||
if (to != address(0)) {
|
||||
_holders.add(to);
|
||||
if (info.tokens.length > 1) {
|
||||
totalShares[4] += info.rate;
|
||||
accountShares[to][4] += info.rate;
|
||||
} else {
|
||||
uint256 idx = addressToType[info.tokens[0]];
|
||||
totalShares[idx] += info.rate;
|
||||
accountShares[to][idx] += info.rate;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function pendingReward(uint256 idx, address account) public view returns (uint256) {
|
||||
return accountShares[account][idx] + (_rewardPerShare(idx) - accountRewardsPerTokenPaid[account][idx]) / 1e18 + accountRewards[account][idx];
|
||||
@ -726,4 +630,8 @@ contract NFT is ERC721EnumerableUpgradeable, SignatureControl {
|
||||
require(isPresale, "!presale");
|
||||
isPresale = false;
|
||||
}
|
||||
|
||||
function updateMetadata(INFTMetadata newValue) external onlyAdmin {
|
||||
metadata = newValue;
|
||||
}
|
||||
}
|
||||
|
83
contracts/nftMetadata.sol
Normal file
83
contracts/nftMetadata.sol
Normal file
@ -0,0 +1,83 @@
|
||||
// SPDX-License-Identifier: MIT OR Apache-2.0
|
||||
|
||||
pragma solidity ^0.8.14;
|
||||
|
||||
import "@openzeppelin/contracts/utils/Strings.sol";
|
||||
import "@openzeppelin/contracts/utils/Base64.sol";
|
||||
import "./interfaces/INFT.sol";
|
||||
|
||||
contract NFTMetadata {
|
||||
function tokenURI(uint256 tokenId, INFT.TokenInfo calldata token) external view returns (string memory) {
|
||||
return
|
||||
string(
|
||||
abi.encodePacked(
|
||||
"data:application/json;base64,",
|
||||
Base64.encode(
|
||||
bytes(
|
||||
abi.encodePacked(
|
||||
'{"name": "Babies of Mars #',
|
||||
Strings.toString(tokenId),
|
||||
'", "description": "adasdasdasd", "image": "',
|
||||
token.image,
|
||||
'",{ "attributes": [ {"trait_type": "tokens", "value": ',
|
||||
addressArrayToString(token.tokens),
|
||||
'}, { "trait_type": "attack", "value": ',
|
||||
compileStatString(token)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function compileStatString(INFT.TokenInfo calldata token) internal view returns (string memory) {
|
||||
return string(abi.encodePacked(
|
||||
'}, { "trait_type": "attack", "value": ',
|
||||
Strings.toString(token.attack),
|
||||
'}, { "trait_type": "defense", "value": ',
|
||||
Strings.toString(token.defense),
|
||||
'}, { "trait_type": "health", "value": ',
|
||||
Strings.toString(token.health),
|
||||
'}, { "trait_type": "critical rate", "value": ',
|
||||
Strings.toString(token.critChance),
|
||||
'}, { "trait_type": "critical damage", "value": ',
|
||||
Strings.toString(token.critDmg),
|
||||
'}, { "trait_type": "recovery", "value": ',
|
||||
Strings.toString(token.recover),
|
||||
"} ] }"
|
||||
));
|
||||
}
|
||||
|
||||
function addressArrayToString(address[] memory addressArray) internal pure returns (string memory) {
|
||||
string memory result = "[";
|
||||
for(uint256 i = 0; i < addressArray.length; i++) {
|
||||
if(i == addressArray.length-1) {
|
||||
result = string.concat(result,"'0x",toAsciiString(addressArray[i]),"'");
|
||||
} else {
|
||||
|
||||
result = string.concat(result,"'0x",toAsciiString(addressArray[i]),"',");
|
||||
}
|
||||
}
|
||||
result = string.concat(result,"]");
|
||||
return result;
|
||||
}
|
||||
|
||||
function toAsciiString(address x) internal pure returns (string memory) {
|
||||
bytes memory s = new bytes(40);
|
||||
for (uint i = 0; i < 20; i++) {
|
||||
bytes1 b = bytes1(uint8(uint(uint160(x)) / (2**(8*(19 - i)))));
|
||||
bytes1 hi = bytes1(uint8(b) / 16);
|
||||
bytes1 lo = bytes1(uint8(b) - 16 * uint8(hi));
|
||||
s[2*i] = char(hi);
|
||||
s[2*i+1] = char(lo);
|
||||
}
|
||||
return string(s);
|
||||
}
|
||||
|
||||
function char(bytes1 b) internal pure returns (bytes1 c) {
|
||||
if (uint8(b) < 10)
|
||||
return bytes1(uint8(b) + 0x30);
|
||||
else
|
||||
return bytes1(uint8(b) + 0x57);
|
||||
}
|
||||
}
|
@ -16,6 +16,10 @@ contract Treasury is RoleControl {
|
||||
uint256 amount
|
||||
);
|
||||
|
||||
constructor() {
|
||||
_setupRole(DEFAULT_ADMIN_ROLE, msg.sender);
|
||||
}
|
||||
|
||||
function initialize(address admin) public initializer {
|
||||
_setupRole(DEFAULT_ADMIN_ROLE, admin);
|
||||
}
|
||||
|
16
deploy/05_metadata.ts
Normal file
16
deploy/05_metadata.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import { DeployFunction } from 'hardhat-deploy/dist/types';
|
||||
|
||||
const deployFunc: DeployFunction = async ({ getNamedAccounts, deployments, getChainId }) => {
|
||||
const { deploy } = deployments;
|
||||
const { deployer } = await getNamedAccounts();
|
||||
await deploy('NFTMetadata', {
|
||||
from: deployer,
|
||||
args: [],
|
||||
log: true,
|
||||
});
|
||||
};
|
||||
|
||||
const tags = ['NFTMetadata'];
|
||||
|
||||
export default deployFunc;
|
||||
export { tags };
|
@ -10,66 +10,73 @@ const deployFunc: DeployFunction = async ({ getNamedAccounts, deployments, ether
|
||||
|
||||
const AddressZero = ethers.constants.AddressZero;
|
||||
const PancakeRouter = '0xD99D1c33F9fC3444f8101754aBC46c52416550D1';
|
||||
const Owner = deployer; //'0x22f60E6BD7973c226979B6F57BC92C2d66a8c151';
|
||||
const Owner = '0x22f60E6BD7973c226979B6F57BC92C2d66a8c151';
|
||||
const BUSD = '0xB08B32EC7E2Aa60a4C2f4343E7EB638187163415';
|
||||
const WETH = '0xF1960ee684B173cf6c17fCdA5F1dFC366Aba55d3';
|
||||
const RedTrustWallet = '0x22f60E6BD7973c226979B6F57BC92C2d66a8c151';
|
||||
|
||||
const treasuryAddress = '0x0Cb09553b2d1Da0459577d7027EdA21d40f2a7Cb'; //(await get('Treasury')).address;
|
||||
const furnaceAddress = '0xe1cCbDFaBc90F15F96A658a6e96c27D0f1DA9Bd4'; //(await get('RedFurnace')).address;
|
||||
const treasuryAddress = (await get('Treasury')).address;
|
||||
const furnaceAddress = (await get('RedFurnace')).address;
|
||||
const nftAddress = (await get('NFT')).address;
|
||||
const marketAddress = '0x92DE9C3a72d787d16F73e18649139341869f4621'; //(await get('Marketplace')).address;
|
||||
const tokenAddress = '0x341D28f61ea857C31BAC30302D88a69f5E8c3ed0'; //(await get('BabiesOfMars')).address;
|
||||
const marketAddress = (await get('Marketplace')).address;
|
||||
const tokenAddress = (await get('BabiesOfMars')).address;
|
||||
const nftMetadataAddress = (await get('NFTMetadata')).address;
|
||||
|
||||
const token = await ethers.getContractAt('BabiesOfMars', tokenAddress);
|
||||
const pancake = await ethers.getContractAt('IPancakeSwapRouter', PancakeRouter);
|
||||
const busd = await ethers.getContractAt('ERC', BUSD);
|
||||
const weth = await ethers.getContractAt('ERC', WETH);
|
||||
const nft = await ethers.getContractAt('NFT', nftAddress);
|
||||
const nftMetadata = await ethers.getContractAt('NFTMetadata', nftMetadataAddress);
|
||||
|
||||
// await execute('Treasury', {
|
||||
// from: deployer,
|
||||
// log: true,
|
||||
// }, 'initialize', Owner)
|
||||
//
|
||||
// await execute('BabiesOfMars', {
|
||||
// from: deployer,
|
||||
// log: true,
|
||||
// }, 'initialize', PancakeRouter, Owner, treasuryAddress, RedTrustWallet, nftAddress, furnaceAddress, BUSD);
|
||||
await execute('Treasury', {
|
||||
from: deployer,
|
||||
log: true,
|
||||
}, 'initialize', Owner)
|
||||
|
||||
// await execute('NFT', {
|
||||
// from: deployer,
|
||||
// log: true,
|
||||
// }, 'initialize', 'NFT Name', 'NFTS', treasuryAddress, RedTrustWallet, tokenAddress, 200, 200, 200, await token.pair(), PancakeRouter, BUSD, WETH);
|
||||
await execute('BabiesOfMars', {
|
||||
from: deployer,
|
||||
log: true,
|
||||
}, 'initialize', PancakeRouter, Owner, treasuryAddress, RedTrustWallet, nftAddress, furnaceAddress, BUSD);
|
||||
|
||||
// await execute('Marketplace', {
|
||||
// from: deployer,
|
||||
// log: true,
|
||||
// }, 'initialize', 200, treasuryAddress, nftAddress, tokenAddress);
|
||||
await execute('NFT', {
|
||||
from: deployer,
|
||||
log: true,
|
||||
}, 'initialize', 'NFT Name', 'NFTS', treasuryAddress, RedTrustWallet, tokenAddress, 200, 200, 200, await token.pair(), PancakeRouter, BUSD, WETH);
|
||||
|
||||
await execute('Marketplace', {
|
||||
from: deployer,
|
||||
log: true,
|
||||
}, 'initialize', 200, treasuryAddress, nftAddress, tokenAddress);
|
||||
|
||||
await execute('NFT', {
|
||||
from: deployer,
|
||||
log: true,
|
||||
}, 'updateMetadata', nftMetadataAddress);
|
||||
|
||||
// await busd.mint(deployer, parseEther('100000000'));
|
||||
// await weth.mint(deployer, parseEther('100000000'));
|
||||
// await weth.approve(PancakeRouter, parseEther('100000000'));
|
||||
// await weth.approve(PancakeRouter, parseEther('100000000'));
|
||||
|
||||
// await token.approve(PancakeRouter, parseEther('1000000000000000000'));
|
||||
// await new Promise((approve) => setTimeout(() => approve(null), 5000));
|
||||
// await pancake.addLiquidity(tokenAddress, WETH, 10000000, parseEther('10'), 0, 0, deployer, getCurrentTimestamp() + 1000);
|
||||
// await pancake.addLiquidity(tokenAddress, BUSD, 10000000, parseEther('1000'), 0, 0, deployer, getCurrentTimestamp() + 1000);
|
||||
await token.approve(PancakeRouter, parseEther('1000000000000000000'));
|
||||
await new Promise((approve) => setTimeout(() => approve(null), 5000));
|
||||
await pancake.addLiquidity(tokenAddress, WETH, 10000000, parseEther('10'), 0, 0, deployer, getCurrentTimestamp() + 1000);
|
||||
await pancake.addLiquidity(tokenAddress, BUSD, 10000000, parseEther('1000'), 0, 0, deployer, getCurrentTimestamp() + 1000);
|
||||
|
||||
console.log(`Treasury: ${treasuryAddress}\nRedFurnace: ${furnaceAddress}\nNFT: ${nftAddress}\nMarketplace: ${marketAddress}\nBabiesOfMars: ${tokenAddress}`);
|
||||
|
||||
// await token.approve(nft.address, constants.MaxUint256);
|
||||
// await nft.finishPresale();
|
||||
// await new Promise((approve) => setTimeout(() => approve(null), 5000));
|
||||
// await nft.mint(10, 0);
|
||||
// await nft.mint(10, 0, { gasLimit: 5000000 });
|
||||
// await new Promise((approve) => setTimeout(() => approve(null), 5000));
|
||||
await nft.combineTokens([1, 2], { value: parseEther('.05'), gasLimit: 5000000 });
|
||||
// await nft.combineTokens([1, 2], { value: parseEther('.05'), gasLimit: 5000000 });
|
||||
|
||||
};
|
||||
|
||||
const tags = ['Initialize'];
|
||||
const dependencies = ['Treasury', 'Furnace', 'NFT', 'Marketplace', 'Token']
|
||||
const dependencies = ['Treasury', 'Furnace', 'NFT', 'Marketplace', 'Token', 'NFTMetadata'];
|
||||
|
||||
export default deployFunc;
|
||||
export { tags, dependencies };
|
Loading…
Reference in New Issue
Block a user