Cryo Explorer Ethereum Mainnet

Address Contract Partially Verified

Address 0xc1d628B9170AD61Ed12F317F2146F099EB4E4727
Balance 0 ETH
Nonce 1785
Code Size 4838 bytes
Indexed Transactions 0
External Etherscan · Sourcify

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