diff --git a/deployment/deploy_anvil.sh b/deployment/deploy_anvil.sh index 5fd3dc6..14f449d 100755 --- a/deployment/deploy_anvil.sh +++ b/deployment/deploy_anvil.sh @@ -55,4 +55,6 @@ BIBOS_ADDRESS="$(get_forge_script_return_value address bibos "$SCRIPT_OUTPUT")" echo "{}" > $DEPLOYMENTS_PATH # # save the bibos address in deployments.json -write_deployment_address "Bibos" $BIBOS_ADDRESS \ No newline at end of file +write_deployment_address "Bibos" $BIBOS_ADDRESS + +echo "$SCRIPT_OUTPUT" \ No newline at end of file diff --git a/foundry.toml b/foundry.toml index 265f363..389a9f4 100644 --- a/foundry.toml +++ b/foundry.toml @@ -1,3 +1,3 @@ -[default] +[profile.default] ffi = true libs = ["node_modules", "lib"] diff --git a/lib/forge-std b/lib/forge-std index 9825609..c19dfd2 160000 --- a/lib/forge-std +++ b/lib/forge-std @@ -1 +1 @@ -Subproject commit 98256095f37d83653ba1617d06ccd9604cbd7c6d +Subproject commit c19dfd2f2a88a461216b0dd1f4961e1a85dcad46 diff --git a/lib/solmate b/lib/solmate index 3c73813..03e4254 160000 --- a/lib/solmate +++ b/lib/solmate @@ -1 +1 @@ -Subproject commit 3c738133a0c1697096d63d28ef7a8ef298f9af6b +Subproject commit 03e425421b24c4f75e4a3209b019b367847b7708 diff --git a/packages/inspector/pages/api/render.ts b/packages/inspector/pages/api/render.ts index ee64737..7ccd9ea 100644 --- a/packages/inspector/pages/api/render.ts +++ b/packages/inspector/pages/api/render.ts @@ -10,9 +10,10 @@ export default async (request: NextApiRequest, response: NextApiResponse) => if (stderr) { // log the error to console console.log("stderr: ", stderr); - response.status(500); - response.send(stderr); - return resolve(); + // ignore errors until solmate updates their foundry.toml + // response.status(500); + // response.send(stderr); + // return resolve(); } console.log("synthesis_engine: synthesized bibos"); response.send(stdout); diff --git a/src/Bibos.sol b/src/Bibos.sol index a74cd28..f286b34 100644 --- a/src/Bibos.sol +++ b/src/Bibos.sol @@ -18,32 +18,113 @@ pragma solidity 0.8.13; /* solhint-enable */ import {ERC721} from "solmate/tokens/ERC721.sol"; -import {Render} from "./libraries/Render.sol"; +import {Owned} from "solmate/auth/Owned.sol"; +import {Render} from "libraries/Render.sol"; + +contract Bibos is ERC721, Owned { + /*////////////////////////////////////////////////////////////// + STATE + //////////////////////////////////////////////////////////////*/ + + uint256 public constant price = .111 ether; + uint256 public constant maxMintAmount = 10; + uint256 public constant maxSupply = 999; -contract Bibos is ERC721 { - address public owner; uint256 public totalSupply; + mapping(uint256 => bytes32) public seeds; // (tokenId => seed) + + /*////////////////////////////////////////////////////////////// + ERRORS + //////////////////////////////////////////////////////////////*/ - // tokenId => seed - mapping(uint256 => bytes32) public seed; + error InsufficentValue(); + error MintedOut(); + error ZeroMintAmount(); + error TooManyBibos(); error InvalidTokenId(); - constructor() ERC721("Bibos", "BBO") { - owner = msg.sender; + /*////////////////////////////////////////////////////////////// + MODIFIERS + //////////////////////////////////////////////////////////////*/ + + modifier OnlyIfYouPayEnough(uint256 _amount) { + if (msg.value != _amount * price) revert InsufficentValue(); + _; + } + + modifier OnlyIfNotMintedOut() { + if (totalSupply >= maxSupply) revert MintedOut(); + _; } + modifier OnlyIfFewerThanMaxMintAmount(uint256 _amount) { + if (_amount > maxMintAmount) revert TooManyBibos(); + _; + } + + modifier OnlyPositiveMintAmount(uint256 _amount) { + if (_amount == 0) revert ZeroMintAmount(); + _; + } + + /*////////////////////////////////////////////////////////////// + CONSTRUCTOR + //////////////////////////////////////////////////////////////*/ + + constructor() ERC721("Bibos", "BBO") Owned(msg.sender) {} + + /*////////////////////////////////////////////////////////////// + TOKENURI + //////////////////////////////////////////////////////////////*/ + function tokenURI(uint256 _tokenId) public view override returns (string memory) { if (_tokenId >= totalSupply) revert InvalidTokenId(); - return Render.tokenURI(_tokenId, seed[_tokenId]); + bytes32 seed = seeds[_tokenId]; + + return Render.tokenURI(_tokenId, seed); + } + + /*////////////////////////////////////////////////////////////// + MINTING + //////////////////////////////////////////////////////////////*/ + + function mint() public payable OnlyIfNotMintedOut OnlyIfYouPayEnough(1) { + _mint(msg.sender); } - function getSeed(uint256 _tokenId) public view returns (bytes32) { - return seed[_tokenId]; + function mint(uint256 _amount) + public + payable + OnlyIfNotMintedOut + OnlyIfYouPayEnough(_amount) + OnlyPositiveMintAmount(_amount) + OnlyIfFewerThanMaxMintAmount(_amount) + { + for (; _amount > 0; ) { + _mint(msg.sender); + _amount--; + } + } + + /*////////////////////////////////////////////////////////////// + WITHDRAW + //////////////////////////////////////////////////////////////*/ + + function withdraw(address payable _to) public onlyOwner { + _to.transfer(address(this).balance); + } + + /*////////////////////////////////////////////////////////////// + INTERNAL + //////////////////////////////////////////////////////////////*/ + + function _mint(address _to) internal { + uint256 tokenId = totalSupply++; + seeds[tokenId] = _computeSeed(tokenId); + ERC721._mint(_to, tokenId); } - function mint() external payable { - uint256 id = totalSupply++; - seed[id] = keccak256(abi.encodePacked(msg.sender, block.timestamp)); - _mint(msg.sender, id); + function _computeSeed(uint256 _tokenId) internal view returns (bytes32) { + return keccak256(abi.encodePacked(msg.sender, block.timestamp, _tokenId)); } } diff --git a/src/dev/PaletteUncompressed.sol b/src/dev/PaletteUncompressed.sol index 3951c43..d36742b 100644 --- a/src/dev/PaletteUncompressed.sol +++ b/src/dev/PaletteUncompressed.sol @@ -2,8 +2,8 @@ pragma solidity >=0.8.0; library PaletteUncompressed { - function lightestPalette(uint256 _value) internal pure returns (string memory) { - string[64] memory lightestPaletteValues = [ + function lightest(uint256 _value) internal pure returns (string memory) { + string[64] memory lightestValues = [ "#ffb3b3", "#ffbab3", "#ffc1b3", @@ -69,11 +69,11 @@ library PaletteUncompressed { "#ffb3c7", "#ffb3c0" ]; - return lightestPaletteValues[_value % 64]; + return lightestValues[_value % 64]; } - function lightPalette(uint256 _value) internal pure returns (string memory) { - string[64] memory lightPaletteValues = [ + function light(uint256 _value) internal pure returns (string memory) { + string[64] memory lightValues = [ "#ff3333", "#ff4633", "#ff5933", @@ -139,11 +139,11 @@ library PaletteUncompressed { "#ff336a", "#ff3357" ]; - return lightPaletteValues[_value % 64]; + return lightValues[_value % 64]; } - function darkestPalette(uint256 _value) internal pure returns (string memory) { - string[64] memory darkestPaletteValues = [ + function darkest(uint256 _value) internal pure returns (string memory) { + string[64] memory darkestValues = [ "#060a06", "#060d07", "#061007", @@ -209,7 +209,7 @@ library PaletteUncompressed { "#230415", "#280217" ]; - return darkestPaletteValues[_value % 64]; + return darkestValues[_value % 64]; } function invertedLightestPalette(uint256 _value) internal pure returns (string memory) { diff --git a/src/dev/PaletteUtil.sol b/src/dev/PaletteUtil.sol index db98751..4a31d5f 100644 --- a/src/dev/PaletteUtil.sol +++ b/src/dev/PaletteUtil.sol @@ -11,7 +11,7 @@ library PaletteUtil { string memory result; uint256 i; for (; i < 64; ) { - string memory strHex = slice7CharColor(PaletteUncompressed.lightestPalette(i)); + string memory strHex = slice7CharColor(PaletteUncompressed.lightest(i)); result = string.concat(result, strHex); ++i; } @@ -22,7 +22,7 @@ library PaletteUtil { string memory result; uint256 i; for (; i < 64; ) { - string memory strHex = slice7CharColor(PaletteUncompressed.lightPalette(i)); + string memory strHex = slice7CharColor(PaletteUncompressed.light(i)); result = string.concat(result, strHex); ++i; } @@ -33,7 +33,7 @@ library PaletteUtil { string memory result; uint256 i; for (; i < 64; ) { - string memory strHex = slice7CharColor(PaletteUncompressed.darkestPalette(i)); + string memory strHex = slice7CharColor(PaletteUncompressed.darkest(i)); result = string.concat(result, strHex); ++i; } diff --git a/src/libraries/Background.sol b/src/libraries/Background.sol index cdbdfba..714986e 100644 --- a/src/libraries/Background.sol +++ b/src/libraries/Background.sol @@ -6,7 +6,15 @@ import {SVG} from "./SVG.sol"; library Background { function render(bytes32 _seed) internal pure returns (string memory) { - string memory fill = Palette.getBackgroundFill(_seed); - return SVG.rect("100%", "100%", fill); + return + SVG.element( + "rect", + SVG.rectAttributes({ + _width: "100%", + _height: "100%", + _fill: Palette.backgroundFill(_seed), + _attributes: "" + }) + ); } } diff --git a/src/libraries/Body.sol b/src/libraries/Body.sol index a3474f9..885ef91 100644 --- a/src/libraries/Body.sol +++ b/src/libraries/Body.sol @@ -8,19 +8,26 @@ import {Util} from "./Util.sol"; import {SVG} from "./SVG.sol"; library Body { - function render(bytes32 _seed) internal pure returns (string memory) { - string memory result = ""; + /*////////////////////////////////////////////////////////////// + RENDER + //////////////////////////////////////////////////////////////*/ + function render(bytes32 _seed) internal pure returns (string memory) { + string memory bodyGroupChildren; string[7] memory radii = ["64", "64", "64", "56", "48", "32", "24"]; - uint256 bodySeed = uint256(keccak256(abi.encodePacked(_seed, "body"))); + string memory backgroundFill = Palette.backgroundFill(_seed); + string memory mixBlendMode = Traits.polarityType(_seed) == PolarityType.POSITIVE ? "lighten" : "multiply"; + + bodyGroupChildren = string.concat(bodyGroupChildren, _bodyBackground(backgroundFill)); - string memory backgroundFill = Palette.getBackgroundFill(_seed); - result = addBodyBackground(result, backgroundFill); uint256 length = Data.length; + // uint256 circlesCount = 7; + for (uint8 i = 0; i < 7; i++) { + uint256 bodySeed = uint256(keccak256(abi.encodePacked(_seed, "body", i))); + string memory bodyFill = Palette.bodyFill(_seed, i); string memory radius = radii[i]; - string memory fill = Palette.getBodyFill(_seed, i); string memory dur = Data.shortTimes(bodySeed); bodySeed /= length; @@ -28,41 +35,45 @@ library Body { string[2] memory coords = (i == 0) ? ["150", "150"] : Data.bodyPoints(bodySeed); bodySeed /= length; - string memory reverse = bodySeed % 2 == 0 ? 'keyPoints="1;0" keyTimes="0;1" ' : ""; + bool reverse = bodySeed % 2 == 0; bodySeed /= 2; - string memory mixBlendMode = Traits.getPolarityType(_seed) == PolarityType.POSITIVE - ? "lighten" - : "multiply"; - - result = addBodyCircle(result, radius, coords, fill, dur, reverse, mixBlendMode); + bodyGroupChildren = string.concat( + bodyGroupChildren, + _bodyCircle(radius, coords, bodyFill, dur, reverse, mixBlendMode) + ); } - - return string.concat('', result, ""); + return + SVG.element( + "g", + string.concat(SVG.filterAttribute("bibo-blur"), 'shape-rendering="optimizeSpeed"'), + bodyGroupChildren + ); } - function addBodyCircle( - string memory _result, + function _bodyCircle( string memory _radius, string[2] memory _coords, string memory _fill, string memory _dur, - string memory _reverse, + bool _reverse, string memory _mixBlendMode ) internal pure returns (string memory) { - string memory mpath = ''; string memory opacity = "1"; - return - string.concat( - _result, - SVG.circle(_radius, _coords, _mixBlendMode, _fill, opacity), - SVG.animateMotion(_reverse, _dur, "linear", mpath), - "" + SVG.element( + "circle", + SVG.circleAttributes(_radius, _coords, _fill, opacity, _mixBlendMode, ""), + SVG.element( + "animateMotion", + SVG.animateMotionAttributes(_reverse, _dur, "linear"), + Data.mpathJitterLg() + ) ); } - function addBodyBackground(string memory _result, string memory _fill) internal pure returns (string memory) { - return string.concat(_result, SVG.rect("100%", "100%", _fill)); + function _bodyBackground(string memory _fill) internal pure returns (string memory) { + return + SVG.element("rect", SVG.rectAttributes({_width: "100%", _height: "100%", _fill: _fill, _attributes: ""})); } } diff --git a/src/libraries/Cheeks.sol b/src/libraries/Cheeks.sol index a2654c3..0590b2d 100644 --- a/src/libraries/Cheeks.sol +++ b/src/libraries/Cheeks.sol @@ -12,16 +12,23 @@ enum CheekType { } library Cheeks { - function render(bytes32 _seed) internal pure returns (string memory) { - CheekType cheekType = Traits.getCheekType(_seed); + /*////////////////////////////////////////////////////////////// + RENDER + //////////////////////////////////////////////////////////////*/ - if (cheekType == CheekType.CIRCULAR) return circular(); - if (cheekType == CheekType.FRECKLES) return freckles(); + function render(bytes32 _seed) internal pure returns (string memory) { + CheekType cheekType = Traits.cheekType(_seed); + if (cheekType == CheekType.CIRCULAR) return _circular(); + if (cheekType == CheekType.FRECKLES) return _freckles(); return ""; } - function circular() internal pure returns (string memory) { + /*////////////////////////////////////////////////////////////// + INTERNAL + //////////////////////////////////////////////////////////////*/ + + function _circular() internal pure returns (string memory) { return string.concat( "", @@ -29,7 +36,7 @@ library Cheeks { ); } - function freckles() internal pure returns (string memory) { + function _freckles() internal pure returns (string memory) { return string.concat( "", diff --git a/src/libraries/Data.sol b/src/libraries/Data.sol index 39bd496..83e7bb2 100644 --- a/src/libraries/Data.sol +++ b/src/libraries/Data.sol @@ -91,7 +91,7 @@ library Data { DEFS //////////////////////////////////////////////////////////////*/ - function defs() internal pure returns (string memory) { + function defs() external pure returns (string memory) { return string.concat( "", @@ -110,6 +110,14 @@ library Data { ); } + function mpathJitterLg() internal pure returns (string memory) { + return ''; + } + + function mpathJitterSm() internal pure returns (string memory) { + return ''; + } + /*////////////////////////////////////////////////////////////// DATA //////////////////////////////////////////////////////////////*/ diff --git a/src/libraries/Eyes.sol b/src/libraries/Eyes.sol index 385a27b..5aedf33 100644 --- a/src/libraries/Eyes.sol +++ b/src/libraries/Eyes.sol @@ -20,23 +20,31 @@ enum EyeType { } library Eyes { + /*////////////////////////////////////////////////////////////// + RENDER + //////////////////////////////////////////////////////////////*/ + function render(bytes32 _seed) internal pure returns (string memory) { string memory fill = "black"; - EyeType eyeType = Traits.getEyeType(_seed); - - if (eyeType == EyeType.OPEN) return open(fill); - if (eyeType == EyeType.SMILEY) return smiley(fill); - if (eyeType == EyeType.WINK) return wink(fill); - if (eyeType == EyeType.SLEEPY) return sleepy(fill); - if (eyeType == EyeType.CLOVER) return clover(fill); - if (eyeType == EyeType.DIZZY) return dizzy(fill); - if (eyeType == EyeType.HEART) return heart(fill); - if (eyeType == EyeType.WINCE) return wince(fill); - if (eyeType == EyeType.CYCLOPS) return cyclops(fill); - return star(fill); + EyeType eyeType = Traits.eyeType(_seed); + + if (eyeType == EyeType.OPEN) return _open(fill); + if (eyeType == EyeType.SMILEY) return _smiley(fill); + if (eyeType == EyeType.WINK) return _wink(fill); + if (eyeType == EyeType.SLEEPY) return _sleepy(fill); + if (eyeType == EyeType.CLOVER) return _clover(fill); + if (eyeType == EyeType.DIZZY) return _dizzy(fill); + if (eyeType == EyeType.HEART) return _heart(fill); + if (eyeType == EyeType.WINCE) return _wince(fill); + if (eyeType == EyeType.CYCLOPS) return _cyclops(fill); + return _star(fill); } - function open(string memory _fill) internal pure returns (string memory) { + /*////////////////////////////////////////////////////////////// + INTERNAL + //////////////////////////////////////////////////////////////*/ + + function _open(string memory _fill) internal pure returns (string memory) { return string.concat( '", - SVG.rect("200", "200", "#00000000"), - SVG.circleFilter("80", ["100", "100"], "lighten", "white", "0.2", "bibo-blur-lg"), - "", - Eyes.render(_seed), - Mouth.render(_seed), - Cheeks.render(_seed), - animateMotion(reverse), - "" + ")", + "'" ); - return result; - } - - function animateMotion(string memory _reverse) internal pure returns (string memory) { return - string.concat( - '', - '', - "" + SVG.element( + "g", + faceGroupAttributes, + SVG.element( + "rect", + SVG.rectAttributes({_width: "200", _height: "200", _fill: "#00000000", _attributes: ""}) + ), + SVG.element("circle", circleAttributes), + Eyes.render(_seed), + Mouth.render(_seed), + Cheeks.render(_seed), + SVG.element( + "animateMotion", + SVG.animateMotionAttributes(reverse, "11s", "linear"), + Data.mpathJitterLg() + ) ); } } diff --git a/src/libraries/Glints.sol b/src/libraries/Glints.sol index 9f30d43..dcad298 100644 --- a/src/libraries/Glints.sol +++ b/src/libraries/Glints.sol @@ -9,77 +9,104 @@ import {SVG} from "./SVG.sol"; library Glints { function render(bytes32 _seed) internal pure returns (string memory) { - string memory result = ""; - uint256 glintSeed = uint256(keccak256(abi.encodePacked(_seed, "glint"))) % 100; - string memory reverseRotate = glintSeed % 2 == 0 ? "from='0 0 0' to='360 0 0'" : "from='360 0 0' to='0 0 0'"; + string memory glintsGroupChildren; + uint256 glintCount = Traits.glintCount(_seed); - uint256 glintCount = Traits.getGlintCount(_seed); - - string memory opacity = Palette.getOpacity(glintSeed, _seed); + uint256 glintSeed = uint256(keccak256(abi.encodePacked(_seed, "glint"))); + bool reverseRotate = glintSeed % 2 == 0; + glintSeed /= 2; + bool reverse = glintSeed % 2 == 0; + glintSeed /= 2; + string memory opacity = Palette.opacity(glintSeed, _seed); glintSeed /= Palette.opacityLength; string[2][3] memory coords = Data.glintPoints(glintSeed); glintSeed /= Data.length; for (uint8 index = 0; index < glintCount; index++) { - string memory reverse = glintSeed % 2 == 0 ? "keyPoints='1;0' keyTimes='0;1'" : ""; - - result = addGlint( - result, - Data.longTimes(glintSeed), - Data.shortTimes(glintSeed), - coords[index], - reverseRotate, - reverse, - opacity + glintsGroupChildren = string.concat( + glintsGroupChildren, + _glint( + Data.shortTimes(glintSeed), + Data.longTimes(glintSeed), + coords[index], + reverseRotate, + reverse, + opacity + ) ); } - return string.concat("", result, ""); + return SVG.element("g", "id='glints'", glintsGroupChildren); } - function addGlint( - string memory _result, - string memory _durationLong, + function _glint( string memory _durationShort, + string memory _durationLong, string[2] memory _coords, - string memory _reverseRotate, - string memory _reverse, + bool _reverseRotate, + bool _reverse, string memory _opacity ) internal pure returns (string memory) { + return + SVG.element( + "g", + _transformAttribute(_coords), + SVG.element( + "g", + "", + SVG.element( + "circle", + SVG.circleAttributes({ + _radius: "10", + _coords: ["0", "0"], + _fill: "white", + _opacity: "1.0", + _mixMode: "lighten", + _attributes: SVG.filterAttribute("bibo-blur-sm") + }) + ), + SVG.element( + "path", + _pathAttributes(_opacity), + '' + ), + _animateTransform(_durationShort, _reverseRotate) + ), + SVG.element( + "animateMotion", + SVG.animateMotionAttributes(_reverse, _durationLong, "linear"), + Data.mpathJitterLg() + ) + ); + } + + function _pathAttributes(string memory _opacity) internal pure returns (string memory) { return string.concat( - _result, - '', - "", - SVG.circleFilter("10", ["0", "0"], "lighten", "white", "1.0", "bibo-blur-sm"), - "", - "', - '', - "", - animateTransform(_durationShort, _reverseRotate), - "", - SVG.animateMotion(_reverse, _durationLong, "linear", ''), - "" + ' fill="white" style="mix-blend-mode:normal" fill-rule="evenodd" clip-rule="evenodd" d="M2.60676 11.4891C2.49095 12.4964 1.95054 13 0.985526 13C0.580218 13 0.223162 12.8644 -0.0856447 12.5932C-0.39445 12.322 -0.577804 11.9831 -0.635705 11.5763C-0.86731 9.71671 -1.10856 8.28329 -1.35947 7.27603C-1.59107 6.2494 -1.97708 5.47458 -2.51749 4.95157C-3.0386 4.42857 -3.85887 4.02179 -4.97829 3.73123C-6.07841 3.42131 -7.62244 3.05327 -9.61037 2.62712C-10.5368 2.43341 -11 1.89104 -11 0.999999C-11 0.593219 -10.8649 0.234868 -10.5947 -0.0750589C-10.3245 -0.384987 -9.98673 -0.569006 -9.58142 -0.627117C-7.61279 -0.878934 -6.07841 -1.13075 -4.97829 -1.38257C-3.87817 -1.63438 -3.0579 -2.03147 -2.51749 -2.57385C-1.97708 -3.11622 -1.59107 -3.92978 -1.35947 -5.01453C-1.10856 -6.09927 -0.86731 -7.60048 -0.635705 -9.51816C-0.500603 -10.5061 0.0398083 -11 0.985526 -11C1.95054 -11 2.49095 -10.4964 2.60676 -9.4891C2.83836 -7.64891 3.06997 -6.2155 3.30157 -5.18886C3.53317 -4.1816 3.91918 -3.42615 4.45959 -2.92252C5 -2.41889 5.82992 -2.0121 6.94934 -1.70218C8.06876 -1.41162 9.61279 -1.05327 11.5814 -0.627117C12.5271 -0.414042 13 0.128328 13 0.999999C13 1.92978 12.4692 2.47215 11.4077 2.62712C9.47768 2.91767 7.97226 3.19855 6.89144 3.46973C5.81062 3.74092 5 4.1477 4.45959 4.69007C3.91918 5.23244 3.53317 6.03632 3.30157 7.10169C3.06997 8.16707 2.83836 9.62954 2.60676 11.4891Z"' ); } - function animateTransform(string memory _dur, string memory _reverseRotate) internal pure returns (string memory) { + function _transformAttribute(string[2] memory _coords) internal pure returns (string memory) { + return string.concat('transform="translate(', _coords[0], ",", _coords[1], ') scale(1)"'); + } + + function _animateTransform(string memory _dur, bool _reverseRotate) internal pure returns (string memory) { + string memory reverseRotate = _reverseRotate ? "from='0 0 0' to='360 0 0'" : "from='360 0 0' to='0 0 0'"; + return - string.concat( - "" + SVG.element( + "animateTransform", + string.concat( + 'attributeName="transform" ', + "dur=", + Util.quote(_dur), + 'repeatCount="indefinite" ', + 'type="rotate" ', + reverseRotate + ) ); } } diff --git a/src/libraries/Metadata.sol b/src/libraries/Metadata.sol index 2df6984..44a4842 100644 --- a/src/libraries/Metadata.sol +++ b/src/libraries/Metadata.sol @@ -14,7 +14,7 @@ library Metadata { /// @param _description, the description of the token /// @param _svg, the svg image /// @return string, the name of the color - function encodeTokenMetadata( + function encodeMetadata( uint256 _id, string memory _name, string memory _description, @@ -34,24 +34,24 @@ library Metadata { ",", Util.keyValue("backgroundColor", _backgroundColor), ",", - Util.keyValue("image", encodeSvg(_svg)), + Util.keyValue("image", _encodeSVG(_svg)), "}" ); - return encodeJson(metadata); + return _encodeJSON(metadata); } /// @notice base64 encode json /// @param _json, stringified json /// @return string, bytes64 encoded json with prefix - function encodeJson(string memory _json) internal pure returns (string memory) { + function _encodeJSON(string memory _json) internal pure returns (string memory) { return string.concat(JSON_BASE64_HEADER, Base64.encode(_json)); } /// @notice base64 encode svg /// @param _svg, stringified json /// @return string, bytes64 encoded svg with prefix - function encodeSvg(string memory _svg) internal pure returns (string memory) { - return string.concat("data:image/svg+xml;base64,", Base64.encode(bytes(_svg))); + function _encodeSVG(string memory _svg) internal pure returns (string memory) { + return string.concat(SVG_XML_BASE64_HEADER, Base64.encode(bytes(_svg))); } } diff --git a/src/libraries/Motes.sol b/src/libraries/Motes.sol index 3b61e3e..635ccdb 100644 --- a/src/libraries/Motes.sol +++ b/src/libraries/Motes.sol @@ -18,12 +18,12 @@ library Motes { uint256 constant GLINT_COUNT = 16; function render(bytes32 _seed) internal pure returns (string memory) { - string memory result; + string memory motesChildren; string memory mixMode = "lighten"; string memory fill = "white"; - MoteType moteType = Traits.getMoteType(_seed); + MoteType moteType = Traits.moteType(_seed); if (moteType == MoteType.NONE) return ""; for (uint8 i = 0; i < GLINT_COUNT; i++) { @@ -35,64 +35,64 @@ library Motes { moteSeed = moteSeed / Data.length; string memory radius = moteSeed % 2 == 0 ? "1" : "2"; moteSeed = moteSeed / 2; - string memory opacity = Palette.getOpacity(moteSeed, _seed); + string memory opacity = Palette.opacity(moteSeed, _seed); moteSeed /= Palette.opacityLength; if (moteType == MoteType.FLOATING) { - string memory reverse = moteSeed % 2 == 0 ? "keyPoints='1;0' keyTimes='0;1'" : ""; - result = addFloatingMote(result, radius, coords, mixMode, fill, opacity, dur, reverse); + bool reverse = moteSeed % 2 == 0; + motesChildren = string.concat( + motesChildren, + _floatingMote(radius, coords, fill, opacity, mixMode, dur, reverse) + ); } else if (moteType == MoteType.RISING) - result = addRisingMote(result, radius, coords, mixMode, fill, opacity, dur); + motesChildren = string.concat(motesChildren, _risingMote(radius, coords, fill, opacity, mixMode, dur)); else if (moteType == MoteType.FALLING) { - result = addFallingMote(result, radius, coords, mixMode, fill, opacity, dur); + motesChildren = string.concat(motesChildren, _fallingMote(radius, coords, fill, opacity, mixMode, dur)); } } - return string.concat("", result, ""); + return SVG.element({_type: "g", _attributes: "", _children: motesChildren}); } - function addRisingMote( - string memory _result, + function _risingMote( string memory _radius, string[2] memory _coords, - string memory _mixMode, string memory _fill, string memory _opacity, + string memory _mixMode, string memory _dur ) internal pure returns (string memory) { return - string.concat( - _result, - '', - SVG.circle(_radius, _coords, _mixMode, _fill, _opacity), - animateTransform(_dur, "-100"), - SVG.animate(_dur), - "", - "" - ); + SVG.element({ + _type: "g", + _attributes: 'transform="translate(0,25)"', + _children: SVG.element( + "circle", + SVG.circleAttributes(_radius, _coords, _fill, _opacity, _mixMode, ""), + _animateTransform(_dur, "-100"), + _animate(_dur) + ) + }); } - function addFloatingMote( - string memory _result, + function _floatingMote( string memory _radius, string[2] memory _coords, - string memory _mixMode, string memory _fill, string memory _opacity, + string memory _mixMode, string memory _dur, - string memory _reverse + bool _reverse ) internal pure returns (string memory) { return - string.concat( - _result, - SVG.circle(_radius, _coords, _mixMode, _fill, _opacity), - SVG.animateMotion(_reverse, _dur, "paced", ''), - "" + SVG.element( + "circle", + SVG.circleAttributes(_radius, _coords, _fill, _opacity, _mixMode, ""), + SVG.element("animateMotion", SVG.animateMotionAttributes(_reverse, _dur, "paced"), Data.mpathJitterSm()) ); } - function addFallingMote( - string memory _result, + function _fallingMote( string memory _radius, string[2] memory _coords, string memory _mixMode, @@ -101,32 +101,46 @@ library Motes { string memory _dur ) internal pure returns (string memory) { return - string.concat( - _result, - '', - SVG.circle(_radius, _coords, _mixMode, _fill, _opacity), - animateTransform(_dur, "100"), - SVG.animate(_dur), - "", - "" + SVG.element( + "g", + 'transform="translate(0,-25)">', + SVG.element( + "circle", + SVG.circleAttributes(_radius, _coords, _fill, _opacity, _mixMode, ""), + _animateTransform(_dur, "100"), + _animate(_dur) + ) ); } - function animateTransform(string memory _dur, string memory _to) internal pure returns (string memory) { + function _animateTransform(string memory _dur, string memory _to) internal pure returns (string memory) { + string memory attributes = string.concat( + 'attributeName="transform" ', + "dur=", + Util.quote(_dur), + 'repeatCount="indefinite" ', + 'type="translate" ', + 'additive="sum" ', + 'from="0 0" ', + 'to="0 ', + _to, + '"' + ); + + return SVG.element("animateTransform", attributes); + } + + function _animate(string memory _dur) internal pure returns (string memory) { return - string.concat( - "" + SVG.element( + "animate", + string.concat( + 'attributeName="opacity" ', + 'values="0;1;0" ', + "dur=", + Util.quote(_dur), + 'repeatCount="indefinite" ' + ) ); } } diff --git a/src/libraries/Mouth.sol b/src/libraries/Mouth.sol index 68d9ad7..3f23001 100644 --- a/src/libraries/Mouth.sol +++ b/src/libraries/Mouth.sol @@ -17,19 +17,19 @@ enum MouthType { library Mouth { function render(bytes32 _seed) internal pure returns (string memory) { string memory fill = "black"; - MouthType mouthType = Traits.getMouthType(_seed); + MouthType mouthType = Traits.mouthType(_seed); - if (mouthType == MouthType.SMILE) return smile(fill); - if (mouthType == MouthType.MEDIUM_SMILE) return mediumSmile(fill); - if (mouthType == MouthType.SMALL_SMILE) return smallSmile(fill); - if (mouthType == MouthType.FLAT) return flat(fill); - if (mouthType == MouthType.FROWN) return frown(fill); - if (mouthType == MouthType.GRIN) return grin(fill); - if (mouthType == MouthType.SMOOCH) return smooch(fill); - return smirk(fill); + if (mouthType == MouthType.SMILE) return _smile(fill); + if (mouthType == MouthType.MEDIUM_SMILE) return _mediumSmile(fill); + if (mouthType == MouthType.SMALL_SMILE) return _smallSmile(fill); + if (mouthType == MouthType.FLAT) return _flat(fill); + if (mouthType == MouthType.FROWN) return _frown(fill); + if (mouthType == MouthType.GRIN) return _grin(fill); + if (mouthType == MouthType.SMOOCH) return _smooch(fill); + return _smirk(fill); } - function smile(string memory _fill) internal pure returns (string memory) { + function _smile(string memory _fill) internal pure returns (string memory) { return string.concat( ""); } - function smirk(string memory _fill) internal pure returns (string memory) { + function _smirk(string memory _fill) internal pure returns (string memory) { return string.concat( "", - _children, - "" ); } - function circle( + function circleAttributes( string memory _radius, string[2] memory _coords, - string memory _mixMode, string memory _fill, string memory _opacity, - string memory _params + string memory _mixMode, + string memory _attributes ) internal pure returns (string memory) { return string.concat( - "" - ); - } - - function circle( - string memory _radius, - string[2] memory _coords, - string memory _mixMode, - string memory _fill, - string memory _opacity - ) internal pure returns (string memory) { - return circle(_radius, _coords, _mixMode, _fill, _opacity, ""); - } - - function circleFilter( - string memory _radius, - string[2] memory _coords, - string memory _mixMode, - string memory _fill, - string memory _opacity, - string memory _filter - ) internal pure returns (string memory) { - return - circle( - _radius, - _coords, - _mixMode, - _fill, - _opacity, - string.concat("filter=", Util.quote(string.concat("url(#", _filter, ")"))) + _attributes, + " " ); } - function rect( + function rectAttributes( string memory _width, string memory _height, - string memory _fill + string memory _fill, + string memory _attributes ) internal pure returns (string memory) { return string.concat( - "" + " ", + _attributes, + " " ); } - function animateMotion( - string memory _rev, + function element( + string memory _type, + string memory _attributes, + string memory _children + ) internal pure returns (string memory) { + return string.concat("<", _type, " ", _attributes, ">", _children, ""); + } + + function element( + string memory _type, + string memory _attributes, + string memory _child1, + string memory _child2 + ) internal pure returns (string memory) { + return element(_type, _attributes, string.concat(_child1, _child2)); + } + + function element( + string memory _type, + string memory _attributes, + string memory _child1, + string memory _child2, + string memory _child3 + ) internal pure returns (string memory) { + return element(_type, _attributes, string.concat(_child1, _child2, _child3)); + } + + function element( + string memory _type, + string memory _attributes, + string memory _child1, + string memory _child2, + string memory _child3, + string memory _child4 + ) internal pure returns (string memory) { + return element(_type, _attributes, string.concat(_child1, _child2, _child3, _child4)); + } + + function element( + string memory _type, + string memory _attributes, + string memory _child1, + string memory _child2, + string memory _child3, + string memory _child4, + string memory _child5 + ) internal pure returns (string memory) { + return element(_type, _attributes, string.concat(_child1, _child2, _child3, _child4, _child5)); + } + + function element( + string memory _type, + string memory _attributes, + string memory _child1, + string memory _child2, + string memory _child3, + string memory _child4, + string memory _child5, + string memory _child6 + ) internal pure returns (string memory) { + return element(_type, _attributes, string.concat(_child1, _child2, _child3, _child4, _child5, _child6)); + } + + function element(string memory _type, string memory _attributes) internal pure returns (string memory) { + return string.concat("<", _type, " ", _attributes, "/>"); + } + + function animateMotionAttributes( + bool _reverse, string memory _dur, - string memory _calcMode, - string memory _mpath + string memory _calcMode ) internal pure returns (string memory) { + string memory reverse = _reverse ? "keyPoints='1;0' keyTimes='0;1'" : ""; + return string.concat( - "", - _mpath, - "" + Util.quote(_calcMode) ); } - function animate(string memory _dur) internal pure returns (string memory) { - return - string.concat( - "" - ); + function filterAttribute(string memory _id) internal pure returns (string memory) { + return string.concat("filter=", '"', "url(#", _id, ")", '" '); } } diff --git a/src/libraries/Traits.sol b/src/libraries/Traits.sol index 52dd34e..be1b8cf 100644 --- a/src/libraries/Traits.sol +++ b/src/libraries/Traits.sol @@ -14,33 +14,37 @@ library Traits { TRAITS //////////////////////////////////////////////////////////////*/ - function getTraits(bytes32 _seed) internal pure returns (string memory) { + function attributes(bytes32 _seed) internal pure returns (string memory) { string memory result = "["; - result = string.concat(result, trait("Density", getDensityTrait(_seed))); - result = string.concat(result, ",", trait("Polarity", getPolarityTrait(_seed))); - result = string.concat(result, ",", trait("Glints", getGlintTrait(_seed))); - result = string.concat(result, ",", trait("Mote", getMoteTrait(_seed))); - result = string.concat(result, ",", trait("Eyes", getEyeTrait(_seed))); - result = string.concat(result, ",", trait("Mouth", getMouthTrait(_seed))); - result = string.concat(result, ",", trait("Cheeks", getCheekTrait(_seed))); + result = string.concat(result, _attribute("Density", densityTrait(_seed))); + result = string.concat(result, ",", _attribute("Polarity", polarityTrait(_seed))); + result = string.concat(result, ",", _attribute("Glints", glintTrait(_seed))); + result = string.concat(result, ",", _attribute("Mote", moteTrait(_seed))); + result = string.concat(result, ",", _attribute("Eyes", eyeTrait(_seed))); + result = string.concat(result, ",", _attribute("Mouth", mouthTrait(_seed))); + result = string.concat(result, ",", _attribute("Cheeks", cheekTrait(_seed))); return string.concat(result, "]"); } - function trait(string memory _traitType, string memory _value) internal pure returns (string memory) { + function _attribute(string memory _traitType, string memory _value) internal pure returns (string memory) { return string.concat("{", Util.keyValue("trait_type", _traitType), ",", Util.keyValue("value", _value), "}"); } + function _computeSeed(bytes32 _seed, string memory _salt) internal pure returns (uint256) { + return uint256(keccak256(abi.encodePacked(_seed, _salt))) % 100; + } + /*////////////////////////////////////////////////////////////// DENSITY //////////////////////////////////////////////////////////////*/ - function getDensityTrait(bytes32 _seed) internal pure returns (string memory) { - DensityType densityType = getDensityType(_seed); - return densityType == DensityType.HIGH ? "High" : "Low"; + function densityTrait(bytes32 _seed) internal pure returns (string memory) { + DensityType type_ = densityType(_seed); + return type_ == DensityType.HIGH ? "High" : "Low"; } - function getDensityType(bytes32 _seed) internal pure returns (DensityType) { - uint256 densitySeed = uint256(keccak256(abi.encodePacked(_seed, "density"))) % 100; + function densityType(bytes32 _seed) internal pure returns (DensityType) { + uint256 densitySeed = _computeSeed(_seed, "density"); if (densitySeed < 80) return DensityType.HIGH; return DensityType.LOW; @@ -50,36 +54,36 @@ library Traits { POLARITY //////////////////////////////////////////////////////////////*/ - function getPolarityTrait(bytes32 _seed) internal pure returns (string memory) { - PolarityType polarityType = getPolarityType(_seed); - return polarityType == PolarityType.POSITIVE ? "Positive" : "Negative"; + function polarityTrait(bytes32 _seed) internal pure returns (string memory) { + PolarityType polarityType_ = polarityType(_seed); + return polarityType_ == PolarityType.POSITIVE ? "Positive" : "Negative"; } - function getPolarityType(bytes32 _seed) internal pure returns (PolarityType) { - uint256 polaritySeed = uint256(keccak256(abi.encodePacked(_seed, "polarity"))) % 100; + function polarityType(bytes32 _seed) internal pure returns (PolarityType) { + uint256 polaritySeed = _computeSeed(_seed, "polarity"); if (polaritySeed < 80) return PolarityType.POSITIVE; return PolarityType.NEGATIVE; } /*////////////////////////////////////////////////////////////// - GLINT + MOTE //////////////////////////////////////////////////////////////*/ - function getMoteTrait(bytes32 _seed) internal pure returns (string memory) { - MoteType moteType = getMoteType(_seed); - if (moteType == MoteType.FLOATING) return "Floating"; - if (moteType == MoteType.RISING) return "Rising"; - if (moteType == MoteType.FALLING) return "Falling"; + function moteTrait(bytes32 _seed) internal pure returns (string memory) { + MoteType type_ = moteType(_seed); + if (type_ == MoteType.FLOATING) return "Floating"; + if (type_ == MoteType.RISING) return "Rising"; + if (type_ == MoteType.FALLING) return "Falling"; return "None"; } - function getMoteType(bytes32 _seed) internal pure returns (MoteType) { - uint256 moteTypeSeed = uint256(keccak256(abi.encodePacked(_seed, "moteType"))) % 100; + function moteType(bytes32 _seed) internal pure returns (MoteType) { + uint256 moteSeed = _computeSeed(_seed, "mote"); - if (moteTypeSeed % 100 < 20) return MoteType.FLOATING; - if (moteTypeSeed % 100 < 35) return MoteType.RISING; - if (moteTypeSeed % 100 < 40) return MoteType.FALLING; + if (moteSeed < 20) return MoteType.FLOATING; + if (moteSeed < 35) return MoteType.RISING; + if (moteSeed < 40) return MoteType.FALLING; return MoteType.NONE; } @@ -87,32 +91,32 @@ library Traits { EYE //////////////////////////////////////////////////////////////*/ - function getEyeTrait(bytes32 _seed) internal pure returns (string memory) { - EyeType eyeType = getEyeType(_seed); - if (eyeType == EyeType.OPEN) return "Open"; - if (eyeType == EyeType.SMILEY) return "Smiley"; - if (eyeType == EyeType.WINK) return "Wink"; - if (eyeType == EyeType.SLEEPY) return "Sleepy"; - if (eyeType == EyeType.CLOVER) return "Clover"; - if (eyeType == EyeType.DIZZY) return "Dizzy"; - if (eyeType == EyeType.HEART) return "Heart"; - if (eyeType == EyeType.WINCE) return "Wince"; - if (eyeType == EyeType.CYCLOPS) return "Cyclops"; + function eyeTrait(bytes32 _seed) internal pure returns (string memory) { + EyeType type_ = eyeType(_seed); + if (type_ == EyeType.OPEN) return "Open"; + if (type_ == EyeType.SMILEY) return "Smiley"; + if (type_ == EyeType.WINK) return "Wink"; + if (type_ == EyeType.SLEEPY) return "Sleepy"; + if (type_ == EyeType.CLOVER) return "Clover"; + if (type_ == EyeType.DIZZY) return "Dizzy"; + if (type_ == EyeType.HEART) return "Heart"; + if (type_ == EyeType.WINCE) return "Wince"; + if (type_ == EyeType.CYCLOPS) return "Cyclops"; return "Star"; } - function getEyeType(bytes32 _seed) internal pure returns (EyeType) { + function eyeType(bytes32 _seed) internal pure returns (EyeType) { uint256 eyeSeed = uint256(keccak256(abi.encodePacked(_seed, "eye"))) % 100; - if (eyeSeed % 100 < 25) return EyeType.OPEN; - if (eyeSeed % 100 < 50) return EyeType.SMILEY; - if (eyeSeed % 100 < 65) return EyeType.WINK; - if (eyeSeed % 100 < 75) return EyeType.SLEEPY; - if (eyeSeed % 100 < 83) return EyeType.CLOVER; - if (eyeSeed % 100 < 89) return EyeType.DIZZY; - if (eyeSeed % 100 < 94) return EyeType.HEART; - if (eyeSeed % 100 < 97) return EyeType.WINCE; - if (eyeSeed % 100 < 99) return EyeType.CYCLOPS; + if (eyeSeed < 25) return EyeType.OPEN; + if (eyeSeed < 50) return EyeType.SMILEY; + if (eyeSeed < 65) return EyeType.WINK; + if (eyeSeed < 75) return EyeType.SLEEPY; + if (eyeSeed < 83) return EyeType.CLOVER; + if (eyeSeed < 89) return EyeType.DIZZY; + if (eyeSeed < 94) return EyeType.HEART; + if (eyeSeed < 97) return EyeType.WINCE; + if (eyeSeed < 99) return EyeType.CYCLOPS; return EyeType.STAR; } @@ -120,27 +124,28 @@ library Traits { MOUTH //////////////////////////////////////////////////////////////*/ - function getMouthTrait(bytes32 _seed) internal pure returns (string memory) { - MouthType mouthType = getMouthType(_seed); - if (mouthType == MouthType.SMILE) return "Smile"; - if (mouthType == MouthType.MEDIUM_SMILE) return "Medium Smile"; - if (mouthType == MouthType.SMALL_SMILE) return "Small Smile"; - if (mouthType == MouthType.FLAT) return "Flat"; - if (mouthType == MouthType.FROWN) return "Frown"; - if (mouthType == MouthType.GRIN) return "Grin"; + function mouthTrait(bytes32 _seed) internal pure returns (string memory) { + MouthType type_ = mouthType(_seed); + + if (type_ == MouthType.SMILE) return "Smile"; + if (type_ == MouthType.MEDIUM_SMILE) return "Medium Smile"; + if (type_ == MouthType.SMALL_SMILE) return "Small Smile"; + if (type_ == MouthType.FLAT) return "Flat"; + if (type_ == MouthType.FROWN) return "Frown"; + if (type_ == MouthType.GRIN) return "Grin"; return "Smooch"; } - function getMouthType(bytes32 _seed) internal pure returns (MouthType) { - uint256 mouthTypeSeed = uint256(keccak256(abi.encodePacked(_seed, "mouthType"))) % 100; + function mouthType(bytes32 _seed) internal pure returns (MouthType) { + uint256 mouthSeed = _computeSeed(_seed, "mouth"); - if (mouthTypeSeed % 100 < 30) return MouthType.SMILE; - if (mouthTypeSeed % 100 < 60) return MouthType.MEDIUM_SMILE; - if (mouthTypeSeed % 100 < 80) return MouthType.SMALL_SMILE; - if (mouthTypeSeed % 100 < 90) return MouthType.FLAT; - if (mouthTypeSeed % 100 < 94) return MouthType.FROWN; - if (mouthTypeSeed % 100 < 97) return MouthType.GRIN; - if (mouthTypeSeed % 100 < 99) return MouthType.SMOOCH; + if (mouthSeed < 30) return MouthType.SMILE; + if (mouthSeed < 60) return MouthType.MEDIUM_SMILE; + if (mouthSeed < 80) return MouthType.SMALL_SMILE; + if (mouthSeed < 90) return MouthType.FLAT; + if (mouthSeed < 94) return MouthType.FROWN; + if (mouthSeed < 97) return MouthType.GRIN; + if (mouthSeed < 99) return MouthType.SMOOCH; return MouthType.SMIRK; } @@ -148,36 +153,36 @@ library Traits { CHEEKS //////////////////////////////////////////////////////////////*/ - function getCheekTrait(bytes32 _seed) internal pure returns (string memory) { - CheekType cheekType = getCheekType(_seed); - if (cheekType == CheekType.NONE) return "None"; - if (cheekType == CheekType.CIRCULAR) return "Circular"; + function cheekTrait(bytes32 _seed) internal pure returns (string memory) { + CheekType type_ = cheekType(_seed); + if (type_ == CheekType.NONE) return "None"; + if (type_ == CheekType.CIRCULAR) return "Circular"; return "Freckles"; } - function getCheekType(bytes32 _seed) internal pure returns (CheekType) { - uint256 cheeksSeed = uint256(keccak256(abi.encodePacked(_seed, "cheeks"))) % 100; + function cheekType(bytes32 _seed) internal pure returns (CheekType) { + uint256 cheeksSeed = _computeSeed(_seed, "cheeks"); - if (cheeksSeed % 100 < 70) return CheekType.NONE; - if (cheeksSeed % 100 < 95) return CheekType.CIRCULAR; + if (cheeksSeed < 70) return CheekType.NONE; + if (cheeksSeed < 95) return CheekType.CIRCULAR; return CheekType.FRECKLES; } /*////////////////////////////////////////////////////////////// - MOTES + GLINT //////////////////////////////////////////////////////////////*/ - function getGlintTrait(bytes32 _seed) internal pure returns (string memory) { - uint256 glintCount = getGlintCount(_seed); - return Util.uint256ToString(glintCount); + function glintTrait(bytes32 _seed) internal pure returns (string memory) { + uint256 count_ = glintCount(_seed); + return Util.uint256ToString(count_); } - function getGlintCount(bytes32 _seed) internal pure returns (uint256) { - uint256 glintSeed = uint256(keccak256(abi.encodePacked(_seed, "glint"))) % 100; + function glintCount(bytes32 _seed) internal pure returns (uint256) { + uint256 glintSeed = _computeSeed(_seed, "glint"); - if (glintSeed % 100 < 1) return 3; - if (glintSeed % 100 < 5) return 2; - if (glintSeed % 100 < 35) return 1; + if (glintSeed < 1) return 3; + if (glintSeed < 5) return 2; + if (glintSeed < 35) return 1; return 0; } } diff --git a/src/scripts/local_render.sol b/src/scripts/local_render.sol index 2d60ef7..c13ac61 100644 --- a/src/scripts/local_render.sol +++ b/src/scripts/local_render.sol @@ -9,7 +9,7 @@ import {time} from "src/util/time.sol"; contract local_render is Test { function run() external returns (string memory tokenURI) { - vm.startPrank(0xa0Ee7A142d267C1f36714E4a8F75612F20a79720); + // vm.startPrank(0xa0Ee7A142d267C1f36714E4a8F75612F20a79720); Bibos bibos = new Bibos(); @@ -26,7 +26,8 @@ contract local_render is Test { vm.store(address(bibos), bytes32(uint256(7)), bytes32(tokenId)); // mint - bibos.mint(); + vm.deal(address(this), .111 ether); + bibos.mint{value: .111 ether}(); tokenURI = bibos.tokenURI(tokenId); } } diff --git a/src/test/Bibos.t.sol b/src/test/Bibos.t.sol index c1d9529..6dedcd8 100644 --- a/src/test/Bibos.t.sol +++ b/src/test/Bibos.t.sol @@ -12,12 +12,19 @@ contract BibosTest is Test { } function testMint() public { - bibos.mint(); + bibos.mint{value: bibos.price()}(); assertEq(bibos.totalSupply(), 1); } + function testMintMultiple(uint8 _amount) public { + vm.assume(_amount > 0); + vm.assume(_amount <= 10); + bibos.mint{value: _amount * bibos.price()}(_amount); + assertEq(bibos.totalSupply(), _amount); + } + function testGetTokenURI() public { - bibos.mint(); + bibos.mint{value: bibos.price()}(); string memory tokenURI = bibos.tokenURI(0); assertGt(bytes(tokenURI).length, 0); diff --git a/src/test/Palette.t.sol b/src/test/Palette.t.sol index 306797d..46abcb8 100644 --- a/src/test/Palette.t.sol +++ b/src/test/Palette.t.sol @@ -4,7 +4,7 @@ pragma solidity >=0.8.0; import {Test} from "forge-std/Test.sol"; import {PointsUtil} from "dev/PointsUtil.sol"; import {Data} from "libraries/Data.sol"; -import {PointsUncompressed} from "dev/PointsUncompressed.sol"; +import {PaletteUncompressed} from "dev/PaletteUncompressed.sol"; import {Palette} from "../libraries/Palette.sol"; contract PaletteTest is Test { @@ -12,24 +12,24 @@ contract PaletteTest is Test { function testLightestPalette(uint8 _i) public { vm.assume(_i < 64); - string memory palette1 = Palette.lightestPalette(_i); - string memory palette2 = Data.lightestPalette(_i); + string memory palette1 = Palette._lightest(_i); + string memory palette2 = PaletteUncompressed.lightest(_i); assertEq(palette1, palette2); } function testLightPalette(uint8 _i) public { vm.assume(_i < 64); - string memory palette1 = Palette.lightPalette(_i); - string memory palette2 = Data.lightPalette(_i); + string memory palette1 = Palette._light(_i); + string memory palette2 = PaletteUncompressed.light(_i); assertEq(palette1, palette2); } function testDarkestPalette(uint8 _i) public { vm.assume(_i < 64); - string memory palette1 = Palette.darkestPalette(_i); - string memory palette2 = Data.darkestPalette(_i); + string memory palette1 = Palette._darkest(_i); + string memory palette2 = PaletteUncompressed.darkest(_i); assertEq(palette1, palette2); } diff --git a/src/test/SvgValidation.t.sol b/src/test/SvgValidation.t.sol index 4f26812..34c212a 100644 --- a/src/test/SvgValidation.t.sol +++ b/src/test/SvgValidation.t.sol @@ -3,7 +3,6 @@ pragma solidity >=0.8.0; import {Test, console2 as console} from "forge-std/Test.sol"; import {Bibos} from "../Bibos.sol"; -import {vm} from "../util/vm.sol"; import {time} from "../util/time.sol"; contract SvgValidationTest is Test { @@ -17,7 +16,7 @@ contract SvgValidationTest is Test { uint256 unixTime = time.getUnixTime(); vm.warp(unixTime); - bibos.mint(); + bibos.mint{value: bibos.price()}(); string memory tokenURI = bibos.tokenURI(0); string[] memory validateInputs = new string[](3);