Skip to content

Commit

Permalink
architecture (#55)
Browse files Browse the repository at this point in the history
* borken

* fix background

* small changes

* lfg

* lft part 2

* mint multiple

* fix: bibos tests

* fix constructor

* small updates

* comments and consistency

* fix face rect

* update script, remove sample.svg

* require exact price

* small change

* cleanup animate transform

* forge update, found.toml update

* remove unused paths script and lib

* patch solmate warning

* remove debug svgs
  • Loading branch information
mshrieve authored Jul 17, 2022
1 parent efa930c commit 803b76c
Show file tree
Hide file tree
Showing 26 changed files with 687 additions and 465 deletions.
4 changes: 3 additions & 1 deletion deployment/deploy_anvil.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
write_deployment_address "Bibos" $BIBOS_ADDRESS

echo "$SCRIPT_OUTPUT"
2 changes: 1 addition & 1 deletion foundry.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
[default]
[profile.default]
ffi = true
libs = ["node_modules", "lib"]
2 changes: 1 addition & 1 deletion lib/forge-std
2 changes: 1 addition & 1 deletion lib/solmate
7 changes: 4 additions & 3 deletions packages/inspector/pages/api/render.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
109 changes: 95 additions & 14 deletions src/Bibos.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}
}
18 changes: 9 additions & 9 deletions src/dev/PaletteUncompressed.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -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) {
Expand Down
6 changes: 3 additions & 3 deletions src/dev/PaletteUtil.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand All @@ -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;
}
Expand All @@ -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;
}
Expand Down
12 changes: 10 additions & 2 deletions src/libraries/Background.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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: ""
})
);
}
}
63 changes: 37 additions & 26 deletions src/libraries/Body.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,61 +8,72 @@ 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;

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('<g filter="url(#bibo-blur)" shape-rendering="optimizeSpeed">', result, "</g>");
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 = '<mpath xlink:href="#bibo-jitter-lg"/>';
string memory opacity = "1";

return
string.concat(
_result,
SVG.circle(_radius, _coords, _mixBlendMode, _fill, opacity),
SVG.animateMotion(_reverse, _dur, "linear", mpath),
"</circle>"
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: ""}));
}
}
19 changes: 13 additions & 6 deletions src/libraries/Cheeks.sol
Original file line number Diff line number Diff line change
Expand Up @@ -12,24 +12,31 @@ 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(
"<circle cx='149' cy='113' r='6' fill='white' fill-opacity='0.6'/>",
"<circle cx='54' cy='113' r='6' fill='white' fill-opacity='0.6'/>"
);
}

function freckles() internal pure returns (string memory) {
function _freckles() internal pure returns (string memory) {
return
string.concat(
"<circle cx='144.5' cy='110.5' r='3.5' fill='white' fill-opacity='0.6'/>",
Expand Down
Loading

0 comments on commit 803b76c

Please sign in to comment.