文件 1 的 6:AnonymiceLibrary.sol
pragma solidity ^0.8.0;
library AnonymiceLibrary {
string internal constant TABLE =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
function encode(bytes memory data) internal pure returns (string memory) {
if (data.length == 0) return "";
string memory table = TABLE;
uint256 encodedLen = 4 * ((data.length + 2) / 3);
string memory result = new string(encodedLen + 32);
assembly {
mstore(result, encodedLen)
let tablePtr := add(table, 1)
let dataPtr := data
let endPtr := add(dataPtr, mload(data))
let resultPtr := add(result, 32)
for {
} lt(dataPtr, endPtr) {
} {
dataPtr := add(dataPtr, 3)
let input := mload(dataPtr)
mstore(
resultPtr,
shl(248, mload(add(tablePtr, and(shr(18, input), 0x3F))))
)
resultPtr := add(resultPtr, 1)
mstore(
resultPtr,
shl(248, mload(add(tablePtr, and(shr(12, input), 0x3F))))
)
resultPtr := add(resultPtr, 1)
mstore(
resultPtr,
shl(248, mload(add(tablePtr, and(shr(6, input), 0x3F))))
)
resultPtr := add(resultPtr, 1)
mstore(
resultPtr,
shl(248, mload(add(tablePtr, and(input, 0x3F))))
)
resultPtr := add(resultPtr, 1)
}
switch mod(mload(data), 3)
case 1 {
mstore(sub(resultPtr, 2), shl(240, 0x3d3d))
}
case 2 {
mstore(sub(resultPtr, 1), shl(248, 0x3d))
}
}
return result;
}
function toString(uint256 value) internal pure returns (string memory) {
if (value == 0) {
return "0";
}
uint256 temp = value;
uint256 digits;
while (temp != 0) {
digits++;
temp /= 10;
}
bytes memory buffer = new bytes(digits);
while (value != 0) {
digits -= 1;
buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
value /= 10;
}
return string(buffer);
}
function parseInt(string memory _a)
internal
pure
returns (uint8 _parsedInt)
{
bytes memory bresult = bytes(_a);
uint8 mint = 0;
for (uint8 i = 0; i < bresult.length; i++) {
if (
(uint8(uint8(bresult[i])) >= 48) &&
(uint8(uint8(bresult[i])) <= 57)
) {
mint *= 10;
mint += uint8(bresult[i]) - 48;
}
}
return mint;
}
function substring(
string memory str,
uint256 startIndex,
uint256 endIndex
) internal pure returns (string memory) {
bytes memory strBytes = bytes(str);
bytes memory result = new bytes(endIndex - startIndex);
for (uint256 i = startIndex; i < endIndex; i++) {
result[i - startIndex] = strBytes[i];
}
return string(result);
}
function isContract(address account) internal view returns (bool) {
uint256 size;
assembly {
size := extcodesize(account)
}
return size > 0;
}
}
文件 2 的 6:Context.sol
pragma solidity ^0.8.0;
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
文件 3 的 6:ERC721sm.sol
pragma solidity >=0.8.0;
abstract contract ERC721 {
event Transfer(
address indexed from,
address indexed to,
uint256 indexed id
);
event Approval(
address indexed owner,
address indexed spender,
uint256 indexed id
);
event ApprovalForAll(
address indexed owner,
address indexed operator,
bool approved
);
string public name;
string public symbol;
function tokenURI(uint256 id) public view virtual returns (string memory);
mapping(uint256 => address) internal _ownerOf;
mapping(address => uint256) internal _balanceOf;
function ownerOf(uint256 id) public view virtual returns (address owner) {
require((owner = _ownerOf[id]) != address(0), "NOT_MINTED");
}
function balanceOf(address owner) public view virtual returns (uint256) {
require(owner != address(0), "ZERO_ADDRESS");
return _balanceOf[owner];
}
mapping(uint256 => address) public getApproved;
mapping(address => mapping(address => bool)) public isApprovedForAll;
constructor(string memory _name, string memory _symbol) {
name = _name;
symbol = _symbol;
}
function approve(address spender, uint256 id) public virtual {
address owner = _ownerOf[id];
require(
msg.sender == owner || isApprovedForAll[owner][msg.sender],
"NOT_AUTHORIZED"
);
getApproved[id] = spender;
emit Approval(owner, spender, id);
}
function setApprovalForAll(address operator, bool approved) public virtual {
isApprovedForAll[msg.sender][operator] = approved;
emit ApprovalForAll(msg.sender, operator, approved);
}
function transferFrom(
address from,
address to,
uint256 id
) public virtual {
require(from == _ownerOf[id], "WRONG_FROM");
require(to != address(0), "INVALID_RECIPIENT");
require(
msg.sender == from ||
isApprovedForAll[from][msg.sender] ||
msg.sender == getApproved[id],
"NOT_AUTHORIZED"
);
unchecked {
_balanceOf[from]--;
_balanceOf[to]++;
}
_ownerOf[id] = to;
delete getApproved[id];
emit Transfer(from, to, id);
}
function safeTransferFrom(
address from,
address to,
uint256 id
) public virtual {
transferFrom(from, to, id);
require(
to.code.length == 0 ||
ERC721TokenReceiver(to).onERC721Received(
msg.sender,
from,
id,
""
) ==
ERC721TokenReceiver.onERC721Received.selector,
"UNSAFE_RECIPIENT"
);
}
function safeTransferFrom(
address from,
address to,
uint256 id,
bytes calldata data
) public virtual {
transferFrom(from, to, id);
require(
to.code.length == 0 ||
ERC721TokenReceiver(to).onERC721Received(
msg.sender,
from,
id,
data
) ==
ERC721TokenReceiver.onERC721Received.selector,
"UNSAFE_RECIPIENT"
);
}
function supportsInterface(bytes4 interfaceId)
public
view
virtual
returns (bool)
{
return
interfaceId == 0x01ffc9a7 ||
interfaceId == 0x80ac58cd ||
interfaceId == 0x5b5e139f;
}
function _mint(address to, uint256 id) internal virtual {
require(to != address(0), "INVALID_RECIPIENT");
require(_ownerOf[id] == address(0), "ALREADY_MINTED");
unchecked {
_balanceOf[to]++;
}
_ownerOf[id] = to;
emit Transfer(address(0), to, id);
}
function _burn(uint256 id) internal virtual {
address owner = _ownerOf[id];
require(owner != address(0), "NOT_MINTED");
unchecked {
_balanceOf[owner]--;
}
delete _ownerOf[id];
delete getApproved[id];
emit Transfer(owner, address(0), id);
}
function _safeMint(address to, uint256 id) internal virtual {
_mint(to, id);
require(
to.code.length == 0 ||
ERC721TokenReceiver(to).onERC721Received(
msg.sender,
address(0),
id,
""
) ==
ERC721TokenReceiver.onERC721Received.selector,
"UNSAFE_RECIPIENT"
);
}
function _safeMint(
address to,
uint256 id,
bytes memory data
) internal virtual {
_mint(to, id);
require(
to.code.length == 0 ||
ERC721TokenReceiver(to).onERC721Received(
msg.sender,
address(0),
id,
data
) ==
ERC721TokenReceiver.onERC721Received.selector,
"UNSAFE_RECIPIENT"
);
}
}
abstract contract ERC721TokenReceiver {
function onERC721Received(
address,
address,
uint256,
bytes calldata
) external virtual returns (bytes4) {
return ERC721TokenReceiver.onERC721Received.selector;
}
}
文件 4 的 6:FoldedFaces.sol
pragma solidity ^0.8.7;
import "./AnonymiceLibrary.sol";
import "./ERC721sm.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol";
contract FoldedFaces is ERC721, Ownable {
using AnonymiceLibrary for uint8;
struct Trait {
string traitName;
string traitType;
}
struct HashNeeds {
uint16 startHash;
uint16 startNonce;
}
mapping(uint256 => Trait[]) public traitTypes;
mapping(address => uint256) private lastWrite;
mapping(address => bool) addressWhitelistMinted;
mapping(address => bool) contributorMints;
uint256 public contributorCount = 0;
uint256 public regularCount = 0;
uint256 public constant MAX_SUPPLY = 533;
uint256 public constant WL_MINT_COST = 0.03 ether;
uint256 public constant PUBLIC_MINT_COST = 0.05 ether;
uint256 public constant PUBLIC_START_TIME = 1653525000;
mapping(uint256 => HashNeeds) tokenIdToHashNeeds;
uint16 SEED_NONCE = 0;
bool ogMinted = false;
bool public MINTING_LIVE = false;
uint16[][8] TIERS;
string p5jsUrl;
string p5jsIntegrity;
string imageUrl;
string animationUrl;
bytes32 constant whitelistRoot =
0x358899790e0e071faed348a1b72ef18efe59029543a4a4da16e13fa2abf2a578;
constructor() payable ERC721("FoldedFaces", "FFACE") {
TIERS[0] = [8000, 1000, 1000];
TIERS[1] = [1000, 9000];
TIERS[2] = [9800, 200];
TIERS[3] = [2250, 2250, 2250, 2250, 1000];
TIERS[4] = [2500, 2500, 2500, 2500];
TIERS[5] = [1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000];
TIERS[6] = [9000, 1000];
TIERS[7] = [1000, 9000];
}
modifier disallowIfStateIsChanging() {
require(
owner() == msg.sender || lastWrite[msg.sender] < block.number,
"not so fast!"
);
_;
}
function rarityGen(uint256 _randinput, uint8 _rarityTier)
internal
view
returns (uint8)
{
uint16 currentLowerBound = 0;
for (uint8 i = 0; i < TIERS[_rarityTier].length; i++) {
uint16 thisPercentage = TIERS[_rarityTier][i];
if (
_randinput >= currentLowerBound &&
_randinput < currentLowerBound + thisPercentage
) return i;
currentLowerBound = currentLowerBound + thisPercentage;
}
revert();
}
function hash(address _a) internal view returns (uint16) {
uint16 _randinput = uint16(
uint256(
keccak256(
abi.encodePacked(block.timestamp, block.difficulty, _a)
)
) % 10000
);
return _randinput;
}
function mintInternal() internal {
require(
MINTING_LIVE == true || msg.sender == owner(),
"Minting not live"
);
uint256 _totalSupply = totalSupply() - 1;
require(_totalSupply < MAX_SUPPLY, "Minted out");
require(!AnonymiceLibrary.isContract(msg.sender), "No Contracts");
require(regularCount < 519, "Minted Out Non Reserved Spots");
uint256 thisTokenId = _totalSupply;
tokenIdToHashNeeds[thisTokenId] = HashNeeds(
hash(msg.sender),
SEED_NONCE
);
lastWrite[msg.sender] = block.number;
SEED_NONCE += 8;
_mint(msg.sender, thisTokenId);
}
function mintOgBatch(address[] memory _addresses)
external
payable
onlyOwner
{
require(ogMinted == false);
require(_addresses.length == 14);
uint16 _nonce = SEED_NONCE;
for (uint256 i = 0; i < 14; i++) {
uint256 thisTokenId = i;
tokenIdToHashNeeds[thisTokenId] = HashNeeds(
hash(_addresses[i]),
_nonce
);
_mint(_addresses[i], thisTokenId);
_nonce += 8;
}
regularCount = 14;
SEED_NONCE += 112;
ogMinted = true;
}
function mintWLFoldedFaces(address account, bytes32[] calldata merkleProof)
external
payable
{
bytes32 node = keccak256(abi.encodePacked(account));
require(
MerkleProof.verify(merkleProof, whitelistRoot, node),
"Not on WL"
);
require(account == msg.sender, "Self mint only");
require(msg.value == WL_MINT_COST, "Insufficient ETH sent");
require(
addressWhitelistMinted[msg.sender] != true,
"Address already minted WL"
);
addressWhitelistMinted[msg.sender] = true;
++regularCount;
return mintInternal();
}
function mintPublicFoldedFaces() external payable {
require(msg.value == PUBLIC_MINT_COST, "Insufficient ETH sent");
require(block.timestamp > PUBLIC_START_TIME, "Public mint not started");
++regularCount;
return mintInternal();
}
function mintCircolorsContributor() external {
require(contributorMints[msg.sender] == true);
require(contributorCount < 15);
contributorMints[msg.sender] = false;
++contributorCount;
return mintInternal();
}
function buildHash(uint256 _t) internal view returns (string memory) {
string memory currentHash = "";
uint256 rInput = tokenIdToHashNeeds[_t].startHash;
uint256 _nonce = tokenIdToHashNeeds[_t].startNonce;
for (uint8 i = 0; i < 8; i++) {
++_nonce;
uint16 _randinput = uint16(
uint256(keccak256(abi.encodePacked(rInput, _t, _nonce))) % 10000
);
currentHash = string(
abi.encodePacked(
currentHash,
rarityGen(_randinput, i).toString()
)
);
}
return currentHash;
}
function hashToHTML(string memory _hash, uint256 _tokenId)
external
view
disallowIfStateIsChanging
returns (string memory)
{
string memory htmlString = string(
abi.encodePacked(
"data:text/html,%3Chtml%3E%3Chead%3E%3Cscript%20src%3D%22",
p5jsUrl,
"%22%20integrity%3D%22",
p5jsIntegrity,
"%22%20crossorigin%3D%22anonymous%22%3E%3C%2Fscript%3E%3C%2Fhead%3E%3Cbody%3E%3Cscript%3Evar%20tokenId%3D",
AnonymiceLibrary.toString(_tokenId),
"%3Bvar%20hash%3D%22",
_hash,
"%22%3B"
)
);
htmlString = string(
abi.encodePacked(
htmlString,
"function%20setup%28%29%7Bs%3D%5B.45%2C1%5D%2Cc%3D%5B0%2C1%5D%2Cn%3D%5B0%2C1%5D%2Cnnw%3D0%2Cci%3D%5B0%2C1%5D%2Cnv%3D%5B%5B.001%2C.0025%5D%2C%5B.0025%2C.01%5D%2C%5B.01%2C.0025%5D%2C%5B.0025%2C.001%5D%2C%5B.001%2C.001%5D%5D%2Cov%3D%5B%5B4500%2C5500%2C6500%2C8e3%5D%2C%5B750%2C950%2C1150%2C1250%5D%2C%5B750%2C950%2C1150%2C1250%5D%2C%5B4500%2C5500%2C6500%2C8e3%5D%2C%5B4e3%2C5e3%2C6e3%2C15e3%5D%5D%2Cp%3D%5B%5B%22%2365010c%22%2C%22%23cb1b16%22%2C%22%23ef3c2d%22%2C%22%23f26a4f%22%2C%22%23f29479%22%2C%22%23fedfd4%22%2C%22%239dcee2%22%2C%22%234091c9%22%2C%22%231368aa%22%2C%22%23033270%22%2C%22%23000%22%2C%22%23faebd7%22%5D%2C%5B%22%230f3375%22%2C%22%2313459c%22%2C%22%231557c0%22%2C%22%23196bde%22%2C%22%232382f7%22%2C%22%234b9cf9%22%2C%22%2377b6fb%22%2C%22%23a4cefc%22%2C%22%23cce4fd%22%2C%22%23e8f3fe%22%2C%22%23000%22%2C%22%23faebd7%22%5D%2C%5B%22%230e0e0e%22%2C%22%23f3bc17%22%2C%22%23d54b0c%22%2C%22%23154255%22%2C%22%23dcdcdc%22%2C%22%23c0504f%22%2C%22%2368b9b0%22%2C%22%23ecbe2c%22%2C%22%232763ab%22%2C%22%23ce4241%22%2C%22%23faebd7%22%2C%22%23000%22%5D%2C%5B%22%23ff0000%22%2C%22%23fe1c00%22%2C%22%23fd3900%22%2C%22%23fc5500%22%2C%22%23fb7100%22%2C%22%23fb8e00%22%2C%22%23faaa00%22%2C%22%23f9c600%22%2C%22%23f8e300%22%2C%22%23f7ff00%22%2C%22%23000%22%2C%22%23faebd7%22%5D%2C%5B%22%23004733%22%2C%22%232b6a4d%22%2C%22%23568d66%22%2C%22%23a5c1ae%22%2C%22%23f3f4f6%22%2C%22%23dcdfe5%22%2C%22%23df8080%22%2C%22%23cb0b0a%22%2C%22%23ad080f%22%2C%22%238e0413%22%2C%22%23000%22%2C%22%23faebd7%22%5D%2C%5B%22%231e1619%22%2C%22%233c2831%22%2C%22%235d424e%22%2C%22%238c6677%22%2C%22%23ad7787%22%2C%22%23ac675b%22%2C%22%23c86166%22%2C%22%23f078b3%22%2C%22%23ec8782%22%2C%22%23dfde80%22%2C%22%23faebd7%22%2C%22%23000%22%5D%2C%5B%22%23008080%22%2C%22%23008080%22%2C%22%23178c8c%22%2C%22%23f7ff00%22%2C%22%2346a3a3%22%2C%22%235daeae%22%2C%22%2374baba%22%2C%22%238bc5c5%22%2C%22%23a2d1d1%22%2C%22%23b5dada%22%2C%22%23000%22%2C%22%23faebd7%22%5D%2C%5B%22%23669900%22%2C%22%2399cc33%22%2C%22%23ccee66%22%2C%22%23006699%22%2C%22%233399cc%22%2C%22%23990066%22%2C%22%23cc3399%22%2C%22%23ff6600%22%2C%22%23ff9900%22%2C%22%23ffcc00%22%2C%22%23000%22%2C%22%23faebd7%22%5D%2C%5B%22%23000%22%2C%22%23fff%22%2C%22%23000%22%2C%22%23fff%22%2C%22%23000%22%2C%22%23fff%22%2C%22%23000%22%2C%22%23fff%22%2C%22%23000%22%2C%22%23fff%22%2C%22%23000%22%2C%22%23fff%22%5D%2C%5B%22%232c6e49%22%2C%22%23618565%22%2C%22%23969c81%22%2C%22%23cbb39d%22%2C%22%23e5beab%22%2C%22%23ffc9b9%22%2C%22%23f5ba9c%22%2C%22%23ebab7f%22%2C%22%23e19c62%22%2C%22%23d68c45%22%2C%22%23000%22%2C%22%23faebd7%22%5D%2C%5B%22%2365010c%22%2C%22%23cb1b16%22%2C%22%23ef3c2d%22%2C%22%23f26a4f%22%2C%22%23f29479%22%2C%22%23fedfd4%22%2C%22%239dcee2%22%2C%22%234091c9%22%2C%22%231368aa%22%2C%22%23033270%22%2C%22%23faebd7%22%2C%22%23000%22%5D%5D%2CcreateCanvas%28700%2C950%29%2CnoiseSeed%28tokenId%29%2CnoLoop%28%29%2CnoStroke%28%29%2CrectMode%28CENTER%29%2CcolorMode%28HSL%29%2CpixelDensity%285%29%2Co%3Dnoise%2Cf%3Dfill%2Cb%3DnoFill%2Cq%3Dwidth%2Ca%3Dheight%2Cyy%3DparseInt%28hash.substring%280%2C1%29%29%2Cci%3Dci%5BparseInt%28hash.substring%281%2C2%29%29%5D%2Cw%3Ds%5BparseInt%28hash.substring%282%2C3%29%29%5D%2Cx%3DparseInt%28hash.substring%283%2C4%29%29%2Czz%3DparseInt%28hash.substring%284%2C5%29%29%2Caa%3Dnv%5Bx%5D%5B0%5D%2Cvb%3Dnv%5Bx%5D%5B1%5D%2Cgb%3Dov%5Bx%5D%5Bzz%5D%2Cff%3D%5B1e-5%2Caa%5D%2Cz%3DparseInt%28hash.substring%285%2C6%29%29%2Cz2%3Dz%2B1%2Cg%3DparseInt%28hash.substring%286%2C7%29%29%2B1%2Cnnw%3Dff%5BparseInt%28hash.substring%287%2C8%29%29%5D%7Dfunction%20draw%28%29%7Bbackground%28p%5Bz%5D%5B10%5D%29%2C2%3D%3Dx%7C%7C3%3D%3Dx%3Fnn%3Dnnw%3Ann%3Daa%3Bfor%28let%20e%3D25%3Be%3C%3Dq-25%3Be%2B%3Dw%29for%28let%20c%3D25%3Bc%3C%3Da-25%3Bc%2B%3Dw%29n%3Do%28e%2Ann%2Cc%2Aaa%29%2Cn2%3Do%28e%2Avb%2Cc%2Avb%29%2Cn3%3Do%28%28e%2Bgb%2An%29%2Aaa%2C%28c%2Bgb%2An2%29%2Avb%29%2Cn4%3Do%28%28e%2Bgb%2An3%29%2Aaa%2C%28c%2Bgb%2An3%29%2Avb%29%2Cn5%3Do%28%28e%2Bgb%2An4%29%2Aaa%2C%28c%2Bgb%2An4%29%2Avb%29%2C0%3D%3Dyy%3Fe%3Cq%2Fg%3Fn5%3E.58%3Fb%28%29%3An5%3E.55%3Ff%28p%5Bz%5D%5B0%5D%29%3An5%3E.53%3Ff%28p%5Bz%5D%5B1%5D%29%3An5%3E.5%3Ff%28p%5Bz%5D%5B2%5D%29%3An5%3E.47%3Ff%28p%5Bz%5D%5B3%5D%29%3An5%3E.44%3Fb%28%29%3An5%3E.41%3Ff%28p%5Bz%5D%5B4%5D%29%3An5%3E.38%3Ff%28p%5Bz%5D%5B5%5D%29%3An5%3E.35%3Ff%28p%5Bz%5D%5B6%5D%29%3An5%3E.31%3Ff%28p%5Bz%5D%5B7%5D%29%3An5%3E.28%3Ff%28p%5Bz%5D%5B8%5D%29%3An5%3E.25%3Ff%28p%5Bz%5D%5B9%5D%29%3Ab%28%29%3An5%3E.58%3Fb%28%29%3An5%3E.55%3Ff%28p%5Bz2%5D%5B0%5D%29%3An5%3E.53%3Ff%28p%5Bz2%5D%5B1%5D%29%3An5%3E.5%3Ff%28p%5Bz2%5D%5B2%5D%29%3An5%3E.47%3Ff%28p%5Bz2%5D%5B3%5D%29%3An5%3E.44%3Fb%28%29%3An5%3E.41%3Ff%28p%5Bz2%5D%5B4%5D%29%3An5%3E.38%3Ff%28p%5Bz2%5D%5B5%5D%29%3An5%3E.35%3Ff%28p%5Bz2%5D%5B6%5D%29%3An5%3E.31%3Ff%28p%5Bz2%5D%5B7%5D%29%3An5%3E.28%3Ff%28p%5Bz2%5D%5B8%5D%29%3An5%3E.25%3Ff%28p%5Bz2%5D%5B9%5D%29%3Ab%28%29%3A1%3D%3Dyy%3Fn5%3E.6%3Fb%28%29%3An5%3E.4%3Ff%28p%5Bz%5D%5B3%5D%29%3Ab%28%29%3Af%281e3%2An2%2C100%2An5%2C100%2An5%29%2Crect%28e%2Cc%2Cw%29%3B0%3D%3Dci%26%26%28push%28%29%2Cb%28%29%2Cstroke%28p%5Bz%5D%5B10%5D%29%2CstrokeWeight%281570%29%2Ccircle%28q%2F2%2Ca%2F2%2C2e3%29%2Cpop%28%29%29%2Cpush%28%29%2CtextSize%283%29%2CtextAlign%28RIGHT%29%2Cf%28p%5Bz%5D%5B11%5D%29%2Ctext%28%22Folded%20Faces.%202022.%22%2Cq-25%2Ca-15%29%2Ctext%28hash%2Cq-25%2Ca-10%29%2Cpop%28%29%7D%3C%2Fscript%3E%3C%2Fbody%3E%3C%2Fhtml%3E"
)
);
return htmlString;
}
function totalSupply() public view returns (uint256) {
return regularCount + contributorCount;
}
function hashToMetadata(string memory _hash)
public
view
disallowIfStateIsChanging
returns (string memory)
{
string memory metadataString;
uint256 metadataLength;
if (
AnonymiceLibrary.parseInt(
AnonymiceLibrary.substring(_hash, 0, 1)
) == 0
) {
metadataLength = 6;
} else {
metadataLength = 5;
}
for (uint8 i = 0; i < metadataLength; i++) {
uint8 thisTraitIndex = AnonymiceLibrary.parseInt(
AnonymiceLibrary.substring(_hash, i, i + 1)
);
metadataString = string(
abi.encodePacked(
metadataString,
'{"trait_type":"',
traitTypes[i][thisTraitIndex].traitType,
'","value":"',
traitTypes[i][thisTraitIndex].traitName,
'"}'
)
);
if (i != metadataLength - 1)
metadataString = string(abi.encodePacked(metadataString, ","));
}
return string(abi.encodePacked("[", metadataString, "]"));
}
function tokenURI(uint256 _tokenId)
public
view
override
returns (string memory)
{
require(_tokenId < totalSupply());
string memory tokenHash = _tokenIdToHash(_tokenId);
string
memory description = '", "description": "533 FoldedFaces. Traits generated on chain & metadata, images mirrored on chain permanently.",';
string memory encodedTokenId = AnonymiceLibrary.encode(
bytes(string(abi.encodePacked(AnonymiceLibrary.toString(_tokenId))))
);
string memory encodedHash = AnonymiceLibrary.encode(
bytes(string(abi.encodePacked(tokenHash)))
);
return
string(
abi.encodePacked(
"data:application/json;base64,",
AnonymiceLibrary.encode(
bytes(
string(
abi.encodePacked(
'{"name": "FoldedFaces #',
AnonymiceLibrary.toString(_tokenId),
description,
'"external_url":"',
animationUrl,
encodedTokenId,
"&t=",
encodedHash,
'","image":"',
imageUrl,
AnonymiceLibrary.toString(_tokenId),
"&t=",
tokenHash,
'","attributes":',
hashToMetadata(tokenHash),
"}"
)
)
)
)
)
);
}
function _tokenIdToHash(uint256 _tokenId)
public
view
disallowIfStateIsChanging
returns (string memory)
{
require(_tokenId < totalSupply());
string memory tokenHash = buildHash(_tokenId);
return tokenHash;
}
function addTraitType(uint256 _traitTypeIndex, Trait[] memory traits)
external
payable
onlyOwner
{
for (uint256 i = 0; i < traits.length; i++) {
traitTypes[_traitTypeIndex].push(
Trait(traits[i].traitName, traits[i].traitType)
);
}
return;
}
function addContributorMint(address _account) external payable onlyOwner {
contributorMints[_account] = true;
}
function flipMintingSwitch() external payable onlyOwner {
MINTING_LIVE = !MINTING_LIVE;
}
function setJsAddress(string memory _p5jsUrl) external payable onlyOwner {
p5jsUrl = _p5jsUrl;
}
function setJsIntegrity(string memory _p5jsIntegrity)
external
payable
onlyOwner
{
p5jsIntegrity = _p5jsIntegrity;
}
function setImageUrl(string memory _imageUrl) external payable onlyOwner {
imageUrl = _imageUrl;
}
function setAnimationUrl(string memory _animationUrl)
external
payable
onlyOwner
{
animationUrl = _animationUrl;
}
function withdraw() external payable onlyOwner {
uint256 sixtyFive = (address(this).balance / 100) * 65;
uint256 fifteen = (address(this).balance / 100) * 15;
uint256 five = (address(this).balance / 100) * 5;
(bool sentT, ) = payable(
address(0xE4260Df86f5261A41D19c2066f1Eb2Eb4F009e84)
).call{value: fifteen}("");
require(sentT, "Failed to send");
(bool sentI, ) = payable(
address(0x4533d1F65906368ebfd61259dAee561DF3f3559D)
).call{value: fifteen}("");
require(sentI, "Failed to send");
(bool sentC, ) = payable(
address(0x888f8AA938dbb18b28bdD111fa4A0D3B8e10C871)
).call{value: five}("");
require(sentC, "Failed to send");
(bool sentG, ) = payable(
address(0xeFEed35D024CF5B59482Fa4BC594AaeAf694E669)
).call{value: sixtyFive}("");
require(sentG, "Failed to send");
}
}
文件 5 的 6:MerkleProof.sol
pragma solidity ^0.8.0;
library MerkleProof {
function verify(
bytes32[] memory proof,
bytes32 root,
bytes32 leaf
) internal pure returns (bool) {
return processProof(proof, leaf) == root;
}
function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {
bytes32 computedHash = leaf;
for (uint256 i = 0; i < proof.length; i++) {
bytes32 proofElement = proof[i];
if (computedHash <= proofElement) {
computedHash = keccak256(abi.encodePacked(computedHash, proofElement));
} else {
computedHash = keccak256(abi.encodePacked(proofElement, computedHash));
}
}
return computedHash;
}
}
文件 6 的 6:Ownable.sol
pragma solidity ^0.8.0;
import "../utils/Context.sol";
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor() {
_transferOwnership(_msgSender());
}
function owner() public view virtual returns (address) {
return _owner;
}
modifier onlyOwner() {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
_;
}
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
{
"compilationTarget": {
"contracts/FoldedFaces.sol": "FoldedFaces"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs",
"useLiteralContent": true
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[],"stateMutability":"payable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"MAX_SUPPLY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MINTING_LIVE","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PUBLIC_MINT_COST","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PUBLIC_START_TIME","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WL_MINT_COST","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"_tokenIdToHash","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"addContributorMint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_traitTypeIndex","type":"uint256"},{"components":[{"internalType":"string","name":"traitName","type":"string"},{"internalType":"string","name":"traitType","type":"string"}],"internalType":"struct FoldedFaces.Trait[]","name":"traits","type":"tuple[]"}],"name":"addTraitType","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"contributorCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"flipMintingSwitch","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_hash","type":"string"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"hashToHTML","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_hash","type":"string"}],"name":"hashToMetadata","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mintCircolorsContributor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_addresses","type":"address[]"}],"name":"mintOgBatch","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"mintPublicFoldedFaces","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32[]","name":"merkleProof","type":"bytes32[]"}],"name":"mintWLFoldedFaces","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"owner","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"regularCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_animationUrl","type":"string"}],"name":"setAnimationUrl","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_imageUrl","type":"string"}],"name":"setImageUrl","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"string","name":"_p5jsUrl","type":"string"}],"name":"setJsAddress","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"string","name":"_p5jsIntegrity","type":"string"}],"name":"setJsIntegrity","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"traitTypes","outputs":[{"internalType":"string","name":"traitName","type":"string"},{"internalType":"string","name":"traitType","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"payable","type":"function"}]