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, "", _type, ">");
+ }
+
+ 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);