编译器
0.8.13+commit.abaa5c0e
文件 1 的 7: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 的 7:ChainWaves.sol
pragma solidity ^0.8.13;
import "solmate/tokens/ERC721.sol";
import "solmate/auth/Owned.sol";
import "openzeppelin-contracts/utils/cryptography/MerkleProof.sol";
import "./AnonymiceLibrary.sol";
import "./ChainWavesGenerator.sol";
import "./ChainWavesErrors.sol";
contract ChainWaves is ChainWavesErrors, ERC721, Owned {
using AnonymiceLibrary for uint8;
struct Trait {
string traitName;
string traitType;
}
uint256 public constant MAX_SUPPLY = 512;
uint256 public constant MINT_PRICE = 0.0256 ether;
uint256 public constant MINT_START = 1674156600;
uint256 public constant MAX_MINT = 3;
uint256 public snowcrashReserve = 120;
bool public MINTING_LIVE;
uint256 public totalSupply;
bytes32 constant snowcrashRoot =
0xea35e50958ff75fe96e04a6dd792de75a26dd0c2a2d12e8a4c485d938961eb39;
bool private freeMinted;
mapping(address => uint256) mintInfo;
mapping(uint256 => uint256) tokenIdToHash;
mapping(uint256 => Trait[]) public traitTypes;
ChainWavesGenerator chainWavesGenerator;
uint16[][6] private TIERS;
constructor()
ERC721("ChainWaves", "CA")
Owned(0xB6eE8B1899e4cad7e28015995B82969e44BD0bb0)
{
chainWavesGenerator = new ChainWavesGenerator();
TIERS[0] = [1000, 1500, 1400, 1700, 1200, 400, 400, 1600, 800];
TIERS[1] = [1000, 4000, 4000, 1000];
TIERS[2] = [1000, 4000, 4000, 1000];
TIERS[3] = [2250, 2250, 2250, 2250, 600, 400];
TIERS[4] = [1000, 6000, 3000];
TIERS[5] = [800, 6200, 2600, 400];
}
modifier disallowIfStateIsChanging() {
if ((mintInfo[msg.sender] >> 8) == block.number) revert Stap();
_;
}
function rarityGen(uint256 _randinput, uint8 _rarityTier)
internal
view
returns (uint8)
{
uint16 currentLowerBound;
uint256 tiersLength = TIERS[_rarityTier].length;
for (uint8 i; i < tiersLength; ++i) {
uint16 thisPercentage = TIERS[_rarityTier][i];
if (
_randinput >= currentLowerBound &&
_randinput < currentLowerBound + thisPercentage
) return i;
currentLowerBound = currentLowerBound + thisPercentage;
}
revert();
}
function hash(address _a, uint256 _tokenId)
internal
view
returns (uint256)
{
return
uint256(
keccak256(
abi.encodePacked(
block.timestamp,
block.difficulty,
_a,
_tokenId
)
)
);
}
function normieMint(uint256 _amount) external payable {
if (_amount > MAX_MINT) revert MaxThree();
if (msg.value != MINT_PRICE * _amount) revert MintPrice();
uint256 minterInfo = mintInfo[msg.sender];
if ((minterInfo & 0xF) != 0) revert PublicMinted();
minterInfo |= 1;
minterInfo = (minterInfo & 0xFF) + (block.number << 8);
mintInfo[msg.sender] = minterInfo;
mintInternal(msg.sender, _amount);
}
function snowcrashMint(bytes32[] calldata merkleProof) external payable {
bytes32 node = keccak256(abi.encodePacked(msg.sender));
require(
MerkleProof.verify(merkleProof, snowcrashRoot, node),
"Not on WL"
);
if (msg.value != MINT_PRICE) revert MintPrice();
uint256 minterInfo = mintInfo[msg.sender];
if (((minterInfo & 0xF0) >> 4) != 0) revert SnowcrashMinted();
if (snowcrashReserve == 0) revert ReserveClosed();
--snowcrashReserve;
minterInfo |= (1 << 4);
minterInfo = (minterInfo & 0xFF) + (block.number << 8);
mintInfo[msg.sender] = minterInfo;
mintInternal(msg.sender, 1);
}
function freeMints(
address[] calldata _addresses,
uint256[] calldata _amount
) external payable onlyOwner {
if (freeMinted) revert FreeMintDone();
uint256 addressesLength = _addresses.length;
if (addressesLength != _amount.length) revert ArrayLengths();
for (uint256 i; i < addressesLength; ++i) {
mintInternal(_addresses[i], _amount[i]);
}
freeMinted = true;
}
function mintInternal(address _to, uint256 _amount) internal {
if (!MINTING_LIVE || block.timestamp < MINT_START) revert NotLive();
if (_amount == 0) revert MintZero();
if (totalSupply + _amount + snowcrashReserve > MAX_SUPPLY)
revert SoldOut();
uint256 nextTokenId = totalSupply;
uint256 newTotalSupply = totalSupply + _amount;
for (; nextTokenId < newTotalSupply; ++nextTokenId) {
tokenIdToHash[nextTokenId] = hash(_to, nextTokenId);
_mint(_to, nextTokenId);
}
totalSupply = newTotalSupply;
}
function buildHash(uint256 _t) internal view returns (string memory) {
string memory currentHash = "";
uint256 tokenHash = tokenIdToHash[_t];
for (uint8 i; i < 6; ++i) {
uint16 _randinput = uint16(
uint256(keccak256(abi.encodePacked(tokenHash, i))) % 10000
);
currentHash = string(
abi.encodePacked(
currentHash,
rarityGen(_randinput, i).toString()
)
);
}
return currentHash;
}
function hashToMetadata(string memory _hash)
public
view
disallowIfStateIsChanging
returns (string memory)
{
string memory metadataString;
for (uint8 i; i < 6; ++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 != 5)
metadataString = string(abi.encodePacked(metadataString, ","));
}
return string(abi.encodePacked("[", metadataString, "]"));
}
function _tokenIdToHash(uint256 _tokenId)
public
view
disallowIfStateIsChanging
returns (string memory tokenHash)
{
if (_tokenId >= totalSupply) revert NonExistantId();
tokenHash = buildHash(_tokenId);
}
function tokenURI(uint256 _tokenId)
public
view
override
returns (string memory _URI)
{
if (_tokenId >= totalSupply) revert NonExistantId();
string memory _hash = _tokenIdToHash(_tokenId);
_URI = string(
abi.encodePacked(
"data:application/json;base64,",
AnonymiceLibrary.encode(
bytes(
string(
abi.encodePacked(
'{"name": "CH41NW4V35 #',
AnonymiceLibrary.toString(_tokenId),
'","description": "Fully onchain generative art SVG collection. Created by McToady & Circolors."',
',"image": "data:image/svg+xml;base64,',
AnonymiceLibrary.encode(
bytes(
abi.encodePacked(
"<svg viewBox='0 0 20 20' width='600' height='600' xmlns='http://www.w3.org/2000/svg' preserveAspectRatio='xMidYMin'><rect width='20' height='20' fill='#",
chainWavesGenerator.buildSVG(
_tokenId,
_hash
),
"</svg>"
)
)
),
'","attributes":',
hashToMetadata(_hash),
"}"
)
)
)
)
)
);
}
function addTraitType(uint256 _traitTypeIndex, Trait[] memory traits)
external
payable
onlyOwner
{
for (uint256 i; i < traits.length; ++i) {
traitTypes[_traitTypeIndex].push(
Trait(traits[i].traitName, traits[i].traitType)
);
}
return;
}
function flipMint() external payable onlyOwner {
MINTING_LIVE = !MINTING_LIVE;
}
function withdraw() external payable onlyOwner {
uint256 twelve = (address(this).balance / 100) * 12;
uint256 eightythree = (address(this).balance / 100) * 83;
uint256 five = (address(this).balance / 100) * 5;
(bool sentI, ) = payable(
address(0x4533d1F65906368ebfd61259dAee561DF3f3559D)
).call{value: twelve}("");
if (!sentI) revert WithdrawFail();
(bool sentC, ) = payable(
address(0x888f8AA938dbb18b28bdD111fa4A0D3B8e10C871)
).call{value: five}("");
if (!sentC) revert WithdrawFail();
(bool sentT, ) = payable(
address(0xE4260Df86f5261A41D19c2066f1Eb2Eb4F009e84)
).call{value: eightythree}("");
if (!sentT) revert WithdrawFail();
}
function wipeSnowcrashReserve() external payable onlyOwner {
snowcrashReserve = 0;
}
}
文件 3 的 7:ChainWavesErrors.sol
pragma solidity ^0.8.13;
interface ChainWavesErrors {
error SoldOut();
error NotLive();
error MintPrice();
error MaxThree();
error PublicMinted();
error SnowcrashMinted();
error NotToad();
error FreeMintDone();
error NotSnowcrashList();
error ReserveClosed();
error SelfMintOnly();
error ArrayLengths();
error NonExistantId();
error Stap();
error WithdrawFail();
error MintZero();
}
文件 4 的 7:ChainWavesGenerator.sol
pragma solidity ^0.8.13;
import "./AnonymiceLibrary.sol";
contract ChainWavesGenerator {
using AnonymiceLibrary for uint8;
string[][9] private PALETTES;
uint256[] private NOISE;
uint256[] private SPEED;
string[] private CHARS;
uint256[] private TIGHTNESS;
struct Traits {
string[] palette;
uint256 noise;
uint256 speed;
string charSet;
uint256 tightness;
uint256 numCols;
}
constructor() {
PALETTES[0] = ["d00000", "370617", "faa307", "e85d04", "03071e"];
PALETTES[1] = ["3a0ca3", "f72585", "4cc9f0", "7209b7", "4cc9f0"];
PALETTES[2] = ["250902", "38040e", "640d14", "800e13", "ad2831"];
PALETTES[3] = ["013026", "a1ce3f", "107e57", "014760", "cbe58e"];
PALETTES[4] = ["009638", "F6D800", "002672", "fff", "f8961e"];
PALETTES[5] = ["23B024", "F02423", "294AF6", "fff", "000"];
PALETTES[6] = ["aabf98", "1f1f1f", "f2f2f2", "b5caa3", "20251e"];
PALETTES[7] = ["7067cf", "b7c0ee", "cbf3d2", "f87575", "ef626c"];
PALETTES[8] = ["414Cb3", "06061a", "e80663", "fff", "ff0066"];
NOISE = [20, 35, 55, 85];
SPEED = [95, 75, 50, 25];
CHARS = ["#83!:", "@94?;", "W72a+", "N$50c", "0101/", "gm;)'"];
TIGHTNESS = [2, 3, 5];
}
struct Palette {
bytes3 bg;
bytes3 colOne;
bytes3 colTwo;
}
function buildLine(
string memory _chars,
uint256 _modJump,
uint8 _x,
uint8 _y
) public pure returns (string memory lineOut) {
bytes memory byteChars = bytes(_chars);
uint256 randomModulo = 1;
lineOut = string(
abi.encodePacked(
"<text x ='-",
_x.toString(),
"' y='",
_y.toString(),
"'>"
)
);
for (uint256 i; i < 12; ++i) {
string memory charChoice = string(
abi.encodePacked(byteChars[randomModulo % 4])
);
lineOut = string(abi.encodePacked(lineOut, charChoice));
randomModulo += _modJump;
}
lineOut = string(abi.encodePacked(lineOut, "</text>"));
}
function buildXLines(
string memory _chars,
uint256 _modStart,
uint256 numLines
) public pure returns (string memory lineOut) {
uint8 x = 1;
uint8 y;
for (uint256 i; i < numLines; ++i) {
lineOut = string(
abi.encodePacked(lineOut, buildLine(_chars, _modStart, x, y))
);
_modStart += 7;
y += 4;
if (x == 1) {
x = 3;
} else {
x = 1;
}
}
}
function buildSVG(uint256 _tokenId, string memory _hash)
public
view
returns (string memory _svg)
{
Traits memory tokenTraits = buildTraits(_hash);
uint256 modStart = tokenTraits.noise + tokenTraits.tightness;
_svg = string(
abi.encodePacked(
tokenTraits.palette[0],
"'/><defs><g id='chars' font-family='monospace'>",
buildXLines(
tokenTraits.charSet,
modStart,
10 - tokenTraits.numCols
),
"<animate attributeName='font-size' attributeType='XML' values='100%;",
AnonymiceLibrary.toString(tokenTraits.speed),
"%;100%' begin='0s' dur='15s' repeatCount='indefinite'/></g><filter id='turbulence'><feTurbulence type='turbulence' baseFrequency='0.",
AnonymiceLibrary.toString(tokenTraits.noise),
"' numOctaves='",
AnonymiceLibrary.toString(tokenTraits.tightness),
"' result='noise' seed='",
AnonymiceLibrary.toString(_tokenId),
buildUseLines(tokenTraits.palette, tokenTraits.numCols)
)
);
}
function buildTraits(string memory _hash)
public
view
returns (Traits memory tokenTraits)
{
uint256[] memory traitArray = new uint256[](6);
for (uint256 i; i < 6; ++i) {
traitArray[i] = AnonymiceLibrary.parseInt(
AnonymiceLibrary.substring(_hash, i, i + 1)
);
}
tokenTraits = Traits(
PALETTES[traitArray[0]],
NOISE[traitArray[1]],
SPEED[traitArray[2]],
CHARS[traitArray[3]],
TIGHTNESS[traitArray[4]],
traitArray[5] + 1
);
}
function buildUseLines(string[] memory _pal, uint256 _numCols)
internal
pure
returns (string memory output)
{
output = "'/><feDisplacementMap in='SourceGraphic' in2='noise' scale='3' /></filter></defs>";
uint256 y;
for (uint256 i; i < _numCols; ++i) {
output = string(
abi.encodePacked(
output,
"<use href='#chars' y='",
AnonymiceLibrary.toString(y),
"' x='0' filter='url(#turbulence)' width='20' height='20' fill='#",
_pal[i + 1],
"'/>"
)
);
y += 3;
}
}
}
文件 5 的 7:ERC721.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;
}
}
文件 6 的 7: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 verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {
return processProofCalldata(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++) {
computedHash = _hashPair(computedHash, proof[i]);
}
return computedHash;
}
function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {
bytes32 computedHash = leaf;
for (uint256 i = 0; i < proof.length; i++) {
computedHash = _hashPair(computedHash, proof[i]);
}
return computedHash;
}
function multiProofVerify(
bytes32[] memory proof,
bool[] memory proofFlags,
bytes32 root,
bytes32[] memory leaves
) internal pure returns (bool) {
return processMultiProof(proof, proofFlags, leaves) == root;
}
function multiProofVerifyCalldata(
bytes32[] calldata proof,
bool[] calldata proofFlags,
bytes32 root,
bytes32[] memory leaves
) internal pure returns (bool) {
return processMultiProofCalldata(proof, proofFlags, leaves) == root;
}
function processMultiProof(
bytes32[] memory proof,
bool[] memory proofFlags,
bytes32[] memory leaves
) internal pure returns (bytes32 merkleRoot) {
uint256 leavesLen = leaves.length;
uint256 totalHashes = proofFlags.length;
require(leavesLen + proof.length - 1 == totalHashes, "MerkleProof: invalid multiproof");
bytes32[] memory hashes = new bytes32[](totalHashes);
uint256 leafPos = 0;
uint256 hashPos = 0;
uint256 proofPos = 0;
for (uint256 i = 0; i < totalHashes; i++) {
bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];
bytes32 b = proofFlags[i]
? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])
: proof[proofPos++];
hashes[i] = _hashPair(a, b);
}
if (totalHashes > 0) {
unchecked {
return hashes[totalHashes - 1];
}
} else if (leavesLen > 0) {
return leaves[0];
} else {
return proof[0];
}
}
function processMultiProofCalldata(
bytes32[] calldata proof,
bool[] calldata proofFlags,
bytes32[] memory leaves
) internal pure returns (bytes32 merkleRoot) {
uint256 leavesLen = leaves.length;
uint256 totalHashes = proofFlags.length;
require(leavesLen + proof.length - 1 == totalHashes, "MerkleProof: invalid multiproof");
bytes32[] memory hashes = new bytes32[](totalHashes);
uint256 leafPos = 0;
uint256 hashPos = 0;
uint256 proofPos = 0;
for (uint256 i = 0; i < totalHashes; i++) {
bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];
bytes32 b = proofFlags[i]
? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])
: proof[proofPos++];
hashes[i] = _hashPair(a, b);
}
if (totalHashes > 0) {
unchecked {
return hashes[totalHashes - 1];
}
} else if (leavesLen > 0) {
return leaves[0];
} else {
return proof[0];
}
}
function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {
return a < b ? _efficientHash(a, b) : _efficientHash(b, a);
}
function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {
assembly {
mstore(0x00, a)
mstore(0x20, b)
value := keccak256(0x00, 0x40)
}
}
}
文件 7 的 7:Owned.sol
pragma solidity >=0.8.0;
abstract contract Owned {
event OwnershipTransferred(address indexed user, address indexed newOwner);
address public owner;
modifier onlyOwner() virtual {
require(msg.sender == owner, "UNAUTHORIZED");
_;
}
constructor(address _owner) {
owner = _owner;
emit OwnershipTransferred(address(0), _owner);
}
function transferOwnership(address newOwner) public virtual onlyOwner {
owner = newOwner;
emit OwnershipTransferred(msg.sender, newOwner);
}
}
{
"compilationTarget": {
"src/ChainWaves.sol": "ChainWaves"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": [
":ds-test/=lib/forge-std/lib/ds-test/src/",
":erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
":forge-std/=lib/forge-std/src/",
":openzeppelin-contracts/=lib/openzeppelin-contracts/contracts/",
":script/=script/",
":solmate/=lib/solmate/src/",
":src/=src/",
":test/=test/"
]
}
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ArrayLengths","type":"error"},{"inputs":[],"name":"FreeMintDone","type":"error"},{"inputs":[],"name":"MaxThree","type":"error"},{"inputs":[],"name":"MintPrice","type":"error"},{"inputs":[],"name":"MintZero","type":"error"},{"inputs":[],"name":"NonExistantId","type":"error"},{"inputs":[],"name":"NotLive","type":"error"},{"inputs":[],"name":"NotSnowcrashList","type":"error"},{"inputs":[],"name":"NotToad","type":"error"},{"inputs":[],"name":"PublicMinted","type":"error"},{"inputs":[],"name":"ReserveClosed","type":"error"},{"inputs":[],"name":"SelfMintOnly","type":"error"},{"inputs":[],"name":"SnowcrashMinted","type":"error"},{"inputs":[],"name":"SoldOut","type":"error"},{"inputs":[],"name":"Stap","type":"error"},{"inputs":[],"name":"WithdrawFail","type":"error"},{"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":"user","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_MINT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"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":"MINT_PRICE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MINT_START","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"_tokenIdToHash","outputs":[{"internalType":"string","name":"tokenHash","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_traitTypeIndex","type":"uint256"},{"components":[{"internalType":"string","name":"traitName","type":"string"},{"internalType":"string","name":"traitType","type":"string"}],"internalType":"struct ChainWaves.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":"flipMint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_addresses","type":"address[]"},{"internalType":"uint256[]","name":"_amount","type":"uint256[]"}],"name":"freeMints","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"}],"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":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"normieMint","outputs":[],"stateMutability":"payable","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":[{"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":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"merkleProof","type":"bytes32[]"}],"name":"snowcrashMint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"snowcrashReserve","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","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":"_URI","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":"wipeSnowcrashReserve","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"payable","type":"function"}]