[TIL] 2023-06-28 DAY66
GIT 주소
https://github.com/dowoo303/SOLIDITY
https://github.com/dowoo303/hardhat
오늘 배운것들
- typescript(0623폴더에 이어서)
각종 팁
회고
시작
npx create-next-app@latest 0628입력 후 각정설정(대부분 yes)(테일윈드 설치 할지말지도 결정가능)
npm run dev로 시작
이미지 경로는 public 폴더부터 시작한다.
src/app 폴더 안에 만드는 폴더 명이 새로운 페이지 경로 이름이다.
mint nft와 sale nft 컨트랙트 구현해보기
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
contract MintNft is ERC721Enumerable {
string metadataUri;
mapping(uint => string) metadataUris;
uint maxAmount;
constructor(string memory _name, string memory _symbol, string memory _metadataUri, uint _maxAmount) ERC721(_name, _symbol) {
metadataUri = _metadataUri;
maxAmount = _maxAmount;
}
function mintNft() public {
// 수량 제한
require(totalSupply() < maxAmount, "No more mint.");
uint tokenId = totalSupply()+1;
_mint(msg.sender, tokenId);
metadataUris[tokenId] = metadataUri;
}
function tokenURI(uint _tokenId) public override view returns(string memory) {
// 아래 if문을 활용하여 reveal전 이미지나 데이터를 보여주다가 리빌이 된 후 바뀌는 식으로 구성해도됨
// 또는 거래가 여러번 이루어진 nft는 이미지나 데이터가 변경된다던가 등등 여기서 모두 작업가능
// if() {
// return "metadata";
// }
return string(abi.encodePacked(metadataUri, '/', Strings.toString(_tokenId), '.json'));
// 만약 위 mapping을 사용한다면
// return metadataUris[_tokenId];
}
// 사용자가 마지막으로 민팅한 NFT 띄워주기
function getLatestNft(address _nftOwner) public view returns(uint) {
uint nftLength = balanceOf(_nftOwner);
uint latestNft = tokenOfOwnerByIndex(_nftOwner, nftLength - 1);
return latestNft;
}
function getAllNft(address _nftOwner) public view returns(uint[] memory) {
uint nftLength = balanceOf(_nftOwner);
uint[] memory allNft = new uint[](nftLength);
for(uint i; i<nftLength; i++) {
allNft[i] = tokenOfOwnerByIndex(_nftOwner, i);
}
return allNft;
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;
import "./230628.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
contract SaleNft is Ownable {
// 범용적으로 사용하기 위해서는 오픈재플린에서 ERC721 import
MintNft mintNftContract;
constructor(address _mintNftAddress) {
mintNftContract = MintNft(_mintNftAddress);
}
mapping(uint => uint) tokenPrices;
uint[] public onSaleNft;
function setSaleNft(uint _tokenId, uint _price) public {
address nftOwner = mintNftContract.ownerOf(_tokenId);
require(nftOwner == msg.sender); // nft 주인 체크
require(mintNftContract.isApprovedForAll(nftOwner, address(this)));
require(_price > 0); // 음수나 0(판매중인 상태가 아닌 상태)방지
require(tokenPrices[_tokenId] == 0); // 판매중이 아닌지 확인
tokenPrices[_tokenId] = _price;
onSaleNft.push(_tokenId);
}
function purchaseNft(uint _tokenId) public payable {
address nftOwner = mintNftContract.ownerOf(_tokenId);
uint nftPrice = tokenPrices[_tokenId];
require(nftOwner != msg.sender); // 자기자신은 구매 불가
require(nftPrice > 0); // 판매중인지 체크
require(nftPrice <= msg.value); // 구매할 돈을 충분히 보냈는지 체크
// 수수료
uint tradeFee = msg.value / 20;
payable(nftOwner).transfer(msg.value - tradeFee); // 비용지불
payable(owner()).transfer(tradeFee); // 수수료
mintNftContract.safeTransferFrom(nftOwner, msg.sender, _tokenId);
}
}