Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
191 changes: 65 additions & 126 deletions dapp/Contract/FishNFT.json

Large diffs are not rendered by default.

28 changes: 27 additions & 1 deletion dapp/pages/mintpage/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,32 @@ const MintPage = () => {
functionName: "maxMintAmount",
args: ['0x76f838819F33606393E40A8188Cf2B279cB98dF6'],
});

console.log("NFT limit:" + mintLimit);

const uris = [
'https://studio.api.manifoldxyz.dev/asset_uploader/1/series/2466823498/metadata/full/1',
'https://studio.api.manifoldxyz.dev/asset_uploader/1/series/2466823498/metadata/full/2',
'https://studio.api.manifoldxyz.dev/asset_uploader/1/series/2466823498/metadata/full/3',
];

const {
write: writeMint,
} = useContractWrite({
address: "0x26076EF77D3b41aC8BDFD5C318bd5157C64AB757",
abi: FishNFTArtifact.abi,
functionName: "mint",
args: [uris],
});

const { data: tokenURI} = useContractRead({
address: "0x55925EdAd7bE61EF7942ae479FA28Edca5C8B158",
abi: FishNFTArtifact.abi,
functionName: 'tokenURI',
args: ['1'],
});

console.log("tokenURI:" + tokenURI);

return (
<Box sx={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '100vh' }}>
<Paper
Expand Down Expand Up @@ -70,6 +93,9 @@ const MintPage = () => {
<Button fullWidth variant="outlined" sx={{
mt: '2rem'
}}
onClick={() => {
writeMint();
}}
>Mint
</Button>

Expand Down
1,061 changes: 712 additions & 349 deletions erc-6551/cache/solidity-files-cache.json

Large diffs are not rendered by default.

152 changes: 125 additions & 27 deletions erc-6551/contracts/FishNFT.sol
Original file line number Diff line number Diff line change
@@ -1,54 +1,152 @@

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

import "@manifoldxyz/creator-core-solidity/contracts/ERC721Creator.sol";
// import "@openzeppelin/contracts/access/Ownable.sol";
import "./FishToken.sol";

contract FishNFT is ERC721Creator {
struct Fish {
uint256 mintTime;
uint256 chargedTime;
uint256 claimedTime;
uint256 productivity;
uint256 appetite;
uint256 rarity;
}
mapping(address => uint256) public maxMintAmount;
mapping(uint256 => Fish) public fishes;
uint256[] public rarities;
uint256[] public productivities;
uint256[] public appetities;
uint256 public produceTime = 24 * 60 * 60; // 24 hours in seconds
uint256 public chargeRatio = 100;
uint256 public productRatio = 120;
address public tokenAddress;
string public defaultURI =
"https://studio.api.manifoldxyz.dev/asset_uploader/1/series/2466823498/metadata/full/1";

contract FishNFT is ERC721Creator {
constructor() ERC721Creator("FishNFT", "FFF") {}

mapping(address => uint256) public maxMintAmount;
mapping(address => uint256) public mintTime;
function setRarities(uint256[] memory values) external onlyOwner {
rarities = values;
}

address public tokenAddress;
function setProductivities(uint256[] memory values) external onlyOwner {
productivities = values;
}

function setAppetities(uint256[] memory values) external onlyOwner {
appetities = values;
}

function setChargeRatio(uint256 value) external onlyOwner {
chargeRatio = value;
}

function setProductRatio(uint256 value) external onlyOwner {
productRatio = value;
}

constructor() ERC721Creator ("FishNFT", "FFF") {
function getFish(uint256 tokenId) public view returns (Fish memory) {
return fishes[tokenId];
}

function charge(uint256[] memory tokenIds) public {
uint256 price;
for (uint i; i < tokenIds.length; ) {
Fish storage fish = fishes[tokenIds[i]];
require(fish.mintTime != 0, "Fish not minted");
// require(fish.chargedTime + produceTime < block.timestamp, "Fish already charged");
price += fish.appetite * chargeRatio;
fish.chargedTime = block.timestamp;
unchecked {
++i;
}
}
FishToken(tokenAddress).burn(msg.sender, price);
}

function setTokenAddress(address _tokenAddress) external onlyOwner {
tokenAddress = _tokenAddress;
}

function randomFish(uint256 tokenId) public view returns (Fish memory) {
uint256 rarity = rarities[tokenId % rarities.length];
uint256 productivity = productivities[tokenId % productivities.length];
uint256 appetite = appetities[tokenId % appetities.length];
return
Fish(
block.timestamp,
block.timestamp,
0,
productivity,
appetite,
rarity
);
} // tmp random fish logic

// called by backend
function setMaxMintAmount(address user, uint256 amount) external onlyOwner {
maxMintAmount[user] = amount;
}

function getReward(address user) public view returns (uint256){
if(mintTime[user] == 0) return 0;
return balanceOf(user) * 10 * (block.timestamp - mintTime[user]);
}

function claimReward(address user) external {
function claimReward(uint256[] memory tokenIds) external {
require(tokenAddress != address(0), "token address not set");

uint256 reward = getReward(user);
uint256 reward;
for (uint i; i < tokenIds.length; ) {
Fish storage fish = fishes[tokenIds[i]];
require(fish.mintTime != 0, "Fish not minted");
address fishOwner = ownerOf(tokenIds[i]);
require(
block.timestamp >= fish.chargedTime + produceTime,
"Fish not generate reward yet"
);
require(
fish.claimedTime < fish.chargedTime + produceTime,
"Reward already claimed"
);
require(fishOwner == msg.sender, "Not fish owner");
reward += fish.productivity * productRatio;
fish.claimedTime = block.timestamp;
unchecked {
++i;
}
}
// mint Fish token ERC20 to user
FishToken(tokenAddress).mint(user, reward);
mintTime[user] = block.timestamp;
FishToken(tokenAddress).mint(msg.sender, reward);
}


function mint(string[] memory uris) external {
uint256[] memory tokenIds = new uint256[](uris.length);
uint256 firstTokenId = _tokenCount+1;
_tokenCount += uris.length;

for (uint i; i < uris.length;) {
tokenIds[i] = _mintBase(msg.sender, uris[i], firstTokenId+i);
unchecked { ++i; }
function mint(
string[] memory uris
) external onlyOwner returns (uint256[] memory tokenIds) {
tokenIds = new uint256[](uris.length);

for (uint i; i < uris.length; ) {
uint256 tokenId = _mintBase(msg.sender, uris[i]);
tokenIds[i] = tokenId;
fishes[tokenId] = randomFish(tokenId);
unchecked {
++i;
}
}

mintTime[msg.sender] = block.timestamp;
return tokenIds;
}

function payMint() external payable {
uint256 currentPrice = getPrice(1);
require(msg.value >= currentPrice, "insufficient funds");
uint256 tokenId = _mintBase(msg.sender, defaultURI);
fishes[tokenId] = randomFish(tokenId);
_tokenCount++;
}

function getPrice(uint256 amount) public view returns (uint256) {
uint256 sum1 = _tokenCount == 0 ? 0 : (_tokenCount - 1 )* (_tokenCount) * (2 * (_tokenCount - 1) + 1) / 6;
uint256 sum2 = _tokenCount == 0 && amount == 1 ? 0 : (_tokenCount - 1 + amount) * (_tokenCount + amount) * (2 * (_tokenCount - 1 + amount) + 1) / 6;
uint256 summation = sum2 - sum1;
uint256 price = summation * 0.5 ether / 16000;
return price;
}
}
}
4 changes: 4 additions & 0 deletions erc-6551/contracts/FishToken.sol
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,8 @@ contract FishToken is ERC20 {
require(msg.sender == nftAddress, "only nft contract can mint token");
_mint(to, amount);
}

function burn(address from, uint256 amount) external {
_burn(from, amount);
}
}
Loading