编译器
0.8.22+commit.4fc1097e
文件 1 的 7:Context.sol
pragma solidity ^0.8.20;
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
}
文件 2 的 7:CypherdudesFileStore.sol
pragma solidity ^0.8.20;
import {SSTORE2} from "./solady/utils/SSTORE2.sol";
import {ICypherdudesFileStore} from "./ICypherdudesFileStore.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {File, Content} from "./File.sol";
import {IContentStore} from "./IContentStore.sol";
interface ICypherDudes {
struct TokenData {
string cypherCard;
}
function tokenData(
uint256 tokenId
) external view returns( string memory);
}
contract CypherdudesFileStore is ICypherdudesFileStore, Ownable {
IContentStore public immutable contentStore;
ICypherDudes public cypherDudesContract;
address cypherDudesContractAddy;
mapping(string => bytes32) public files;
constructor(IContentStore _contentStore) Ownable(msg.sender){
contentStore = _contentStore;
}
function setCypherCardContract(address _cypherCardContract) public onlyOwner{
cypherDudesContract = ICypherDudes(_cypherCardContract);
cypherDudesContractAddy = _cypherCardContract;
}
function fileExists(string memory filename) public view returns (bool) {
return files[filename] != bytes32(0);
}
function getChecksum(string memory filename)
public
view
returns (bytes32 checksum)
{
checksum = files[filename];
if (checksum == bytes32(0)) {
revert FileNotFound(filename);
}
return checksum;
}
function getFile(string memory filename)
public
view
returns (File memory file)
{
bytes32 checksum = files[filename];
if (checksum == bytes32(0)) {
revert FileNotFound(filename);
}
address pointer = contentStore.pointers(checksum);
if (pointer == address(0)) {
revert FileNotFound(filename);
}
return abi.decode(SSTORE2.read(pointer), (File));
}
function readFile(string memory filename) public view returns (string memory content){
return getFile(filename).read();
}
function storeFile(string memory filename, bytes memory content) public returns(File memory file) {
(bytes32 checksum,) = contentStore.addContent(content);
bytes32[] memory checksums = new bytes32[](1);
checksums[0] = checksum;
return createFile(filename, checksums);
}
function createFile(string memory filename, bytes32[] memory checksums)
public
returns (File memory file)
{
return createFile(filename, checksums, new bytes(0));
}
function createFile(
string memory filename,
bytes32[] memory checksums,
bytes memory extraData
) public returns (File memory file) {
if (files[filename] != bytes32(0)) {
revert FilenameExists(filename);
}
return _createFile(filename, checksums, extraData);
}
function _createFile(
string memory filename,
bytes32[] memory checksums,
bytes memory extraData
) private returns (File memory file) {
Content[] memory contents = new Content[](checksums.length);
uint256 size = 0;
for (uint256 i = 0; i < checksums.length; ++i) {
size += contentStore.contentLength(checksums[i]);
contents[i] = Content({
checksum: checksums[i],
pointer: contentStore.getPointer(checksums[i])
});
}
if (size == 0) {
revert EmptyFile();
}
file = File({size: size, contents: contents});
(bytes32 checksum,) = contentStore.addContent(abi.encode(file));
files[filename] = checksum;
emit FileCreated(filename, checksum, filename, file.size, extraData);
}
function deleteFile(string memory filename) public onlyOwner {
bytes32 checksum = files[filename];
if (checksum == bytes32(0)) {
revert FileNotFound(filename);
}
delete files[filename];
emit FileDeleted(filename, checksum, filename);
}
function deleteCard(string memory filename) public {
if (msg.sender == cypherDudesContractAddy){
bytes32 checksum = files[filename];
if (checksum == bytes32(0)) {
revert FileNotFound(filename);
}
delete files[filename];
emit FileDeleted(filename, checksum, filename);
} else{
revert NottheOwner(filename, msg.sender);
}
}
function getScript(string memory filename) public view returns (bytes memory script){
bytes32 checksum = files[filename];
if (checksum == bytes32(0)) {
revert FileNotFound(filename);
}
address pointer = contentStore.pointers(checksum);
if (pointer == address(0)) {
revert FileNotFound(filename);
}
return SSTORE2.read(pointer);
}
}
文件 3 的 7:File.sol
pragma solidity ^0.8.20;
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;
文件 4 的 7:IContentStore.sol
pragma solidity ^0.8.20;
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);
}
文件 5 的 7:ICypherdudesFileStore.sol
pragma solidity ^0.8.20;
import {File} from "./File.sol";
import {IContentStore} from "./IContentStore.sol";
interface ICypherdudesFileStore {
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 NottheOwner(string filename, address wrongAddress);
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;
function deleteCard(string memory filename) external;
function getScript(string memory filename) external view returns (bytes memory script);
}
文件 6 的 7:Ownable.sol
pragma solidity ^0.8.20;
import {Context} from "../utils/Context.sol";
abstract contract Ownable is Context {
address private _owner;
error OwnableUnauthorizedAccount(address account);
error OwnableInvalidOwner(address owner);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor(address initialOwner) {
if (initialOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(initialOwner);
}
modifier onlyOwner() {
_checkOwner();
_;
}
function owner() public view virtual returns (address) {
return _owner;
}
function _checkOwner() internal view virtual {
if (owner() != _msgSender()) {
revert OwnableUnauthorizedAccount(_msgSender());
}
}
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
function transferOwnership(address newOwner) public virtual onlyOwner {
if (newOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(newOwner);
}
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
文件 7 的 7:SSTORE2.sol
pragma solidity ^0.8.4;
library SSTORE2 {
error DeploymentFailed();
error InvalidPointer();
error ReadOutOfBounds();
function write(bytes memory data) internal returns (address pointer) {
assembly {
let originalDataLength := mload(data)
let dataSize := add(originalDataLength, 1)
mstore(
data,
or(
0x61000080600a3d393df300,
shl(0x40, dataSize)
)
)
pointer := create(0, add(data, 0x15), add(dataSize, 0xa))
if iszero(pointer) {
mstore(0x00, 0x30116425)
revert(0x1c, 0x04)
}
mstore(data, originalDataLength)
}
}
function read(address pointer) internal view returns (bytes memory data) {
assembly {
let pointerCodesize := extcodesize(pointer)
if iszero(pointerCodesize) {
mstore(0x00, 0x11052bb4)
revert(0x1c, 0x04)
}
let size := sub(pointerCodesize, 1)
data := mload(0x40)
mstore(0x40, add(data, and(add(size, 0x3f), 0xffe0)))
mstore(data, size)
extcodecopy(pointer, add(data, 0x20), 1, size)
}
}
function read(address pointer, uint256 start) internal view returns (bytes memory data) {
assembly {
let pointerCodesize := extcodesize(pointer)
if iszero(pointerCodesize) {
mstore(0x00, 0x11052bb4)
revert(0x1c, 0x04)
}
if iszero(gt(pointerCodesize, start)) {
mstore(0x00, 0x84eb0dd1)
revert(0x1c, 0x04)
}
let size := sub(pointerCodesize, add(start, 1))
data := mload(0x40)
mstore(0x40, add(data, and(add(size, 0x3f), 0xffe0)))
mstore(data, size)
extcodecopy(pointer, add(data, 0x20), add(start, 1), size)
}
}
function read(
address pointer,
uint256 start,
uint256 end
) internal view returns (bytes memory data) {
assembly {
let pointerCodesize := extcodesize(pointer)
if iszero(pointerCodesize) {
mstore(0x00, 0x11052bb4)
revert(0x1c, 0x04)
}
if iszero(
and(
gt(pointerCodesize, end),
iszero(gt(start, end))
)
) {
mstore(0x00, 0x84eb0dd1)
revert(0x1c, 0x04)
}
let size := sub(end, start)
data := mload(0x40)
mstore(0x40, add(data, and(add(size, 0x3f), 0xffe0)))
mstore(data, size)
extcodecopy(pointer, add(data, 0x20), add(start, 1), size)
}
}
}
{
"compilationTarget": {
"contracts/ethfs/CypherdudesFileStore.sol": "CypherdudesFileStore"
},
"evmVersion": "paris",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": false,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"contract IContentStore","name":"_contentStore","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"EmptyFile","type":"error"},{"inputs":[{"internalType":"string","name":"filename","type":"string"}],"name":"FileNotFound","type":"error"},{"inputs":[{"internalType":"string","name":"filename","type":"string"}],"name":"FilenameExists","type":"error"},{"inputs":[{"internalType":"string","name":"filename","type":"string"},{"internalType":"address","name":"wrongAddress","type":"address"}],"name":"NottheOwner","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"string","name":"indexedFilename","type":"string"},{"indexed":true,"internalType":"bytes32","name":"checksum","type":"bytes32"},{"indexed":false,"internalType":"string","name":"filename","type":"string"},{"indexed":false,"internalType":"uint256","name":"size","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"metadata","type":"bytes"}],"name":"FileCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"string","name":"indexedFilename","type":"string"},{"indexed":true,"internalType":"bytes32","name":"checksum","type":"bytes32"},{"indexed":false,"internalType":"string","name":"filename","type":"string"}],"name":"FileDeleted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[],"name":"contentStore","outputs":[{"internalType":"contract IContentStore","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"filename","type":"string"},{"internalType":"bytes32[]","name":"checksums","type":"bytes32[]"}],"name":"createFile","outputs":[{"components":[{"internalType":"uint256","name":"size","type":"uint256"},{"components":[{"internalType":"bytes32","name":"checksum","type":"bytes32"},{"internalType":"address","name":"pointer","type":"address"}],"internalType":"struct Content[]","name":"contents","type":"tuple[]"}],"internalType":"struct File","name":"file","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"filename","type":"string"},{"internalType":"bytes32[]","name":"checksums","type":"bytes32[]"},{"internalType":"bytes","name":"extraData","type":"bytes"}],"name":"createFile","outputs":[{"components":[{"internalType":"uint256","name":"size","type":"uint256"},{"components":[{"internalType":"bytes32","name":"checksum","type":"bytes32"},{"internalType":"address","name":"pointer","type":"address"}],"internalType":"struct Content[]","name":"contents","type":"tuple[]"}],"internalType":"struct File","name":"file","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"cypherDudesContract","outputs":[{"internalType":"contract ICypherDudes","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"filename","type":"string"}],"name":"deleteCard","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"filename","type":"string"}],"name":"deleteFile","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"filename","type":"string"}],"name":"fileExists","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"","type":"string"}],"name":"files","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"filename","type":"string"}],"name":"getChecksum","outputs":[{"internalType":"bytes32","name":"checksum","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"filename","type":"string"}],"name":"getFile","outputs":[{"components":[{"internalType":"uint256","name":"size","type":"uint256"},{"components":[{"internalType":"bytes32","name":"checksum","type":"bytes32"},{"internalType":"address","name":"pointer","type":"address"}],"internalType":"struct Content[]","name":"contents","type":"tuple[]"}],"internalType":"struct File","name":"file","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"filename","type":"string"}],"name":"getScript","outputs":[{"internalType":"bytes","name":"script","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"filename","type":"string"}],"name":"readFile","outputs":[{"internalType":"string","name":"content","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_cypherCardContract","type":"address"}],"name":"setCypherCardContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"filename","type":"string"},{"internalType":"bytes","name":"content","type":"bytes"}],"name":"storeFile","outputs":[{"components":[{"internalType":"uint256","name":"size","type":"uint256"},{"components":[{"internalType":"bytes32","name":"checksum","type":"bytes32"},{"internalType":"address","name":"pointer","type":"address"}],"internalType":"struct Content[]","name":"contents","type":"tuple[]"}],"internalType":"struct File","name":"file","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]