我已经在 Polygon 网络上部署了一份合约来铸造 NFT,但遇到了一个问题:只有其中一笔交易成功,而后续尝试会导致错误。以下是交易哈希:
经过分析,我怀疑这个问题可能与我如何获取 MATIC 的美元价格有关。有趣的是,在成功铸造的过程中我没有对这个过程做任何改变。值得一提的是,该合约的mint功能在本地开发环境以及测试网络上完美运行。
这是我的PriceConverter
文件的相关部分,我在其中处理价格转换:
/**
* @dev Get the latest price from a Chainlink Price Feed and convert it to a fixed-point integer.
* @param _priceFeed The Chainlink Price Feed interface.
* @return The latest price in fixed-point integer format (with 10 additional decimal places).
*/
function getPrice(AggregatorV3Interface _priceFeed) internal view returns (uint256) {
unchecked {
try _priceFeed.latestRoundData() returns
(
uint80 roundId,
int256 answer,
uint256,
uint256 ,
uint80 answeredInRound
){
if(answer <= 0) revert AnswerIsNotGreaterThanZero();
if(roundId != answeredInRound) revert InconsistentRoundId();
return uint256(answer);
} catch {
revert CantFetchLatestRoundData();
}
}
}
/**
* @dev Convert an amount in MATIC to its equivalent value in USD using a Chainlink Price Feed.
* @param _maticAmount The amount in MATIC to convert.
* @param _priceFeed The Chainlink Price Feed interface.
* @return The equivalent value in USD (with 10 additional decimal places).
*/
function getConversionRate(uint256 _maticAmount, AggregatorV3Interface _priceFeed) internal view returns (uint256) {
unchecked {
uint256 maticPrice = getPrice(_priceFeed);
uint256 decimals = _priceFeed.decimals();
uint256 maticAmountInUsd = (maticPrice * _maticAmount) / 10 ** decimals;
// The actual MATIC/USD conversion rate, after adjusting the extra 0s.
return maticAmountInUsd;
}
}
/**
* @dev Convert an amount in USD to its equivalent value in MATIC using a Chainlink Price Feed.
* @param _usdAmount The amount in USD to convert.
* @param _priceFeed The Chainlink Price Feed interface.
* @return The equivalent value in MATIC (with 10 additional decimal places).
*/
function getMaticValueFromUsd(uint256 _usdAmount, AggregatorV3Interface _priceFeed) internal view returns (uint256) {
unchecked {
uint256 maticPrice = getPrice(_priceFeed);
uint256 decimals = _priceFeed.decimals();
uint256 maticValue = (_usdAmount * 10 ** decimals) / maticPrice;
// The actual USD/MATIC conversion rate, after adjusting the extra 0s.
return maticValue;
}
}
这就是 Mint 功能:
function mint() external payable {
uint16 localNftQuantityMinted = nftQuantityMinted;
uint256 nftPriceInMatic = nftPriceUsd.getMaticValueFromUsd(priceFeed);
// CHECKS
if(msg.sender != owner()){
unchecked { if(nftCountPerAddress[msg.sender] >= maxNftsAllowedPerUser) revert Only10NFTsPerAddress(); }
}
unchecked { if(localNftQuantityMinted >= maxNftsAllowed) revert AllNFTsMinted(); }
unchecked { if(msg.value < nftPriceInMatic) revert InsufficientFunds({required: nftPriceUsd}); }
unchecked { if(msg.value > nftPriceInMatic) revert UserIsOverpaying({required: nftPriceUsd}); }
// EFFECTS
// Mark the ID as minted
_mintedIds[localNftQuantityMinted] = true ;
unchecked { ++nftCountPerAddress[msg.sender]; }
++nftQuantityMinted;
// INTERACTIONS
// Transfer MATIC to this contract from the sender account
bytes memory data = bytes("0x");
_mint(msg.sender, localNftQuantityMinted, 1, data);
emit NFTMinted(msg.sender, localNftQuantityMinted);
// Set royalty for the token minted
_setTokenRoyalty(localNftQuantityMinted, safe, 1000);
}
有人可以帮我找出可能导致此问题的原因吗?
讨论中提到的,与主网相比,测试网上的转化率变化并不快,这主要是因为rounds
的速度可能是由于更高数量的轮次数据提交所致主网的节点数量和更快的确认速度。处理此问题的一种方法是删除
UserIsOverpaying
错误:
unchecked { if(msg.value > nftPriceInMatic) revert UserIsOverpaying({required: nftPriceUsd}); }
相反,将其替换为“向用户退还多付金额”的逻辑,例如:
if (msg.value > nftPriceInMatic) {
// Transfer MATIC equivalent to (msg.value - nftPriceInMatic) back to the sender account
(bool callSuccess, ) = payable(msg.sender).call{
value: msg.value - nftPriceInMatic
}("");
require(callSuccess, "Call failed");
}
gist
。这是当我调用mintTest()
函数时的 transaction,其中我将 0.02 MATIC
作为
value
传递,但是
getMaticValueFromUsd(10000000000000000)
显示在
0.014 MATIC
周围,因此它将剩余的
0.006 MATIC
退还到我的钱包.