编译器
0.8.20+commit.a1b79de6
文件 1 的 19:AngelMatter.sol
pragma solidity 0.8.20;
import {Program, Params} from "./Program.sol";
import {ERC721} from "../lib/solmate/src/tokens/ERC721.sol";
import {Antigraviton} from "./Antigraviton.sol";
import {Research} from "./Research.sol";
import {LibString} from "../lib/solady/src/utils/LibString.sol";
import {ERC2981} from "lib/openzeppelin-contracts/contracts/token/common/ERC2981.sol";
contract AngelMatter is ERC721("Angel Matter", "AM"), ERC2981 {
uint256 constant SUPPLY = 3333;
uint256 constant PRICE = 0.01618 ether;
uint256 constant COLLISION = 3333333 ether;
Antigraviton public anti;
Research public research;
Program public program;
address public owner;
uint256 public startTime;
uint256 public currentId;
mapping(uint256 => uint256) public prestige;
mapping(uint256 => uint256) public seed;
mapping(uint256 => uint8) public level;
mapping(uint256 => uint8) public spin;
mapping(uint256 => uint8) public redacted;
mapping(uint256 => string) public prism;
mapping(uint256 => uint256) public claimed;
modifier onlyHolder(uint256 id) {
require(msg.sender == ownerOf(id));
_;
}
constructor(address _owner, uint256 _startTime) {
anti = new Antigraviton();
research = new Research();
program = new Program();
owner = _owner;
startTime = _startTime;
_setDefaultRoyalty(_owner, 333);
}
function mint(uint256 _amount) external payable {
require(startTime <= block.timestamp || msg.sender == owner);
require(msg.value == _amount * PRICE || msg.sender == owner);
require(currentId + _amount <= SUPPLY);
uint256 i;
for (i; i < _amount; ) {
unchecked {
uint256 id = ++currentId;
seed[id] = _prandom(id);
_mint(msg.sender, id);
++i;
if (id % 2 == 0) {
spin[id] = 1;
}
prism[id] = "0";
}
}
}
function claimAnti(uint256 id) public onlyHolder(id) {
uint256 vb = virtualAnti(id);
claimed[id] += vb;
anti.mint(msg.sender, vb);
}
function virtualAnti(uint256 id) public view returns (uint256) {
return ((block.timestamp - startTime) * 1 ether) - claimed[id];
}
function collide(uint256 id, string memory signal) external onlyHolder(id) {
require((anti.balanceOf(msg.sender) + virtualAnti(id)) >= COLLISION);
claimAnti(id);
anti.burn(msg.sender, COLLISION);
research.mint(msg.sender, ++prestige[id]);
if (redacted[id] == 1) {
redacted[id] = 0;
research.mint(msg.sender, 0);
}
seed[id] = uint256(keccak256(abi.encodePacked(signal, id)));
level[id] = 0;
prism[id] = "0";
}
function observe(
uint256 id,
uint256[][] memory arr
) external onlyHolder(id) {
require(arr.length == 5);
string memory str = "[";
for (uint256 i; i < 5; ++i) {
require(arr[i].length == 5);
str = string.concat(str, "[");
for (uint256 j; j < 5; ++j) {
require(arr[i][j] < 6);
str = string.concat(str, LibString.toString(arr[i][j]));
if (j < 4) {
str = string.concat(str, ",");
} else {
str = string.concat(str, "]");
}
}
if (i < 4) {
str = string.concat(str, ",");
} else {
str = string.concat(str, "]");
}
}
prism[id] = str;
}
function xe(uint256 id) external onlyHolder(id) {
require(redacted[id] == 0);
require(level[id] == 100);
require(
keccak256(abi.encodePacked(prism[id])) ==
0x18dd307dad56bbc1962747ba3045a38d4d58443f58f1cc44ef53fb0c22e75bdf
);
require(block.timestamp % 5256000 > 5169600);
redacted[id] = 1;
}
function invert(uint256 id) external onlyHolder(id) {
if (spin[id] == 0) {
spin[id] = 1;
} else {
spin[id] = 0;
}
}
function tokenURI(uint256 id) public view override returns (string memory) {
Params memory params = Params(
id,
seed[id],
prestige[id],
prism[id],
ownerOf(id),
spin[id],
level[id],
redacted[id]
);
return program.uri(params);
}
function transferFrom(
address from,
address to,
uint256 id
) public override {
if (level[id] < 100) {
++level[id];
}
super.transferFrom(from, to, id);
}
function safeTransferFrom(
address from,
address to,
uint256 id
) public override {
if (level[id] < 100) {
++level[id];
}
super.safeTransferFrom(from, to, id);
}
function safeTransferFrom(
address from,
address to,
uint256 id,
bytes calldata data
) public override {
if (level[id] < 100) {
++level[id];
}
super.safeTransferFrom(from, to, id, data);
}
function _prandom(uint256 id) internal view returns (uint256) {
return
uint256(
keccak256(abi.encodePacked(blockhash(block.number - 1), id))
);
}
function withdraw() external {
require(msg.sender == owner);
(bool succ, ) = owner.call{value: address(this).balance}("");
require(succ);
}
function supportsInterface(
bytes4 interfaceId
) public view override(ERC721, ERC2981) returns (bool) {
return
interfaceId == 0x01ffc9a7 ||
interfaceId == 0x80ac58cd ||
interfaceId == 0x5b5e139f ||
interfaceId == 0x2a55205a;
}
}
文件 2 的 19:Antigraviton.sol
pragma solidity 0.8.20;
import {ERC20} from "../lib/solmate/src/tokens/ERC20.sol";
contract Antigraviton is ERC20 {
address immutable angel;
constructor() ERC20("Antigraviton", "φ", 18) {
angel = msg.sender;
}
function mint(address to, uint256 amount) external {
require(msg.sender == angel);
_mint(to, amount);
}
function burn(address from, uint256 amount) external {
require(msg.sender == angel);
_burn(from, amount);
}
}
文件 3 的 19:Base64.sol
pragma solidity ^0.8.4;
library Base64 {
function encode(bytes memory data, bool fileSafe, bool noPadding)
internal
pure
returns (string memory result)
{
assembly {
let dataLength := mload(data)
if dataLength {
let encodedLength := shl(2, div(add(dataLength, 2), 3))
result := mload(0x40)
mstore(0x1f, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdef")
mstore(0x3f, sub("ghijklmnopqrstuvwxyz0123456789-_", mul(iszero(fileSafe), 0x0230)))
let ptr := add(result, 0x20)
let end := add(ptr, encodedLength)
for {} 1 {} {
data := add(data, 3)
let input := mload(data)
mstore8(0, mload(and(shr(18, input), 0x3F)))
mstore8(1, mload(and(shr(12, input), 0x3F)))
mstore8(2, mload(and(shr(6, input), 0x3F)))
mstore8(3, mload(and(input, 0x3F)))
mstore(ptr, mload(0x00))
ptr := add(ptr, 4)
if iszero(lt(ptr, end)) { break }
}
mstore(0x40, add(end, 0x20))
let o := div(2, mod(dataLength, 3))
mstore(sub(ptr, o), shl(240, 0x3d3d))
o := mul(iszero(iszero(noPadding)), o)
mstore(sub(ptr, o), 0)
mstore(result, sub(encodedLength, o))
}
}
}
function encode(bytes memory data) internal pure returns (string memory result) {
result = encode(data, false, false);
}
function encode(bytes memory data, bool fileSafe)
internal
pure
returns (string memory result)
{
result = encode(data, fileSafe, false);
}
function decode(string memory data) internal pure returns (bytes memory result) {
assembly {
let dataLength := mload(data)
if dataLength {
let decodedLength := mul(shr(2, dataLength), 3)
for {} 1 {} {
if iszero(and(dataLength, 3)) {
let t := xor(mload(add(data, dataLength)), 0x3d3d)
decodedLength := sub(
decodedLength,
add(iszero(byte(30, t)), iszero(byte(31, t)))
)
break
}
decodedLength := add(decodedLength, sub(and(dataLength, 3), 1))
break
}
result := mload(0x40)
mstore(result, decodedLength)
let ptr := add(result, 0x20)
let end := add(ptr, decodedLength)
let m := 0xfc000000fc00686c7074787c8084888c9094989ca0a4a8acb0b4b8bcc0c4c8cc
mstore(0x5b, m)
mstore(0x3b, 0x04080c1014181c2024282c3034383c4044484c5054585c6064)
mstore(0x1a, 0xf8fcf800fcd0d4d8dce0e4e8ecf0f4)
for {} 1 {} {
data := add(data, 4)
let input := mload(data)
mstore(ptr, or(
and(m, mload(byte(28, input))),
shr(6, or(
and(m, mload(byte(29, input))),
shr(6, or(
and(m, mload(byte(30, input))),
shr(6, mload(byte(31, input)))
))
))
))
ptr := add(ptr, 3)
if iszero(lt(ptr, end)) { break }
}
mstore(0x40, add(end, 0x20))
mstore(end, 0)
mstore(0x60, 0)
}
}
}
}
文件 4 的 19:Collision.sol
pragma solidity 0.8.20;
import {Data} from "./Data.sol";
import {Base64} from "../lib/solady/src/utils/Base64.sol";
import {LibString} from "../lib/solady/src/utils/LibString.sol";
import {IFileStore} from "../lib/ethfs/packages/contracts/src/IFileStore.sol";
contract Collision {
using LibString for uint256;
IFileStore fileStore;
string desc =
'"description":"In a far away parallel universe an advanced civilization built a computer around a star and escaped into a simulated reality. After some immeasurable amount of time these facts were forgotten and after another immeasurable amount of time that star began to die. Even so, life Inside this simulation progressed, and on one planet some of that life progressed enough to form a government. You are the new member of a mysterious project under a secret agency of this government researching the elementary particles that make up your universe.",';
constructor() {
fileStore = IFileStore(0x9746fD0A77829E12F8A9DBe70D7a322412325B91);
}
function _parameters(uint256 _id) internal pure returns (string memory) {
return
string.concat(
'<script src="data:text/javascript;base64,',
Base64.encode(
abi.encodePacked(
string.concat(
"let seed = ",
_id.toString(),
_id == 0 ? "; let mode = 1;" : "; let mode = 0;"
)
)
)
);
}
function _scripts(uint256 _id) internal view returns (string memory) {
return
string.concat(
'<script type="text/javascript+gzip" src="data:text/javascript;base64,',
fileStore.getFile("p5-v1.5.0.min.js.gz").read(),
'"></script>',
'<script src="data:text/javascript;base64,',
fileStore.getFile("gunzipScripts-0.0.1.js").read(),
'"></script>',
_parameters(_id),
'"></script><script src="data:text/javascript;base64,',
fileStore.getFile("(:").read(),
'"></script>'
);
}
function _page(uint256 _id) internal view returns (string memory) {
return
string.concat(
'"animation_url":"data:text/html;base64,',
Base64.encode(
abi.encodePacked(
string.concat(
'<!DOCTYPE html><html style="height: 100%;"><head>',
_scripts(_id),
'</head><body style="margin: 0;display: flex;justify-content: center;align-items: center;height: 100%;"></body></html>'
)
)
),
'"}'
);
}
function uri(uint256 _id) external view returns (string memory) {
return
string.concat(
"data:application/json;base64,",
Base64.encode(
abi.encodePacked(
string.concat(
'{"name":"< ',
_id > 0 ? _id.toString() : "...",
' >",',
desc,
'"image":"',
Data._image(_id),
'",',
_page(_id)
)
)
)
);
}
}
文件 5 的 19:Data.sol
pragma solidity 0.8.20;
import {Base64} from "../lib/solady/src/utils/Base64.sol";
import {LibString} from "../lib/solady/src/utils/LibString.sol";
library Data {
function _image(uint256 id) internal pure returns (string memory) {
if (id > 0) {
return _main(id);
} else {
return _$ECRET(id);
}
}
function _main(uint256 id) internal pure returns (string memory) {
string
memory im = '<svg height="500" width="500" xmlns="http://www.w3.org/2000/svg"><rect x="0" y="0" width="500" height="500"/>';
for (uint256 i; i < 26; ++i) {
string memory y = LibString.toString((i * 20) + 10);
im = string.concat(
im,
'<text fill="#FFF" font-size="20" font-family="monospace" x="250" y="',
y,
'" text-anchor="middle">',
LibString.toHexStringNoPrefix(
abi.encode(
(keccak256(abi.encode(i, keccak256(abi.encode(id)))))
)
),
'<animate attributeName="opacity" values="1;0;1" dur="1s" repeatCount="indefinite"/></text><text fill="#FFF" font-size="20" font-family="monospace" x="250" y="',
y,
'" text-anchor="middle">',
LibString.toHexStringNoPrefix(
abi.encode(
(
keccak256(
abi.encode(i + 1, keccak256(abi.encode(id)))
)
)
)
),
'<animate attributeName="opacity" values="0;1;0" dur="1s" repeatCount="indefinite"/></text><text fill="#FFF" font-size="20" font-family="monospace" x="250" y="',
y,
'" text-anchor="middle">',
LibString.toHexStringNoPrefix(
abi.encode(
(
keccak256(
abi.encode(i + 2, keccak256(abi.encode(id)))
)
)
)
),
'<animate attributeName="opacity" values="0;1;0" dur="2s" repeatCount="indefinite"/></text>'
);
}
for (uint256 i; i < 11; ++i) {
string memory y = LibString.toString((i * 50) + 25);
im = string.concat(
im,
'<text fill="#000" font-size="80" font-family="monospace" x="250" y="',
y,
'" text-anchor="middle">',
LibString.toHexStringNoPrefix(
abi.encode(
(keccak256(abi.encode(i, keccak256(abi.encode(id)))))
)
),
'<animate attributeName="opacity" values="1;0;1" dur="1s" repeatCount="indefinite"/></text><text fill="#000" font-size="80" font-family="monospace" x="250" y="',
y,
'" text-anchor="middle">',
LibString.toHexStringNoPrefix(
abi.encode(
(
keccak256(
abi.encode(i + 1, keccak256(abi.encode(id)))
)
)
)
),
'<animate attributeName="opacity" values="0;1;0" dur="1s" repeatCount="indefinite"/></text><text fill="#000" font-size="80" font-family="monospace" x="250" y="',
y,
'" text-anchor="middle">',
LibString.toHexStringNoPrefix(
abi.encode(
(
keccak256(
abi.encode(i + 2, keccak256(abi.encode(id)))
)
)
)
),
'<animate attributeName="opacity" values="0;1;0" dur="2s" repeatCount="indefinite"/></text>'
);
}
im = string.concat(im, "</svg>");
return
string.concat(
"data:image/svg+xml;base64,",
Base64.encode(bytes(im))
);
}
function _$ECRET(uint256 id) internal pure returns (string memory) {
string
memory im = '<svg height="500" width="500" xmlns="http://www.w3.org/2000/svg">';
for (uint256 i; i < 26; ++i) {
string memory y = LibString.toString((i * 20) + 10);
im = string.concat(
im,
'<text fill="#000" font-size="20" font-family="monospace" x="250" y="',
y,
'" text-anchor="middle">',
LibString.toHexStringNoPrefix(
abi.encode(
(keccak256(abi.encode(i, keccak256(abi.encode(id)))))
)
),
'<animate attributeName="opacity" values="1;0;1" dur="2s" repeatCount="indefinite"/></text><text fill="#000" font-size="20" font-family="monospace" x="250" y="',
y,
'" text-anchor="middle">',
LibString.toHexStringNoPrefix(
abi.encode(
(
keccak256(
abi.encode(i + 1, keccak256(abi.encode(id)))
)
)
)
),
'<animate attributeName="opacity" values="0;1;0" dur="2s" repeatCount="indefinite"/></text><text fill="#000" font-size="20" font-family="monospace" x="250" y="',
y,
'" text-anchor="middle">',
LibString.toHexStringNoPrefix(
abi.encode(
(
keccak256(
abi.encode(i + 2, keccak256(abi.encode(id)))
)
)
)
),
'<animate attributeName="opacity" values="0;1;0" dur="3s" repeatCount="indefinite"/></text>'
);
}
for (uint256 i; i < 11; ++i) {
string memory y = LibString.toString((i * 50) + 25);
im = string.concat(
im,
'<text fill="#FFF" font-size="80" font-family="monospace" x="250" y="',
y,
'" text-anchor="middle">',
LibString.toHexStringNoPrefix(
abi.encode(
(keccak256(abi.encode(i, keccak256(abi.encode(id)))))
)
),
'<animate attributeName="opacity" values="1;0;1" dur="2s" repeatCount="indefinite"/></text><text fill="#FFF" font-size="80" font-family="monospace" x="250" y="',
y,
'" text-anchor="middle">',
LibString.toHexStringNoPrefix(
abi.encode(
(
keccak256(
abi.encode(i + 1, keccak256(abi.encode(id)))
)
)
)
),
'<animate attributeName="opacity" values="0;1;0" dur="2s" repeatCount="indefinite"/></text><text fill="#FFF" font-size="80" font-family="monospace" x="250" y="',
y,
'" text-anchor="middle">',
LibString.toHexStringNoPrefix(
abi.encode(
(
keccak256(
abi.encode(i + 2, keccak256(abi.encode(id)))
)
)
)
),
'<animate attributeName="opacity" values="0;1;0" dur="3s" repeatCount="indefinite"/></text>'
);
}
im = string.concat(
im,
'<text fill="#F00" font-size="80" font-family="monospace" x="420" y="275" text-anchor="middle">< ></text></svg>'
);
return
string.concat(
"data:image/svg+xml;base64,",
Base64.encode(bytes(im))
);
}
}
文件 6 的 19:ERC1155.sol
pragma solidity >=0.8.0;
abstract contract ERC1155 {
event TransferSingle(
address indexed operator,
address indexed from,
address indexed to,
uint256 id,
uint256 amount
);
event TransferBatch(
address indexed operator,
address indexed from,
address indexed to,
uint256[] ids,
uint256[] amounts
);
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
event URI(string value, uint256 indexed id);
mapping(address => mapping(uint256 => uint256)) public balanceOf;
mapping(address => mapping(address => bool)) public isApprovedForAll;
function uri(uint256 id) public view virtual returns (string memory);
function setApprovalForAll(address operator, bool approved) public virtual {
isApprovedForAll[msg.sender][operator] = approved;
emit ApprovalForAll(msg.sender, operator, approved);
}
function safeTransferFrom(
address from,
address to,
uint256 id,
uint256 amount,
bytes calldata data
) public virtual {
require(msg.sender == from || isApprovedForAll[from][msg.sender], "NOT_AUTHORIZED");
balanceOf[from][id] -= amount;
balanceOf[to][id] += amount;
emit TransferSingle(msg.sender, from, to, id, amount);
require(
to.code.length == 0
? to != address(0)
: ERC1155TokenReceiver(to).onERC1155Received(msg.sender, from, id, amount, data) ==
ERC1155TokenReceiver.onERC1155Received.selector,
"UNSAFE_RECIPIENT"
);
}
function safeBatchTransferFrom(
address from,
address to,
uint256[] calldata ids,
uint256[] calldata amounts,
bytes calldata data
) public virtual {
require(ids.length == amounts.length, "LENGTH_MISMATCH");
require(msg.sender == from || isApprovedForAll[from][msg.sender], "NOT_AUTHORIZED");
uint256 id;
uint256 amount;
for (uint256 i = 0; i < ids.length; ) {
id = ids[i];
amount = amounts[i];
balanceOf[from][id] -= amount;
balanceOf[to][id] += amount;
unchecked {
++i;
}
}
emit TransferBatch(msg.sender, from, to, ids, amounts);
require(
to.code.length == 0
? to != address(0)
: ERC1155TokenReceiver(to).onERC1155BatchReceived(msg.sender, from, ids, amounts, data) ==
ERC1155TokenReceiver.onERC1155BatchReceived.selector,
"UNSAFE_RECIPIENT"
);
}
function balanceOfBatch(address[] calldata owners, uint256[] calldata ids)
public
view
virtual
returns (uint256[] memory balances)
{
require(owners.length == ids.length, "LENGTH_MISMATCH");
balances = new uint256[](owners.length);
unchecked {
for (uint256 i = 0; i < owners.length; ++i) {
balances[i] = balanceOf[owners[i]][ids[i]];
}
}
}
function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
return
interfaceId == 0x01ffc9a7 ||
interfaceId == 0xd9b67a26 ||
interfaceId == 0x0e89341c;
}
function _mint(
address to,
uint256 id,
uint256 amount,
bytes memory data
) internal virtual {
balanceOf[to][id] += amount;
emit TransferSingle(msg.sender, address(0), to, id, amount);
require(
to.code.length == 0
? to != address(0)
: ERC1155TokenReceiver(to).onERC1155Received(msg.sender, address(0), id, amount, data) ==
ERC1155TokenReceiver.onERC1155Received.selector,
"UNSAFE_RECIPIENT"
);
}
function _batchMint(
address to,
uint256[] memory ids,
uint256[] memory amounts,
bytes memory data
) internal virtual {
uint256 idsLength = ids.length;
require(idsLength == amounts.length, "LENGTH_MISMATCH");
for (uint256 i = 0; i < idsLength; ) {
balanceOf[to][ids[i]] += amounts[i];
unchecked {
++i;
}
}
emit TransferBatch(msg.sender, address(0), to, ids, amounts);
require(
to.code.length == 0
? to != address(0)
: ERC1155TokenReceiver(to).onERC1155BatchReceived(msg.sender, address(0), ids, amounts, data) ==
ERC1155TokenReceiver.onERC1155BatchReceived.selector,
"UNSAFE_RECIPIENT"
);
}
function _batchBurn(
address from,
uint256[] memory ids,
uint256[] memory amounts
) internal virtual {
uint256 idsLength = ids.length;
require(idsLength == amounts.length, "LENGTH_MISMATCH");
for (uint256 i = 0; i < idsLength; ) {
balanceOf[from][ids[i]] -= amounts[i];
unchecked {
++i;
}
}
emit TransferBatch(msg.sender, from, address(0), ids, amounts);
}
function _burn(
address from,
uint256 id,
uint256 amount
) internal virtual {
balanceOf[from][id] -= amount;
emit TransferSingle(msg.sender, from, address(0), id, amount);
}
}
abstract contract ERC1155TokenReceiver {
function onERC1155Received(
address,
address,
uint256,
uint256,
bytes calldata
) external virtual returns (bytes4) {
return ERC1155TokenReceiver.onERC1155Received.selector;
}
function onERC1155BatchReceived(
address,
address,
uint256[] calldata,
uint256[] calldata,
bytes calldata
) external virtual returns (bytes4) {
return ERC1155TokenReceiver.onERC1155BatchReceived.selector;
}
}
文件 7 的 19:ERC165.sol
pragma solidity ^0.8.19;
import "./IERC165.sol";
abstract contract ERC165 is IERC165 {
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}
文件 8 的 19:ERC20.sol
pragma solidity >=0.8.0;
abstract contract ERC20 {
event Transfer(address indexed from, address indexed to, uint256 amount);
event Approval(address indexed owner, address indexed spender, uint256 amount);
string public name;
string public symbol;
uint8 public immutable decimals;
uint256 public totalSupply;
mapping(address => uint256) public balanceOf;
mapping(address => mapping(address => uint256)) public allowance;
uint256 internal immutable INITIAL_CHAIN_ID;
bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR;
mapping(address => uint256) public nonces;
constructor(
string memory _name,
string memory _symbol,
uint8 _decimals
) {
name = _name;
symbol = _symbol;
decimals = _decimals;
INITIAL_CHAIN_ID = block.chainid;
INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator();
}
function approve(address spender, uint256 amount) public virtual returns (bool) {
allowance[msg.sender][spender] = amount;
emit Approval(msg.sender, spender, amount);
return true;
}
function transfer(address to, uint256 amount) public virtual returns (bool) {
balanceOf[msg.sender] -= amount;
unchecked {
balanceOf[to] += amount;
}
emit Transfer(msg.sender, to, amount);
return true;
}
function transferFrom(
address from,
address to,
uint256 amount
) public virtual returns (bool) {
uint256 allowed = allowance[from][msg.sender];
if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount;
balanceOf[from] -= amount;
unchecked {
balanceOf[to] += amount;
}
emit Transfer(from, to, amount);
return true;
}
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) public virtual {
require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED");
unchecked {
address recoveredAddress = ecrecover(
keccak256(
abi.encodePacked(
"\x19\x01",
DOMAIN_SEPARATOR(),
keccak256(
abi.encode(
keccak256(
"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"
),
owner,
spender,
value,
nonces[owner]++,
deadline
)
)
)
),
v,
r,
s
);
require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER");
allowance[recoveredAddress][spender] = value;
}
emit Approval(owner, spender, value);
}
function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {
return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator();
}
function computeDomainSeparator() internal view virtual returns (bytes32) {
return
keccak256(
abi.encode(
keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
keccak256(bytes(name)),
keccak256("1"),
block.chainid,
address(this)
)
);
}
function _mint(address to, uint256 amount) internal virtual {
totalSupply += amount;
unchecked {
balanceOf[to] += amount;
}
emit Transfer(address(0), to, amount);
}
function _burn(address from, uint256 amount) internal virtual {
balanceOf[from] -= amount;
unchecked {
totalSupply -= amount;
}
emit Transfer(from, address(0), amount);
}
}
文件 9 的 19:ERC2981.sol
pragma solidity ^0.8.19;
import "../../interfaces/IERC2981.sol";
import "../../utils/introspection/ERC165.sol";
abstract contract ERC2981 is IERC2981, ERC165 {
struct RoyaltyInfo {
address receiver;
uint96 royaltyFraction;
}
RoyaltyInfo private _defaultRoyaltyInfo;
mapping(uint256 => RoyaltyInfo) private _tokenRoyaltyInfo;
function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {
return interfaceId == type(IERC2981).interfaceId || super.supportsInterface(interfaceId);
}
function royaltyInfo(uint256 tokenId, uint256 salePrice) public view virtual override returns (address, uint256) {
RoyaltyInfo memory royalty = _tokenRoyaltyInfo[tokenId];
if (royalty.receiver == address(0)) {
royalty = _defaultRoyaltyInfo;
}
uint256 royaltyAmount = (salePrice * royalty.royaltyFraction) / _feeDenominator();
return (royalty.receiver, royaltyAmount);
}
function _feeDenominator() internal pure virtual returns (uint96) {
return 10000;
}
function _setDefaultRoyalty(address receiver, uint96 feeNumerator) internal virtual {
require(feeNumerator <= _feeDenominator(), "ERC2981: royalty fee will exceed salePrice");
require(receiver != address(0), "ERC2981: invalid receiver");
_defaultRoyaltyInfo = RoyaltyInfo(receiver, feeNumerator);
}
function _deleteDefaultRoyalty() internal virtual {
delete _defaultRoyaltyInfo;
}
function _setTokenRoyalty(uint256 tokenId, address receiver, uint96 feeNumerator) internal virtual {
require(feeNumerator <= _feeDenominator(), "ERC2981: royalty fee will exceed salePrice");
require(receiver != address(0), "ERC2981: Invalid parameters");
_tokenRoyaltyInfo[tokenId] = RoyaltyInfo(receiver, feeNumerator);
}
function _resetTokenRoyalty(uint256 tokenId) internal virtual {
delete _tokenRoyaltyInfo[tokenId];
}
}
文件 10 的 19: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;
}
}
文件 11 的 19:File.sol
pragma solidity ^0.8.13;
struct Content {
bytes32 checksum;
address pointer;
}
struct File {
uint256 size;
Content[] contents;
}
function read(File memory file) view returns (string memory contents) {
Content[] memory chunks = file.contents;
assembly {
let len := mload(chunks)
let totalSize := 0x20
contents := mload(0x40)
let size
let chunk
let pointer
for { let i := 0 } lt(i, len) { i := add(i, 1) } {
chunk := mload(add(chunks, add(0x20, mul(i, 0x20))))
pointer := mload(add(chunk, 0x20))
size := sub(extcodesize(pointer), 1)
extcodecopy(pointer, add(contents, totalSize), 1, size)
totalSize := add(totalSize, size)
}
mstore(contents, sub(totalSize, 0x20))
mstore(0x40, add(contents, and(add(totalSize, 0x1f), not(0x1f))))
}
}
using {read} for File global;
文件 12 的 19:IContentStore.sol
pragma solidity ^0.8.13;
interface IContentStore {
event NewChecksum(bytes32 indexed checksum, uint256 contentSize);
error ChecksumExists(bytes32 checksum);
error ChecksumNotFound(bytes32 checksum);
function pointers(bytes32 checksum)
external
view
returns (address pointer);
function checksumExists(bytes32 checksum) external view returns (bool);
function contentLength(bytes32 checksum)
external
view
returns (uint256 size);
function addPointer(address pointer) external returns (bytes32 checksum);
function addContent(bytes memory content)
external
returns (bytes32 checksum, address pointer);
function getPointer(bytes32 checksum)
external
view
returns (address pointer);
}
文件 13 的 19:IERC165.sol
pragma solidity ^0.8.19;
interface IERC165 {
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
文件 14 的 19:IERC2981.sol
pragma solidity ^0.8.19;
import "../utils/introspection/IERC165.sol";
interface IERC2981 is IERC165 {
function royaltyInfo(
uint256 tokenId,
uint256 salePrice
) external view returns (address receiver, uint256 royaltyAmount);
}
文件 15 的 19:IFileStore.sol
pragma solidity ^0.8.13;
import {File} from "./File.sol";
import {IContentStore} from "./IContentStore.sol";
interface IFileStore {
event FileCreated(
string indexed indexedFilename,
bytes32 indexed checksum,
string filename,
uint256 size,
bytes metadata
);
event FileDeleted(
string indexed indexedFilename,
bytes32 indexed checksum,
string filename
);
error FileNotFound(string filename);
error FilenameExists(string filename);
error EmptyFile();
function contentStore() external view returns (IContentStore);
function files(string memory filename)
external
view
returns (bytes32 checksum);
function fileExists(string memory filename) external view returns (bool);
function getChecksum(string memory filename)
external
view
returns (bytes32 checksum);
function getFile(string memory filename)
external
view
returns (File memory file);
function createFile(string memory filename, bytes32[] memory checksums)
external
returns (File memory file);
function createFile(
string memory filename,
bytes32[] memory checksums,
bytes memory extraData
) external returns (File memory file);
function deleteFile(string memory filename) external;
}
文件 16 的 19:LibString.sol
pragma solidity ^0.8.4;
library LibString {
error HexLengthInsufficient();
uint256 internal constant NOT_FOUND = type(uint256).max;
function toString(uint256 value) internal pure returns (string memory str) {
assembly {
str := add(mload(0x40), 0x80)
mstore(0x40, add(str, 0x20))
mstore(str, 0)
let end := str
let w := not(0)
for { let temp := value } 1 {} {
str := add(str, w)
mstore8(str, add(48, mod(temp, 10)))
temp := div(temp, 10)
if iszero(temp) { break }
}
let length := sub(end, str)
str := sub(str, 0x20)
mstore(str, length)
}
}
function toString(int256 value) internal pure returns (string memory str) {
if (value >= 0) {
return toString(uint256(value));
}
unchecked {
str = toString(uint256(-value));
}
assembly {
let length := mload(str)
mstore(str, 0x2d)
str := sub(str, 1)
mstore(str, add(length, 1))
}
}
function toHexString(uint256 value, uint256 length) internal pure returns (string memory str) {
str = toHexStringNoPrefix(value, length);
assembly {
let strLength := add(mload(str), 2)
mstore(str, 0x3078)
str := sub(str, 2)
mstore(str, strLength)
}
}
function toHexStringNoPrefix(uint256 value, uint256 length)
internal
pure
returns (string memory str)
{
assembly {
str := add(mload(0x40), and(add(shl(1, length), 0x42), not(0x1f)))
mstore(0x40, add(str, 0x20))
mstore(str, 0)
let end := str
mstore(0x0f, 0x30313233343536373839616263646566)
let start := sub(str, add(length, length))
let w := not(1)
let temp := value
for {} 1 {} {
str := add(str, w)
mstore8(add(str, 1), mload(and(temp, 15)))
mstore8(str, mload(and(shr(4, temp), 15)))
temp := shr(8, temp)
if iszero(xor(str, start)) { break }
}
if temp {
mstore(0x00, 0x2194895a)
revert(0x1c, 0x04)
}
let strLength := sub(end, str)
str := sub(str, 0x20)
mstore(str, strLength)
}
}
function toHexString(uint256 value) internal pure returns (string memory str) {
str = toHexStringNoPrefix(value);
assembly {
let strLength := add(mload(str), 2)
mstore(str, 0x3078)
str := sub(str, 2)
mstore(str, strLength)
}
}
function toHexStringNoPrefix(uint256 value) internal pure returns (string memory str) {
assembly {
str := add(mload(0x40), 0x80)
mstore(0x40, add(str, 0x20))
mstore(str, 0)
let end := str
mstore(0x0f, 0x30313233343536373839616263646566)
let w := not(1)
for { let temp := value } 1 {} {
str := add(str, w)
mstore8(add(str, 1), mload(and(temp, 15)))
mstore8(str, mload(and(shr(4, temp), 15)))
temp := shr(8, temp)
if iszero(temp) { break }
}
let strLength := sub(end, str)
str := sub(str, 0x20)
mstore(str, strLength)
}
}
function toHexStringChecksumed(address value) internal pure returns (string memory str) {
str = toHexString(value);
assembly {
let mask := shl(6, div(not(0), 255))
let o := add(str, 0x22)
let hashed := and(keccak256(o, 40), mul(34, mask))
let t := shl(240, 136)
for { let i := 0 } 1 {} {
mstore(add(i, i), mul(t, byte(i, hashed)))
i := add(i, 1)
if eq(i, 20) { break }
}
mstore(o, xor(mload(o), shr(1, and(mload(0x00), and(mload(o), mask)))))
o := add(o, 0x20)
mstore(o, xor(mload(o), shr(1, and(mload(0x20), and(mload(o), mask)))))
}
}
function toHexString(address value) internal pure returns (string memory str) {
str = toHexStringNoPrefix(value);
assembly {
let strLength := add(mload(str), 2)
mstore(str, 0x3078)
str := sub(str, 2)
mstore(str, strLength)
}
}
function toHexStringNoPrefix(address value) internal pure returns (string memory str) {
assembly {
str := mload(0x40)
mstore(0x40, add(str, 0x80))
mstore(0x0f, 0x30313233343536373839616263646566)
str := add(str, 2)
mstore(str, 40)
let o := add(str, 0x20)
mstore(add(o, 40), 0)
value := shl(96, value)
for { let i := 0 } 1 {} {
let p := add(o, add(i, i))
let temp := byte(i, value)
mstore8(add(p, 1), mload(and(temp, 15)))
mstore8(p, mload(shr(4, temp)))
i := add(i, 1)
if eq(i, 20) { break }
}
}
}
function toHexString(bytes memory raw) internal pure returns (string memory str) {
str = toHexStringNoPrefix(raw);
assembly {
let strLength := add(mload(str), 2)
mstore(str, 0x3078)
str := sub(str, 2)
mstore(str, strLength)
}
}
function toHexStringNoPrefix(bytes memory raw) internal pure returns (string memory str) {
assembly {
let length := mload(raw)
str := add(mload(0x40), 2)
mstore(str, add(length, length))
mstore(0x0f, 0x30313233343536373839616263646566)
let o := add(str, 0x20)
let end := add(raw, length)
for {} iszero(eq(raw, end)) {} {
raw := add(raw, 1)
mstore8(add(o, 1), mload(and(mload(raw), 15)))
mstore8(o, mload(and(shr(4, mload(raw)), 15)))
o := add(o, 2)
}
mstore(o, 0)
mstore(0x40, add(o, 0x20))
}
}
function runeCount(string memory s) internal pure returns (uint256 result) {
assembly {
if mload(s) {
mstore(0x00, div(not(0), 255))
mstore(0x20, 0x0202020202020202020202020202020202020202020202020303030304040506)
let o := add(s, 0x20)
let end := add(o, mload(s))
for { result := 1 } 1 { result := add(result, 1) } {
o := add(o, byte(0, mload(shr(250, mload(o)))))
if iszero(lt(o, end)) { break }
}
}
}
}
function is7BitASCII(string memory s) internal pure returns (bool result) {
assembly {
let mask := shl(7, div(not(0), 255))
result := 1
let n := mload(s)
if n {
let o := add(s, 0x20)
let end := add(o, n)
let last := mload(end)
mstore(end, 0)
for {} 1 {} {
if and(mask, mload(o)) {
result := 0
break
}
o := add(o, 0x20)
if iszero(lt(o, end)) { break }
}
mstore(end, last)
}
}
}
function replace(string memory subject, string memory search, string memory replacement)
internal
pure
returns (string memory result)
{
assembly {
let subjectLength := mload(subject)
let searchLength := mload(search)
let replacementLength := mload(replacement)
subject := add(subject, 0x20)
search := add(search, 0x20)
replacement := add(replacement, 0x20)
result := add(mload(0x40), 0x20)
let subjectEnd := add(subject, subjectLength)
if iszero(gt(searchLength, subjectLength)) {
let subjectSearchEnd := add(sub(subjectEnd, searchLength), 1)
let h := 0
if iszero(lt(searchLength, 0x20)) { h := keccak256(search, searchLength) }
let m := shl(3, sub(0x20, and(searchLength, 0x1f)))
let s := mload(search)
for {} 1 {} {
let t := mload(subject)
if iszero(shr(m, xor(t, s))) {
if h {
if iszero(eq(keccak256(subject, searchLength), h)) {
mstore(result, t)
result := add(result, 1)
subject := add(subject, 1)
if iszero(lt(subject, subjectSearchEnd)) { break }
continue
}
}
for { let o := 0 } 1 {} {
mstore(add(result, o), mload(add(replacement, o)))
o := add(o, 0x20)
if iszero(lt(o, replacementLength)) { break }
}
result := add(result, replacementLength)
subject := add(subject, searchLength)
if searchLength {
if iszero(lt(subject, subjectSearchEnd)) { break }
continue
}
}
mstore(result, t)
result := add(result, 1)
subject := add(subject, 1)
if iszero(lt(subject, subjectSearchEnd)) { break }
}
}
let resultRemainder := result
result := add(mload(0x40), 0x20)
let k := add(sub(resultRemainder, result), sub(subjectEnd, subject))
for {} lt(subject, subjectEnd) {} {
mstore(resultRemainder, mload(subject))
resultRemainder := add(resultRemainder, 0x20)
subject := add(subject, 0x20)
}
result := sub(result, 0x20)
let last := add(add(result, 0x20), k)
mstore(last, 0)
mstore(0x40, add(last, 0x20))
mstore(result, k)
}
}
function indexOf(string memory subject, string memory search, uint256 from)
internal
pure
returns (uint256 result)
{
assembly {
for { let subjectLength := mload(subject) } 1 {} {
if iszero(mload(search)) {
if iszero(gt(from, subjectLength)) {
result := from
break
}
result := subjectLength
break
}
let searchLength := mload(search)
let subjectStart := add(subject, 0x20)
result := not(0)
subject := add(subjectStart, from)
let end := add(sub(add(subjectStart, subjectLength), searchLength), 1)
let m := shl(3, sub(0x20, and(searchLength, 0x1f)))
let s := mload(add(search, 0x20))
if iszero(and(lt(subject, end), lt(from, subjectLength))) { break }
if iszero(lt(searchLength, 0x20)) {
for { let h := keccak256(add(search, 0x20), searchLength) } 1 {} {
if iszero(shr(m, xor(mload(subject), s))) {
if eq(keccak256(subject, searchLength), h) {
result := sub(subject, subjectStart)
break
}
}
subject := add(subject, 1)
if iszero(lt(subject, end)) { break }
}
break
}
for {} 1 {} {
if iszero(shr(m, xor(mload(subject), s))) {
result := sub(subject, subjectStart)
break
}
subject := add(subject, 1)
if iszero(lt(subject, end)) { break }
}
break
}
}
}
function indexOf(string memory subject, string memory search)
internal
pure
returns (uint256 result)
{
result = indexOf(subject, search, 0);
}
function lastIndexOf(string memory subject, string memory search, uint256 from)
internal
pure
returns (uint256 result)
{
assembly {
for {} 1 {} {
result := not(0)
let searchLength := mload(search)
if gt(searchLength, mload(subject)) { break }
let w := result
let fromMax := sub(mload(subject), searchLength)
if iszero(gt(fromMax, from)) { from := fromMax }
let end := add(add(subject, 0x20), w)
subject := add(add(subject, 0x20), from)
if iszero(gt(subject, end)) { break }
for { let h := keccak256(add(search, 0x20), searchLength) } 1 {} {
if eq(keccak256(subject, searchLength), h) {
result := sub(subject, add(end, 1))
break
}
subject := add(subject, w)
if iszero(gt(subject, end)) { break }
}
break
}
}
}
function lastIndexOf(string memory subject, string memory search)
internal
pure
returns (uint256 result)
{
result = lastIndexOf(subject, search, uint256(int256(-1)));
}
function startsWith(string memory subject, string memory search)
internal
pure
returns (bool result)
{
assembly {
let searchLength := mload(search)
result := and(
iszero(gt(searchLength, mload(subject))),
eq(
keccak256(add(subject, 0x20), searchLength),
keccak256(add(search, 0x20), searchLength)
)
)
}
}
function endsWith(string memory subject, string memory search)
internal
pure
returns (bool result)
{
assembly {
let searchLength := mload(search)
let subjectLength := mload(subject)
let withinRange := iszero(gt(searchLength, subjectLength))
result := and(
withinRange,
eq(
keccak256(
add(add(subject, 0x20), mul(withinRange, sub(subjectLength, searchLength))),
searchLength
),
keccak256(add(search, 0x20), searchLength)
)
)
}
}
function repeat(string memory subject, uint256 times)
internal
pure
returns (string memory result)
{
assembly {
let subjectLength := mload(subject)
if iszero(or(iszero(times), iszero(subjectLength))) {
subject := add(subject, 0x20)
result := mload(0x40)
let output := add(result, 0x20)
for {} 1 {} {
for { let o := 0 } 1 {} {
mstore(add(output, o), mload(add(subject, o)))
o := add(o, 0x20)
if iszero(lt(o, subjectLength)) { break }
}
output := add(output, subjectLength)
times := sub(times, 1)
if iszero(times) { break }
}
mstore(output, 0)
let resultLength := sub(output, add(result, 0x20))
mstore(result, resultLength)
mstore(0x40, add(result, add(resultLength, 0x20)))
}
}
}
function slice(string memory subject, uint256 start, uint256 end)
internal
pure
returns (string memory result)
{
assembly {
let subjectLength := mload(subject)
if iszero(gt(subjectLength, end)) { end := subjectLength }
if iszero(gt(subjectLength, start)) { start := subjectLength }
if lt(start, end) {
result := mload(0x40)
let resultLength := sub(end, start)
mstore(result, resultLength)
subject := add(subject, start)
let w := not(0x1f)
for { let o := and(add(resultLength, 0x1f), w) } 1 {} {
mstore(add(result, o), mload(add(subject, o)))
o := add(o, w)
if iszero(o) { break }
}
mstore(add(add(result, 0x20), resultLength), 0)
mstore(0x40, add(result, and(add(resultLength, 0x3f), w)))
}
}
}
function slice(string memory subject, uint256 start)
internal
pure
returns (string memory result)
{
result = slice(subject, start, uint256(int256(-1)));
}
function indicesOf(string memory subject, string memory search)
internal
pure
returns (uint256[] memory result)
{
assembly {
let subjectLength := mload(subject)
let searchLength := mload(search)
if iszero(gt(searchLength, subjectLength)) {
subject := add(subject, 0x20)
search := add(search, 0x20)
result := add(mload(0x40), 0x20)
let subjectStart := subject
let subjectSearchEnd := add(sub(add(subject, subjectLength), searchLength), 1)
let h := 0
if iszero(lt(searchLength, 0x20)) { h := keccak256(search, searchLength) }
let m := shl(3, sub(0x20, and(searchLength, 0x1f)))
let s := mload(search)
for {} 1 {} {
let t := mload(subject)
if iszero(shr(m, xor(t, s))) {
if h {
if iszero(eq(keccak256(subject, searchLength), h)) {
subject := add(subject, 1)
if iszero(lt(subject, subjectSearchEnd)) { break }
continue
}
}
mstore(result, sub(subject, subjectStart))
result := add(result, 0x20)
subject := add(subject, searchLength)
if searchLength {
if iszero(lt(subject, subjectSearchEnd)) { break }
continue
}
}
subject := add(subject, 1)
if iszero(lt(subject, subjectSearchEnd)) { break }
}
let resultEnd := result
result := mload(0x40)
mstore(result, shr(5, sub(resultEnd, add(result, 0x20))))
mstore(0x40, add(resultEnd, 0x20))
}
}
}
function split(string memory subject, string memory delimiter)
internal
pure
returns (string[] memory result)
{
uint256[] memory indices = indicesOf(subject, delimiter);
assembly {
let w := not(0x1f)
let indexPtr := add(indices, 0x20)
let indicesEnd := add(indexPtr, shl(5, add(mload(indices), 1)))
mstore(add(indicesEnd, w), mload(subject))
mstore(indices, add(mload(indices), 1))
let prevIndex := 0
for {} 1 {} {
let index := mload(indexPtr)
mstore(indexPtr, 0x60)
if iszero(eq(index, prevIndex)) {
let element := mload(0x40)
let elementLength := sub(index, prevIndex)
mstore(element, elementLength)
for { let o := and(add(elementLength, 0x1f), w) } 1 {} {
mstore(add(element, o), mload(add(add(subject, prevIndex), o)))
o := add(o, w)
if iszero(o) { break }
}
mstore(add(add(element, 0x20), elementLength), 0)
mstore(0x40, add(element, and(add(elementLength, 0x3f), w)))
mstore(indexPtr, element)
}
prevIndex := add(index, mload(delimiter))
indexPtr := add(indexPtr, 0x20)
if iszero(lt(indexPtr, indicesEnd)) { break }
}
result := indices
if iszero(mload(delimiter)) {
result := add(indices, 0x20)
mstore(result, sub(mload(indices), 2))
}
}
}
function concat(string memory a, string memory b)
internal
pure
returns (string memory result)
{
assembly {
let w := not(0x1f)
result := mload(0x40)
let aLength := mload(a)
for { let o := and(add(mload(a), 0x20), w) } 1 {} {
mstore(add(result, o), mload(add(a, o)))
o := add(o, w)
if iszero(o) { break }
}
let bLength := mload(b)
let output := add(result, mload(a))
for { let o := and(add(bLength, 0x20), w) } 1 {} {
mstore(add(output, o), mload(add(b, o)))
o := add(o, w)
if iszero(o) { break }
}
let totalLength := add(aLength, bLength)
let last := add(add(result, 0x20), totalLength)
mstore(last, 0)
mstore(result, totalLength)
mstore(0x40, and(add(last, 0x1f), w))
}
}
function toCase(string memory subject, bool toUpper)
internal
pure
returns (string memory result)
{
assembly {
let length := mload(subject)
if length {
result := add(mload(0x40), 0x20)
subject := add(subject, 1)
let flags := shl(add(70, shl(5, toUpper)), 0x3ffffff)
let w := not(0)
for { let o := length } 1 {} {
o := add(o, w)
let b := and(0xff, mload(add(subject, o)))
mstore8(add(result, o), xor(b, and(shr(b, flags), 0x20)))
if iszero(o) { break }
}
result := mload(0x40)
mstore(result, length)
let last := add(add(result, 0x20), length)
mstore(last, 0)
mstore(0x40, add(last, 0x20))
}
}
}
function lower(string memory subject) internal pure returns (string memory result) {
result = toCase(subject, false);
}
function upper(string memory subject) internal pure returns (string memory result) {
result = toCase(subject, true);
}
function escapeHTML(string memory s) internal pure returns (string memory result) {
assembly {
for {
let end := add(s, mload(s))
result := add(mload(0x40), 0x20)
mstore(0x1f, 0x900094)
mstore(0x08, 0xc0000000a6ab)
mstore(0x00, shl(64, 0x2671756f743b26616d703b262333393b266c743b2667743b))
} iszero(eq(s, end)) {} {
s := add(s, 1)
let c := and(mload(s), 0xff)
if iszero(and(shl(c, 1), 0x500000c400000000)) {
mstore8(result, c)
result := add(result, 1)
continue
}
let t := shr(248, mload(c))
mstore(result, mload(and(t, 0x1f)))
result := add(result, shr(5, t))
}
let last := result
mstore(last, 0)
result := mload(0x40)
mstore(result, sub(last, add(result, 0x20)))
mstore(0x40, add(last, 0x20))
}
}
function escapeJSON(string memory s) internal pure returns (string memory result) {
assembly {
for {
let end := add(s, mload(s))
result := add(mload(0x40), 0x20)
mstore(0x15, 0x5c75303030303031323334353637383961626364656662746e006672)
let e := or(shl(0x22, 1), shl(0x5c, 1))
} iszero(eq(s, end)) {} {
s := add(s, 1)
let c := and(mload(s), 0xff)
if iszero(lt(c, 0x20)) {
if iszero(and(shl(c, 1), e)) {
mstore8(result, c)
result := add(result, 1)
continue
}
mstore8(result, 0x5c)
mstore8(add(result, 1), c)
result := add(result, 2)
continue
}
if iszero(and(shl(c, 1), 0x3700)) {
mstore8(0x1d, mload(shr(4, c)))
mstore8(0x1e, mload(and(c, 15)))
mstore(result, mload(0x19))
result := add(result, 6)
continue
}
mstore8(result, 0x5c)
mstore8(add(result, 1), mload(add(c, 8)))
result := add(result, 2)
}
let last := result
mstore(last, 0)
result := mload(0x40)
mstore(result, sub(last, add(result, 0x20)))
mstore(0x40, add(last, 0x20))
}
}
function eq(string memory a, string memory b) internal pure returns (bool result) {
assembly {
result := eq(keccak256(add(a, 0x20), mload(a)), keccak256(add(b, 0x20), mload(b)))
}
}
function packOne(string memory a) internal pure returns (bytes32 result) {
assembly {
result :=
mul(
mload(add(a, 0x1f)),
lt(sub(mload(a), 1), 0x1f)
)
}
}
function unpackOne(bytes32 packed) internal pure returns (string memory result) {
assembly {
result := mload(0x40)
mstore(0x40, add(result, 0x40))
mstore(result, 0)
mstore(add(result, 0x1f), packed)
mstore(add(add(result, 0x20), mload(result)), 0)
}
}
function packTwo(string memory a, string memory b) internal pure returns (bytes32 result) {
assembly {
let aLength := mload(a)
result :=
mul(
or(
shl(shl(3, sub(0x1f, aLength)), mload(add(a, aLength))),
mload(sub(add(b, 0x1e), aLength))
),
lt(sub(add(aLength, mload(b)), 1), 0x1e)
)
}
}
function unpackTwo(bytes32 packed)
internal
pure
returns (string memory resultA, string memory resultB)
{
assembly {
resultA := mload(0x40)
resultB := add(resultA, 0x40)
mstore(0x40, add(resultB, 0x40))
mstore(resultA, 0)
mstore(resultB, 0)
mstore(add(resultA, 0x1f), packed)
mstore(add(resultB, 0x1f), mload(add(add(resultA, 0x20), mload(resultA))))
mstore(add(add(resultA, 0x20), mload(resultA)), 0)
mstore(add(add(resultB, 0x20), mload(resultB)), 0)
}
}
function directReturn(string memory a) internal pure {
assembly {
let retStart := sub(a, 0x20)
let retSize := add(mload(a), 0x40)
mstore(add(retStart, retSize), 0)
mstore(retStart, 0x20)
return(retStart, retSize)
}
}
}
文件 17 的 19:Particle.sol
pragma solidity 0.8.20;
import {Base64} from "../lib/solady/src/utils/Base64.sol";
import {LibString} from "../lib/solady/src/utils/LibString.sol";
library Particle {
using LibString for uint8;
using LibString for uint160;
using LibString for uint256;
function _upper() internal pure returns (string memory) {
return
string(
abi.encodePacked(
'<svg height="250" width="250" xmlns="http://www.w3.org/2000/svg">',
"<defs>",
'<radialGradient id="myGradient">'
)
);
}
function _orbital(
bytes32 seed,
uint8 num
) internal pure returns (string memory) {
string memory first = string(
abi.encodePacked(
'<stop offset="',
(5 + num * 20).toString(),
'%" stop-color="rgb(',
uint8(seed[0 + (num * 6)]).toString(),
",",
uint8(seed[1 + (num * 6)]).toString(),
",",
uint8(seed[2 + (num * 6)]).toString(),
')" />'
)
);
string memory second = string(
abi.encodePacked(
'<stop offset="',
(15 + num * 20).toString(),
'%" stop-color="rgb(',
uint8(seed[3 + (num * 6)]).toString(),
",",
uint8(seed[4 + (num * 6)]).toString(),
",",
uint8(seed[5 + (num * 6)]).toString(),
')" />'
)
);
return string(abi.encodePacked(first, second));
}
function _lower() internal pure returns (string memory) {
return
string(
abi.encodePacked(
"</radialGradient>",
"</defs>",
'<rect height="250" width="250" fill="#000"></rect>'
)
);
}
function _elements(bytes32 seed) internal pure returns (string memory) {
string[16] memory elements = [
"⧈",
"☉",
"⊕",
"🝊",
"✧",
"◈",
"❖",
"⨳",
"✸",
"❉",
"🜋",
"⚛",
"⁂",
"☊",
"♾",
"ↂ"
];
string memory a = elements[uint8(seed[31]) & 15];
string memory b = elements[(uint8(seed[31]) & 240) / 16];
string memory c = elements[uint8(seed[30]) & 15];
string memory d = elements[(uint8(seed[30]) & 240) / 16];
return
string(
abi.encodePacked(
'<text fill="#ffffff" font-size="30" font-family="Verdana" x="32" y="42" text-anchor="middle">',
a,
"</text>",
'<text fill="#ffffff" font-size="30" font-family="Verdana" x="218" y="42" text-anchor="middle">',
b,
"</text>",
'<text fill="#ffffff" font-size="30" font-family="Verdana" x="32" y="228" text-anchor="middle">',
c,
"</text>",
'<text fill="#ffffff" font-size="30" font-family="Verdana" x="218" y="228" text-anchor="middle">',
d,
"</text>"
)
);
}
function _power() internal pure returns (string memory) {
return
string(
abi.encodePacked(
'<circle cx="125" cy="125" r="100" fill="url(\'#myGradient\')" />',
"</svg>"
)
);
}
function _particle(bytes32 seed) internal pure returns (string memory) {
return
string(
abi.encodePacked(
_upper(),
_orbital(seed, 0),
_orbital(seed, 1),
_orbital(seed, 2),
_orbital(seed, 3),
_orbital(seed, 4),
_lower(),
_elements(seed),
_power()
)
);
}
function _image(bytes32 seed) internal pure returns (string memory) {
string memory image = _particle(seed);
return
string(
abi.encodePacked(
"data:image/svg+xml;base64,",
Base64.encode(bytes(image))
)
);
}
}
文件 18 的 19:Program.sol
pragma solidity 0.8.20;
import {Particle} from "./Particle.sol";
import {Base64} from "../lib/solady/src/utils/Base64.sol";
import {LibString} from "../lib/solady/src/utils/LibString.sol";
import {IFileStore} from "../lib/ethfs/packages/contracts/src/IFileStore.sol";
struct Params {
uint256 id;
uint256 seed;
uint256 pres;
string ar;
address wal;
uint8 inv;
uint8 lvl;
uint8 asc;
}
contract Program {
using LibString for uint256;
using LibString for uint160;
using LibString for uint8;
IFileStore fileStore;
string desc =
'"description":"In a far away parallel universe an advanced civilization built a computer around a star and escaped into a simulated reality. After some immeasurable amount of time these facts were forgotten and after another immeasurable amount of time that star began to die. Even so, life Inside this simulation progressed, and on one planet some of that life progressed enough to form a government. You are the new member of a mysterious project under a secret agency of this government researching the elementary particles that make up your universe.",';
constructor() {
fileStore = IFileStore(0x9746fD0A77829E12F8A9DBe70D7a322412325B91);
}
function _parameters(
Params memory _params
) internal view returns (string memory) {
return
string.concat(
'<script src="data:text/javascript;base64,',
Base64.encode(
abi.encodePacked(
string.concat(
"let seed = ",
(_params.seed % 9007199254740991).toString(),
"; let tim = ",
block.timestamp.toString(),
"; let ar = ",
_params.ar,
"; let wal = ",
(uint160(_params.wal) % 9007199254740991)
.toString(),
"; let inv = ",
_params.inv.toString(),
"; let lvl = ",
_params.lvl.toString(),
"; let asc = ",
_params.asc.toString(),
";"
)
)
)
);
}
function _scripts(
Params memory _params
) internal view returns (string memory) {
return
string.concat(
'<script type="text/javascript+gzip" src="data:text/javascript;base64,',
fileStore.getFile("p5-v1.5.0.min.js.gz").read(),
'"></script>',
'<script src="data:text/javascript;base64,',
fileStore.getFile("gunzipScripts-0.0.1.js").read(),
'"></script>',
_parameters(_params),
'"></script><script src="data:text/javascript;base64,',
fileStore.getFile(":)").read(),
'"></script>'
);
}
function _page(
Params memory _params
) internal view returns (string memory) {
return
string.concat(
'"animation_url":"data:text/html;base64,',
Base64.encode(
abi.encodePacked(
string.concat(
'<!DOCTYPE html><html style="height: 100%;"><head>',
_scripts(_params),
'</head><body style="margin: 0;display: flex;justify-content: center;align-items: center;height: 100%;"></body></html>'
)
)
),
'",'
);
}
function _attributes(
Params memory _params
) internal pure returns (string memory) {
string memory atr = string.concat(
'"attributes": [{"trait_type": "Decay", "value": ',
_params.lvl.toString(),
"}, ",
'{"display_type": "number","trait_type": "Prestige", "value": ',
_params.pres.toString(),
"}, "
);
atr = _params.inv > 0
? string.concat(atr, '{"trait_type": "Spin", "value": "Up"},')
: string.concat(atr, '{"trait_type": "Spin", "value": "Down"},');
atr = bytes(_params.ar).length > 1
? string.concat(atr, '{"trait_type": "Prism", "value": "Advanced"}')
: string.concat(
atr,
'{"trait_type": "Prism", "value": "Original"}'
);
if (_params.asc > 0) {
atr = string.concat(
atr,
', {"trait_type": "[REDACTED]", "value": "[REDACTED]"}'
);
}
if (_params.id < 1000 && _params.id % 111 == 0) {
atr = string.concat(
atr,
', {"trait_type": "Angel", "value": "',
_params.id.toString(),
'"}'
);
}
if (_params.id % 1111 == 0) {
atr = string.concat(
atr,
', {"trait_type": "Hyper Angel", "value": "',
_params.id.toString(),
'"}'
);
}
return string.concat(atr, "]}");
}
function uri(Params memory _params) external view returns (string memory) {
return
string.concat(
"data:application/json;base64,",
Base64.encode(
abi.encodePacked(
string.concat(
'{"name":">>> ',
_params.id.toString(),
' <<<",',
desc,
'"image":"',
Particle._image(bytes32(_params.seed)),
'",',
_page(_params),
_attributes(_params)
)
)
)
);
}
}
文件 19 的 19:Research.sol
pragma solidity 0.8.20;
import {ERC1155} from "../lib/solmate/src/tokens/ERC1155.sol";
import {Collision} from "./Collision.sol";
contract Research is ERC1155 {
address immutable angel;
Collision public collision;
string public name = "Angel Matter Research";
string public symbol = "AMR";
constructor() {
angel = msg.sender;
collision = new Collision();
}
function mint(address to, uint256 id) external {
require(msg.sender == angel);
_mint(to, id, 1, "");
}
function uri(uint256 id) public view override returns (string memory) {
return collision.uri(id);
}
}
{
"compilationTarget": {
"src/AngelMatter.sol": "AngelMatter"
},
"evmVersion": "paris",
"libraries": {},
"metadata": {
"bytecodeHash": "none"
},
"optimizer": {
"enabled": true,
"runs": 1000000
},
"remappings": [
":ds-test/=lib/solady/lib/ds-test/src/",
":ethfs/=lib/ethfs/",
":ethier/=lib/ethfs/packages/contracts/lib/ethier/",
":forge-std/=lib/forge-std/src/",
":openzeppelin-contracts/=lib/openzeppelin-contracts/",
":openzeppelin/=lib/openzeppelin-contracts/contracts/",
":solady/=lib/solady/src/",
":solmate/=lib/solmate/src/"
]
}
[{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"uint256","name":"_startTime","type":"uint256"}],"stateMutability":"nonpayable","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":"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":"anti","outputs":[{"internalType":"contract Antigraviton","name":"","type":"address"}],"stateMutability":"view","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":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"claimAnti","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"claimed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"string","name":"signal","type":"string"}],"name":"collide","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"currentId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"invert","outputs":[],"stateMutability":"nonpayable","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":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"level","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256[][]","name":"arr","type":"uint256[][]"}],"name":"observe","outputs":[],"stateMutability":"nonpayable","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":"uint256","name":"","type":"uint256"}],"name":"prestige","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"prism","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"program","outputs":[{"internalType":"contract Program","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"redacted","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"research","outputs":[{"internalType":"contract Research","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"salePrice","type":"uint256"}],"name":"royaltyInfo","outputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"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":"uint256","name":"","type":"uint256"}],"name":"seed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"spin","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"startTime","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":"id","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","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":"uint256","name":"id","type":"uint256"}],"name":"virtualAnti","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"xe","outputs":[],"stateMutability":"nonpayable","type":"function"}]