Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
.env

cache/
out/
broadcast/
node_modules
node_modules/

.DS_Store

Expand Down
1,113 changes: 1,113 additions & 0 deletions data/seeds.json

Large diffs are not rendered by default.

41,884 changes: 41,884 additions & 0 deletions data/traits.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion lib/forge-std
2 changes: 1 addition & 1 deletion lib/solmate
24 changes: 24 additions & 0 deletions scripts/compute_traits.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#!/usr/bin/env bash

BIBOS_TOTAL_SUPPLY=1111
PAGE=0
PAGE_COUNT=12
PAGE_LENGTH=100
TRAITS_PATH='./data/traits.json'
ALL_TRAITS='[]'

get_traits() {
forge script -s "run(uint256,uint256)" src/scripts/compute_traits.sol $1 $2 --json | grep "{" | jq '.logs[0]' | jq . -r
}

while [ $PAGE -lt $PAGE_COUNT ]
do
START=$(( PAGE * PAGE_LENGTH))
END=$(((PAGE + 1) * PAGE_LENGTH ))
TRAITS=$(get_traits $START $END )
ALL_TRAITS=$(echo $ALL_TRAITS | jq ". + $TRAITS")
echo "COMPUTE BIBOS $START $END"
PAGE=$(( $PAGE + 1 ))
done

echo $ALL_TRAITS > $TRAITS_PATH
210 changes: 210 additions & 0 deletions src/scripts/compute_traits.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
// SPDX-License-Identifier: Unlicense
pragma solidity >=0.8.0;

import {Script, console2 as console} from "forge-std/Script.sol";
import {Json} from "util/Json.sol";
import {Palette, DensityType, PolarityType} from "libraries/Palette.sol";
import {Traits} from "libraries/Traits.sol";
import {Data} from "libraries/Data.sol";
import {Util} from "libraries/Util.sol";
import {MoteType} from "libraries/Motes.sol";

// usage:
// forge script compute_traits -s "run(uint256)" $TOKEN_ID

/// @title compute_traits
/// @notice Computes Bibos extended attributes
/// @dev Seeds need to have already have been obtained on-chain
/// @author Bumblebee Systems
contract compute_traits is Script {
string constant SEEDS_PATH = "data/seeds.json";
uint256 constant CIRCLES_COUNT = 7;
uint256 constant MOTE_COUNT = 20;
uint256 constant BIBOS_TOTAL_SUPPLY = 1111;

function run(uint256 _start, uint256 _end) external {
uint256 end_ = _end > BIBOS_TOTAL_SUPPLY ? BIBOS_TOTAL_SUPPLY : _end;
require(_start < _end);
string memory bibosTraits = "[";

for (uint256 i = _start; i < end_; ++i) {
if (i != _start) bibosTraits = string.concat(bibosTraits, ",");
bibosTraits = string.concat(bibosTraits, bibosData(i));
}
bibosTraits = string.concat(bibosTraits, "]");

console.log(bibosTraits);
}

function bibosData(uint256 _tokenId) internal returns (string memory) {
string memory filter = string.concat(".[", Util.uint256ToString(_tokenId), "]");
bytes32 seed = abi.decode(Json.readData(SEEDS_PATH, filter), (bytes32));

string memory result = string.concat(
"{",
_keyValue("tokenId", Util.uint256ToString(_tokenId)),
",",
_keyValue("traits", _traits(seed, _tokenId)),
",",
_keyValue("background", _background(seed, _tokenId)),
",",
_keyValue("body", _body(seed, _tokenId)),
",",
_keyValue("motes", _motes(seed, _tokenId)),
",",
_keyValue("glints", _glints(seed)),
"}"
);

return result;
}

function _traits(bytes32 _seed, uint256 _tokenId) internal pure returns (string memory) {
string memory result = "{";
// density
result = string.concat(result, _quote("density"));
result = string.concat(result, ":");
result = string.concat(result, _quote(Traits.densityTrait(_seed, _tokenId)));
result = string.concat(result, ",");
// polarity
result = string.concat(result, _quote("polarity"));
result = string.concat(result, ":");
result = string.concat(result, _quote(Traits.polarityTrait(_seed, _tokenId)));
result = string.concat(result, ",");
// glints
result = string.concat(result, _quote("glints"));
result = string.concat(result, ":");
result = string.concat(result, _quote(Traits.glintTrait(_seed)));
result = string.concat(result, ",");
// motes
result = string.concat(result, _quote("motes"));
result = string.concat(result, ":");
result = string.concat(result, _quote(Traits.moteTrait(_seed)));
result = string.concat(result, ",");
// eyes
result = string.concat(result, _quote("eyes"));
result = string.concat(result, ":");
result = string.concat(result, _quote(Traits.eyeTrait(_seed)));
result = string.concat(result, ",");
// mouth
result = string.concat(result, _quote("mouth"));
result = string.concat(result, ":");
result = string.concat(result, _quote(Traits.mouthTrait(_seed)));
result = string.concat(result, ",");
// cheeks
result = string.concat(result, _quote("cheeks"));
result = string.concat(result, ":");
result = string.concat(result, _quote(Traits.cheekTrait(_seed)));
result = string.concat(result, ",");
// virtue
result = string.concat(result, _quote("virtue"));
result = string.concat(result, ":");
result = string.concat(result, _quote(Traits.virtueTrait(_seed)));

result = string.concat(result, "}");
return result;
}

function _background(bytes32 _seed, uint256 _tokenId) internal pure returns (string memory) {
return _quote(Palette.backgroundFill(_seed, _tokenId));
}

function _motes(bytes32 _seed, uint256 _tokenId) internal pure returns (string memory) {
if (Traits.moteType(_seed) == MoteType.NONE) return "[]";

string memory result = "[";
for (uint8 i = 0; i < MOTE_COUNT; ++i) {
uint256 moteSeed = uint256(keccak256(abi.encodePacked(_seed, "mote", i)));

moteSeed /= Data.length; // dur
moteSeed /= Data.length; // delay
string[2] memory coords = Data.motePoints(moteSeed /= Data.length);
string memory radius = (moteSeed /= 2) % 2 == 0 ? "1" : "2";
string memory opacity = Palette.opacity(moteSeed /= Palette.opacityLength, _seed, _tokenId);
// reverse

string memory mote = "{";
mote = string.concat(mote, _quote("coords"), ":", _coords(coords));
mote = string.concat(mote, ",");
mote = string.concat(mote, _quote("radius"), ":", _quote(radius));
mote = string.concat(mote, ",");
mote = string.concat(mote, _quote("opacity"), ":", _quote(opacity));
mote = string.concat(mote, "}");

if (i > 0) mote = string.concat(",", mote);
result = string.concat(result, mote);
}

result = string.concat(result, "]");

return result;
}

function _glints(bytes32 _seed) internal pure returns (string memory) {
uint256 glintCount = Traits.glintCount(_seed);

uint256 glintSeed = uint256(keccak256(abi.encodePacked(_seed, "glint")));
glintSeed /= 2; // reverseRotate
glintSeed /= 2; // reverse
string[2][3] memory coords = Data.glintPoints(glintSeed);

string memory result = "[";
for (uint8 index = 0; index < glintCount; ++index) {
result = string.concat(result, _coords(coords[index]));
if (index < glintCount - 1) result = string.concat(result, ",");
}
result = string.concat(result, "]");
return result;
}

function _body(bytes32 _seed, uint256 _tokenId) internal pure returns (string memory) {
string memory result = "[";
for (uint8 index = 0; index < CIRCLES_COUNT; ++index) {
result = string.concat(result, _bodyCircle(_seed, index, _tokenId));
if (index < CIRCLES_COUNT - 1) result = string.concat(result, ",");
}
result = string.concat(result, "]");

return result;
}

function _bodyCircle(
bytes32 _seed,
uint256 _index,
uint256 _tokenId
) internal pure returns (string memory) {
string[7] memory radii = ["64", "64", "64", "56", "48", "32", "24"];

uint256 bodySeed = uint256(keccak256(abi.encodePacked(_seed, "body", _index)));
string memory bodyFill1 = Palette.bodyFill(_seed, _index, _tokenId);
string memory bodyFill2 = Palette.bodyFill(_seed, _index + CIRCLES_COUNT, _tokenId);
bodySeed /= Data.length;
string[2] memory coords = (_index == 0) ? ["150", "150"] : Data.bodyPoints(bodySeed /= 2);

string memory result = "{";
result = string.concat(result, _quote("fill"), ":", _quote(bodyFill1));
result = string.concat(result, ",");
if (_tokenId == 0) {
result = string.concat(result, _quote("fill2"), ":", _quote(bodyFill2));
result = string.concat(result, ",");
}
result = string.concat(result, _quote("coords"), ":", _coords(coords));
result = string.concat(result, ",");
result = string.concat(result, _quote("radius"), ":", _quote(radii[_index]));
result = string.concat(result, "}");
return result;
}

function _keyValue(string memory _key, string memory _value) internal pure returns (string memory) {
return string.concat(_quote(_key), ":", _value);
}

function _quote(string memory _value) internal pure returns (string memory) {
return string.concat('"', _value, '"');
}

function _coords(string[2] memory __coords) internal pure returns (string memory) {
return
string.concat("{", _quote("x"), ":", _quote(__coords[0]), ",", _quote("y"), ":", _quote(__coords[1]), "}");
}
}
30 changes: 30 additions & 0 deletions src/scripts/get_seeds.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// SPDX-License-Identifier: Unlicense
pragma solidity >=0.8.0;

import {Script, console2 as console} from "forge-std/Script.sol";

import {Bibos} from "../Bibos.sol";

// usage:
// forge script --rpc-url $RPC_URL get_seeds

/// @title get_seeds
/// @notice gets all the Bibos bytes32 seeds sequentially
/// @author Bumblebee Systems
contract get_seeds is Script {
address constant BIBOS_ADDRESS = 0xF528e3381372c43F5e8a55b3E6c252E32F1a26e4;

function run() external view returns (bytes32[] memory) {
Bibos bibos = Bibos(BIBOS_ADDRESS);

uint256 totalSupply = bibos.totalSupply();
bytes32[] memory seeds = new bytes32[](totalSupply);

uint256 i;
for (; i < totalSupply; ++i) {
seeds[i] = Bibos(BIBOS_ADDRESS).seeds(i);
}

return seeds;
}
}
39 changes: 39 additions & 0 deletions src/util/Json.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// SPDX-License-Identifier: Unlicense
pragma solidity >=0.8.0;

import {Test, console2 as console} from "forge-std/Test.sol";
import {vm} from "./vm.sol";

library Json {
function read(string memory _path, string memory _filter) internal returns (bytes memory) {
string[] memory c = new string[](3);
c[0] = "bash";
c[1] = "-c";
c[2] = string.concat('cast ae "response(bytes)" $(jq -j ', _filter, " ", _path, " | xxd -p)");
// in general should dump with xxd -p (or whatever)
bytes memory data = vm.std_cheats.ffi(c);

return data;
}

function readData(string memory _path, string memory _filter) internal returns (bytes memory) {
string[] memory c = new string[](3);
c[0] = "bash";
c[1] = "-c";
c[2] = string.concat('cast ae "response(bytes)" $(jq -j ', _filter, " ", _path, ")");

bytes memory data = vm.std_cheats.ffi(c);
bytes memory result = abi.decode(data, (bytes));

return result;
}

// function write(string memory filePath, string memory data) internal {
// string[] memory writeInputs = new string[](3);
// writeInputs[0] = "scripts/io_write.sh";
// writeInputs[1] = filePath;
// writeInputs[2] = data;

// vm.std_cheats.ffi(writeInputs);
// }
}