Stack Overflow社区!
我目前正在做一个项目,涉及一个名为DynamicSvgNft的NFT合同。该合约旨在根据Chainlink的价格提要更改NFT的SVG图像URI。然而,我面临着一个问题,即getHighSVG()
和getLowSVG()
函数返回的值是混淆的。
以下是合同的相关代码:
// DynamicSvgNft.sol
contract DynamicSvgNft is ERC721, Ownable {
uint256 private s_tokenCounter;
string private s_lowImageURI;
string private s_highImageURI;
AggregatorV3Interface internal immutable i_priceFeed;
mapping (uint256 => int256) private s_tokenToHighValue;
event CreatedNft(uint256 indexed tokenId, int256 highValue);
constructor(address priceFeedAddress, string memory lowSvg, string memory highSvg) ERC721("Dynamic SVG NFT", "DSN") {
s_tokenCounter = 0;
i_priceFeed = AggregatorV3Interface(priceFeedAddress);
s_lowImageURI = svgToImageUri(lowSvg);
s_highImageURI = svgToImageUri(highSvg);
}
// functionalities
function mintNft(int256 highValue) public {
_safeMint(msg.sender, s_tokenCounter);
s_tokenToHighValue[s_tokenCounter] = highValue;
s_tokenCounter = s_tokenCounter + 1;
emit CreatedNft(s_tokenCounter, highValue);
}
function svgToImageUri(string memory svg) public pure returns (string memory) {
// convert the svgs to image uris and store them in variables for later use
string memory baseURL = "data:image/svg+xml;base64,";
string memory svgBase64Encoded = Base64.encode(bytes(string(abi.encodePacked(svg))));
return string(abi.encodePacked(baseURL, svgBase64Encoded));
}
function _baseURI() internal pure override returns (string memory) {
return "data:application/json;base64,";
}
function tokenURI(uint256 tokenId) public view override returns (string memory) {
if(!_exists(tokenId)) {
revert ERC721Metadata__URI_QueryFor_NonExistentToken();
}
(, int256 price, , , ) = i_priceFeed.latestRoundData();
string memory imageURI;
if (price >= s_tokenToHighValue[tokenId]) {
imageURI = s_highImageURI;
} else {
imageURI = s_lowImageURI;
}
return
string(
abi.encodePacked(
_baseURI(),
Base64.encode(
bytes(
abi.encodePacked(
'{"name":"',
name(),
'", "description":"An NFT that changes based on the chainlink feed",',
'"attributes": [{"trait_type": "coolness", "value": 100}], "image":"',
imageURI,
'"}'
)
)
)
)
);
}
function getLowSVG() public view returns (string memory) {
return s_lowImageURI;
}
function getHighSVG() public view returns (string memory) {
return s_highImageURI;
}
function getTokenCounter() public view returns (uint256 ) {
return s_tokenCounter;
}
function getPriceFeed() public view returns (AggregatorV3Interface) {
return i_priceFeed;
}
}
字符串
下面是观察到问题的测试代码:
//DynamicSvgNft.test.js
const highSVGImageUri = "data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMjAwIDIwMCIgd2lkdGg9IjQwMCIgIGhlaWdodD0iNDAwIiB4bWxucz0";
const lowSVGImageUri = "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBzdGFuZGFsb25lPSJubyI/...";
describe("Constructor", () => {
it("sets the initial values correctly", async () => {
const highSVG = await dynamicSvgNft.getHighSVG(); // Returns lowSVGImageUri instead of the highSVGImageUri
const lowSVG = await dynamicSvgNft.getLowSVG(); // Returns the highSVGImageUri instead of the lowSVGImageUri
// ... (assertions)
console.log(`highSVG is => ${highSVG}`)
assert.equal(highSVG, highSVGImageUri)
console.log(`lowSVG is => ${lowSVG}`)
assert.equal(lowSVG, lowSVGImageUri)
assert.equal(tokenCounter.toString(), "0")
assert.equal(priceFeed, MockV3Aggregator.address)
});
});
// ... (other test code)
型
DynamicSvgNft.deploy.js
const { network } = require("hardhat");
const { developmentChains, networkConfig } = require("../helper-hardhat-config");
const { verify } = require("../utils/verify");
const fs = require("fs")
module.exports = async ({getNamedAccounts, deployments}) => {
const {deploy, log} = deployments
const {deployer} = await getNamedAccounts()
const chainId = network.config.chainId
let ethUsdPriceFeedAddress
if(developmentChains.includes(network.name)) {
const EthUsdAggregator = await deployments.get("MockV3Aggregator")
ethUsdPriceFeedAddress = EthUsdAggregator.address
} else {
ethUsdPriceFeedAddress = networkConfig[chainId].ethUsdPriceFeed
}
log("#####################################");
// read the nft images
const lowSVG = fs.readFileSync("images/dynamicNft/frown.svg", {encoding: "utf8"})
const highSVG = fs.readFileSync("images/dynamicNft/happy.svg", {encoding: "utf8"})
args = [ethUsdPriceFeedAddress, highSVG, lowSVG]
const dynamicSvgNft = await deploy("DynamicSvgNft", {
from: deployer,
args:args,
log: true,
waitConfirmations: network.config.blockConfirmations || 1
})
if(!developmentChains.includes(network.name) && process.env.ETHERSCAN_API_KEY) {
log("verifying.....")
await verify(dynamicSvgNft.address, args)
log("verified!")
log("#########################################")
}
}
module.exports.tags = ["all", "dynamicsvg", "main"]
型
问题是getHighSVG()
函数返回s_lowImageURI
的值,反之亦然,导致在测试期间返回不正确的值
我已经彻底检查了合同和测试代码,但我无法确定问题的根本原因。我怀疑合约部署或合约中使用的svgToImageUri
函数可能存在问题。
任何关于如何调试和修复此问题的见解或建议都将受到高度赞赏!如果需要,我还可以提供合同和测试文件的完整代码。
提前感谢您的帮助!
1条答案
按热度按时间6kkfgxo01#
我遇到了一个DynamicSvgNft合约的问题,其中
getHighSVG()
和getLowSVG()
函数返回了不正确的图像URI。该合约旨在根据Chainlink oracle中的price feed值设置不同的SVG图像。经过调查,我发现问题出在部署过程中向契约构造函数传递参数的方式上。构造函数需要价格提要地址,然后是低SVG和高SVG,按此顺序。但是,我错误地以错误的顺序传递了参数,导致在合约中存储了不正确的图像URI。
字符串
为了解决这个问题,我更正了参数顺序:
型
致:
型
通过以正确的顺序传递参数,合约现在可以根据提供的SVG正确地设置图像URI。
getHighSVG()
和getLowSVG()
函数现在返回预期的图像URI,并且测试按预期通过。我希望这些信息可以帮助其他任何在DynamicSvgNft合同中遇到类似问题的人。请记住,在部署具有多个参数的合约时,始终要验证参数的顺序,以避免此类问题。
干杯