阅读量:0
通过Solidity编写的合约基于 ERC721 标准,并使用 OpenZeppelin 库来实现基本功能。
导入库
import '@openzeppelin/contracts/token/ERC721/ERC721.sol'; import '@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol'; import '@openzeppelin/contracts/utils/Counters.sol'; import 'base64-sol/base64.sol'; import "@openzeppelin/contracts/utils/Strings.sol";
这些导入语句包含了 ERC721 标准合约、扩展功能、计数器工具、Base64 编码工具和字符串工具。
合约定义
contract DynamicSvgToken is ERC721URIStorage { using Counters for Counters.Counter; Counters.Counter private _tokenCounter; string[] palette; constructor() ERC721('Dynamic SVG Token', 'DST') { palette = ["blue", "red", "maroon", "black", "yellow", "orange", "purple", "gold", "lawngreen", "lightblue", "olive"]; } function mint() external { _tokenCounter.increment(); uint256 newTokenId = _tokenCounter.current(); _safeMint(msg.sender, newTokenId); _setTokenURI(newTokenId, _constructTokenURI(newTokenId)); } function _constructTokenURI(uint256 tokenId) internal view returns (string memory) { string memory svg = _constructSVG(tokenId); string memory json = Base64.encode(bytes(string(abi.encodePacked( '{"name": "', name(), '", "description": "A dynamic SVG NFT with animated gradient background", "image": "data:image/svg+xml;base64,', Base64.encode(bytes(svg)), '"}' )))); return string(abi.encodePacked('data:application/json;base64,', json)); } function _constructSVG(uint256 tokenId) internal view returns (string memory) { uint seed = uint(keccak256(abi.encodePacked(block.timestamp, tokenId))); string memory gradientColors = _getRandomGradientColors(seed); string memory animationDuration = Strings.toString(5 + (seed % 10)); // 5-14 seconds return string(abi.encodePacked( "<svg width='500' height='500' xmlns='http://www.w3.org/2000/svg'>", "<defs>", "<linearGradient id='bg' x1='0%' y1='0%' x2='100%' y2='100%'>", gradientColors, "</linearGradient>", "</defs>", "<rect width='100%' height='100%' fill='url(#bg)'>", "<animate attributeName='x' from='-500' to='500' dur='", animationDuration, "s' repeatCount='indefinite'/>", "</rect>", _generateCircles(seed), "</svg>" )); } function _getRandomGradientColors(uint seed) internal view returns (string memory) { string memory color1 = palette[seed % palette.length]; string memory color2 = palette[(seed / palette.length) % palette.length]; string memory color3 = palette[(seed / (palette.length * palette.length)) % palette.length]; return string(abi.encodePacked( "<stop offset='0%' stop-color='", color1, "'>", "<animate attributeName='stop-color' values='", color1, ";", color2, ";", color3, ";", color1, "' dur='10s' repeatCount='indefinite'/>", "</stop>", "<stop offset='100%' stop-color='", color2, "'>", "<animate attributeName='stop-color' values='", color2, ";", color3, ";", color1, ";", color2, "' dur='10s' repeatCount='indefinite'/>", "</stop>" )); } function _generateCircles(uint seed) internal pure returns (string memory) { string memory circles; for (uint i = 0; i < 3; i++) { uint circleSeed = uint(keccak256(abi.encodePacked(seed, i))); circles = string(abi.encodePacked(circles, _generateCircle(circleSeed, i))); } return circles; } function _generateCircle(uint seed, uint index) internal pure returns (string memory) { uint cx = seed % 400 + 50; uint cy = (seed / 1000) % 400 + 50; uint r = (seed / 1000000) % 50 + 10; string memory animationDuration = Strings.toString(3 + index * 2); // 3, 5, or 7 seconds return string(abi.encodePacked( "<circle cx='", Strings.toString(cx), "' cy='", Strings.toString(cy), "' r='", Strings.toString(r), "' fill='rgba(255,255,255,0.5)' stroke='white'>", "<animate attributeName='r' values='", Strings.toString(r), ";", Strings.toString(r + 10), ";", Strings.toString(r), "' dur='", animationDuration, "s' repeatCount='indefinite'/>", "</circle>" )); } }
定义了一个名为 DynamicSvgToken
的合约,继承自ERC721URIStorage
,并使用 Counters
库来管理代币 ID。palette
是一个包含颜色的字符串数组。构造函数初始化合约,设置代币名称为 "Dynamic SVG Token",符号为 "DST",并填充 palette
数组。mint
函数用于铸造新的代币,增加计数器并安全地将代币铸造给调用者,同时设置代币的 URI。_constructTokenURI
函数构建代币的 JSON 元数据,并将其编码为 Base64。_getRandomGradientColors
函数根据种子生成三个随机颜色,并创建渐变动画。_generateCircles
函数生成多个圆形元素,每个圆形都有不同的种子和动画。_generateCircle
函数生成一个带有动画的圆形元素。
总体来说,这段代码实现了一个动态生成 SVG 图像的 NFT,每个图像都有随机的渐变背景和动画圆形。