编译器
0.8.19+commit.7dd6d404
文件 1 的 32:Base64.sol
pragma solidity ^0.8.0;
library Base64 {
string internal constant _TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
function encode(bytes memory data) internal pure returns (string memory) {
if (data.length == 0) return "";
string memory table = _TABLE;
string memory result = new string(4 * ((data.length + 2) / 3));
assembly {
let tablePtr := add(table, 1)
let resultPtr := add(result, 32)
for {
let dataPtr := data
let endPtr := add(data, mload(data))
} lt(dataPtr, endPtr) {
} {
dataPtr := add(dataPtr, 3)
let input := mload(dataPtr)
mstore8(resultPtr, mload(add(tablePtr, and(shr(18, input), 0x3F))))
resultPtr := add(resultPtr, 1)
mstore8(resultPtr, mload(add(tablePtr, and(shr(12, input), 0x3F))))
resultPtr := add(resultPtr, 1)
mstore8(resultPtr, mload(add(tablePtr, and(shr(6, input), 0x3F))))
resultPtr := add(resultPtr, 1)
mstore8(resultPtr, mload(add(tablePtr, and(input, 0x3F))))
resultPtr := add(resultPtr, 1)
}
switch mod(mload(data), 3)
case 1 {
mstore8(sub(resultPtr, 1), 0x3d)
mstore8(sub(resultPtr, 2), 0x3d)
}
case 2 {
mstore8(sub(resultPtr, 1), 0x3d)
}
}
return result;
}
}
文件 2 的 32:Clones.sol
pragma solidity ^0.8.0;
library Clones {
function clone(address implementation) internal returns (address instance) {
assembly {
mstore(0x00, or(shr(0xe8, shl(0x60, implementation)), 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000))
mstore(0x20, or(shl(0x78, implementation), 0x5af43d82803e903d91602b57fd5bf3))
instance := create(0, 0x09, 0x37)
}
require(instance != address(0), "ERC1167: create failed");
}
function cloneDeterministic(address implementation, bytes32 salt) internal returns (address instance) {
assembly {
mstore(0x00, or(shr(0xe8, shl(0x60, implementation)), 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000))
mstore(0x20, or(shl(0x78, implementation), 0x5af43d82803e903d91602b57fd5bf3))
instance := create2(0, 0x09, 0x37, salt)
}
require(instance != address(0), "ERC1167: create2 failed");
}
function predictDeterministicAddress(
address implementation,
bytes32 salt,
address deployer
) internal pure returns (address predicted) {
assembly {
let ptr := mload(0x40)
mstore(add(ptr, 0x38), deployer)
mstore(add(ptr, 0x24), 0x5af43d82803e903d91602b57fd5bf3ff)
mstore(add(ptr, 0x14), implementation)
mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73)
mstore(add(ptr, 0x58), salt)
mstore(add(ptr, 0x78), keccak256(add(ptr, 0x0c), 0x37))
predicted := keccak256(add(ptr, 0x43), 0x55)
}
}
function predictDeterministicAddress(
address implementation,
bytes32 salt
) internal view returns (address predicted) {
return predictDeterministicAddress(implementation, salt, address(this));
}
}
文件 3 的 32:ECDSA.sol
pragma solidity ^0.8.0;
import "../Strings.sol";
library ECDSA {
enum RecoverError {
NoError,
InvalidSignature,
InvalidSignatureLength,
InvalidSignatureS,
InvalidSignatureV
}
function _throwError(RecoverError error) private pure {
if (error == RecoverError.NoError) {
return;
} else if (error == RecoverError.InvalidSignature) {
revert("ECDSA: invalid signature");
} else if (error == RecoverError.InvalidSignatureLength) {
revert("ECDSA: invalid signature length");
} else if (error == RecoverError.InvalidSignatureS) {
revert("ECDSA: invalid signature 's' value");
}
}
function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {
if (signature.length == 65) {
bytes32 r;
bytes32 s;
uint8 v;
assembly {
r := mload(add(signature, 0x20))
s := mload(add(signature, 0x40))
v := byte(0, mload(add(signature, 0x60)))
}
return tryRecover(hash, v, r, s);
} else {
return (address(0), RecoverError.InvalidSignatureLength);
}
}
function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, signature);
_throwError(error);
return recovered;
}
function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {
bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
uint8 v = uint8((uint256(vs) >> 255) + 27);
return tryRecover(hash, v, r, s);
}
function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, r, vs);
_throwError(error);
return recovered;
}
function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {
if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
return (address(0), RecoverError.InvalidSignatureS);
}
address signer = ecrecover(hash, v, r, s);
if (signer == address(0)) {
return (address(0), RecoverError.InvalidSignature);
}
return (signer, RecoverError.NoError);
}
function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, v, r, s);
_throwError(error);
return recovered;
}
function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 message) {
assembly {
mstore(0x00, "\x19Ethereum Signed Message:\n32")
mstore(0x1c, hash)
message := keccak256(0x00, 0x3c)
}
}
function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s));
}
function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 data) {
assembly {
let ptr := mload(0x40)
mstore(ptr, "\x19\x01")
mstore(add(ptr, 0x02), domainSeparator)
mstore(add(ptr, 0x22), structHash)
data := keccak256(ptr, 0x42)
}
}
function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19\x00", validator, data));
}
}
文件 4 的 32:EIP712.sol
pragma solidity ^0.8.8;
import "./ECDSA.sol";
import "../ShortStrings.sol";
import "../../interfaces/IERC5267.sol";
abstract contract EIP712 is IERC5267 {
using ShortStrings for *;
bytes32 private constant _TYPE_HASH =
keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)");
bytes32 private immutable _cachedDomainSeparator;
uint256 private immutable _cachedChainId;
address private immutable _cachedThis;
bytes32 private immutable _hashedName;
bytes32 private immutable _hashedVersion;
ShortString private immutable _name;
ShortString private immutable _version;
string private _nameFallback;
string private _versionFallback;
constructor(string memory name, string memory version) {
_name = name.toShortStringWithFallback(_nameFallback);
_version = version.toShortStringWithFallback(_versionFallback);
_hashedName = keccak256(bytes(name));
_hashedVersion = keccak256(bytes(version));
_cachedChainId = block.chainid;
_cachedDomainSeparator = _buildDomainSeparator();
_cachedThis = address(this);
}
function _domainSeparatorV4() internal view returns (bytes32) {
if (address(this) == _cachedThis && block.chainid == _cachedChainId) {
return _cachedDomainSeparator;
} else {
return _buildDomainSeparator();
}
}
function _buildDomainSeparator() private view returns (bytes32) {
return keccak256(abi.encode(_TYPE_HASH, _hashedName, _hashedVersion, block.chainid, address(this)));
}
function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {
return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);
}
function eip712Domain()
public
view
virtual
override
returns (
bytes1 fields,
string memory name,
string memory version,
uint256 chainId,
address verifyingContract,
bytes32 salt,
uint256[] memory extensions
)
{
return (
hex"0f",
_name.toStringWithFallback(_nameFallback),
_version.toStringWithFallback(_versionFallback),
block.chainid,
address(this),
bytes32(0),
new uint256[](0)
);
}
}
文件 5 的 32:ERC165.sol
pragma solidity ^0.8.0;
interface IERC165 {
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
abstract contract ERC165 is IERC165 {
function supportsInterface(bytes4 interfaceId)
public
view
virtual
override
returns (bool)
{
return interfaceId == type(IERC165).interfaceId;
}
}
文件 6 的 32:ERC7015.sol
pragma solidity ^0.8.0;
import "openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol";
import "openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol";
import "openzeppelin-contracts/contracts/interfaces/IERC1271.sol";
import "solady/utils/LibString.sol";
abstract contract ERC7015 is EIP712 {
error InvalidCreatorAttributionSignature();
error NameAndVersionTooLong();
error InvalidCreator();
event CreatorAttribution(
bytes32 structHash,
string domainName,
string version,
address creator,
bytes signature
);
bytes4 internal constant MAGIC_VALUE =
bytes4(keccak256("isValidSignature(bytes32,bytes)"));
bytes32 public constant TYPEHASH =
keccak256("TokenCreation(bytes32 structHash)");
bytes32 public immutable packedDomainNameAndVersion;
constructor(
string memory name,
string memory version
) EIP712(name, version) {
packedDomainNameAndVersion = LibString.packTwo(name, version);
if (packedDomainNameAndVersion == bytes32(0))
revert NameAndVersionTooLong();
}
function _validateSignature(
address creator,
bytes32 structHash,
bytes calldata signature
) internal {
if (!_isValid(structHash, creator, signature))
revert InvalidCreatorAttributionSignature();
(string memory _domainName, string memory _domainVersion) = LibString
.unpackTwo(packedDomainNameAndVersion);
emit CreatorAttribution(
structHash,
_domainName,
_domainVersion,
creator,
signature
);
}
function _isValid(
bytes32 structHash,
address signer,
bytes calldata signature
) internal view returns (bool) {
if (signer == address(0)) revert InvalidCreator();
bytes32 digest = _hashTypedDataV4(
keccak256(abi.encode(TYPEHASH, structHash))
);
if (signer.code.length != 0) {
try IERC1271(signer).isValidSignature(digest, signature) returns (
bytes4 magicValue
) {
return MAGIC_VALUE == magicValue;
} catch {
return false;
}
}
address recoveredSigner = ECDSA.recover(digest, signature);
return recoveredSigner == signer;
}
}
文件 7 的 32:ERC721.sol
pragma solidity ^0.8.0;
import "./interface/IERC721.sol";
import "../ERC165/ERC165.sol";
contract ERC721 is ERC165, IERC721, IERC721Events {
mapping(uint256 => address) internal _owners;
mapping(address => uint256) internal _balances;
mapping(uint256 => address) private _tokenApprovals;
mapping(address => mapping(address => bool)) private _operatorApprovals;
function supportsInterface(bytes4 interfaceId)
public
view
virtual
override
returns (bool)
{
return
interfaceId == type(IERC721).interfaceId ||
interfaceId == type(IERC721Metadata).interfaceId ||
super.supportsInterface(interfaceId);
}
function balanceOf(address owner)
external
view
virtual
override
returns (uint256)
{
require(
owner != address(0),
"ERC721: balance query for the zero address"
);
return _balances[owner];
}
function ownerOf(uint256 tokenId) external view virtual returns (address) {
return _ownerOf(tokenId);
}
function _ownerOf(uint256 tokenId) internal view returns (address) {
address owner = _owners[tokenId];
require(
owner != address(0),
"ERC721: owner query for nonexistent token"
);
return owner;
}
function approve(address to, uint256 tokenId) external virtual override {
address owner = _ownerOf(tokenId);
require(to != owner, "ERC721: approval to current owner");
require(
msg.sender == owner || isApprovedForAll(owner, msg.sender),
"ERC721: approve caller is not owner nor approved for all"
);
_approve(to, tokenId);
}
function getApproved(uint256 tokenId)
public
view
virtual
override
returns (address)
{
require(
_exists(tokenId),
"ERC721: approved query for nonexistent token"
);
return _tokenApprovals[tokenId];
}
function setApprovalForAll(address operator, bool approved)
external
virtual
override
{
require(operator != msg.sender, "ERC721: approve to caller");
_operatorApprovals[msg.sender][operator] = approved;
emit ApprovalForAll(msg.sender, operator, approved);
}
function isApprovedForAll(address owner, address operator)
public
view
virtual
override
returns (bool)
{
return _operatorApprovals[owner][operator];
}
function transferFrom(
address from,
address to,
uint256 tokenId
) external virtual override {
require(
_isApprovedOrOwner(msg.sender, tokenId),
"ERC721: transfer caller is not owner nor approved"
);
_transfer(from, to, tokenId);
}
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) external virtual override {
_safeTransferFrom(from, to, tokenId, "");
}
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes memory _data
) external virtual override {
_safeTransferFrom(from, to, tokenId, _data);
}
function _safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes memory _data
) internal virtual {
require(
_isApprovedOrOwner(msg.sender, tokenId),
"ERC721: transfer caller is not owner nor approved"
);
_safeTransfer(from, to, tokenId, _data);
}
function _safeTransfer(
address from,
address to,
uint256 tokenId,
bytes memory _data
) internal virtual {
_transfer(from, to, tokenId);
require(
_checkOnERC721Received(from, to, tokenId, _data),
"ERC721: transfer to non ERC721Receiver implementer"
);
}
function _exists(uint256 tokenId) internal view virtual returns (bool) {
return _owners[tokenId] != address(0);
}
function _isApprovedOrOwner(address spender, uint256 tokenId)
internal
view
virtual
returns (bool)
{
require(
_exists(tokenId),
"ERC721: operator query for nonexistent token"
);
address owner = _ownerOf(tokenId);
return (spender == owner ||
getApproved(tokenId) == spender ||
isApprovedForAll(owner, spender));
}
function _safeMint(address to, uint256 tokenId) internal virtual {
_safeMint(to, tokenId, "");
}
function _safeMint(
address to,
uint256 tokenId,
bytes memory _data
) internal virtual {
_mint(to, tokenId);
require(
_checkOnERC721Received(address(0), to, tokenId, _data),
"ERC721: transfer to non ERC721Receiver implementer"
);
}
function _mint(address to, uint256 tokenId) internal virtual {
require(to != address(0), "ERC721: mint to the zero address");
require(!_exists(tokenId), "ERC721: token already minted");
_beforeTokenTransfer(address(0), to, tokenId);
_balances[to] += 1;
_owners[tokenId] = to;
emit Transfer(address(0), to, tokenId);
}
function _burn(uint256 tokenId) internal virtual {
address owner = _ownerOf(tokenId);
_beforeTokenTransfer(owner, address(0), tokenId);
_approve(address(0), tokenId);
_balances[owner] -= 1;
delete _owners[tokenId];
emit Transfer(owner, address(0), tokenId);
}
function _transfer(
address from,
address to,
uint256 tokenId
) internal virtual {
require(
_ownerOf(tokenId) == from,
"ERC721: transfer of token that is not own"
);
require(to != address(0), "ERC721: transfer to the zero address");
_beforeTokenTransfer(from, to, tokenId);
_approve(address(0), tokenId);
_balances[from] -= 1;
_balances[to] += 1;
_owners[tokenId] = to;
emit Transfer(from, to, tokenId);
}
function _approve(address to, uint256 tokenId) internal virtual {
_tokenApprovals[tokenId] = to;
emit Approval(_ownerOf(tokenId), to, tokenId);
}
function _checkOnERC721Received(
address from,
address to,
uint256 tokenId,
bytes memory _data
) private returns (bool) {
if (to.code.length > 0) {
try
IERC721Receiver(to).onERC721Received(
msg.sender,
from,
tokenId,
_data
)
returns (bytes4 retval) {
return retval == IERC721Receiver(to).onERC721Received.selector;
} catch (bytes memory reason) {
if (reason.length == 0) {
revert(
"ERC721: transfer to non ERC721Receiver implementer"
);
} else {
assembly {
revert(add(32, reason), mload(reason))
}
}
}
} else {
return true;
}
}
function _beforeTokenTransfer(
address from,
address to,
uint256 tokenId
) internal virtual {}
}
文件 8 的 32:IERC1271.sol
pragma solidity ^0.8.0;
interface IERC1271 {
function isValidSignature(bytes32 hash, bytes memory signature) external view returns (bytes4 magicValue);
}
文件 9 的 32:IERC2981.sol
pragma solidity ^0.8.0;
interface IERC2981 {
function royaltyInfo(uint256 _tokenId, uint256 _salePrice)
external
view
returns (address receiver, uint256 royaltyAmount);
}
文件 10 的 32:IERC5267.sol
pragma solidity ^0.8.0;
interface IERC5267 {
event EIP712DomainChanged();
function eip712Domain()
external
view
returns (
bytes1 fields,
string memory name,
string memory version,
uint256 chainId,
address verifyingContract,
bytes32 salt,
uint256[] memory extensions
);
}
文件 11 的 32:IERC721.sol
pragma solidity ^0.8.0;
interface IERC721 {
function balanceOf(address owner) external view returns (uint256 balance);
function ownerOf(uint256 tokenId) external view returns (address owner);
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) external;
function transferFrom(
address from,
address to,
uint256 tokenId
) external;
function approve(address to, uint256 tokenId) external;
function getApproved(uint256 tokenId)
external
view
returns (address operator);
function setApprovalForAll(address operator, bool _approved) external;
function isApprovedForAll(address owner, address operator)
external
view
returns (bool);
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes calldata data
) external;
}
interface IERC721Events {
event Transfer(
address indexed from,
address indexed to,
uint256 indexed tokenId
);
event Approval(
address indexed owner,
address indexed approved,
uint256 indexed tokenId
);
event ApprovalForAll(
address indexed owner,
address indexed operator,
bool approved
);
}
interface IERC721Metadata {
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function tokenURI(uint256 tokenId) external view returns (string memory);
}
interface IERC721Burnable is IERC721 {
function burn(uint256 tokenId) external;
}
interface IERC721Receiver {
function onERC721Received(
address operator,
address from,
uint256 tokenId,
bytes calldata data
) external returns (bytes4);
}
interface IERC721Royalties {
function getFeeRecipients(uint256 id)
external
view
returns (address payable[] memory);
function getFeeBps(uint256 id) external view returns (uint256[] memory);
}
文件 12 的 32:IFeeConfiguration.sol
pragma solidity ^0.8.0;
interface IFeeConfigurationEvents {
event FeeSwitch(bool on);
event FlatFeeSwitch(bool on);
event MinimumFee(uint16 fee);
event MaximumFee(uint16 fee);
event FlatFeeAmount(uint256 fee);
}
interface IFeeConfiguration {
function on() external returns (bool);
function flatFeeOn() external returns (bool);
function flatFeeAmount() external returns (uint256);
function maximumFee() external returns (uint16);
function minimumFee() external returns (uint16);
function switchFee() external;
function setMinimumFee(uint16 newFee) external;
function setMaximumFee(uint16 newFe) external;
function valid(uint16 feeBPS) external view returns (bool);
}
文件 13 的 32:IObservability.sol
pragma solidity ^0.8.0;
interface IObservabilityEvents {
event CloneDeployed(
address indexed factory,
address indexed owner,
address indexed clone
);
event TributarySet(
address indexed factory,
address indexed clone,
address oldTributary,
address indexed newTributary
);
event FactoryLimitSet(
address indexed factory,
uint256 oldLimit,
uint256 newLimit
);
event FactoryGuardSet(bool guard);
event FactoryImplementationSet(
address indexed factory,
address indexed oldImplementation,
address indexed newImplementation
);
event WritingEditionPurchased(
address indexed clone,
uint256 tokenId,
address indexed recipient,
uint256 price,
string message,
uint256 flatFeeAmount
);
event Transfer(
address indexed clone,
address indexed from,
address indexed to,
uint256 tokenId
);
event RoyaltyChange(
address indexed clone,
address indexed oldRoyaltyRecipient,
uint256 oldRoyaltyBPS,
address indexed newRoyaltyRecipient,
uint256 newRoyaltyBPS
);
event RendererSet(address indexed clone, address indexed renderer);
event WritingEditionLimitSet(
address indexed clone,
uint256 oldLimit,
uint256 newLimit
);
event PriceSet(address indexed clone, uint256 oldLimit, uint256 newLimit);
event FundingRecipientSet(
address indexed clone,
address indexed oldFundingRecipient,
address indexed newFundingRecipient
);
event BaseDescriptionURISet(
address indexed clone,
string oldBaseDescriptionURI,
string newBaseDescriptionURI
);
}
interface IObservability {
function emitDeploymentEvent(address owner, address clone) external;
function emitTributarySet(
address clone,
address oldTributary,
address newTributary
) external;
function emitFactoryGuardSet(bool guard) external;
function emitFactoryImplementationSet(
address oldImplementation,
address newImplementation
) external;
function emitFactoryLimitSet(uint256 oldLimit, uint256 newLimit) external;
function emitTransferEvent(
address from,
address to,
uint256 tokenId
) external;
function emitWritingEditionPurchased(
uint256 tokenId,
address recipient,
uint256 price,
string memory message,
uint256 flatFeeAmount
) external;
function emitRoyaltyChange(
address oldRoyaltyRecipient,
uint256 oldRoyaltyBPS,
address newRoyaltyRecipient,
uint256 newRoyaltyBPS
) external;
function emitRendererSet(address renderer) external;
function emitWritingEditionLimitSet(
uint256 oldLimit,
uint256 newLimit
) external;
function emitFundingRecipientSet(
address oldFundingRecipient,
address newFundingRecipient
) external;
function emitPriceSet(uint256 oldPrice, uint256 newPrice) external;
function emitBaseDescriptionURISet(
string memory oldBaseDescriptionURI,
string memory newBaseDescriptionURI
) external;
}
文件 14 的 32:IRenderer.sol
pragma solidity ^0.8.0;
interface IRenderer {
function tokenURI(uint256 tokenId) external view returns (string calldata);
function contractURI() external view returns (string calldata);
}
文件 15 的 32:ITreasury.sol
pragma solidity ^0.8.0;
interface ITreasuryEvents {
event Transfer(address indexed from, address indexed to, uint256 value);
event ERC20Transfer(
address indexed token,
address indexed from,
address indexed to,
uint256 amount
);
event ERC721Transfer(
address indexed token,
address indexed from,
address indexed to,
uint256 tokenId
);
}
interface ITreasury {
struct Call {
address target;
uint96 value;
bytes data;
}
function treasuryConfiguration() external view returns (address);
function transferFunds(address payable to, uint256 value) external;
function transferERC20(
address token,
address to,
uint256 value
) external;
function transferERC721(
address token,
address from,
address to,
uint256 tokenId
) external;
function contributeWithTributary(address tributary) external payable;
function contribute(uint256 amount) external payable;
}
文件 16 的 32:ITreasuryConfiguration.sol
pragma solidity ^0.8.0;
interface ITreasuryConfigurationEvents {
event TreasurySet(address indexed treasury, address indexed newTreasury);
event TributaryRegistrySet(
address indexed tributaryRegistry,
address indexed newTributaryRegistry
);
event DistributionSet(
address indexed distribution,
address indexed newDistribution
);
event FeeConfigurationSet(
address indexed feeConfiguration,
address indexed newFeeConfiguration
);
}
interface ITreasuryConfiguration {
function treasury() external returns (address payable);
function tributaryRegistry() external returns (address);
function distribution() external returns (address);
function feeConfiguration() external returns (address);
function setTreasury(address payable newTreasury) external;
function setTributaryRegistry(address newTributaryRegistry) external;
function setDistribution(address newDistribution) external;
function setFeeConfiguration(address newFeeConfiguration) external;
}
文件 17 的 32:ITributaryRegistry.sol
pragma solidity ^0.8.0;
interface ITributaryRegistry {
function allowedRegistrar(address account) external view returns (bool);
function producerToTributary(address producer)
external
view
returns (address tributary);
function singletonProducer(address producer) external view returns (bool);
function addRegistrar(address registrar) external;
function removeRegistrar(address registrar) external;
function addSingletonProducer(address producer) external;
function removeSingletonProducer(address producer) external;
function setTributary(address producer, address newTributary) external;
}
文件 18 的 32:IWritingEditions.sol
pragma solidity ^0.8.0;
interface IWritingEditionEvents {
event RoyaltyChange(
address indexed oldRoyaltyRecipient,
uint256 oldRoyaltyBPS,
address indexed newRoyaltyRecipient,
uint256 newRoyaltyBPS
);
event RendererSet(address indexed renderer);
event WritingEditionLimitSet(uint256 oldLimit, uint256 newLimit);
event PriceSet(uint256 price);
event RewardsDistributed(
uint256 creatorReward,
uint256 fee,
uint256 mintReferralReward,
uint256 firstMinterReward,
address creator,
address mintReferral,
address firstMinter
);
}
interface IWritingEditions {
struct WritingEdition {
string name;
string symbol;
string description;
string imageURI;
string contentURI;
uint256 price;
uint256 limit;
address fundingRecipient;
address renderer;
uint256 nonce;
}
function VERSION() external view returns (uint8);
function factory() external returns (address);
function treasuryConfiguration() external returns (address);
function o11y() external returns (address);
function baseDescriptionURI() external view returns (string memory);
function description() external view returns (string memory);
function totalSupply() external view returns (uint256);
function price() external view returns (uint256);
function limit() external view returns (uint256);
function contentURI() external view returns (string memory);
function imageURI() external view returns (string memory);
function fundingRecipient() external returns (address);
function royaltyRecipient() external returns (address);
function royaltyBPS() external returns (uint256);
function renderer() external view returns (address);
function firstMinter() external view returns (address);
function ownerOf(
uint256[] memory tokenIds
) external view returns (address[] memory owners);
function initializeWithSignature(
address _creator,
bytes32 structHash,
bytes calldata signature,
WritingEdition memory edition,
address tokenRecipient,
string memory message,
address mintReferral,
bool _guardOn,
address sender
) external payable;
function initialize(
address _creator,
WritingEdition memory edition,
address recipient,
string memory message,
address mintReferral,
bool _guard
) external payable;
function setFundingRecipient(address fundingRecipient_) external;
function setPrice(uint256 price_) external;
function setBaseDescriptionURI(string memory _baseDescriptionURI) external;
function setLimit(uint256 limit_) external;
function setMaxLimit() external;
function setRoyaltyInfo(
address royaltyRecipient_,
uint256 royaltyPercentage_
) external;
function toggleGuard() external;
function purchase(
address tokenRecipient,
string memory message,
address mintReferral
) external payable returns (uint256 tokenId);
function mint(address tokenRecipient) external returns (uint256 tokenId);
function setRenderer(address renderer_) external;
function contractURI() external view returns (string memory);
}
文件 19 的 32:IWritingEditionsFactory.sol
pragma solidity ^0.8.0;
import "./IWritingEditions.sol";
interface IWritingEditionsFactoryEvents {
event NewImplementation(
address indexed oldImplementation,
address indexed newImplementation
);
event EditionsDeployed(
address indexed owner,
address indexed clone,
address indexed implementation
);
}
interface IWritingEditionsFactory {
function VERSION() external view returns (uint8);
function implementation() external view returns (address);
function o11y() external view returns (address);
function treasuryConfiguration() external view returns (address);
function guardOn() external view returns (bool);
function salts(bytes32 salt) external view returns (bool);
function maxLimit() external view returns (uint256);
function baseDescriptionURI() external view returns (string memory);
function predictDeterministicAddress(
address implementation_,
bytes32 salt
) external view returns (address);
function setLimit(uint256 _maxLimit) external;
function setGuard(bool _guardOn) external;
function setImplementation(address _implementation) external;
function create(
IWritingEditions.WritingEdition memory edition_
) external returns (address clone);
function createWithSignature(
address owner_,
IWritingEditions.WritingEdition memory edition_,
uint8 v,
bytes32 r,
bytes32 s,
address recipient,
string memory message,
address mintReferral
) external payable returns (address clone);
function setTributary(address clone, address _tributary) external;
}
文件 20 的 32: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 toMinimalHexString(uint256 value) internal pure returns (string memory str) {
str = toHexStringNoPrefix(value);
assembly {
let o := eq(byte(0, mload(add(str, 0x20))), 0x30)
let strLength := add(mload(str), 2)
mstore(add(str, o), 0x3078)
str := sub(add(str, o), 2)
mstore(str, sub(strLength, o))
}
}
function toMinimalHexStringNoPrefix(uint256 value) internal pure returns (string memory str) {
str = toHexStringNoPrefix(value);
assembly {
let o := eq(byte(0, mload(add(str, 0x20))), 0x30)
let strLength := mload(str)
str := add(str, o)
mstore(str, sub(strLength, o))
}
}
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 toHexStringChecksummed(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(aLength, 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, aLength)
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 fromSmallString(bytes32 smallString) internal pure returns (string memory result) {
if (smallString == bytes32(0)) return result;
assembly {
result := mload(0x40)
let n := 0
for {} 1 {} {
n := add(n, 1)
if iszero(byte(n, smallString)) { break }
}
mstore(result, n)
let o := add(result, 0x20)
mstore(o, smallString)
mstore(add(o, n), 0)
mstore(0x40, add(result, 0x40))
}
}
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 {
let end := add(s, mload(s))
result := add(mload(0x40), 0x20)
mstore(0x1f, 0x900094)
mstore(0x08, 0xc0000000a6ab)
mstore(0x00, shl(64, 0x2671756f743b26616d703b262333393b266c743b2667743b))
for {} 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, bool addDoubleQuotes)
internal
pure
returns (string memory result)
{
assembly {
let end := add(s, mload(s))
result := add(mload(0x40), 0x20)
if addDoubleQuotes {
mstore8(result, 34)
result := add(1, result)
}
mstore(0x15, 0x5c75303030303031323334353637383961626364656662746e006672)
let e := or(shl(0x22, 1), shl(0x5c, 1))
for {} 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)
}
if addDoubleQuotes {
mstore8(result, 34)
result := add(1, result)
}
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) {
result = escapeJSON(s, false);
}
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 eqs(string memory a, bytes32 b) internal pure returns (bool result) {
assembly {
let x := and(b, add(not(b), 1))
let r := or(shl(8, iszero(b)), shl(7, iszero(iszero(shr(128, x)))))
r := or(r, shl(6, iszero(iszero(shr(64, shr(r, x))))))
r := or(r, shl(5, lt(0xffffffff, shr(r, x))))
r := or(r, shl(4, lt(0xffff, shr(r, x))))
r := or(r, shl(3, lt(0xff, shr(r, x))))
result := gt(eq(mload(a), sub(32, shr(3, r))), shr(r, xor(b, mload(add(a, 0x20)))))
}
}
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)
}
}
}
文件 21 的 32:Math.sol
pragma solidity ^0.8.0;
library Math {
enum Rounding {
Down,
Up,
Zero
}
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a > b ? a : b;
}
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
function average(uint256 a, uint256 b) internal pure returns (uint256) {
return (a & b) + (a ^ b) / 2;
}
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
return a == 0 ? 0 : (a - 1) / b + 1;
}
function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
unchecked {
uint256 prod0;
uint256 prod1;
assembly {
let mm := mulmod(x, y, not(0))
prod0 := mul(x, y)
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
if (prod1 == 0) {
return prod0 / denominator;
}
require(denominator > prod1, "Math: mulDiv overflow");
uint256 remainder;
assembly {
remainder := mulmod(x, y, denominator)
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
uint256 twos = denominator & (~denominator + 1);
assembly {
denominator := div(denominator, twos)
prod0 := div(prod0, twos)
twos := add(div(sub(0, twos), twos), 1)
}
prod0 |= prod1 * twos;
uint256 inverse = (3 * denominator) ^ 2;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
result = prod0 * inverse;
return result;
}
}
function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
uint256 result = mulDiv(x, y, denominator);
if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
result += 1;
}
return result;
}
function sqrt(uint256 a) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
uint256 result = 1 << (log2(a) >> 1);
unchecked {
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
return min(result, a / result);
}
}
function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
}
}
function log2(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 128;
}
if (value >> 64 > 0) {
value >>= 64;
result += 64;
}
if (value >> 32 > 0) {
value >>= 32;
result += 32;
}
if (value >> 16 > 0) {
value >>= 16;
result += 16;
}
if (value >> 8 > 0) {
value >>= 8;
result += 8;
}
if (value >> 4 > 0) {
value >>= 4;
result += 4;
}
if (value >> 2 > 0) {
value >>= 2;
result += 2;
}
if (value >> 1 > 0) {
result += 1;
}
}
return result;
}
function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log2(value);
return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
}
}
function log10(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10 ** 64) {
value /= 10 ** 64;
result += 64;
}
if (value >= 10 ** 32) {
value /= 10 ** 32;
result += 32;
}
if (value >= 10 ** 16) {
value /= 10 ** 16;
result += 16;
}
if (value >= 10 ** 8) {
value /= 10 ** 8;
result += 8;
}
if (value >= 10 ** 4) {
value /= 10 ** 4;
result += 4;
}
if (value >= 10 ** 2) {
value /= 10 ** 2;
result += 2;
}
if (value >= 10 ** 1) {
result += 1;
}
}
return result;
}
function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log10(value);
return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);
}
}
function log256(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 16;
}
if (value >> 64 > 0) {
value >>= 64;
result += 8;
}
if (value >> 32 > 0) {
value >>= 32;
result += 4;
}
if (value >> 16 > 0) {
value >>= 16;
result += 2;
}
if (value >> 8 > 0) {
result += 1;
}
}
return result;
}
function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log256(value);
return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);
}
}
}
文件 22 的 32:Observability.sol
pragma solidity ^0.8.0;
import "./interface/IObservability.sol";
contract Observability is IObservability, IObservabilityEvents {
function emitDeploymentEvent(
address owner,
address clone
) external override {
emit CloneDeployed(msg.sender, owner, clone);
}
function emitTributarySet(
address clone,
address oldTributary,
address newTributary
) external override {
emit TributarySet(msg.sender, clone, oldTributary, newTributary);
}
function emitFactoryLimitSet(
uint256 oldLimit,
uint256 newLimit
) external override {
emit FactoryLimitSet(msg.sender, oldLimit, newLimit);
}
function emitFactoryGuardSet(bool guard) external override {
emit FactoryGuardSet(guard);
}
function emitFactoryImplementationSet(
address oldImplementation,
address newImplementation
) external override {
emit FactoryImplementationSet(
msg.sender,
oldImplementation,
newImplementation
);
}
function emitWritingEditionPurchased(
uint256 tokenId,
address recipient,
uint256 price,
string memory message,
uint256 flatFeeAmount
) external override {
emit WritingEditionPurchased(
msg.sender,
tokenId,
recipient,
price,
message,
flatFeeAmount
);
}
function emitTransferEvent(
address from,
address to,
uint256 tokenId
) external override {
emit Transfer(msg.sender, from, to, tokenId);
}
function emitRoyaltyChange(
address oldRoyaltyRecipient,
uint256 oldRoyaltyBPS,
address newRoyaltyRecipient,
uint256 newRoyaltyBPS
) external override {
emit RoyaltyChange(
msg.sender,
oldRoyaltyRecipient,
oldRoyaltyBPS,
newRoyaltyRecipient,
newRoyaltyBPS
);
}
function emitRendererSet(address renderer) external override {
emit RendererSet(msg.sender, renderer);
}
function emitWritingEditionLimitSet(
uint256 oldLimit,
uint256 newLimit
) external override {
emit WritingEditionLimitSet(msg.sender, oldLimit, newLimit);
}
function emitPriceSet(
uint256 oldPrice,
uint256 newPrice
) external override {
emit PriceSet(msg.sender, oldPrice, newPrice);
}
function emitFundingRecipientSet(
address oldFundingRecipient,
address newFundingRecipient
) external override {
emit FundingRecipientSet(
msg.sender,
oldFundingRecipient,
newFundingRecipient
);
}
function emitBaseDescriptionURISet(
string memory oldBaseDescriptionURI,
string memory newBaseDescriptionURI
) external override {
emit BaseDescriptionURISet(
msg.sender,
oldBaseDescriptionURI,
newBaseDescriptionURI
);
}
}
文件 23 的 32:Ownable.sol
pragma solidity ^0.8.0;
interface IOwnableEvents {
event OwnershipTransferred(
address indexed previousOwner,
address indexed newOwner
);
}
interface IOwnable {
function transferOwnership(address nextOwner_) external;
function cancelOwnershipTransfer() external;
function acceptOwnership() external;
function renounceOwnership() external;
function isOwner() external view returns (bool);
function isNextOwner() external view returns (bool);
}
contract Ownable is IOwnable, IOwnableEvents {
address public owner;
address private nextOwner;
modifier onlyOwner() {
require(isOwner(), "caller is not the owner.");
_;
}
modifier onlyNextOwner() {
require(isNextOwner(), "current owner must set caller as next owner.");
_;
}
constructor(address owner_) {
_setInitialOwner(owner_);
}
function transferOwnership(address nextOwner_) external override onlyOwner {
require(nextOwner_ != address(0), "Next owner is the zero address.");
nextOwner = nextOwner_;
}
function cancelOwnershipTransfer() external override onlyOwner {
delete nextOwner;
}
function acceptOwnership() external override onlyNextOwner {
delete nextOwner;
owner = msg.sender;
emit OwnershipTransferred(owner, msg.sender);
}
function renounceOwnership() external override onlyOwner {
_renounceOwnership();
}
function isOwner() public view override returns (bool) {
return msg.sender == owner;
}
function isNextOwner() public view override returns (bool) {
return msg.sender == nextOwner;
}
function _setOwner(address previousOwner, address newOwner) internal {
owner = newOwner;
emit OwnershipTransferred(previousOwner, owner);
}
function _setInitialOwner(address newOwner) internal {
owner = newOwner;
emit OwnershipTransferred(address(0), newOwner);
}
function _renounceOwnership() internal {
emit OwnershipTransferred(owner, address(0));
owner = address(0);
}
}
文件 24 的 32:ReentrancyGuard.sol
pragma solidity ^0.8.0;
abstract contract ReentrancyGuard {
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor() {
_status = _NOT_ENTERED;
}
modifier nonReentrant() {
_nonReentrantBefore();
_;
_nonReentrantAfter();
}
function _nonReentrantBefore() private {
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
_status = _ENTERED;
}
function _nonReentrantAfter() private {
_status = _NOT_ENTERED;
}
function _reentrancyGuardEntered() internal view returns (bool) {
return _status == _ENTERED;
}
}
文件 25 的 32:Rewards.sol
pragma solidity ^0.8.0;
library Rewards {
error FeeTooLowError();
uint256 constant _FREE_CREATOR_REWARD_PERCENTAGE = 40_00;
uint256 constant _FREE_MINT_REFERRAL_REWARD_PERCENTAGE = 10_00;
uint256 constant _FREE_FEE_PERCENTAGE = 30_00;
uint256 constant _FREE_FIRST_MINTER_REWARD_PECENTAGE = 20_00;
uint256 constant _PAID_MINT_REFERRAL_REWARD_PERCENTAGE = 25_00;
uint256 constant _PAID_FEE_PERCENTAGE = 50_00;
uint256 constant _PAID_FIRST_MINTER_REWARD_PERCENTAGE = 25_00;
function getRewards(
address mintReferral,
bool freeMint,
uint256 flatFeeAmount
) external pure returns (uint256, uint256, uint256, uint256) {
if (flatFeeAmount < 10) revert FeeTooLowError();
if (freeMint) {
return _getFreeMintRewards(mintReferral, flatFeeAmount);
}
return _getPaidMintRewards(mintReferral, flatFeeAmount);
}
function _getFreeMintRewards(
address mintReferral,
uint256 flatFeeAmount
) internal pure returns (uint256, uint256, uint256, uint256) {
uint256 mintReferralReward = 0;
uint256 creatorReward = (flatFeeAmount *
_FREE_CREATOR_REWARD_PERCENTAGE) / 100_00;
uint256 firstMinterReward = (flatFeeAmount *
_FREE_FIRST_MINTER_REWARD_PECENTAGE) / 100_00;
uint256 fee = (flatFeeAmount * _FREE_FEE_PERCENTAGE) / 100_00;
if (mintReferral != address(0))
mintReferralReward =
(flatFeeAmount * _FREE_MINT_REFERRAL_REWARD_PERCENTAGE) /
100_00;
else
fee +=
(flatFeeAmount * _FREE_MINT_REFERRAL_REWARD_PERCENTAGE) /
100_00;
return (creatorReward, fee, mintReferralReward, firstMinterReward);
}
function _getPaidMintRewards(
address mintReferral,
uint256 flatFeeAmount
) internal pure returns (uint256, uint256, uint256, uint256) {
uint256 mintReferralReward = 0;
uint256 fee = (flatFeeAmount * _PAID_FEE_PERCENTAGE) / 100_00;
uint256 firstMinterReward = (flatFeeAmount *
_PAID_FIRST_MINTER_REWARD_PERCENTAGE) / 100_00;
if (mintReferral != address(0))
mintReferralReward =
(flatFeeAmount * _PAID_MINT_REFERRAL_REWARD_PERCENTAGE) /
100_00;
else
fee +=
(flatFeeAmount * _PAID_MINT_REFERRAL_REWARD_PERCENTAGE) /
100_00;
return (0, fee, mintReferralReward, firstMinterReward);
}
}
文件 26 的 32:ShortStrings.sol
pragma solidity ^0.8.8;
import "./StorageSlot.sol";
type ShortString is bytes32;
library ShortStrings {
bytes32 private constant _FALLBACK_SENTINEL = 0x00000000000000000000000000000000000000000000000000000000000000FF;
error StringTooLong(string str);
error InvalidShortString();
function toShortString(string memory str) internal pure returns (ShortString) {
bytes memory bstr = bytes(str);
if (bstr.length > 31) {
revert StringTooLong(str);
}
return ShortString.wrap(bytes32(uint256(bytes32(bstr)) | bstr.length));
}
function toString(ShortString sstr) internal pure returns (string memory) {
uint256 len = byteLength(sstr);
string memory str = new string(32);
assembly {
mstore(str, len)
mstore(add(str, 0x20), sstr)
}
return str;
}
function byteLength(ShortString sstr) internal pure returns (uint256) {
uint256 result = uint256(ShortString.unwrap(sstr)) & 0xFF;
if (result > 31) {
revert InvalidShortString();
}
return result;
}
function toShortStringWithFallback(string memory value, string storage store) internal returns (ShortString) {
if (bytes(value).length < 32) {
return toShortString(value);
} else {
StorageSlot.getStringSlot(store).value = value;
return ShortString.wrap(_FALLBACK_SENTINEL);
}
}
function toStringWithFallback(ShortString value, string storage store) internal pure returns (string memory) {
if (ShortString.unwrap(value) != _FALLBACK_SENTINEL) {
return toString(value);
} else {
return store;
}
}
function byteLengthWithFallback(ShortString value, string storage store) internal view returns (uint256) {
if (ShortString.unwrap(value) != _FALLBACK_SENTINEL) {
return byteLength(value);
} else {
return bytes(store).length;
}
}
}
文件 27 的 32:SignedMath.sol
pragma solidity ^0.8.0;
library SignedMath {
function max(int256 a, int256 b) internal pure returns (int256) {
return a > b ? a : b;
}
function min(int256 a, int256 b) internal pure returns (int256) {
return a < b ? a : b;
}
function average(int256 a, int256 b) internal pure returns (int256) {
int256 x = (a & b) + ((a ^ b) >> 1);
return x + (int256(uint256(x) >> 255) & (a ^ b));
}
function abs(int256 n) internal pure returns (uint256) {
unchecked {
return uint256(n >= 0 ? n : -n);
}
}
}
文件 28 的 32:StorageSlot.sol
pragma solidity ^0.8.0;
library StorageSlot {
struct AddressSlot {
address value;
}
struct BooleanSlot {
bool value;
}
struct Bytes32Slot {
bytes32 value;
}
struct Uint256Slot {
uint256 value;
}
struct StringSlot {
string value;
}
struct BytesSlot {
bytes value;
}
function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
assembly {
r.slot := slot
}
}
function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
assembly {
r.slot := slot
}
}
function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
assembly {
r.slot := slot
}
}
function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
assembly {
r.slot := slot
}
}
function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {
assembly {
r.slot := slot
}
}
function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {
assembly {
r.slot := store.slot
}
}
function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {
assembly {
r.slot := slot
}
}
function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {
assembly {
r.slot := store.slot
}
}
}
文件 29 的 32:Strings.sol
pragma solidity ^0.8.0;
import "./math/Math.sol";
import "./math/SignedMath.sol";
library Strings {
bytes16 private constant _SYMBOLS = "0123456789abcdef";
uint8 private constant _ADDRESS_LENGTH = 20;
function toString(uint256 value) internal pure returns (string memory) {
unchecked {
uint256 length = Math.log10(value) + 1;
string memory buffer = new string(length);
uint256 ptr;
assembly {
ptr := add(buffer, add(32, length))
}
while (true) {
ptr--;
assembly {
mstore8(ptr, byte(mod(value, 10), _SYMBOLS))
}
value /= 10;
if (value == 0) break;
}
return buffer;
}
}
function toString(int256 value) internal pure returns (string memory) {
return string(abi.encodePacked(value < 0 ? "-" : "", toString(SignedMath.abs(value))));
}
function toHexString(uint256 value) internal pure returns (string memory) {
unchecked {
return toHexString(value, Math.log256(value) + 1);
}
}
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = _SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
function toHexString(address addr) internal pure returns (string memory) {
return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
}
function equal(string memory a, string memory b) internal pure returns (bool) {
return keccak256(bytes(a)) == keccak256(bytes(b));
}
}
文件 30 的 32:TransactionReentrancyGuard.sol
pragma solidity ^0.8.0;
contract TransactionReentrancyGuard {
bool public guardOn;
uint256 internal GUARD = 1;
modifier guard() {
if (guardOn) {
_guard();
}
_;
}
constructor(bool _guardOn) {
_setGuard(_guardOn);
}
function _guard() internal view {
uint256 t0 = gasleft();
uint256 g = GUARD;
uint256 t1 = gasleft();
uint256 m = GUARD;
require(t1 - gasleft() < t0 - t1);
}
function _toggleGuard() internal {
_setGuard(!guardOn);
}
function _setGuard(bool _guardOn) internal {
guardOn = _guardOn;
}
}
文件 31 的 32:WritingEditions.sol
pragma solidity ^0.8.0;
import "./interface/IWritingEditions.sol";
import "./interface/IWritingEditionsFactory.sol";
import "../ERC7015/ERC7015.sol";
import "../observability/interface/IObservability.sol";
import "../fee-configuration/interface/IFeeConfiguration.sol";
import "../renderer/interface/IRenderer.sol";
import "../treasury/Rewards.sol";
import "../treasury/interface/ITreasuryConfiguration.sol";
import "../treasury/interface/ITreasury.sol";
import "../treasury/interface/ITributaryRegistry.sol";
import "../lib/Ownable.sol";
import "../lib/ERC721/ERC721.sol";
import "../lib/ERC165/ERC165.sol";
import "../lib/ERC721/interface/IERC721.sol";
import "../lib/ERC2981/interface/IERC2981.sol";
import "../lib/transaction-reentrancy-guard/TransactionReentrancyGuard.sol";
import "openzeppelin-contracts/contracts/security/ReentrancyGuard.sol";
import "openzeppelin-contracts/contracts/utils/Base64.sol";
import "openzeppelin-contracts/contracts/utils/Strings.sol";
contract WritingEditions is
ERC7015,
Ownable,
TransactionReentrancyGuard,
ReentrancyGuard,
ERC721,
IERC721Metadata,
IERC2981,
IWritingEditions,
IWritingEditionEvents,
IObservabilityEvents
{
uint8 public immutable override VERSION = 3;
address public immutable override factory;
address public immutable override treasuryConfiguration;
address public immutable override o11y;
string public override name;
string public override symbol;
string internal _baseDescriptionURI;
uint256 public override totalSupply;
string public override contentURI;
string public override imageURI;
uint256 public override price;
uint256 public override limit;
address public override fundingRecipient;
address public override royaltyRecipient;
uint256 public override royaltyBPS;
address public override renderer;
address public override firstMinter;
constructor(
address _factory,
address _treasuryConfiguration,
address _o11y
)
Ownable(address(0))
TransactionReentrancyGuard(true)
ERC7015("WritingEditions", "1")
{
require(_factory != address(0), "must set factory");
factory = _factory;
require(
_treasuryConfiguration != address(0),
"must set treasury configuration"
);
treasuryConfiguration = _treasuryConfiguration;
require(_o11y != address(0), "must set observability");
o11y = _o11y;
}
function initializeWithSignature(
address _creator,
bytes32 structHash,
bytes calldata signature,
WritingEdition memory edition,
address tokenRecipient,
string memory message,
address mintReferral,
bool _guardOn,
address sender
) external payable override nonReentrant {
_validateSignature(_creator, structHash, signature);
if (sender != _creator) {
firstMinter = sender;
}
_initialize(
_creator,
edition,
tokenRecipient,
message,
mintReferral,
_guardOn
);
}
function initialize(
address _creator,
WritingEdition memory edition,
address tokenRecipient,
string memory message,
address mintReferral,
bool _guardOn
) external payable override nonReentrant {
_initialize(
_creator,
edition,
tokenRecipient,
message,
mintReferral,
_guardOn
);
}
function _initialize(
address _creator,
WritingEdition memory edition,
address tokenRecipient,
string memory message,
address mintReferral,
bool _guardOn
) internal {
require(msg.sender == factory, "unauthorized caller");
name = edition.name;
symbol = edition.symbol;
imageURI = edition.imageURI;
contentURI = edition.contentURI;
price = edition.price;
limit = edition.limit;
fundingRecipient = edition.fundingRecipient;
renderer = edition.renderer;
_setInitialOwner(_creator);
_setGuard(_guardOn);
if (tokenRecipient != address(0)) {
_purchase(tokenRecipient, message, mintReferral);
}
}
function baseDescriptionURI()
external
view
override
returns (string memory)
{
return _getBaseDescriptionURI();
}
function description() public view override returns (string memory) {
return
string(
abi.encodePacked(
_getBaseDescriptionURI(),
Strings.toString(block.chainid),
"/",
_addressToString(address(this))
)
);
}
function ownerOf(
uint256[] memory tokenIds
) external view override returns (address[] memory owners) {
owners = new address[](tokenIds.length);
for (uint256 i = 0; i < tokenIds.length; i++) {
owners[i] = _owners[tokenIds[i]];
}
}
function setFundingRecipient(
address _fundingRecipient
) external override onlyOwner {
IObservability(o11y).emitFundingRecipientSet(
fundingRecipient,
_fundingRecipient
);
fundingRecipient = _fundingRecipient;
}
function setPrice(uint256 _price) external override onlyOwner {
IObservability(o11y).emitPriceSet(
price,
_price
);
price = _price;
}
function setBaseDescriptionURI(
string memory newBaseDescriptionURI
) external override onlyOwner {
IObservability(o11y).emitBaseDescriptionURISet(
_getBaseDescriptionURI(),
newBaseDescriptionURI
);
_baseDescriptionURI = newBaseDescriptionURI;
}
function toggleGuard() external override onlyOwner {
_toggleGuard();
}
function purchase(
address tokenRecipient,
string memory message,
address mintReferral
) external payable override guard nonReentrant returns (uint256 tokenId) {
return _purchase(tokenRecipient, message, mintReferral);
}
function mint(
address tokenRecipient
) external override onlyOwner returns (uint256 tokenId) {
tokenId = _getTokenIdAndMint(tokenRecipient);
}
function setLimit(uint256 newLimit) external override onlyOwner {
require(
newLimit >= totalSupply && (limit == 0 || newLimit < limit),
"limit must be < than current limit"
);
IObservability(o11y).emitWritingEditionLimitSet(
limit,
newLimit
);
limit = newLimit;
}
function setMaxLimit() external override onlyOwner {
IObservability(o11y).emitWritingEditionLimitSet(
limit,
totalSupply
);
limit = totalSupply;
}
function royaltyInfo(
uint256 _tokenId,
uint256 _salePrice
) external view override returns (address receiver, uint256 royaltyAmount) {
receiver = royaltyRecipient;
royaltyAmount = (_salePrice * royaltyBPS) / 10_000;
}
function setRoyaltyInfo(
address royaltyRecipient_,
uint256 royaltyBPS_
) external override onlyOwner {
require(
royaltyBPS_ <= 10_000,
"bps must be less than or equal to 10,000"
);
IObservability(o11y).emitRoyaltyChange(
royaltyRecipient,
royaltyBPS,
royaltyRecipient_,
royaltyBPS_
);
royaltyRecipient = royaltyRecipient_;
royaltyBPS = royaltyBPS_;
}
function setRenderer(address _renderer) external override onlyOwner {
require(renderer == address(0), "renderer already set");
renderer = _renderer;
IObservability(o11y).emitRendererSet(
_renderer
);
}
function contractURI() external view override returns (string memory) {
if (renderer != address(0)) {
try IRenderer(renderer).contractURI() returns (
string memory result
) {
return result;
} catch {
return _generateContractURI();
}
}
return _generateContractURI();
}
function tokenURI(
uint256 tokenId
) external view override returns (string memory) {
require(_exists(tokenId), "ERC721: query for nonexistent token");
if (renderer != address(0)) {
return IRenderer(renderer).tokenURI(tokenId);
}
bytes memory editionNumber;
if (limit != 0) {
editionNumber = abi.encodePacked("/", Strings.toString(limit));
}
string memory json = Base64.encode(
bytes(
string(
abi.encodePacked(
'{"name": "',
_escapeQuotes(name),
" ",
Strings.toString(tokenId),
editionNumber,
'", "description": "',
_escapeQuotes(description()),
'", "content": "ar://',
contentURI,
'", "image": "ipfs://',
imageURI,
'", "attributes":[{ "trait_type": "Serial", "value": ',
Strings.toString(tokenId),
"}] }"
)
)
)
);
return string(abi.encodePacked("data:application/json;base64,", json));
}
function supportsInterface(
bytes4 interfaceId
) public pure override returns (bool) {
return
interfaceId == type(IERC721).interfaceId ||
interfaceId == type(IERC721Metadata).interfaceId ||
interfaceId == type(IERC165).interfaceId ||
interfaceId == type(IERC2981).interfaceId;
}
function _generateContractURI() internal view returns (string memory) {
string memory json = Base64.encode(
bytes(
string(
abi.encodePacked(
'{"name": "',
_escapeQuotes(name),
'", "description": "',
_escapeQuotes(description()),
'", "content": "ar://',
contentURI,
'", "image": "ipfs://',
imageURI,
'", "seller_fee_basis_points": ',
Strings.toString(royaltyBPS),
', "fee_recipient": "',
_addressToString(royaltyRecipient),
'", "external_link": "',
_getBaseDescriptionURI(),
'"}'
)
)
)
);
return string(abi.encodePacked("data:application/json;base64,", json));
}
function _beforeTokenTransfer(
address from,
address to,
uint256 tokenId
) internal virtual override {
IObservability(o11y).emitTransferEvent(from, to, tokenId);
}
function _purchase(
address tokenRecipient,
string memory message,
address mintReferral
) internal returns (uint256 tokenId) {
tokenId = _getTokenIdAndMint(tokenRecipient);
uint256 flatFeeAmount = 0;
address feeConfiguration = _getFeeConfiguration();
if (
feeConfiguration != address(0) &&
IFeeConfiguration(feeConfiguration).flatFeeOn()
) {
flatFeeAmount = IFeeConfiguration(feeConfiguration).flatFeeAmount();
}
IObservability(o11y).emitWritingEditionPurchased(
tokenId,
tokenRecipient,
price,
message,
flatFeeAmount
);
_withdraw(fundingRecipient, msg.value, flatFeeAmount, mintReferral);
}
function _getFeeConfiguration() internal returns (address) {
return ITreasuryConfiguration(treasuryConfiguration).feeConfiguration();
}
function _getTributaryRegistry() internal returns (address) {
return
ITreasuryConfiguration(treasuryConfiguration).tributaryRegistry();
}
function _withdraw(
address fundsRecipient,
uint256 amount,
uint256 flatFeeAmount,
address mintReferral
) internal {
address treasury = ITreasuryConfiguration(treasuryConfiguration)
.treasury();
if (flatFeeAmount != 0 && treasury != address(0)) {
require(amount == price + flatFeeAmount, "invalid amount");
(
uint256 creatorReward,
uint256 fee,
uint256 mintReferralReward,
uint256 firstMinterReward
) = Rewards.getRewards(
mintReferral,
price == 0,
flatFeeAmount
);
if (firstMinter == address(0)) {
_sendEther(
payable(fundsRecipient),
price + creatorReward + firstMinterReward
);
} else {
_sendEther(payable(firstMinter), firstMinterReward);
_sendEther(payable(fundsRecipient), price + creatorReward);
}
_sendEther(payable(treasury), fee);
emit RewardsDistributed(
creatorReward,
fee,
mintReferralReward,
firstMinterReward,
fundsRecipient,
mintReferral,
firstMinter
);
if (mintReferralReward != 0) {
_sendEther(payable(mintReferral), mintReferralReward);
}
} else {
require(amount == price, "invalid amount");
_sendEther(payable(fundsRecipient), amount);
}
}
function _sendEther(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "insufficient balance");
(bool success, ) = recipient.call{value: amount, gas: gasleft()}("");
require(success, "recipient reverted");
}
function _getTokenIdAndMint(
address tokenRecipient
) internal returns (uint256 tokenId) {
tokenId = ++totalSupply;
require(
limit == 0 || limit == type(uint256).max || tokenId < limit + 1,
"sold out"
);
_mint(tokenRecipient, tokenId);
}
function _getBaseDescriptionURI() internal view returns (string memory) {
return
bytes(_baseDescriptionURI).length == 0
? IWritingEditionsFactory(factory).baseDescriptionURI()
: _baseDescriptionURI;
}
function _addressToString(address x) internal pure returns (string memory) {
bytes memory s = new bytes(40);
for (uint256 i = 0; i < 20; i++) {
bytes1 b = bytes1(
uint8(uint256(uint160(x)) / (2 ** (8 * (19 - i))))
);
bytes1 hi = bytes1(uint8(b) / 16);
bytes1 lo = bytes1(uint8(b) - 16 * uint8(hi));
s[2 * i] = _char(hi);
s[2 * i + 1] = _char(lo);
}
return string(abi.encodePacked("0x", s));
}
function _char(bytes1 b) internal pure returns (bytes1 c) {
if (uint8(b) < 10) return bytes1(uint8(b) + 0x30);
else return bytes1(uint8(b) + 0x57);
}
function _escapeQuotes(
string memory str
) internal pure returns (string memory) {
bytes memory strBytes = bytes(str);
uint8 quotesCount = 0;
for (uint8 i = 0; i < strBytes.length; i++) {
if (strBytes[i] == '"') {
quotesCount++;
}
}
if (quotesCount > 0) {
bytes memory escapedBytes = new bytes(
strBytes.length + (quotesCount)
);
uint256 index;
for (uint8 i = 0; i < strBytes.length; i++) {
if (strBytes[i] == '"') {
escapedBytes[index++] = "\\";
}
escapedBytes[index++] = strBytes[i];
}
return string(escapedBytes);
}
return str;
}
}
文件 32 的 32:WritingEditionsFactory.sol
pragma solidity 0.8.19;
import "./WritingEditions.sol";
import "./interface/IWritingEditionsFactory.sol";
import "../observability/Observability.sol";
import "../lib/Ownable.sol";
import "openzeppelin-contracts/contracts/proxy/Clones.sol";
import "openzeppelin-contracts/contracts/security/ReentrancyGuard.sol";
contract WritingEditionsFactory is
Ownable,
ReentrancyGuard,
IWritingEditionsFactoryEvents,
IWritingEditionsFactory,
IObservabilityEvents
{
uint8 public immutable override VERSION = 3;
address public immutable override o11y;
address public immutable override treasuryConfiguration;
bool public override guardOn;
address public override implementation;
mapping(bytes32 => bool) public override salts;
uint256 public override maxLimit;
string public constant override baseDescriptionURI = "https://mirror.xyz/";
constructor(
address _owner,
address _treasuryConfiguration,
address _o11y,
uint256 _maxLimit,
bool _guardOn
) Ownable(_owner) {
require(
_treasuryConfiguration != address(0),
"must set treasury config"
);
treasuryConfiguration = _treasuryConfiguration;
implementation = address(
new WritingEditions(address(this), _treasuryConfiguration, _o11y)
);
o11y = _o11y;
IObservability(_o11y).emitFactoryImplementationSet(
address(0),
implementation
);
guardOn = _guardOn;
maxLimit = _maxLimit;
}
function predictDeterministicAddress(
address _implementation,
bytes32 salt
) external view override returns (address) {
return
Clones.predictDeterministicAddress(
_implementation,
salt,
address(this)
);
}
function setLimit(uint256 _maxLimit) external override onlyOwner {
IObservability(o11y).emitFactoryLimitSet(
maxLimit,
_maxLimit
);
maxLimit = _maxLimit;
}
function setGuard(bool _guardOn) external override onlyOwner {
IObservability(o11y).emitFactoryGuardSet(_guardOn);
guardOn = _guardOn;
}
function setImplementation(
address _implementation
) external override onlyOwner {
IObservability(o11y).emitFactoryImplementationSet(
implementation,
_implementation
);
implementation = _implementation;
}
function create(
WritingEditions.WritingEdition memory edition
) external override returns (address clone) {
clone = _deployCloneAndInitialize(
msg.sender,
edition,
address(0),
"",
address(0)
);
}
function createWithSignature(
address owner,
WritingEditions.WritingEdition memory edition,
uint8 v,
bytes32 r,
bytes32 s,
address tokenRecipient,
string memory message,
address mintReferral
) external payable override nonReentrant returns (address clone) {
bytes32 salt = keccak256(
abi.encode(owner, edition.name, edition.symbol, edition.nonce)
);
if (salts[salt]) {
clone = Clones.predictDeterministicAddress(
implementation,
salt,
address(this)
);
require(clone.code.length > 0, "invalid clone address");
WritingEditions(clone).purchase{value: msg.value}(
tokenRecipient,
message,
mintReferral
);
} else {
salts[salt] = true;
clone = _deployCloneAndInitializeWithSignature(
owner,
edition,
v,
r,
s,
tokenRecipient,
message,
mintReferral
);
}
}
function setTributary(address clone, address _tributary) external override {
require(msg.sender == Ownable(clone).owner(), "unauthorized");
address tributaryRegistry = _getTributaryRegistry();
IObservability(o11y).emitTributarySet(
clone,
ITributaryRegistry(tributaryRegistry).producerToTributary(clone),
_tributary
);
ITributaryRegistry(tributaryRegistry).setTributary(clone, _tributary);
}
function _deployCloneAndInitialize(
address owner,
WritingEditions.WritingEdition memory edition,
address tokenRecipient,
string memory message,
address mintReferral
) internal returns (address clone) {
clone = _validateEditionAndDeployClone(owner, edition);
WritingEditions(clone).initialize{value: msg.value}(
owner,
edition,
tokenRecipient,
message,
mintReferral,
guardOn
);
}
function _deployCloneAndInitializeWithSignature(
address owner,
WritingEditions.WritingEdition memory edition,
uint8 v,
bytes32 r,
bytes32 s,
address tokenRecipient,
string memory message,
address mintReferral
) internal returns (address clone) {
bytes32 salt = keccak256(
abi.encode(owner, edition.name, edition.symbol, edition.nonce)
);
clone = _validateEditionAndDeployClone(owner, edition);
WritingEditions(clone).initializeWithSignature{value: msg.value}(
owner,
salt,
abi.encodePacked(r, s, v),
edition,
tokenRecipient,
message,
mintReferral,
guardOn,
msg.sender
);
}
function _validateEditionAndDeployClone(
address owner,
WritingEditions.WritingEdition memory edition
) internal returns (address clone) {
require(
edition.fundingRecipient != address(0),
"must specify recipient"
);
require(
maxLimit == 0 || (edition.limit > 0 && edition.limit <= maxLimit),
"invalid limit"
);
clone = Clones.cloneDeterministic(
implementation,
keccak256(
abi.encode(owner, edition.name, edition.symbol, edition.nonce)
)
);
address tributaryRegistry = _getTributaryRegistry();
if (tributaryRegistry != address(0)) {
IObservability(o11y).emitTributarySet(
clone,
address(0),
edition.fundingRecipient
);
ITributaryRegistry(tributaryRegistry).setTributary(
clone,
edition.fundingRecipient
);
}
IObservability(o11y).emitDeploymentEvent(owner, clone);
}
function _getTributaryRegistry() internal returns (address) {
return
ITreasuryConfiguration(treasuryConfiguration).tributaryRegistry();
}
}
{
"compilationTarget": {
"src/writing-editions/WritingEditionsFactory.sol": "WritingEditionsFactory"
},
"evmVersion": "paris",
"libraries": {
"src/treasury/Rewards.sol:Rewards": "0x77bcbbb7783ea8c43ae1893e35c76daf7ec153e3"
},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": [
":ds-test/=lib/ds-test/src/",
":erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
":forge-std/=lib/forge-std/src/",
":multicall/=lib/multicall/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":"address","name":"_treasuryConfiguration","type":"address"},{"internalType":"address","name":"_o11y","type":"address"},{"internalType":"uint256","name":"_maxLimit","type":"uint256"},{"internalType":"bool","name":"_guardOn","type":"bool"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"clone","type":"address"},{"indexed":false,"internalType":"string","name":"oldBaseDescriptionURI","type":"string"},{"indexed":false,"internalType":"string","name":"newBaseDescriptionURI","type":"string"}],"name":"BaseDescriptionURISet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"factory","type":"address"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"clone","type":"address"}],"name":"CloneDeployed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"clone","type":"address"},{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"EditionsDeployed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"guard","type":"bool"}],"name":"FactoryGuardSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"factory","type":"address"},{"indexed":true,"internalType":"address","name":"oldImplementation","type":"address"},{"indexed":true,"internalType":"address","name":"newImplementation","type":"address"}],"name":"FactoryImplementationSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"factory","type":"address"},{"indexed":false,"internalType":"uint256","name":"oldLimit","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newLimit","type":"uint256"}],"name":"FactoryLimitSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"clone","type":"address"},{"indexed":true,"internalType":"address","name":"oldFundingRecipient","type":"address"},{"indexed":true,"internalType":"address","name":"newFundingRecipient","type":"address"}],"name":"FundingRecipientSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldImplementation","type":"address"},{"indexed":true,"internalType":"address","name":"newImplementation","type":"address"}],"name":"NewImplementation","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"clone","type":"address"},{"indexed":false,"internalType":"uint256","name":"oldLimit","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newLimit","type":"uint256"}],"name":"PriceSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"clone","type":"address"},{"indexed":true,"internalType":"address","name":"renderer","type":"address"}],"name":"RendererSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"clone","type":"address"},{"indexed":true,"internalType":"address","name":"oldRoyaltyRecipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"oldRoyaltyBPS","type":"uint256"},{"indexed":true,"internalType":"address","name":"newRoyaltyRecipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"newRoyaltyBPS","type":"uint256"}],"name":"RoyaltyChange","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"clone","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"factory","type":"address"},{"indexed":true,"internalType":"address","name":"clone","type":"address"},{"indexed":false,"internalType":"address","name":"oldTributary","type":"address"},{"indexed":true,"internalType":"address","name":"newTributary","type":"address"}],"name":"TributarySet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"clone","type":"address"},{"indexed":false,"internalType":"uint256","name":"oldLimit","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newLimit","type":"uint256"}],"name":"WritingEditionLimitSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"clone","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"price","type":"uint256"},{"indexed":false,"internalType":"string","name":"message","type":"string"},{"indexed":false,"internalType":"uint256","name":"flatFeeAmount","type":"uint256"}],"name":"WritingEditionPurchased","type":"event"},{"inputs":[],"name":"VERSION","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"baseDescriptionURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cancelOwnershipTransfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"string","name":"description","type":"string"},{"internalType":"string","name":"imageURI","type":"string"},{"internalType":"string","name":"contentURI","type":"string"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"uint256","name":"limit","type":"uint256"},{"internalType":"address","name":"fundingRecipient","type":"address"},{"internalType":"address","name":"renderer","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"}],"internalType":"struct IWritingEditions.WritingEdition","name":"edition","type":"tuple"}],"name":"create","outputs":[{"internalType":"address","name":"clone","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"string","name":"description","type":"string"},{"internalType":"string","name":"imageURI","type":"string"},{"internalType":"string","name":"contentURI","type":"string"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"uint256","name":"limit","type":"uint256"},{"internalType":"address","name":"fundingRecipient","type":"address"},{"internalType":"address","name":"renderer","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"}],"internalType":"struct IWritingEditions.WritingEdition","name":"edition","type":"tuple"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"},{"internalType":"address","name":"tokenRecipient","type":"address"},{"internalType":"string","name":"message","type":"string"},{"internalType":"address","name":"mintReferral","type":"address"}],"name":"createWithSignature","outputs":[{"internalType":"address","name":"clone","type":"address"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"guardOn","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"implementation","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isNextOwner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isOwner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"o11y","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_implementation","type":"address"},{"internalType":"bytes32","name":"salt","type":"bytes32"}],"name":"predictDeterministicAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"salts","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"_guardOn","type":"bool"}],"name":"setGuard","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_implementation","type":"address"}],"name":"setImplementation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxLimit","type":"uint256"}],"name":"setLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"clone","type":"address"},{"internalType":"address","name":"_tributary","type":"address"}],"name":"setTributary","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"nextOwner_","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"treasuryConfiguration","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]