我正在尝试使用 ethers.js 铸造 NFT,我的前端代码似乎有问题
I am trying to mint NFT using ethers.js, there seems to be a problem with my frontend code
我曾多次尝试使用 ethers.js 铸造 NFT。我的代码有问题吗?我总是收到此错误:Error: transaction failed [ See: https://links.ethers.org/v5-errors-CALL_EXCEPTION ]
而且我的solidity代码似乎没有任何问题。
我的前端代码:
const player: PlayerInterface = {
name: "Lionel Messi",
preferredPosition: "RWF",
id: 1,
age: 34,
level: 20,
lastUpgrade: new Date().getTime(),
suitablePositions: ["ST", "CF", "RMF", "CAM"],
imageURI:
"https://bafybeicfhmevzs4aso7rqvx7l5ndb2ly7gudjyj5xjkztvohpwxw2za7iy.ipfs.dweb.link/nft.png",
};
const provider = new ethers.providers.Web3Provider(
(window as any).ethereum
);
const signer = provider.getSigner();
const tx = await futNFT.connect(signer).mint(player, {
gasPrice: 30000000000,
gasLimit: 2000000,
});
await tx.wait();
console.log("minted");
const player1 = await futNFT.getPlayer(1);
console.log(player1);
这是我的 solidity 智能合约:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.12;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
contract FutNFT is ERC721, ERC721Enumerable, Ownable {
/// @dev Should have logic for players with no suitable position array
struct Player {
string name;
string preferredPosition;
uint256 id;
uint8 age;
uint8 level;
uint64 lastUpgrade;
string[] suitablePositions;
string imageURI;
}
struct History {
uint256 winCount;
uint256 lossCount;
}
mapping(address => History) ownerHistory;
mapping(uint256 => Player) players;
mapping(uint256 => address) public playerToOwner;
mapping(uint256 => uint256) listedPlayerIndex;
uint256[] public listedPlayers;
uint256[] playerIds;
event PlayerAdded(uint256 playerId);
modifier owned(uint256 id) {
require(getPlayerExists(id), "Player does not exist");
require(msg.sender == ownerOf(id), "Not the owner!");
_;
}
constructor() ERC721("FutNFT", "FNFT") {}
function getListedPlayers() public view returns (uint256[] memory) {
return listedPlayers;
}
function getPlayer(uint256 _id) public view returns (Player memory) {
return players[_id];
}
function getPlayersByOwner(address _owner)
public
view
returns (uint256[] memory)
{
uint256[] memory result;
uint256 index = 0;
for (uint256 i = 0; i < playerIds.length; i++) {
if (playerToOwner[playerIds[i]] == _owner) {
result[index] = playerIds[i];
index++;
}
}
return result;
}
function ownerOf(uint256 tokenId)
public
view
override(ERC721, IERC721)
returns (address)
{
return super.ownerOf(tokenId);
}
function getPlayerExists(uint256 _id) public view returns (bool) {
return playerToOwner[_id] != address(0);
}
function mint(Player memory _player) public onlyOwner {
require(playerToOwner[_player.id] == address(0), "Player Exists!");
players[_player.id] = _player;
playerIds.push(_player.id);
playerToOwner[_player.id] = msg.sender;
_mint(msg.sender, _player.id);
emit PlayerAdded(_player.id);
}
function _beforeTokenTransfer(
address from,
address to,
uint256 tokenId
) internal override(ERC721, ERC721Enumerable) {
super._beforeTokenTransfer(from, to, tokenId);
}
function supportsInterface(bytes4 interfaceId)
public
view
override(ERC721, ERC721Enumerable)
returns (bool)
{
return super.supportsInterface(interfaceId);
}
}
请告诉我这是否有问题。也请询问您是否需要更多信息。
您的 mint()
函数使用了 onlyOwner
修饰符。在 OpenZeppelin implementation 中,这意味着该函数只能从存储在 _owner
变量中的地址执行。如果您尝试从不同的地址执行它,它会恢复原状。
默认情况下(根据 OZ 实现),_owner
地址是部署合约的地址。
所以你需要从当前的 _owner
地址执行 mint()
函数——在你的例子中是部署合约的相同地址。或者删除 onlyOwner
修饰符(并重新部署合约),它打开任何人都可以执行的函数。
我曾多次尝试使用 ethers.js 铸造 NFT。我的代码有问题吗?我总是收到此错误:Error: transaction failed [ See: https://links.ethers.org/v5-errors-CALL_EXCEPTION ]
而且我的solidity代码似乎没有任何问题。
我的前端代码:
const player: PlayerInterface = {
name: "Lionel Messi",
preferredPosition: "RWF",
id: 1,
age: 34,
level: 20,
lastUpgrade: new Date().getTime(),
suitablePositions: ["ST", "CF", "RMF", "CAM"],
imageURI:
"https://bafybeicfhmevzs4aso7rqvx7l5ndb2ly7gudjyj5xjkztvohpwxw2za7iy.ipfs.dweb.link/nft.png",
};
const provider = new ethers.providers.Web3Provider(
(window as any).ethereum
);
const signer = provider.getSigner();
const tx = await futNFT.connect(signer).mint(player, {
gasPrice: 30000000000,
gasLimit: 2000000,
});
await tx.wait();
console.log("minted");
const player1 = await futNFT.getPlayer(1);
console.log(player1);
这是我的 solidity 智能合约:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.12;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
contract FutNFT is ERC721, ERC721Enumerable, Ownable {
/// @dev Should have logic for players with no suitable position array
struct Player {
string name;
string preferredPosition;
uint256 id;
uint8 age;
uint8 level;
uint64 lastUpgrade;
string[] suitablePositions;
string imageURI;
}
struct History {
uint256 winCount;
uint256 lossCount;
}
mapping(address => History) ownerHistory;
mapping(uint256 => Player) players;
mapping(uint256 => address) public playerToOwner;
mapping(uint256 => uint256) listedPlayerIndex;
uint256[] public listedPlayers;
uint256[] playerIds;
event PlayerAdded(uint256 playerId);
modifier owned(uint256 id) {
require(getPlayerExists(id), "Player does not exist");
require(msg.sender == ownerOf(id), "Not the owner!");
_;
}
constructor() ERC721("FutNFT", "FNFT") {}
function getListedPlayers() public view returns (uint256[] memory) {
return listedPlayers;
}
function getPlayer(uint256 _id) public view returns (Player memory) {
return players[_id];
}
function getPlayersByOwner(address _owner)
public
view
returns (uint256[] memory)
{
uint256[] memory result;
uint256 index = 0;
for (uint256 i = 0; i < playerIds.length; i++) {
if (playerToOwner[playerIds[i]] == _owner) {
result[index] = playerIds[i];
index++;
}
}
return result;
}
function ownerOf(uint256 tokenId)
public
view
override(ERC721, IERC721)
returns (address)
{
return super.ownerOf(tokenId);
}
function getPlayerExists(uint256 _id) public view returns (bool) {
return playerToOwner[_id] != address(0);
}
function mint(Player memory _player) public onlyOwner {
require(playerToOwner[_player.id] == address(0), "Player Exists!");
players[_player.id] = _player;
playerIds.push(_player.id);
playerToOwner[_player.id] = msg.sender;
_mint(msg.sender, _player.id);
emit PlayerAdded(_player.id);
}
function _beforeTokenTransfer(
address from,
address to,
uint256 tokenId
) internal override(ERC721, ERC721Enumerable) {
super._beforeTokenTransfer(from, to, tokenId);
}
function supportsInterface(bytes4 interfaceId)
public
view
override(ERC721, ERC721Enumerable)
returns (bool)
{
return super.supportsInterface(interfaceId);
}
}
请告诉我这是否有问题。也请询问您是否需要更多信息。
您的 mint()
函数使用了 onlyOwner
修饰符。在 OpenZeppelin implementation 中,这意味着该函数只能从存储在 _owner
变量中的地址执行。如果您尝试从不同的地址执行它,它会恢复原状。
默认情况下(根据 OZ 实现),_owner
地址是部署合约的地址。
所以你需要从当前的 _owner
地址执行 mint()
函数——在你的例子中是部署合约的相同地址。或者删除 onlyOwner
修饰符(并重新部署合约),它打开任何人都可以执行的函数。