提示:服务外包区块链学习
5被ban了,也不知道怎么改能过,无所谓了,我以后能看的见就行,不知道这篇能不能过审
说明:从这篇博客开始就不用Ubuntu写区块链了,改用Windows,因为需要链接前面写的有关NFT系统的后台,而后台在Windows的主机上,即便用VMware设置了端口映射,主机的MataMask还是链接不上虚拟机上的,所以改用Windows,感觉都差不多,甚至Windows还要简单些。
只记录操作
尚硅谷以太坊区块链直达链接
直接上代码了,需要详细理解的自己百度吧,因为我也不是很懂
反正原理就是NFT的详细实体不可能传上区块链,完全上去要耗费太多gas了
所以只能将实体保存在系统后台,将NFT的文件URI上传到区块链形成NFT
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.1;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
contract NFTMarket is ERC721, ERC721Enumerable, ERC721URIStorage {
using Strings for uint256;
using Counters for Counters.Counter;
Counters.Counter private _tokenIds;
address private owner;
mapping (uint256 => string) private _tokenURIs;
string private _baseURIextended;
constructor () ERC721("NFTMarket", "NFTMKT") {
owner = msg.sender;
//currToken = IERC20(_currTokenAddress);
}
function setBaseURI(string memory baseURI_) external {
_baseURIextended = baseURI_;
}
function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual
override(ERC721URIStorage){
require(_exists(tokenId), "ERC721Metadata: URI set of nonexistent token");
_tokenURIs[tokenId] = _tokenURI;
}
function _baseURI() internal view virtual override returns (string memory) {
return _baseURIextended;
}
function tokenURI(uint256 tokenId) public view virtual override(ERC721, ERC721URIStorage) returns (string memory) {
require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");
string memory _tokenURI = _tokenURIs[tokenId];
string memory base = _baseURI();
if (bytes(base).length == 0) {
return _tokenURI;
}
if (bytes(_tokenURI).length > 0) {
return string(abi.encodePacked(base, _tokenURI));
}
return string(abi.encodePacked(base, tokenId.toString()));
}
function supportsInterface(bytes4 interfaceId) public view override(ERC721, ERC721Enumerable) returns (bool) {
return super.supportsInterface(interfaceId);
}
function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal override(ERC721, ERC721Enumerable) {
super._beforeTokenTransfer(from, to, tokenId);
}
function _burn(uint256 tokenId) internal override(ERC721, ERC721URIStorage) {
super._burn(tokenId);
}
function burnNFT(uint256 tokenId) public returns (uint256) {
require(msg.sender == ownerOf(tokenId),"Only the owner of this Token could Burn It!");
_burn(tokenId);
return tokenId;
}
function mintNFT(address _to,string memory tokenURI_) public returns (uint256){
_tokenIds.increment();
uint256 newItemId = _tokenIds.current();
_mint(_to, newItemId);
_setTokenURI(newItemId, tokenURI_);
return newItemId;
}
function transNFT(address _from,address _to,uint256 tokenId) public returns (uint256) {
require(msg.sender == ownerOf(tokenId),"Only the owner of this Token could transfer It!");
transferFrom(_from,_to,tokenId);
return tokenId;
}
function destroy() virtual public {
require(msg.sender == owner,"Only the owner of this Contract could destroy It!");
selfdestruct(payable(owner));
}
}
每一个推送成功的合约地址和使用的命令最好用一个文档记起来,方便后续使用
简单说一下一些方法的使用:
mintNFT(铸造NFT)
burnNFT(销毁NFT)
safeTransferFrom(发NFT给指定账号)
transNFT(交易NFT)
balanceOf(查看指定用户有多少个NFT)
ownerOf(查看指定tokenId的拥有者)
tokenByIndex(查看指定索引的NFT)
tokenOfOwner(查看指定地址的指定索引的NFT)
totalSupply(查看NFT总数)
新建两个账号,再用MataMask导入账号
call方法都是不用提交交易就可以调用的,所以不需要挖矿
NFT总数
刚刚铸造的NFT在我的账号里是第二个,所以它的索引是1(从0开始哈)
这个时候返回的就是这个NFT的tokenId了,有了tokenId既可以看这个NFT的tokenURI了
使用结束!
NFT商家智能合约代码
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.1;
import "@openzeppelin/contracts/utils/Context.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
contract NFTStore is Context, ERC20 {
address private owner;
struct Mints {
address minter;
uint256 amount;
}
mapping(uint256 => Mints) public tokenToMint;
mapping(uint256 => uint256) private tokenAmounts;
/**
* @dev Constructor that gives _msgSender() all of existing tokens.
*/
constructor (uint256 tokenNum) ERC20("NFTStore", "NFC") {
owner = msg.sender;
_mint(_msgSender(), tokenNum * (10 ** uint256(decimals())));
}
function mint(address _to,uint256 amount,uint256 tokenId) public {
require(msg.sender == owner,"Only the owner of this Contract could mint!"); // 本文添加,否则函数 mint 会有逻辑错误
_mint( _to, amount) ; // 如果没有添加上一句 require,此处会有逻辑错误,任何人都可以免费获得NFC
tokenAmounts[tokenId] = amount;
Mints memory mintted = Mints({
minter: _to,
amount: amount
});
tokenToMint[tokenId]=mintted;
}
function getTokenAmount (uint256 tokenId) public view returns (uint256) {
return tokenAmounts[tokenId];
}
function gettokenMints(uint256 tokenId) public view returns ( address, uint256){
Mints memory mintted = tokenToMint[tokenId];
return (mintted.minter,mintted.amount);
}
function destroy() virtual public {
require(msg.sender == owner,"Only the owner of this Contract could destroy It!");
selfdestruct(payable(owner));
}
}
这个我还没怎么使用过,有兴趣的小伙伴可以自己进行尝试。
明天写Java的区块链框架Web3j的使用
Over