Address Contract Partially Verified
Address
0xc1d628B9170AD61Ed12F317F2146F099EB4E4727
Balance
0 ETH
Nonce
1785
Code Size
4838 bytes
Creator
0xb6235EAE...2F3A at tx 0x6e1c388f...d240c9
Indexed Transactions
0
Contract Bytecode
4838 bytes
0x6080604052600436106100f35760003560e01c80638610292c1161008a578063b7d8622511610059578063b7d86225146102dd578063dce0b4e4146102fd578063f2fde38b14610321578063fa4a389b14610341576100f3565b80638610292c1461025f5780638ada6b0f1461027f5780638da5cb5b1461029f5780639c76b654146102bd576100f3565b80635c975abb116100c65780635c975abb146101f8578063715018a61461022257806377881972146102375780638456cb591461024a576100f3565b80630479734f14610164578063319fc415146101a15780633f4ba83a146101c15780634a3f42b2146101d8575b3480156100ff57600080fd5b5060405162461bcd60e51b815260206004820152602e60248201527f455243373231436f6c6c656374697665466163746f72793a206e6f6e2d65786960448201526d39ba32b73a10333ab731ba34b7b760911b60648201526084015b60405180910390fd5b34801561017057600080fd5b50600154610184906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b3480156101ad57600080fd5b50600254610184906001600160a01b031681565b3480156101cd57600080fd5b506101d6610361565b005b3480156101e457600080fd5b50600354610184906001600160a01b031681565b34801561020457600080fd5b50600054600160a01b900460ff166040519015158152602001610198565b34801561022e57600080fd5b506101d6610373565b610184610245366004610f90565b610385565b34801561025657600080fd5b506101d66106de565b34801561026b57600080fd5b506101d661027a366004611068565b6106ee565b34801561028b57600080fd5b50600554610184906001600160a01b031681565b3480156102ab57600080fd5b506000546001600160a01b0316610184565b3480156102c957600080fd5b506101846102d83660046110d9565b610866565b3480156102e957600080fd5b506101d66102f83660046110d9565b610885565b34801561030957600080fd5b5061031360065481565b604051908152602001610198565b34801561032d57600080fd5b506101d661033c3660046110f2565b6108c0565b34801561034d57600080fd5b50600454610184906001600160a01b031681565b61036961095c565b6103716109b6565b565b61037b61095c565b6103716000610a0b565b600061038f610a5b565b600654156105455760065434146104195760405162461bcd60e51b815260206004820152604260248201527f455243373231436f6c6c656374697665466163746f72793a204d75737420736560448201527f6e6420636f727265637420616d6f756e7420666f72206372656174696f6e2066606482015261656560f01b608482015260a40161015b565b6000306001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610459573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061047d919061110f565b6001600160a01b03163460405160006040518083038185875af1925050503d80600081146104c7576040519150601f19603f3d011682016040523d82523d6000602084013e6104cc565b606091505b50509050806105435760405162461bcd60e51b815260206004820152603760248201527f455243373231436f6c6c656374697665466163746f72793a204661696c65642060448201527f746f20636f6c6c656374206372656174696f6e20666565000000000000000000606482015260840161015b565b505b610550888888610aa8565b90508360005b818110156106785760008787838181106105725761057261112c565b905060200201602081019061058791906110f2565b6001600160a01b03168686848181106105a2576105a261112c565b90506020028101906105b49190611142565b6040516105c2929190611189565b6000604051808303816000865af19150503d80600081146105ff576040519150601f19603f3d011682016040523d82523d6000602084013e610604565b606091505b505090508061066f5760405162461bcd60e51b815260206004820152603160248201527f455243373231436f6c6c656374697665466163746f72793a204572726f72206d604482015270616b696e672073657475702063616c6c7360781b606482015260840161015b565b50600101610556565b5060405163f2fde38b60e01b81523360048201526001600160a01b0383169063f2fde38b90602401600060405180830381600087803b1580156106ba57600080fd5b505af11580156106ce573d6000803e3d6000fd5b5050505050979650505050505050565b6106e661095c565b610371610bb1565b6106f661095c565b8461070081610bf4565b6001600160a01b0385161580159061072057506001600160a01b03841615155b801561073457506001600160a01b03831615155b801561074857506001600160a01b03821615155b6107ba5760405162461bcd60e51b815260206004820152603d60248201527f455243373231436f6c6c656374697665466163746f72793a20696d706c656d6560448201527f6e746174696f6e732063616e6e6f742062652061646472657373283029000000606482015260840161015b565b600180546001600160a01b038881166001600160a01b031992831681179093556002805489831690841681179091556003805489841690851681179091556004805489851690861681179091556005805494891694909516841790945560408051928352602083019190915281019290925260608201527f7d6700c1aa484999dc3340d18a3279e5b3472afa0c5fb8f3b2c8d0c5fdf11fd19060800160405180910390a2505050505050565b60015460009061087f906001600160a01b031683610c8f565b92915050565b61088d61095c565b600681905560405181907f88a973fd5506071e0cf878b30898776c47d5250a7ee1e6ee0b36df3b03c7c16a90600090a250565b6108c861095c565b6001600160a01b03811661092d5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161015b565b61093681610a0b565b50565b600061094483610cf5565b801561095557506109558383610d28565b9392505050565b6000546001600160a01b031633146103715760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161015b565b6109be610db1565b6000805460ff60a01b191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600054600160a01b900460ff16156103715760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015260640161015b565b6000610ab2610a5b565b600154610ac8906001600160a01b031683610e01565b60025460035460048054600554604051630a7a8eef60e01b81529596506001600160a01b0380881696630a7a8eef96610b16968d968d969285169591851694928316939190921691016111f5565b600060405180830381600087803b158015610b3057600080fd5b505af1158015610b44573d6000803e3d6000fd5b50505050806001600160a01b03167f8df221cbe6176f9849aba9effa58b764f046ef045824b7c8cc52b5a01e93605f8585604051602001610b85919061124e565b60408051601f1981840301815290829052610ba29291879061127a565b60405180910390a29392505050565b610bb9610a5b565b6000805460ff60a01b1916600160a01b1790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586109ee3390565b610bff816000610939565b6109365760405162461bcd60e51b815260206004820152605560248201527f455243313635436865636b6572455243373231436f6c6c6563746976653a206360448201527f6f6c6c656374697665206164647265737320646f6573206e6f7420696d706c656064820152746d656e742070726f70657220696e7465726661636560581b608482015260a40161015b565b6000610955838330604051733d602d80600a3d3981f3363d3d373d3d3d363d7360601b8152606093841b60148201526f5af43d82803e903d91602b57fd5bf3ff60801b6028820152921b6038830152604c8201526037808220606c830152605591012090565b6000610d08826301ffc9a760e01b610d28565b801561087f5750610d21826001600160e01b0319610d28565b1592915050565b604080516001600160e01b03198316602480830191909152825180830390910181526044909101909152602080820180516001600160e01b03166301ffc9a760e01b178152825160009392849283928392918391908a617530fa92503d91506000519050828015610d9a575060208210155b8015610da65750600081115b979650505050505050565b600054600160a01b900460ff166103715760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b604482015260640161015b565b6000604051733d602d80600a3d3981f3363d3d373d3d3d363d7360601b81528360601b60148201526e5af43d82803e903d91602b57fd5bf360881b6028820152826037826000f59150506001600160a01b03811661087f5760405162461bcd60e51b815260206004820152601760248201527f455243313136373a2063726561746532206661696c6564000000000000000000604482015260640161015b565b634e487b7160e01b600052604160045260246000fd5b600082601f830112610ec857600080fd5b813567ffffffffffffffff80821115610ee357610ee3610ea1565b604051601f8301601f19908116603f01168101908282118183101715610f0b57610f0b610ea1565b81604052838152866020858801011115610f2457600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008083601f840112610f5657600080fd5b50813567ffffffffffffffff811115610f6e57600080fd5b6020830191508360208260051b8501011115610f8957600080fd5b9250929050565b600080600080600080600060a0888a031215610fab57600080fd5b873567ffffffffffffffff80821115610fc357600080fd5b610fcf8b838c01610eb7565b985060208a0135915080821115610fe557600080fd5b610ff18b838c01610eb7565b975060408a0135965060608a013591508082111561100e57600080fd5b61101a8b838c01610f44565b909650945060808a013591508082111561103357600080fd5b506110408a828b01610f44565b989b979a50959850939692959293505050565b6001600160a01b038116811461093657600080fd5b600080600080600060a0868803121561108057600080fd5b853561108b81611053565b9450602086013561109b81611053565b935060408601356110ab81611053565b925060608601356110bb81611053565b915060808601356110cb81611053565b809150509295509295909350565b6000602082840312156110eb57600080fd5b5035919050565b60006020828403121561110457600080fd5b813561095581611053565b60006020828403121561112157600080fd5b815161095581611053565b634e487b7160e01b600052603260045260246000fd5b6000808335601e1984360301811261115957600080fd5b83018035915067ffffffffffffffff82111561117457600080fd5b602001915036819003821315610f8957600080fd5b8183823760009101908152919050565b60005b838110156111b457818101518382015260200161119c565b838111156111c3576000848401525b50505050565b600081518084526111e1816020860160208601611199565b601f01601f19169290920160200192915050565b60c08152600061120860c08301896111c9565b828103602084015261121a81896111c9565b6001600160a01b03978816604085015295871660608401525050918416608083015290921660a09092019190915292915050565b62714e5d60e91b8152815160009061126d816003850160208701611199565b9190910160030192915050565b60608152600061128d60608301866111c9565b828103602084015261129f81866111c9565b91505082604083015294935050505056fea2646970667358221220a6036462decf367a2e310f7e4736fc24282327651b16fc7e49434d6e6eecd77664736f6c634300080f0033
Verified Source Code Partial Match
Compiler: v0.8.15+commit.e14f2714
EVM: london
Optimization: Yes (200 runs)
ERC721CollectiveFactory.sol 1357 lines
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.15;
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(
address indexed previousOwner,
address indexed newOwner
);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor() {
_transferOwnership(_msgSender());
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(
newOwner != address(0),
"Ownable: new owner is the zero address"
);
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)
/**
* @dev Contract module which allows children to implement an emergency stop
* mechanism that can be triggered by an authorized account.
*
* This module is used through inheritance. It will make available the
* modifiers `whenNotPaused` and `whenPaused`, which can be applied to
* the functions of your contract. Note that they will not be pausable by
* simply including this module, only once the modifiers are put in place.
*/
abstract contract Pausable is Context {
/**
* @dev Emitted when the pause is triggered by `account`.
*/
event Paused(address account);
/**
* @dev Emitted when the pause is lifted by `account`.
*/
event Unpaused(address account);
bool private _paused;
/**
* @dev Initializes the contract in unpaused state.
*/
constructor() {
_paused = false;
}
/**
* @dev Modifier to make a function callable only when the contract is not paused.
*
* Requirements:
*
* - The contract must not be paused.
*/
modifier whenNotPaused() {
_requireNotPaused();
_;
}
/**
* @dev Modifier to make a function callable only when the contract is paused.
*
* Requirements:
*
* - The contract must be paused.
*/
modifier whenPaused() {
_requirePaused();
_;
}
/**
* @dev Returns true if the contract is paused, and false otherwise.
*/
function paused() public view virtual returns (bool) {
return _paused;
}
/**
* @dev Throws if the contract is paused.
*/
function _requireNotPaused() internal view virtual {
require(!paused(), "Pausable: paused");
}
/**
* @dev Throws if the contract is not paused.
*/
function _requirePaused() internal view virtual {
require(paused(), "Pausable: not paused");
}
/**
* @dev Triggers stopped state.
*
* Requirements:
*
* - The contract must not be paused.
*/
function _pause() internal virtual whenNotPaused {
_paused = true;
emit Paused(_msgSender());
}
/**
* @dev Returns to normal state.
*
* Requirements:
*
* - The contract must be paused.
*/
function _unpause() internal virtual whenPaused {
_paused = false;
emit Unpaused(_msgSender());
}
}
// OpenZeppelin Contracts (last updated v4.7.0) (proxy/Clones.sol)
/**
* @dev https://eips.ethereum.org/EIPS/eip-1167[EIP 1167] is a standard for
* deploying minimal proxy contracts, also known as "clones".
*
* > To simply and cheaply clone contract functionality in an immutable way, this standard specifies
* > a minimal bytecode implementation that delegates all calls to a known, fixed address.
*
* The library includes functions to deploy a proxy using either `create` (traditional deployment) or `create2`
* (salted deterministic deployment). It also includes functions to predict the addresses of clones deployed using the
* deterministic method.
*
* _Available since v3.4._
*/
library Clones {
/**
* @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`.
*
* This function uses the create opcode, which should never revert.
*/
function clone(address implementation) internal returns (address instance) {
/// @solidity memory-safe-assembly
assembly {
let ptr := mload(0x40)
mstore(
ptr,
0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000
)
mstore(add(ptr, 0x14), shl(0x60, implementation))
mstore(
add(ptr, 0x28),
0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000
)
instance := create(0, ptr, 0x37)
}
require(instance != address(0), "ERC1167: create failed");
}
/**
* @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`.
*
* This function uses the create2 opcode and a `salt` to deterministically deploy
* the clone. Using the same `implementation` and `salt` multiple time will revert, since
* the clones cannot be deployed twice at the same address.
*/
function cloneDeterministic(address implementation, bytes32 salt)
internal
returns (address instance)
{
/// @solidity memory-safe-assembly
assembly {
let ptr := mload(0x40)
mstore(
ptr,
0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000
)
mstore(add(ptr, 0x14), shl(0x60, implementation))
mstore(
add(ptr, 0x28),
0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000
)
instance := create2(0, ptr, 0x37, salt)
}
require(instance != address(0), "ERC1167: create2 failed");
}
/**
* @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.
*/
function predictDeterministicAddress(
address implementation,
bytes32 salt,
address deployer
) internal pure returns (address predicted) {
/// @solidity memory-safe-assembly
assembly {
let ptr := mload(0x40)
mstore(
ptr,
0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000
)
mstore(add(ptr, 0x14), shl(0x60, implementation))
mstore(
add(ptr, 0x28),
0x5af43d82803e903d91602b57fd5bf3ff00000000000000000000000000000000
)
mstore(add(ptr, 0x38), shl(0x60, deployer))
mstore(add(ptr, 0x4c), salt)
mstore(add(ptr, 0x6c), keccak256(ptr, 0x37))
predicted := keccak256(add(ptr, 0x37), 0x55)
}
}
/**
* @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.
*/
function predictDeterministicAddress(address implementation, bytes32 salt)
internal
view
returns (address predicted)
{
return predictDeterministicAddress(implementation, salt, address(this));
}
}
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165Checker.sol)
/**
* @dev Library used to query support of an interface declared via {IERC165}.
*
* Note that these functions return the actual result of the query: they do not
* `revert` if an interface is not supported. It is up to the caller to decide
* what to do in these cases.
*/
library ERC165Checker {
// As per the EIP-165 spec, no interface should ever match 0xffffffff
bytes4 private constant _INTERFACE_ID_INVALID = 0xffffffff;
/**
* @dev Returns true if `account` supports the {IERC165} interface,
*/
function supportsERC165(address account) internal view returns (bool) {
// Any contract that implements ERC165 must explicitly indicate support of
// InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid
return
supportsERC165InterfaceUnchecked(
account,
type(IERC165).interfaceId
) &&
!supportsERC165InterfaceUnchecked(account, _INTERFACE_ID_INVALID);
}
/**
* @dev Returns true if `account` supports the interface defined by
* `interfaceId`. Support for {IERC165} itself is queried automatically.
*
* See {IERC165-supportsInterface}.
*/
function supportsInterface(address account, bytes4 interfaceId)
internal
view
returns (bool)
{
// query support of both ERC165 as per the spec and support of _interfaceId
return
supportsERC165(account) &&
supportsERC165InterfaceUnchecked(account, interfaceId);
}
/**
* @dev Returns a boolean array where each value corresponds to the
* interfaces passed in and whether they're supported or not. This allows
* you to batch check interfaces for a contract where your expectation
* is that some interfaces may not be supported.
*
* See {IERC165-supportsInterface}.
*
* _Available since v3.4._
*/
function getSupportedInterfaces(
address account,
bytes4[] memory interfaceIds
) internal view returns (bool[] memory) {
// an array of booleans corresponding to interfaceIds and whether they're supported or not
bool[] memory interfaceIdsSupported = new bool[](interfaceIds.length);
// query support of ERC165 itself
if (supportsERC165(account)) {
// query support of each interface in interfaceIds
for (uint256 i = 0; i < interfaceIds.length; i++) {
interfaceIdsSupported[i] = supportsERC165InterfaceUnchecked(
account,
interfaceIds[i]
);
}
}
return interfaceIdsSupported;
}
/**
* @dev Returns true if `account` supports all the interfaces defined in
* `interfaceIds`. Support for {IERC165} itself is queried automatically.
*
* Batch-querying can lead to gas savings by skipping repeated checks for
* {IERC165} support.
*
* See {IERC165-supportsInterface}.
*/
function supportsAllInterfaces(
address account,
bytes4[] memory interfaceIds
) internal view returns (bool) {
// query support of ERC165 itself
if (!supportsERC165(account)) {
return false;
}
// query support of each interface in _interfaceIds
for (uint256 i = 0; i < interfaceIds.length; i++) {
if (!supportsERC165InterfaceUnchecked(account, interfaceIds[i])) {
return false;
}
}
// all interfaces supported
return true;
}
/**
* @notice Query if a contract implements an interface, does not check ERC165 support
* @param account The address of the contract to query for support of an interface
* @param interfaceId The interface identifier, as specified in ERC-165
* @return true if the contract at account indicates support of the interface with
* identifier interfaceId, false otherwise
* @dev Assumes that account contains a contract that supports ERC165, otherwise
* the behavior of this method is undefined. This precondition can be checked
* with {supportsERC165}.
* Interface identification is specified in ERC-165.
*/
function supportsERC165InterfaceUnchecked(
address account,
bytes4 interfaceId
) internal view returns (bool) {
// prepare call
bytes memory encodedParams = abi.encodeWithSelector(
IERC165.supportsInterface.selector,
interfaceId
);
// perform static call
bool success;
uint256 returnSize;
uint256 returnValue;
assembly {
success := staticcall(
30000,
account,
add(encodedParams, 0x20),
mload(encodedParams),
0x00,
0x20
)
returnSize := returndatasize()
returnValue := mload(0x00)
}
return success && returnSize >= 0x20 && returnValue > 0;
}
}
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165Upgradeable {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC721/IERC721.sol)
/**
* @dev Required interface of an ERC721 compliant contract.
*/
interface IERC721Upgradeable is IERC165Upgradeable {
/**
* @dev Emitted when `tokenId` token is transferred from `from` to `to`.
*/
event Transfer(
address indexed from,
address indexed to,
uint256 indexed tokenId
);
/**
* @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
*/
event Approval(
address indexed owner,
address indexed approved,
uint256 indexed tokenId
);
/**
* @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
*/
event ApprovalForAll(
address indexed owner,
address indexed operator,
bool approved
);
/**
* @dev Returns the number of tokens in ``owner``'s account.
*/
function balanceOf(address owner) external view returns (uint256 balance);
/**
* @dev Returns the owner of the `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function ownerOf(uint256 tokenId) external view returns (address owner);
/**
* @dev Safely transfers `tokenId` token from `from` to `to`.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes calldata data
) external;
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
* are aware of the ERC721 protocol to prevent tokens from being forever locked.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) external;
/**
* @dev Transfers `tokenId` token from `from` to `to`.
*
* WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address from,
address to,
uint256 tokenId
) external;
/**
* @dev Gives permission to `to` to transfer `tokenId` token to another account.
* The approval is cleared when the token is transferred.
*
* Only a single account can be approved at a time, so approving the zero address clears previous approvals.
*
* Requirements:
*
* - The caller must own the token or be an approved operator.
* - `tokenId` must exist.
*
* Emits an {Approval} event.
*/
function approve(address to, uint256 tokenId) external;
/**
* @dev Approve or remove `operator` as an operator for the caller.
* Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
*
* Requirements:
*
* - The `operator` cannot be the caller.
*
* Emits an {ApprovalForAll} event.
*/
function setApprovalForAll(address operator, bool _approved) external;
/**
* @dev Returns the account approved for `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function getApproved(uint256 tokenId)
external
view
returns (address operator);
/**
* @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
*
* See {setApprovalForAll}
*/
function isApprovedForAll(address owner, address operator)
external
view
returns (bool);
}
// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)
/**
* @title ERC-721 Non-Fungible Token Standard, optional metadata extension
* @dev See https://eips.ethereum.org/EIPS/eip-721
*/
interface IERC721MetadataUpgradeable is IERC721Upgradeable {
/**
* @dev Returns the token collection name.
*/
function name() external view returns (string memory);
/**
* @dev Returns the token collection symbol.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.
*/
function tokenURI(uint256 tokenId) external view returns (string memory);
}
/**
* Interface for a Guard that governs whether a token can be minted, burned, or
* transferred by a particular operator, from a particular sender (`from` is
* address 0 iff the token is being minted), to a particular recipient (`to` is
* address 0 iff the token is being burned).
*/
interface IGuard {
/**
* @return True iff the transaction is allowed
* @param operator Transaction msg.sender
* @param from Token sender
* @param to Token recipient
* @param value Amount (ERC20) or token ID (ERC721)
*/
function isAllowed(
address operator,
address from,
address to,
uint256 value // amount (ERC20) or tokenId (ERC721)
) external view returns (bool);
}
interface ITokenEnforceable {
event ControlDisabled(address indexed controller);
event GuardLocked(
bool mintGuardLocked,
bool burnGuardLocked,
bool transferGuardLocked
);
event GuardUpdated(GuardType indexed guard, address indexed implementation);
event BatcherUpdated(address batcher);
/**
* @return The address of the transaction batcher used to batch calls over
* onlyOwner functions.
*/
function batcher() external view returns (address);
/**
* @return True iff the token contract owner is allowed to mint, burn, or
* transfer on behalf of arbitrary addresses.
*/
function isControllable() external view returns (bool);
/**
* @return The address of the Guard used to determine whether a mint is
* allowed. The contract at this address is assumed to implement the IGuard
* interface.
*/
function mintGuard() external view returns (IGuard);
/**
* @return The address of the Guard used to determine whether a burn is
* allowed. The contract at this address is assumed to implement the IGuard
* interface.
*/
function burnGuard() external view returns (IGuard);
/**
* @return The address of the Guard used to determine whether a transfer is
* allowed. The contract at this address is assumed to implement the IGuard
* interface.
*/
function transferGuard() external view returns (IGuard);
/**
* @return True iff the mint Guard cannot be changed.
*/
function mintGuardLocked() external view returns (bool);
/**
* @return True iff the burn Guard cannot be changed.
*/
function burnGuardLocked() external view returns (bool);
/**
* @return True iff the transfer Guard cannot be changed.
*/
function transferGuardLocked() external view returns (bool);
/**
* Irreversibly disables the token contract owner from minting, burning,
* and transferring on behalf of arbitrary addresses.
*
* Emits a `ControlDisabled` event.
*
* Requirements:
* - The caller must be the token contract owner.
*/
function disableControl() external;
/**
* Irreversibly prevents the token contract owner from changing the mint,
* burn, and/or transfer Guards.
*
* If at least one guard was requested to be locked, emits a `GuardLocked`
* event confirming whether each Guard is locked.
*
* Requirements:
* - The caller must be the owner.
* @param mintGuardLock If true, the mint Guard will be locked. If false,
* does nothing to the mint Guard.
* @param burnGuardLock If true, the mint Guard will be locked. If false,
* does nothing to the burn Guard.
* @param transferGuardLock If true, the mint Guard will be locked. If
* false, does nothing to the transfer Guard.
*/
function lockGuards(
bool mintGuardLock,
bool burnGuardLock,
bool transferGuardLock
) external;
/**
* Update the address of the batcher for batching calls over
* onlyOwner functions.
*
* Emits a `BatcherUpdated` event.
*
* Requirements:
* - The caller must be the token contract owner or the batcher.
* @param implementation Address of the batcher.
*/
function updateBatcher(address implementation) external;
/**
* Update the address of the Guard for minting. The contract at the
* passed-in address is assumed to implement the IGuard interface.
*
* Emits a `GuardUpdated` event with `GuardType.Mint`.
*
* Requirements:
* - The caller must be the token contract owner or the batcher.
* - The mint Guard must not be locked.
* @param implementation Address of mint Guard
*/
function updateMintGuard(address implementation) external;
/**
* Update the address of the Guard for burning. The contract at the
* passed-in address is assumed to implement the IGuard interface.
*
* Emits a `GuardUpdated` event with `GuardType.Burn`.
*
* Requirements:
* - The caller must be the token contract owner or the batcher.
* - The burn Guard must not be locked.
* @param implementation Address of new burn Guard
*/
function updateBurnGuard(address implementation) external;
/**
* Update the address of the Guard for transferring. The contract at the
* passed-in address is assumed to implement the IGuard interface.
*
* Emits a `GuardUpdated` event with `GuardType.Transfer`.
*
* Requirements:
* - The caller must be the token contract owner or the batcher.
* - The transfer Guard must not be locked.
* @param implementation Address of transfer Guard
*/
function updateTransferGuard(address implementation) external;
/**
* @return True iff a token can be minted, burned, or transferred by a
* particular operator, from a particular sender (`from` is address 0 iff
* the token is being minted), to a particular recipient (`to` is address 0
* iff the token is being burned).
* @param operator Transaction msg.sender
* @param from Token sender
* @param to Token recipient
* @param value Amount (ERC20) or token ID (ERC721)
*/
function isAllowed(
address operator,
address from,
address to,
uint256 value // amount (ERC20) or tokenId (ERC721)
) external view returns (bool);
/**
* @return owner The address of the token contract owner
*/
function owner() external view returns (address);
/**
* Transfers ownership of the contract to a new account (`newOwner`)
*
* Requirements:
* - The caller must be the current owner.
* @param newOwner Address that will become the owner
*/
function transferOwnership(address newOwner) external;
/**
* Leaves the contract without an owner. After calling this function, it
* will no longer be possible to call `onlyOwner` functions.
*
* Requirements:
* - The caller must be the current owner.
*/
function renounceOwnership() external;
}
enum GuardType {
Mint,
Burn,
Transfer
}
/**
* @title IERC1644 Controller Token Operation (part of the ERC1400 Security
* Token Standards)
*
* See https://github.com/ethereum/EIPs/issues/1644. Data and operatorData
* parameters were removed.
*/
interface IERC1644 {
event ControllerRedemption(
address account,
address indexed from,
uint256 value
);
event ControllerTransfer(
address controller,
address indexed from,
address indexed to,
uint256 value
);
/**
* Burns `tokenId` without checking whether the caller owns or is approved
* to spend the token.
*
* Requirements:
* - The caller must be the token contract owner.
* - `isControllable must be true.
* @param account The account whose token will be burned.
* @param value Amount (ERC20) or token ID (ERC721)
*/
function controllerRedeem(
address account,
uint256 value // amount (ERC20) or tokenId (ERC721))
) external;
/**
* Transfers `tokenId` token from `from` to `to`, without checking whether
* the caller owns or is approved to spend the token.
*
* Requirements:
* - The caller must be the token contract owner.
* - `isControllable` must be true.
* @param from The account sending the token.
* @param to The account to receive the token.
* @param value Amount (ERC20) or token ID (ERC721)
*/
function controllerTransfer(
address from,
address to,
uint256 value // amount (ERC20) or tokenId (ERC721)
) external;
}
/**
* Interface for functions defined in ERC721UpgradeableFork
*/
interface IERC721UpgradeableFork is IERC721MetadataUpgradeable {
/**
* @return ID of the next token that will be minted. Existing tokens are
* limited to IDs between `STARTING_TOKEN_ID` and `_nextTokenId` (including
* `STARTING_TOKEN_ID` and excluding `_nextTokenId`, though not all of these
* IDs may be in use if tokens have been burned).
*/
function nextTokenId() external view returns (uint256);
}
/**
* Interface for only functions defined in ERC721Collective (excludes inherited
* and overridden functions)
*/
interface IERC721CollectiveUnchained is IERC1644 {
event RendererUpdated(address indexed implementation);
event RendererLocked();
/**
* Initializes ERC721Collective.
* @param name_ Name of token
* @param symbol_ Symbol of token
* @param mintGuard_ Address of mint guard
* @param burnGuard_ Address of burn guard
* @param transferGuard_ Address of transfer guard
* @param renderer_ Address of renderer
*/
function __ERC721Collective_init(
string memory name_,
string memory symbol_,
address mintGuard_,
address burnGuard_,
address transferGuard_,
address renderer_
) external;
/**
* @return Number of currently-existing tokens (tokens that have been
* minted and that have not been burned).
*/
function totalSupply() external view returns (uint256);
// name(), symbol(), and tokenURI() overriding ERC721UpgradeableFork
// declared in IERC721Fork
/**
* @return The address of the token Renderer. The contract at this address
* is assumed to implement the IRenderer interface.
*/
function renderer() external view returns (address);
/**
* @return True iff the Renderer cannot be changed.
*/
function rendererLocked() external view returns (bool);
/**
* Update the address of the token Renderer. The contract at the passed-in
* address is assumed to implement the IRenderer interface.
*
* Emits a `RendererUpdated` event.
*
* Requirements:
* - The caller must be the token contract owner.
* - Renderer must not be locked.
* @param implementation Address of new Renderer
*/
function updateRenderer(address implementation) external;
/**
* Irreversibly prevents the token contract owner from changing the token
* Renderer.
*
* Emits a `RendererLocked` event.
*
* Requirements:
* - The caller must be the token contract owner.
*/
function lockRenderer() external;
// supportsInterface(bytes4 interfaceId) overriding ERC1644 declared in
// IERC1644
/**
* @return True after successfully executing mint and transfer of
* `nextTokenId` to `account`.
*
* Emits a `Transfer` event with `address(0)` as `from`.
*
* Requirements:
* - `account` cannot be the zero address.
* @param account The account to receive the minted token.
*/
function mintTo(address account) external returns (bool);
/**
* @return True after successfully bulk minting and transferring the
* `nextTokenId` through `nextTokenId + amount` tokens to `account`.
*
* Emits a `Transfer` event (with `address(0)` as `from`) for each token
* that is minted.
*
* Requirements:
* - `account` cannot be the zero address.
* @param account The account to receive the minted tokens.
* @param amount The number of tokens to be minted.
*/
function bulkMintToOneAddress(address account, uint256 amount)
external
returns (bool);
/**
* @return True after successfully bulk minting and transferring one of the
* `nextTokenId` through `nextTokenId + accounts.length` tokens to each of
* the addresses in `accounts`.
*
* Emits a `Transfer` event (with `address(0)` as `from`) for each token
* that is minted.
*
* Requirements:
* - `accounts` cannot have length 0.
* - None of the addresses in `accounts` can be the zero address.
* @param accounts The accounts to receive the minted tokens.
*/
function bulkMintToNAddresses(address[] calldata accounts)
external
returns (bool);
/**
* @return True after successfully burning `tokenId`.
*
* Emits a `Transfer` event with `address(0)` as `to`.
*
* Requirements:
* - The caller must either own or be approved to spend the `tokenId` token.
* - `tokenId` must exist.
* @param tokenId The tokenId to be burned.
*/
function redeem(uint256 tokenId) external returns (bool);
// controllerRedeem() and controllerTransfer() declared in IERC1644
}
/**
* Interface for all functions in ERC721Collective, including inherited and
* overridden functions
*/
interface IERC721Collective is
ITokenEnforceable,
IERC721UpgradeableFork,
IERC721CollectiveUnchained
{
}
/// Mixin can be used by any module using an address that should be an
/// ERC721Collective and needs to check if it indeed is one.
abstract contract ERC165CheckerERC721Collective {
/// Only proceed if collective implements IERC721Collective interface
/// @param collective collective to check
modifier onlyCollectiveInterface(address collective) {
_checkCollectiveInterface(collective);
_;
}
function _checkCollectiveInterface(address collective) internal view {
require(
ERC165Checker.supportsInterface(
collective,
type(IERC721Collective).interfaceId
),
"ERC165CheckerERC721Collective: collective address does not implement proper interface"
);
}
}
/**
* Factory for creating new Syndicate Collectives. The Collective token is
* cloned from a default Collective address and implements default guards
* and renderer.
*
* Copyright (c) 2021-present Syndicate Inc. All rights reserved.
*/
contract ERC721CollectiveFactory is
Ownable,
Pausable,
ERC165CheckerERC721Collective
{
address public collective;
address public mintGuard;
address public burnGuard;
address public transferGuard;
address public renderer;
uint256 public creationFee;
event ERC721CollectiveCreated(
address indexed collective,
string name,
string symbol,
bytes32 salt
);
event ERC721CollectiveFactoryImplementationsSet(
address indexed collective,
address mintGuard,
address burnGuard,
address transferGuard,
address renderer
);
event CreationFeeUpdated(uint256 indexed creationFee);
/**
* Configure factory with owner and set default guard contracts
* @param owner_ Address to make the factory owner
* @param collective_ Address of the deployed ERC721Collective
* token to be cloned
* @param mintGuard_ Address of mint guard contract
* @param burnGuard_ Address of burn guard contract
* @param transferGuard_ Address of transfer guard contract
* @param renderer_ Address of token renderer contract
*/
constructor(
address owner_,
address collective_,
address mintGuard_,
address burnGuard_,
address transferGuard_,
address renderer_
) Ownable() Pausable() {
setImplementations(
collective_,
mintGuard_,
burnGuard_,
transferGuard_,
renderer_
);
transferOwnership(owner_);
}
/// Set creation fee
/// @notice only the owner of the factory can set this
/// @param creationFee_ creation fee in wei
function setCreationFee(uint256 creationFee_) external onlyOwner {
creationFee = creationFee_;
emit CreationFeeUpdated(creationFee_);
}
/// Predict collective token address for given salt
/// @param salt Salt for determinisitic clone
/// @return token Address of token created with salt
function predictAddress(bytes32 salt) external view returns (address) {
return Clones.predictDeterministicAddress(collective, salt);
}
/**
* Create a new Collective via Clone
* @return token Address of new token
* @param name Name of token
* @param symbol Symbol of token
* @param salt random salt for deterministic token creation
* @param setupContracts array of contracts to setup
* @param data array of bytes for setup contract calls
*/
function create(
string memory name,
string memory symbol,
bytes32 salt,
address[] calldata setupContracts,
bytes[] calldata data
) external payable whenNotPaused returns (address token) {
if (creationFee > 0) {
require(
msg.value == creationFee,
"ERC721CollectiveFactory: Must send correct amount for creation fee"
);
(bool sent, ) = payable(this.owner()).call{value: msg.value}("");
require(
sent,
"ERC721CollectiveFactory: Failed to collect creation fee"
);
}
token = _clone(name, symbol, salt);
uint256 length = setupContracts.length;
for (uint256 i; i < length; ) {
// solhint-disable-next-line avoid-low-level-calls
(bool sent, ) = setupContracts[i].call(data[i]);
require(sent, "ERC721CollectiveFactory: Error making setup calls");
unchecked {
++i;
}
}
Ownable(token).transferOwnership(msg.sender);
}
/**
* Clone new CollectiveERC721 token
* @return token Address of new token
* @param name Name of token
* @param symbol Symbol of token
* @param salt random salt for deterministic token creation
*/
function _clone(
string memory name,
string memory symbol,
bytes32 salt
) internal whenNotPaused returns (address token) {
token = Clones.cloneDeterministic(collective, salt);
IERC721Collective(token).__ERC721Collective_init(
name,
symbol,
mintGuard,
burnGuard,
transferGuard,
renderer
);
emit ERC721CollectiveCreated(
token,
name,
string(abi.encodePacked(unicode"✺", symbol)),
salt
);
}
/**
* Set implementation addresses.
*
* Requirements:
* - Only the owner can call this function.
* - The `collective_` to clone must implement IERC721Collective.
* - The guards and renderer cannot be address 0.
* @param collective_ Address of the deployed ERC721Collective
* implementation to be cloned
* @param mintGuard_ Address of mint guard contract
* @param burnGuard_ Address of burn guard contract
* @param transferGuard_ Address of transfer guard contract
* @param renderer_ Address of token renderer contract
*/
function setImplementations(
address collective_,
address mintGuard_,
address burnGuard_,
address transferGuard_,
address renderer_
) public onlyOwner onlyCollectiveInterface(collective_) {
require(
mintGuard_ != address(0) &&
burnGuard_ != address(0) &&
transferGuard_ != address(0) &&
renderer_ != address(0),
"ERC721CollectiveFactory: implementations cannot be address(0)"
);
collective = collective_;
mintGuard = mintGuard_;
burnGuard = burnGuard_;
transferGuard = transferGuard_;
renderer = renderer_;
emit ERC721CollectiveFactoryImplementationsSet(
collective,
mintGuard,
burnGuard,
transferGuard,
renderer
);
}
/**
* Triggers paused state. Only accessible by the club owner.
*/
function pause() external onlyOwner {
_pause();
}
/**
* Returns to normal state. Only accessible by the club owner.
*/
function unpause() external onlyOwner {
_unpause();
}
/**
* This function is called for all messages sent to this contract (there
* are no other functions). Sending Ether to this contract will cause an
* exception, because the fallback function does not have the `payable`
* modifier.
* Source: https://docs.soliditylang.org/en/v0.8.9/contracts.html?highlight=fallback#fallback-function
*/
fallback() external {
revert("ERC721CollectiveFactory: non-existent function");
}
}
Read Contract
burnGuard 0x4a3f42b2 → address
collective 0x0479734f → address
creationFee 0xdce0b4e4 → uint256
mintGuard 0x319fc415 → address
owner 0x8da5cb5b → address
paused 0x5c975abb → bool
predictAddress 0x9c76b654 → address
renderer 0x8ada6b0f → address
transferGuard 0xfa4a389b → address
Write Contract 7 functions
These functions modify contract state and require a wallet transaction to execute.
create 0x77881972
string name
string symbol
bytes32 salt
address[] setupContracts
bytes[] data
returns: address
pause 0x8456cb59
No parameters
renounceOwnership 0x715018a6
No parameters
setCreationFee 0xb7d86225
uint256 creationFee_
setImplementations 0x8610292c
address collective_
address mintGuard_
address burnGuard_
address transferGuard_
address renderer_
transferOwnership 0xf2fde38b
address newOwner
unpause 0x3f4ba83a
No parameters
Recent Transactions
No transactions found for this address