我是 Solidity 新手,我有一个类项目的智能合约代码。
pragma solidity ^0.5.0;
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v2.5.0/contracts/token/ERC721/ERC721Full.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v2.5.0/contracts/math/SafeMath.sol";
contract MemToken is ERC721Full {
using SafeMath for uint256;
address public contractOwner;
struct Trait {
string name;
uint256 Price;
uint256 maxSupply;
uint256 mintedCount;
}
Trait[] public traits;
constructor() public ERC721Full("MemToken", "WINE") {
contractOwner = msg.sender;
// Initialize the traits array in the constructor
traits.push(Trait({name: "Russian River Valley", Price: 0.2 ether, maxSupply: 100, mintedCount: 0}));
traits.push(Trait({name: "Napa Valley", Price: 0.6 ether, maxSupply: 100, mintedCount: 0}));
traits.push(Trait({name: "Oregon", Price: 0.3 ether, maxSupply: 100, mintedCount: 0}));
traits.push(Trait({name: "Columbia Valley", Price: 0.4 ether, maxSupply: 100, mintedCount: 0}));
traits.push(Trait({name: "Finger Lakes", Price: 0.5 ether, maxSupply: 100, mintedCount: 0}));
}
mapping(uint256 => uint256) public tokenToTrait;
function generateTokenURI(uint256 tokenId) internal view returns (string memory) {
require(tokenId < totalSupply(), "Token does not exist");
uint256 traitIndex = tokenToTrait[tokenId];
Trait memory trait = traits[traitIndex];
return string(abi.encodePacked(trait.name, "-", tokenId));
}
function mintMembership(address owner, uint256 traitIndex)
public
payable // Allow receiving payments with the function call
returns (uint256)
{
require(traitIndex < traits.length, "Invalid trait index");
Trait storage trait = traits[traitIndex];
require(trait.mintedCount < trait.maxSupply, "Trait supply limit reached");
require(msg.value >= trait.Price, "Insufficient payment"); // Check if payment is sufficient
uint256 tokenId = totalSupply();
_mint(owner, tokenId);
string memory tokenURI = generateTokenURI(tokenId);
_setTokenURI(tokenId, tokenURI);
tokenToTrait[tokenId] = traitIndex;
trait.mintedCount++;
// Transfer the payment to the contract owner
address payable ownerPayable = address(uint64(contractOwner));
ownerPayable.transfer(msg.value);
return tokenId;
}
function getMembershipType(uint256 tokenId) public view returns (string memory name, uint256 Price) {
require(tokenId < totalSupply(), "Token does not exist");
uint256 traitIndex = tokenToTrait[tokenId];
Trait memory trait = traits[traitIndex];
return (trait.name, trait.Price);
}
function getMembershipInfo(uint256 traitIndex) public view returns (string memory name, uint256 Price, uint256 maxSupply, uint256 mintedCount) {
require(traitIndex < traits.length, "Invalid trait index");
Trait memory trait = traits[traitIndex];
return (trait.name, trait.Price, trait.maxSupply, trait.mintedCount);
}
}
我至少有一个问题:在 Remix 中编译和部署合约后,mintMembership 功能不起作用(侧边栏中显示为红色,并且尝试推动交易无论如何都会导致 Gas 估算过高,因此无论如何都会失败) 。我还会注意到,Remix 估计所有函数的无限气体。
事实证明,当我注释掉 mintMembership 函数的这一部分时,我能够运行该函数而不会出现任何错误(尽管 Remix 仍然会估计无限气体)。
require(msg.value >= trait.Price, "Insufficient payment"); // Check if payment is sufficient
缺点是,traitPrice 不再包含在传输给合约所有者的 msg.value 中(mintMembership 函数结束)。
如有任何建议,我们将不胜感激。
您有几个问题。
您使用的 Solidity 版本太旧。最好至少使用
0.8.0
。
require
设计的失败将使用完整的gas限制(这是您看到的极高的gas估计值)。您可以在交易中为此设置较低的 Gas 限额。
require(msg.value >= trait.Price)
意味着除非您在交易中发送至少trait.Price
ETH,否则您的智能合约调用将会失败。这就是这里发生的事情。
查看构造函数,这可以在
0.2
- 0.6
ETH 之间。