Last active
January 15, 2025 14:56
-
-
Save nakajo2011/50c4ed047338c554844d15962aba59ff to your computer and use it in GitHub Desktop.
Created using remix-ide: Realtime Ethereum Contract Compiler and Runtime. Load this file by pasting this gists URL or ID at https://remix.ethereum.org/#version=soljson-v0.8.26+commit.8a97fa7a.js&optimize=false&runs=200&gist=
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// hardhat ignition module | |
// filepath: ignition/modules/MyNFT.js | |
const { buildModule } = require("@nomicfoundation/hardhat-ignition/modules"); | |
module.exports = buildModule("MyNFTModule", (m) => { | |
const token = m.contract("MyNFT", [], {}); | |
return { token }; | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// SPDX-License-Identifier: MIT | |
pragma solidity ^0.8.0; | |
import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; | |
import "@openzeppelin/contracts/access/Ownable.sol"; | |
contract MyNFT is ERC721, Ownable { | |
uint constant NFT_PRICE = 0.001 ether; | |
event Minted(address indexed owner, uint256 tokenId); | |
error InsufficientPrice(); | |
mapping(uint => string) _tokenURIs; | |
constructor() ERC721("MyNFT", "MNFT") Ownable(msg.sender) {} | |
function mint(address to, uint256 tokenId) public onlyOwner { | |
_safeMint(to, tokenId); | |
emit Minted(to, tokenId); | |
} | |
function mint(uint256 tokenId) public payable { | |
if(msg.value < NFT_PRICE) { | |
revert InsufficientPrice(); | |
} | |
_safeMint(msg.sender, tokenId); | |
emit Minted(msg.sender, tokenId); | |
} | |
/** | |
* @dev See {IERC721Metadata-tokenURI}. | |
*/ | |
function tokenURI(uint256 tokenId) public view override returns (string memory) { | |
_requireOwned(tokenId); | |
return _tokenURIs[tokenId]; | |
} | |
function updateTokenURI(uint256 tokenId, string memory newURI) public { | |
_requireOwned(tokenId); | |
// 所有者じゃない場合はエラー | |
if(ownerOf(tokenId) != msg.sender) { | |
revert ERC721InvalidOwner(msg.sender); | |
} | |
_tokenURIs[tokenId] = newURI; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const hre = require("hardhat"); | |
async function main() { | |
const [owner, addr1] = await hre.viem.getWalletClients(); | |
const nft = await hre.viem.deployContract("MyNFT"); | |
console.log("nft address:", nft.address); | |
await nft.write.mint([addr1.account.address, 1]); | |
await addr1.writeContract({ | |
address: nft.address, | |
abi: nft.abi, | |
functionName: "mint", | |
args: [2], | |
value: hre.ethers.parseEther("0.001") | |
}); | |
console.log("nft balance:", await nft.read.balanceOf([addr1.account.address])); | |
} | |
main().catch((error) => { | |
console.error(error); | |
process.exitCode = 1; | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const { expect } = require("chai"); | |
const { | |
time, | |
mine, | |
loadFixture, | |
} = require("@nomicfoundation/hardhat-toolbox/network-helpers"); | |
describe("NFT contract", function () { | |
// ...previous test... | |
it("Should Mint with Owner", async function() { | |
const [owner, addr1, addr2] = await ethers.getSigners(); | |
const nft = await ethers.deployContract("MyNFT"); | |
// Mint NFT from owner to addr1 | |
await nft["mint(address,uint256)"](addr1.address, 1); | |
expect(await nft.balanceOf(addr1.address)).to.equal(1); | |
// Transfer NFT from addr1 to addr2 | |
await nft.connect(addr1).transferFrom(addr1.address, addr2.address, 1); | |
expect(await nft.balanceOf(addr1.address)).to.equal(0); | |
}); | |
it("Should Mint with not Owner", async function() { | |
const [owner, addr1] = await ethers.getSigners(); | |
const GWEI = 1_000_000_000 | |
const NFT_PRICE = 10**6 * GWEI | |
const nft = await ethers.deployContract("MyNFT"); | |
// Transfer 50 tokens from owner to addr1 | |
await nft.connect(addr1)["mint(uint256)"](1, {value: NFT_PRICE}); | |
expect(await nft.balanceOf(addr1.address)).to.equal(1); | |
}); | |
it("Should error when payment is unser price", async function() { | |
const [owner, addr1] = await ethers.getSigners(); | |
const GWEI = 1_000_000_000 | |
const NFT_PRICE = 10**6 * GWEI | |
const nft = await ethers.deployContract("MyNFT"); | |
await expect(nft.connect(addr1)["mint(uint256)"](1, {value: NFT_PRICE / 100})).to.be.reverted; | |
await expect(nft.connect(addr1)["mint(uint256)"](1, {value: NFT_PRICE / 100})).to.be.revertedWithCustomError( | |
nft, | |
"InsufficientPrice" | |
); | |
}); | |
}); | |
describe("Using fixture", function () { | |
deployNFTFixture = async () => { | |
// deploy NFT | |
const [owner, addr1] = await ethers.getSigners(); | |
const nft = await ethers.deployContract("MyNFT"); | |
// and mint to addr1 | |
await nft["mint(address,uint256)"](addr1.address, 1); | |
return nft; | |
}; | |
it("Should Mint with Owner", async function() { | |
const [owner, addr1, addr2] = await ethers.getSigners(); | |
const nft = await loadFixture(deployNFTFixture); | |
expect(await nft.balanceOf(addr1.address)).to.equal(1); | |
// Transfer NFT from addr1 to addr2 | |
await nft.connect(addr1).transferFrom(addr1.address, addr2.address, 1); | |
expect(await nft.balanceOf(addr1.address)).to.equal(0); | |
}); | |
}); | |
describe("helper test", function () { | |
it("mine block", async function() { | |
await mine(1000); | |
const blockNumber = await ethers.provider.getBlockNumber(); | |
console.log("blockNumber", blockNumber); | |
}); | |
it("change timestamp", async function() { | |
const now = await time.latest(); | |
console.log("now", now); | |
const toTime = now + (60 * 60 * 24); | |
await time.increaseTo(toTime); | |
const after = await time.latest(); | |
console.log("after", after); | |
}); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment