ETH Price: $3,054.54 (+0.45%)

Contract

0xC0137140B2D2a146d20dBbb0153e5Ac1048f30E3

Overview

ETH Balance

0 ETH

ETH Value

$0.00

More Info

Private Name Tags

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To

There are no matching entries

Please try again later

Advanced mode:
Parent Transaction Hash Block From To
View All Internal Transactions

Cross-Chain Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
RMRKCatalogFactory

Compiler Version
v0.8.21+commit.d9974bed

Optimization Enabled:
Yes with 200 runs

Other Settings:
london EvmVersion, Apache-2.0 license
// SPDX-License-Identifier: Apache-2.0

pragma solidity ^0.8.21;

import {RMRKCatalogImpl} from "./RMRKCatalogImpl.sol";

/**
 * @title RMRKCatalogFactory
 * @author RMRK team
 * @notice Smart contract to deploy catalog implementations and keep track of deployers.
 */
contract RMRKCatalogFactory {
    mapping(address deployer => address[] catalogs) private _deployerCatalogs;

    event CatalogDeployed(address indexed deployer, address indexed catalog);

    /**
     * @notice Used to deploy a new RMRKCatalog implementation.
     * @param metadataURI Base metadata URI of the catalog
     * @param type_ The type of the catalog
     * @return The address of the deployed catalog
     */
    function deployCatalog(
        string memory metadataURI,
        string memory type_
    ) public returns (address) {
        RMRKCatalogImpl catalog = new RMRKCatalogImpl(metadataURI, type_);
        _deployerCatalogs[msg.sender].push(address(catalog));
        emit CatalogDeployed(msg.sender, address(catalog));
        return address(catalog);
    }

    /**
     * @notice Used to get all catalogs deployed by a given deployer.
     * @param deployer The address of the deployer
     * @return An array of addresses of the catalogs deployed by the deployer
     */
    function getDeployerCatalogs(
        address deployer
    ) public view returns (address[] memory) {
        return _deployerCatalogs[deployer];
    }

    /**
     * @notice Used to get the total number of catalogs deployed by a given deployer.
     * @param deployer The address of the deployer
     * @return total The total number of catalogs deployed by the deployer
     */
    function getTotalDeployerCatalogs(
        address deployer
    ) public view returns (uint256 total) {
        total = _deployerCatalogs[deployer].length;
    }

    /**
     * @notice Used to get a catalog deployed by a given deployer at a given index.
     * @param deployer The address of the deployer
     * @param index The index of the catalog
     * @return catalogAddress The address of the catalog
     */
    function getDeployerCatalogAtIndex(
        address deployer,
        uint256 index
    ) public view returns (address catalogAddress) {
        catalogAddress = _deployerCatalogs[deployer][index];
    }

    /**
     * @notice Used to get the last catalog deployed by a given deployer.
     * @param deployer The address of the deployer
     * @return catalogAddress The address of the last catalog deployed by the deployer
     */
    function getLastDeployerCatalog(
        address deployer
    ) public view returns (address catalogAddress) {
        catalogAddress = _deployerCatalogs[deployer][
            _deployerCatalogs[deployer].length - 1
        ];
    }
}

// SPDX-License-Identifier: Apache-2.0

pragma solidity ^0.8.21;

import {OwnableLock} from "../../RMRK/access/OwnableLock.sol";
import {RMRKCatalog, IERC165} from "../../RMRK/catalog/RMRKCatalog.sol";
import {IRMRKCatalogExtended} from "./IRMRKCatalogExtended.sol";

/**
 * @title RMRKCatalogImpl
 * @author RMRK team
 * @notice Implementation of RMRK catalog.
 * @dev Contract for storing 'catalog' elements of NFTs to be accessed by instances of RMRKAsset implementing contracts.
 *  This default implementation includes an OwnableLock dependency, which allows the deployer to freeze the state of the
 *  catalog contract.
 */
contract RMRKCatalogImpl is OwnableLock, RMRKCatalog, IRMRKCatalogExtended {
    /**
     * @notice Used to initialize the smart contract.
     * @param metadataURI Base metadata URI of the contract
     * @param type_ The type of the catalog
     */
    constructor(
        string memory metadataURI,
        string memory type_
    ) RMRKCatalog(metadataURI, type_) {}

    /**
     * @notice Used to add a single `Part` to storage.
     * @dev The full `IntakeStruct` looks like this:
     *  [
     *          partID,
     *      [
     *          itemType,
     *          z,
     *          [
     *               permittedCollectionAddress0,
     *               permittedCollectionAddress1,
     *               permittedCollectionAddress2
     *           ],
     *           metadataURI
     *       ]
     *   ]
     * @param intakeStruct `IntakeStruct` struct consisting of `partId` and a nested `Part` struct
     */
    function addPart(
        IntakeStruct memory intakeStruct
    ) public virtual onlyOwnerOrContributor notLocked {
        _addPart(intakeStruct);
    }

    /**
     * @notice Used to add multiple `Part`s to storage.
     * @dev The full `IntakeStruct` looks like this:
     *  [
     *          partID,
     *      [
     *          itemType,
     *          z,
     *          [
     *               permittedCollectionAddress0,
     *               permittedCollectionAddress1,
     *               permittedCollectionAddress2
     *           ],
     *           metadataURI
     *       ]
     *   ]
     * @param intakeStructs[] An array of `IntakeStruct` structs consisting of `partId` and a nested `Part` struct
     */
    function addPartList(
        IntakeStruct[] memory intakeStructs
    ) public virtual onlyOwnerOrContributor notLocked {
        _addPartList(intakeStructs);
    }

    /**
     * @notice Used to add multiple `equippableAddresses` to a single catalog entry.
     * @dev Can only be called on `Part`s of `Slot` type.
     * @param partId ID of the `Part` that we are adding the equippable addresses to
     * @param equippableAddresses An array of addresses that can be equipped into the `Part` associated with the `partId`
     */
    function addEquippableAddresses(
        uint64 partId,
        address[] memory equippableAddresses
    ) public virtual onlyOwnerOrContributor {
        _addEquippableAddresses(partId, equippableAddresses);
    }

    /**
     * @notice Function used to set the new list of `equippableAddresses`.
     * @dev Overwrites existing `equippableAddresses`.
     * @dev Can only be called on `Part`s of `Slot` type.
     * @param partId ID of the `Part`s that we are overwiting the `equippableAddresses` for
     * @param equippableAddresses A full array of addresses that can be equipped into this `Part`
     */
    function setEquippableAddresses(
        uint64 partId,
        address[] memory equippableAddresses
    ) public virtual onlyOwnerOrContributor {
        _setEquippableAddresses(partId, equippableAddresses);
    }

    /**
     * @notice Sets the isEquippableToAll flag to true, meaning that any collection may be equipped into the `Part` with
     *  this `partId`.
     * @dev Can only be called on `Part`s of `Slot` type.
     * @param partId ID of the `Part` that we are setting as equippable by any address
     */
    function setEquippableToAll(
        uint64 partId
    ) public virtual onlyOwnerOrContributor {
        _setEquippableToAll(partId);
    }

    /**
     * @notice Used to remove all of the `equippableAddresses` for a `Part` associated with the `partId`.
     * @dev Can only be called on `Part`s of `Slot` type.
     * @param partId ID of the part that we are clearing the `equippableAddresses` from
     */
    function resetEquippableAddresses(
        uint64 partId
    ) public virtual onlyOwnerOrContributor {
        _resetEquippableAddresses(partId);
    }

    /**
     * @inheritdoc IRMRKCatalogExtended
     */
    function getAllPartIds() public view returns (uint64[] memory partIds) {
        partIds = _partIds;
    }

    /**
     * @inheritdoc IRMRKCatalogExtended
     */
    function getPaginatedPartIds(
        uint256 offset,
        uint256 limit
    ) public view returns (uint64[] memory partIds) {
        if (offset >= _partIds.length) limit = 0; // Could revert but UI would have to handle it
        if (offset + limit > _partIds.length) limit = _partIds.length - offset;
        partIds = new uint64[](limit);
        for (uint256 i; i < limit; ) {
            partIds[i] = _partIds[offset + i];
            unchecked {
                ++i;
            }
        }
    }

    /**
     * @inheritdoc IRMRKCatalogExtended
     */
    function getTotalParts() public view returns (uint256 totalParts) {
        totalParts = _partIds.length;
    }

    /**
     * @inheritdoc IRMRKCatalogExtended
     */
    function getPartByIndex(
        uint256 index
    ) public view returns (Part memory part) {
        part = getPart(_partIds[index]);
    }

    /**
     * @inheritdoc IRMRKCatalogExtended
     */
    function setMetadataURI(
        string memory newContractURI
    ) public virtual onlyOwnerOrContributor {
        _setMetadataURI(newContractURI);
        emit ContractURIUpdated();
    }

    /**
     * @inheritdoc IRMRKCatalogExtended
     */
    function setType(
        string memory newType
    ) public virtual onlyOwnerOrContributor {
        _setType(newType);
        emit TypeUpdated(newType);
    }

    /**
     * @inheritdoc IERC165
     */
    function supportsInterface(
        bytes4 interfaceId
    ) public view virtual override(RMRKCatalog, IERC165) returns (bool) {
        return
            interfaceId == type(IRMRKCatalogExtended).interfaceId ||
            super.supportsInterface(interfaceId);
    }
}

// SPDX-License-Identifier: Apache-2.0

pragma solidity ^0.8.21;

import {Ownable} from "./Ownable.sol";
import "../library/RMRKErrors.sol";

/**
 * @title OwnableLock
 * @author RMRK team
 * @notice A minimal ownable lock smart contract.
 */
contract OwnableLock is Ownable {
    uint256 private _lock;

    /**
     * @notice Emitted when the smart contract is locked.
     */
    event LockSet();

    /**
     * @notice Reverts if the lock flag is set to true.
     */
    modifier notLocked() {
        _onlyNotLocked();
        _;
    }

    /**
     * @notice Locks the operation.
     * @dev Once locked, functions using `notLocked` modifier cannot be executed.
     * @dev Emits ***LockSet*** event.
     */
    function setLock() public virtual onlyOwner {
        _lock = 1;
        emit LockSet();
    }

    /**
     * @notice Used to retrieve the status of a lockable smart contract.
     * @return isLocked A boolean value signifying whether the smart contract has been locked
     */
    function getLock() public view returns (bool isLocked) {
        isLocked = _lock == 1;
    }

    /**
     * @notice Used to verify that the operation of the smart contract is not locked.
     * @dev If the operation of the smart contract is locked, the execution will be reverted.
     */
    function _onlyNotLocked() private view {
        if (_lock == 1) revert RMRKLocked();
    }
}

// SPDX-License-Identifier: Apache-2.0

pragma solidity ^0.8.21;

import {IRMRKCatalog, IERC165} from "./IRMRKCatalog.sol";
import {Address} from "@openzeppelin/contracts/utils/Address.sol";
import "../library/RMRKErrors.sol";

/**
 * @title RMRKCatalog
 * @author RMRK team
 * @notice Catalog contract for RMRK equippable module.
 */
contract RMRKCatalog is IRMRKCatalog {
    using Address for address;

    /**
     * @notice Mapping of uint64 `partId` to IRMRKCatalog `Part` struct
     */
    mapping(uint64 => Part) private _parts;

    /**
     * @notice Mapping of uint64 `partId` to boolean flag, indicating that a given `Part` can be equippable by any
     *  address
     */
    mapping(uint64 => bool) private _isEquippableToAll;

    uint64[] internal _partIds;
    string internal _metadataURI;
    string internal _type;

    /**
     * @notice Used to initialize the Catalog.
     * @param metadataURI Base metadata URI of the Catalog
     * @param type_ Type of Catalog
     */
    constructor(string memory metadataURI, string memory type_) {
        _setMetadataURI(metadataURI);
        _setType(type_);
    }

    /**
     * @notice Used to limit execution of functions intended for the `Slot` parts to only execute when used with such
     *  parts.
     * @dev Reverts execution of a function if the part with associated `partId` is uninitailized or is `Fixed`.
     * @param partId ID of the part that we want the function to interact with
     */
    modifier onlySlot(uint64 partId) {
        _onlySlot(partId);
        _;
    }

    /**
     * @notice Used to verify that an operation is only executed on slot Parts.
     * @dev If the Part is not Slot type, the execution will be reverted.
     * @param partId ID of the part to check
     */
    function _onlySlot(uint64 partId) private view {
        ItemType itemType = _parts[partId].itemType;
        if (itemType == ItemType.None) revert RMRKPartDoesNotExist();
        if (itemType == ItemType.Fixed) revert RMRKPartIsNotSlot();
    }

    /**
     * @inheritdoc IERC165
     */
    function supportsInterface(
        bytes4 interfaceId
    ) public view virtual returns (bool) {
        return
            interfaceId == type(IERC165).interfaceId ||
            interfaceId == type(IRMRKCatalog).interfaceId;
    }

    /**
     * @inheritdoc IRMRKCatalog
     */
    function getMetadataURI() external view returns (string memory) {
        return _metadataURI;
    }

    /**
     * @inheritdoc IRMRKCatalog
     */
    function getType() external view returns (string memory) {
        return _type;
    }

    /**
     * @notice Internal helper function that sets the base metadata URI of the contract.
     * @param metadataURI Base metadata URI of the contract
     */
    function _setMetadataURI(string memory metadataURI) internal {
        _metadataURI = metadataURI;
    }

    /**
     * @notice Internal helper function that sets the type of the contract.
     * @param type_ Type of the contract
     */
    function _setType(string memory type_) internal {
        _type = type_;
    }

    /**
     * @notice Internal helper function that adds `Part` entries to storage.
     * @dev Delegates to { _addPart } below.
     * @param partIntake An array of `IntakeStruct` structs, consisting of `partId` and a nested `Part` struct
     */
    function _addPartList(IntakeStruct[] memory partIntake) internal {
        uint256 len = partIntake.length;
        for (uint256 i; i < len; ) {
            _addPart(partIntake[i]);
            unchecked {
                ++i;
            }
        }
    }

    /**
     * @notice Internal function that adds a single `Part` to storage.
     * @param partIntake `IntakeStruct` struct consisting of `partId` and a nested `Part` struct
     *
     */
    function _addPart(IntakeStruct memory partIntake) internal {
        uint64 partId = partIntake.partId;
        Part memory part = partIntake.part;

        if (partId == uint64(0)) revert RMRKIdZeroForbidden();
        if (_parts[partId].itemType != ItemType.None)
            revert RMRKPartAlreadyExists();
        if (part.itemType == ItemType.None) revert RMRKBadConfig();
        if (part.itemType == ItemType.Fixed && part.equippable.length != 0)
            revert RMRKBadConfig();

        _parts[partId] = part;
        _partIds.push(partId);

        emit AddedPart(
            partId,
            part.itemType,
            part.z,
            part.equippable,
            part.metadataURI
        );
    }

    /**
     * @notice Internal function used to add multiple `equippableAddresses` to a single catalog entry.
     * @dev Can only be called on `Part`s of `Slot` type.
     * @dev Emits ***AddedEquippables*** event.
     * @param partId ID of the `Part` that we are adding the equippable addresses to
     * @param equippableAddresses An array of addresses that can be equipped into the `Part` associated with the `partId`
     */
    function _addEquippableAddresses(
        uint64 partId,
        address[] memory equippableAddresses
    ) internal onlySlot(partId) {
        if (equippableAddresses.length <= 0) revert RMRKZeroLengthIdsPassed();

        uint256 len = equippableAddresses.length;
        for (uint256 i; i < len; ) {
            _parts[partId].equippable.push(equippableAddresses[i]);
            unchecked {
                ++i;
            }
        }
        delete _isEquippableToAll[partId];

        emit AddedEquippables(partId, equippableAddresses);
    }

    /**
     * @notice Internal function used to set the new list of `equippableAddresses`.
     * @dev Overwrites existing `equippableAddresses`.
     * @dev Can only be called on `Part`s of `Slot` type.
     * @dev Emits ***SetEquippable*** event.
     * @param partId ID of the `Part`s that we are overwiting the `equippableAddresses` for
     * @param equippableAddresses A full array of addresses that can be equipped into this `Part`
     */
    function _setEquippableAddresses(
        uint64 partId,
        address[] memory equippableAddresses
    ) internal onlySlot(partId) {
        if (equippableAddresses.length <= 0) revert RMRKZeroLengthIdsPassed();
        _parts[partId].equippable = equippableAddresses;
        delete _isEquippableToAll[partId];

        emit SetEquippables(partId, equippableAddresses);
    }

    /**
     * @notice Internal function used to remove all of the `equippableAddresses` for a `Part` associated with the `partId`.
     * @dev Can only be called on `Part`s of `Slot` type.
     * @dev Emits ***SetEquippable*** event.
     * @param partId ID of the part that we are clearing the `equippableAddresses` from
     */
    function _resetEquippableAddresses(
        uint64 partId
    ) internal onlySlot(partId) {
        delete _parts[partId].equippable;
        delete _isEquippableToAll[partId];

        emit SetEquippables(partId, new address[](0));
    }

    /**
     * @notice Sets the isEquippableToAll flag to true, meaning that any collection may be equipped into the `Part` with this
     *  `partId`.
     * @dev Can only be called on `Part`s of `Slot` type.
     * @dev Emits ***SetEquippableToAll*** event.
     * @param partId ID of the `Part` that we are setting as equippable by any address
     */
    function _setEquippableToAll(uint64 partId) internal onlySlot(partId) {
        _isEquippableToAll[partId] = true;
        emit SetEquippableToAll(partId);
    }

    /**
     * @inheritdoc IRMRKCatalog
     */
    function checkIsEquippableToAll(
        uint64 partId
    ) public view returns (bool isEquippable) {
        isEquippable = _isEquippableToAll[partId];
    }

    /**
     * @inheritdoc IRMRKCatalog
     */
    function checkIsEquippable(
        uint64 partId,
        address targetAddress
    ) public view returns (bool isEquippable) {
        // If this is equippable to all, we're good
        isEquippable = _isEquippableToAll[partId];

        // Otherwise, must check against each of the equippable for the part
        if (!isEquippable && _parts[partId].itemType == ItemType.Slot) {
            address[] memory equippable = _parts[partId].equippable;
            uint256 len = equippable.length;
            for (uint256 i; i < len; ) {
                if (targetAddress == equippable[i]) {
                    isEquippable = true;
                    break;
                }
                unchecked {
                    ++i;
                }
            }
        }
    }

    /**
     * @inheritdoc IRMRKCatalog
     */
    function getPart(uint64 partId) public view returns (Part memory part) {
        part = (_parts[partId]);
    }

    /**
     * @inheritdoc IRMRKCatalog
     */
    function getParts(
        uint64[] memory partIds
    ) public view returns (Part[] memory parts) {
        uint256 numParts = partIds.length;
        parts = new Part[](numParts);

        for (uint256 i; i < numParts; ) {
            uint64 partId = partIds[i];
            parts[i] = _parts[partId];
            unchecked {
                ++i;
            }
        }
    }
}

// SPDX-License-Identifier: Apache-2.0

pragma solidity ^0.8.21;

import {IRMRKCatalog} from "../../RMRK/catalog/IRMRKCatalog.sol";

/**
 * @title IRMRKCatalogExtended
 * @author RMRK team
 * @notice An extended interface for Catalog for RMRK equippable module.
 */
interface IRMRKCatalogExtended is IRMRKCatalog {
    /**
     * @notice From ERC7572 (Draft) Emitted when the contract-level metadata is updated
     */
    event ContractURIUpdated();

    /**
     * @notice Emited when the type of the catalog is updated
     * @param newType The new type of the catalog
     */
    event TypeUpdated(string newType);

    /**
     * @notice Used to get all the part IDs in the catalog.
     * @dev Can get at least 10k parts. Higher limits were not tested.
     * @dev It may fail if there are too many parts, in that case use either `getPaginatedPartIds` or `getTotalParts` and `getPartByIndex`.
     * @return partIds An array of all the part IDs in the catalog
     */
    function getAllPartIds() external view returns (uint64[] memory partIds);

    /**
     * @notice Used to get all the part IDs in the catalog.
     * @param offset The offset to start from
     * @param limit The maximum number of parts to return
     * @return partIds An array of all the part IDs in the catalog
     */
    function getPaginatedPartIds(
        uint256 offset,
        uint256 limit
    ) external view returns (uint64[] memory partIds);

    /**
     * @notice Used to get the total number of parts in the catalog.
     * @return totalParts The total number of parts in the catalog
     */
    function getTotalParts() external view returns (uint256 totalParts);

    /**
     * @notice Used to get a single `Part` by the index of its `partId`.
     * @param index The index of the `partId`.
     * @return part The `Part` struct associated with the `partId` at the given index
     */
    function getPartByIndex(
        uint256 index
    ) external view returns (Part memory part);

    /**
     * @notice Used to set the metadata URI of the catalog.
     * @param newContractURI The new metadata URI
     * @dev emits `ContractURIUpdated` event
     */
    function setMetadataURI(string memory newContractURI) external;

    /**
     * @notice Used to set the type of the catalog.
     * @param newType The new type of the catalog
     * @dev emits `TypeUpdated` event
     */
    function setType(string memory newType) external;
}

// SPDX-License-Identifier: Apache-2.0

pragma solidity ^0.8.21;

import {Context} from "@openzeppelin/contracts/utils/Context.sol";
import "../library/RMRKErrors.sol";

/**
 * @title Ownable
 * @author RMRK team
 * @notice A minimal ownable smart contract or owner and contributors.
 * @dev This smart contract is based on "openzeppelin's access/Ownable.sol".
 */
contract Ownable is Context {
    address private _owner;
    mapping(address => uint256) private _contributors;

    /**
     * @notice Used to anounce the transfer of ownership.
     * @param previousOwner Address of the account that transferred their ownership role
     * @param newOwner Address of the account receiving the ownership role
     */
    event OwnershipTransferred(
        address indexed previousOwner,
        address indexed newOwner
    );

    /**
     * @notice Event that signifies that an address was granted contributor role or that the permission has been
     *  revoked.
     * @dev This can only be triggered by a current owner, so there is no need to include that information in the event.
     * @param contributor Address of the account that had contributor role status updated
     * @param isContributor A boolean value signifying whether the role has been granted (`true`) or revoked (`false`)
     */
    event ContributorUpdate(address indexed contributor, bool isContributor);

    /**
     * @dev Reverts if called by any account other than the owner or an approved contributor.
     */
    modifier onlyOwnerOrContributor() {
        _onlyOwnerOrContributor();
        _;
    }

    /**
     * @dev Reverts if called by any account other than the owner.
     */
    modifier onlyOwner() {
        _onlyOwner();
        _;
    }

    /**
     * @dev Initializes the contract by setting the deployer as the initial owner.
     */
    constructor() {
        _transferOwnership(_msgSender());
    }

    /**
     * @notice Returns the address of the current owner.
     * @return owner_ Address of the current owner
     */
    function owner() public view virtual returns (address owner_) {
        owner_ = _owner;
    }

    /**
     * @notice Leaves the contract without owner. Functions using the `onlyOwner` modifier will be disabled.
     * @dev Can only be called by the current owner.
     * @dev 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));
    }

    /**
     * @notice Transfers ownership of the contract to a new owner.
     * @dev Can only be called by the current owner.
     * @param newOwner Address of the new owner's account
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        if (newOwner == address(0)) revert RMRKNewOwnerIsZeroAddress();
        _transferOwnership(newOwner);
    }

    /**
     * @notice Transfers ownership of the contract to a new owner.
     * @dev Internal function without access restriction.
     * @dev Emits ***OwnershipTransferred*** event.
     * @param newOwner Address of the new owner's account
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }

    /**
     * @notice Adds or removes a contributor to the smart contract.
     * @dev Can only be called by the owner.
     * @dev Emits ***ContributorUpdate*** event.
     * @param contributor Address of the contributor's account
     * @param grantRole A boolean value signifying whether the contributor role is being granted (`true`) or revoked
     *  (`false`)
     */
    function manageContributor(
        address contributor,
        bool grantRole
    ) external onlyOwner {
        if (contributor == address(0)) revert RMRKNewContributorIsZeroAddress();
        grantRole
            ? _contributors[contributor] = 1
            : _contributors[contributor] = 0;
        emit ContributorUpdate(contributor, grantRole);
    }

    /**
     * @notice Used to check if the address is one of the contributors.
     * @param contributor Address of the contributor whose status we are checking
     * @return isContributor_ Boolean value indicating whether the address is a contributor or not
     */
    function isContributor(
        address contributor
    ) public view returns (bool isContributor_) {
        isContributor_ = _contributors[contributor] == 1;
    }

    /**
     * @notice Used to verify that the caller is either the owner or a contributor.
     * @dev If the caller is not the owner or a contributor, the execution will be reverted.
     */
    function _onlyOwnerOrContributor() private view {
        if (owner() != _msgSender() && !isContributor(_msgSender()))
            revert RMRKNotOwnerOrContributor();
    }

    /**
     * @notice Used to verify that the caller is the owner.
     * @dev If the caller is not the owner, the execution will be reverted.
     */
    function _onlyOwner() private view {
        if (owner() != _msgSender()) revert RMRKNotOwner();
    }
}

File 7 of 11 : RMRKErrors.sol
// SPDX-License-Identifier: Apache-2.0

pragma solidity ^0.8.21;

/// @title RMRKErrors
/// @author RMRK team
/// @notice A collection of errors used in the RMRK suite
/// @dev Errors are kept in a centralised file in order to provide a central point of reference and to avoid error
///  naming collisions due to inheritance

/// Attempting to grant the token to 0x0 address
error ERC721AddressZeroIsNotaValidOwner();
/// Attempting to grant approval to the current owner of the token
error ERC721ApprovalToCurrentOwner();
/// Attempting to grant approval when not being owner or approved for all should not be permitted
error ERC721ApproveCallerIsNotOwnerNorApprovedForAll();
/// Attempting to grant approval to self
error ERC721ApproveToCaller();
/// Attempting to use an invalid token ID
error ERC721InvalidTokenId();
/// Attempting to mint to 0x0 address
error ERC721MintToTheZeroAddress();
/// Attempting to manage a token without being its owner or approved by the owner
error ERC721NotApprovedOrOwner();
/// Attempting to mint an already minted token
error ERC721TokenAlreadyMinted();
/// Attempting to transfer the token from an address that is not the owner
error ERC721TransferFromIncorrectOwner();
/// Attempting to safe transfer to an address that is unable to receive the token
error ERC721TransferToNonReceiverImplementer();
/// Attempting to transfer the token to a 0x0 address
error ERC721TransferToTheZeroAddress();
/// Attempting to grant approval of assets to their current owner
error RMRKApprovalForAssetsToCurrentOwner();
/// Attempting to grant approval of assets without being the caller or approved for all
error RMRKApproveForAssetsCallerIsNotOwnerNorApprovedForAll();
/// Attempting to incorrectly configue a Catalog item
error RMRKBadConfig();
/// Attempting to set the priorities with an array of length that doesn't match the length of active assets array
error RMRKBadPriorityListLength();
/// Attempting to add an asset entry with `Part`s, without setting the `Catalog` address
error RMRKCatalogRequiredForParts();
/// Attempting to transfer a soulbound (non-transferrable) token
error RMRKCannotTransferSoulbound();
/// Attempting to accept a child that has already been accepted
error RMRKChildAlreadyExists();
/// Attempting to interact with a child, using index that is higher than the number of children
error RMRKChildIndexOutOfRange();
/// Attempting to find the index of a child token on a parent which does not own it.
error RMRKChildNotFoundInParent();
/// Attempting to equip a `Part` with a child not approved by the Catalog
error RMRKEquippableEquipNotAllowedByCatalog();
/// Attempting to use ID 0, which is not supported
/// @dev The ID 0 in RMRK suite is reserved for empty values. Guarding against its use ensures the expected operation
error RMRKIdZeroForbidden();
/// Attempting to interact with an asset, using index greater than number of assets
error RMRKIndexOutOfRange();
/// Attempting to reclaim a child that can't be reclaimed
error RMRKInvalidChildReclaim();
/// Attempting to interact with an end-user account when the contract account is expected
error RMRKIsNotContract();
/// Attempting to interact with a contract that had its operation locked
error RMRKLocked();
/// Attempting to add a pending child after the number of pending children has reached the limit (default limit is 128)
error RMRKMaxPendingChildrenReached();
/// Attempting to add a pending asset after the number of pending assets has reached the limit (default limit is
///  128)
error RMRKMaxPendingAssetsReached();
/// Attempting to burn a total number of recursive children higher than maximum set
/// @param childContract Address of the collection smart contract in which the maximum number of recursive burns was reached
/// @param childId ID of the child token at which the maximum number of recursive burns was reached
error RMRKMaxRecursiveBurnsReached(address childContract, uint256 childId);
/// Attempting to mint a number of tokens that would cause the total supply to be greater than maximum supply
error RMRKMintOverMax();
/// Attempting to mint zero tokens
error RMRKMintZero();
/// Attempting to pass complementary arrays of different lengths
error RMRKMismachedArrayLength();
/// Attempting to transfer a child before it is unequipped
error RMRKMustUnequipFirst();
/// Attempting to nest a child over the nestable limit (current limit is 100 levels of nesting)
error RMRKNestableTooDeep();
/// Attempting to nest the token to own descendant, which would create a loop and leave the looped tokens in limbo
error RMRKNestableTransferToDescendant();
/// Attempting to nest the token to a smart contract that doesn't support nesting
error RMRKNestableTransferToNonRMRKNestableImplementer();
/// Attempting to nest the token into itself
error RMRKNestableTransferToSelf();
/// Attempting to interact with an asset that can not be found
error RMRKNoAssetMatchingId();
/// Attempting to manage an asset without owning it or having been granted permission by the owner to do so
error RMRKNotApprovedForAssetsOrOwner();
/// Attempting to interact with a token without being its owner or having been granted permission by the
///  owner to do so
/// @dev When a token is nested, only the direct owner (NFT parent) can mange it. In that case, approved addresses are
///  not allowed to manage it, in order to ensure the expected behaviour
error RMRKNotApprovedOrDirectOwner();
/// Attempting to compose an asset wihtout having an associated Catalog
error RMRKNotComposableAsset();
/// Attempting to unequip an item that isn't equipped
error RMRKNotEquipped();
/// Attempting to interact with a management function without being the smart contract's owner
error RMRKNotOwner();
/// Attempting to interact with a function without being the owner or contributor of the collection
error RMRKNotOwnerOrContributor();
/// Attempting to transfer the ownership to the 0x0 address
error RMRKNewOwnerIsZeroAddress();
/// Attempting to assign a 0x0 address as a contributor
error RMRKNewContributorIsZeroAddress();
/// Attempting an operation requiring the token being nested, while it is not
error RMRKParentIsNotNFT();
/// Attempting to add a `Part` with an ID that is already used
error RMRKPartAlreadyExists();
/// Attempting to use a `Part` that doesn't exist
error RMRKPartDoesNotExist();
/// Attempting to use a `Part` that is `Fixed` when `Slot` kind of `Part` should be used
error RMRKPartIsNotSlot();
/// Attempting to interact with a pending child using an index greater than the size of pending array
error RMRKPendingChildIndexOutOfRange();
/// Attempting to add an asset using an ID that has already been used
error RMRKAssetAlreadyExists();
/// Attempting to equip an item into a slot that already has an item equipped
error RMRKSlotAlreadyUsed();
/// Attempting to equip an item into a `Slot` that the target asset does not implement
error RMRKTargetAssetCannotReceiveSlot();
/// Attempting to equip a child into a `Slot` and parent that the child's collection doesn't support
error RMRKTokenCannotBeEquippedWithAssetIntoSlot();
/// Attempting to compose a NFT of a token without active assets
error RMRKTokenDoesNotHaveAsset();
/// Attempting to determine the asset with the top priority on a token without assets
error RMRKTokenHasNoAssets();
/// Attempting to accept or transfer a child which does not match the one at the specified index
error RMRKUnexpectedChildId();
/// Attempting to reject all pending assets but more assets than expected are pending
error RMRKUnexpectedNumberOfAssets();
/// Attempting to reject all pending children but children assets than expected are pending
error RMRKUnexpectedNumberOfChildren();
/// Attempting to accept or reject an asset which does not match the one at the specified index
error RMRKUnexpectedAssetId();
/// Attempting an operation expecting a parent to the token which is not the actual one
error RMRKUnexpectedParent();
/// Attempting not to pass an empty array of equippable addresses when adding or setting the equippable addresses
error RMRKZeroLengthIdsPassed();
/// Attempting to set the royalties to a value higher than 100% (10000 in basis points)
error RMRKRoyaltiesTooHigh();
/// Attempting to do a bulk operation on a token that is not owned by the caller
error RMRKCanOnlyDoBulkOperationsOnOwnedTokens();
/// Attempting to do a bulk operation with multiple tokens at a time
error RMRKCanOnlyDoBulkOperationsWithOneTokenAtATime();
/// Attempting to pay with native token with a value different than expected
error RMRKWrongValueSent();
// Attempting to send native token to a recipient that is unable to receive it
error TransferFailed();

// SPDX-License-Identifier: Apache-2.0

pragma solidity ^0.8.21;

import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol";

/**
 * @title IRMRKCatalog
 * @author RMRK team
 * @notice An interface Catalog for RMRK equippable module.
 */
interface IRMRKCatalog is IERC165 {
    /**
     * @notice Event to announce addition of a new part.
     * @dev It is emitted when a new part is added.
     * @param partId ID of the part that was added
     * @param itemType Enum value specifying whether the part is `None`, `Slot` and `Fixed`
     * @param zIndex An uint specifying the z value of the part. It is used to specify the depth which the part should
     *  be rendered at
     * @param equippableAddresses An array of addresses that can equip this part
     * @param metadataURI The metadata URI of the part
     */
    event AddedPart(
        uint64 indexed partId,
        ItemType indexed itemType,
        uint8 zIndex,
        address[] equippableAddresses,
        string metadataURI
    );

    /**
     * @notice Event to announce new equippables to the part.
     * @dev It is emitted when new addresses are marked as equippable for `partId`.
     * @param partId ID of the part that had new equippable addresses added
     * @param equippableAddresses An array of the new addresses that can equip this part
     */
    event AddedEquippables(
        uint64 indexed partId,
        address[] equippableAddresses
    );

    /**
     * @notice Event to announce the overriding of equippable addresses of the part.
     * @dev It is emitted when the existing list of addresses marked as equippable for `partId` is overwritten by a new one.
     * @param partId ID of the part whose list of equippable addresses was overwritten
     * @param equippableAddresses The new, full, list of addresses that can equip this part
     */
    event SetEquippables(uint64 indexed partId, address[] equippableAddresses);

    /**
     * @notice Event to announce that a given part can be equipped by any address.
     * @dev It is emitted when a given part is marked as equippable by any.
     * @param partId ID of the part marked as equippable by any address
     */
    event SetEquippableToAll(uint64 indexed partId);

    /**
     * @notice Used to define a type of the item. Possible values are `None`, `Slot` or `Fixed`.
     * @dev Used for fixed and slot parts.
     */
    enum ItemType {
        None,
        Slot,
        Fixed
    }

    /**
     * @notice The integral structure of a standard RMRK catalog item defining it.
     * @dev Requires a minimum of 3 storage slots per catalog item, equivalent to roughly 60,000 gas as of Berlin hard
     *  fork (April 14, 2021), though 5-7 storage slots is more realistic, given the standard length of an IPFS URI.
     *  This will result in between 25,000,000 and 35,000,000 gas per 250 assets--the maximum block size of Ethereum
     *  mainnet is 30M at peak usage.
     * @return itemType The item type of the part
     * @return z The z value of the part defining how it should be rendered when presenting the full NFT
     * @return equippable The array of addresses allowed to be equipped in this part
     * @return metadataURI The metadata URI of the part
     */
    struct Part {
        ItemType itemType; //1 byte
        uint8 z; //1 byte
        address[] equippable; //n Collections that can be equipped into this slot
        string metadataURI; //n bytes 32+
    }

    /**
     * @notice The structure used to add a new `Part`.
     * @dev The part is added with specified ID, so you have to make sure that you are using an unused `partId`,
     *  otherwise the addition of the part vill be reverted.
     * @dev The full `IntakeStruct` looks like this:
     *  [
     *          partID,
     *      [
     *          itemType,
     *          z,
     *          [
     *               permittedCollectionAddress0,
     *               permittedCollectionAddress1,
     *               permittedCollectionAddress2
     *           ],
     *           metadataURI
     *       ]
     *   ]
     * @return partId ID to be assigned to the `Part`
     * @return part A `Part` to be added
     */
    struct IntakeStruct {
        uint64 partId;
        Part part;
    }

    /**
     * @notice Used to return the metadata URI of the associated Catalog.
     * @return Catalog metadata URI
     */
    function getMetadataURI() external view returns (string memory);

    /**
     * @notice Used to return the `itemType` of the associated Catalog
     * @return `itemType` of the associated Catalog
     */
    function getType() external view returns (string memory);

    /**
     * @notice Used to check whether the given address is allowed to equip the desired `Part`.
     * @dev Returns true if a collection may equip asset with `partId`.
     * @param partId The ID of the part that we are checking
     * @param targetAddress The address that we are checking for whether the part can be equipped into it or not
     * @return isEquippable The status indicating whether the `targetAddress` can be equipped into `Part` with `partId` or not
     */
    function checkIsEquippable(
        uint64 partId,
        address targetAddress
    ) external view returns (bool isEquippable);

    /**
     * @notice Used to check if the part is equippable by all addresses.
     * @dev Returns true if part is equippable to all.
     * @param partId ID of the part that we are checking
     * @return isEquippableToAll The status indicating whether the part with `partId` can be equipped by any address or not
     */
    function checkIsEquippableToAll(
        uint64 partId
    ) external view returns (bool isEquippableToAll);

    /**
     * @notice Used to retrieve a `Part` with id `partId`
     * @param partId ID of the part that we are retrieving
     * @return part The `Part` struct associated with given `partId`
     */
    function getPart(uint64 partId) external view returns (Part memory part);

    /**
     * @notice Used to retrieve multiple parts at the same time.
     * @param partIds An array of part IDs that we want to retrieve
     * @return part An array of `Part` structs associated with given `partIds`
     */
    function getParts(
        uint64[] memory partIds
    ) external view returns (Part[] memory part);
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)

pragma solidity ^0.8.20;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev The ETH balance of the account is not enough to perform the operation.
     */
    error AddressInsufficientBalance(address account);

    /**
     * @dev There's no code at `target` (it is not a contract).
     */
    error AddressEmptyCode(address target);

    /**
     * @dev A call to an address target failed. The target may have reverted.
     */
    error FailedInnerCall();

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        if (address(this).balance < amount) {
            revert AddressInsufficientBalance(address(this));
        }

        (bool success, ) = recipient.call{value: amount}("");
        if (!success) {
            revert FailedInnerCall();
        }
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain `call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason or custom error, it is bubbled
     * up by this function (like regular Solidity function calls). However, if
     * the call reverted with no returned reason, this function reverts with a
     * {FailedInnerCall} error.
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
        if (address(this).balance < value) {
            revert AddressInsufficientBalance(address(this));
        }
        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResultFromTarget(target, success, returndata);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResultFromTarget(target, success, returndata);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     */
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResultFromTarget(target, success, returndata);
    }

    /**
     * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target
     * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an
     * unsuccessful call.
     */
    function verifyCallResultFromTarget(
        address target,
        bool success,
        bytes memory returndata
    ) internal view returns (bytes memory) {
        if (!success) {
            _revert(returndata);
        } else {
            // only check if target is a contract if the call was successful and the return data is empty
            // otherwise we already know that it was a contract
            if (returndata.length == 0 && target.code.length == 0) {
                revert AddressEmptyCode(target);
            }
            return returndata;
        }
    }

    /**
     * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the
     * revert reason or with a default {FailedInnerCall} error.
     */
    function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {
        if (!success) {
            _revert(returndata);
        } else {
            return returndata;
        }
    }

    /**
     * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.
     */
    function _revert(bytes memory returndata) private pure {
        // Look for revert reason and bubble it up if present
        if (returndata.length > 0) {
            // The easiest way to bubble the revert reason is using memory via assembly
            /// @solidity memory-safe-assembly
            assembly {
                let returndata_size := mload(returndata)
                revert(add(32, returndata), returndata_size)
            }
        } else {
            revert FailedInnerCall();
        }
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)

pragma solidity ^0.8.20;

/**
 * @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;
    }

    function _contextSuffixLength() internal view virtual returns (uint256) {
        return 0;
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)

pragma solidity ^0.8.20;

/**
 * @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);
}

Settings
{
  "remappings": [
    "@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/",
    "@rmrk-team/evm-contracts/=contracts/",
    "hardhat/=node_modules/hardhat/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "ipfs",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "abi"
      ]
    }
  },
  "evmVersion": "london",
  "viaIR": false
}

Contract Security Audit

Contract ABI

API
[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"deployer","type":"address"},{"indexed":true,"internalType":"address","name":"catalog","type":"address"}],"name":"CatalogDeployed","type":"event"},{"inputs":[{"internalType":"string","name":"metadataURI","type":"string"},{"internalType":"string","name":"type_","type":"string"}],"name":"deployCatalog","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"deployer","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getDeployerCatalogAtIndex","outputs":[{"internalType":"address","name":"catalogAddress","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"deployer","type":"address"}],"name":"getDeployerCatalogs","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"deployer","type":"address"}],"name":"getLastDeployerCatalog","outputs":[{"internalType":"address","name":"catalogAddress","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"deployer","type":"address"}],"name":"getTotalDeployerCatalogs","outputs":[{"internalType":"uint256","name":"total","type":"uint256"}],"stateMutability":"view","type":"function"}]

608060405234801561001057600080fd5b506127e2806100206000396000f3fe60806040523480156200001157600080fd5b50600436106200005e5760003560e01c806327126e6914620000635780634e89276214620000975780637c8f649a14620000bd578063a3911df114620000f8578063d9a8a509146200010f575b600080fd5b6200007a6200007436600462000314565b62000126565b6040516001600160a01b0390911681526020015b60405180910390f35b620000ae620000a836600462000314565b6200017c565b6040516200008e919062000339565b620000e9620000ce36600462000314565b6001600160a01b031660009081526020819052604090205490565b6040519081526020016200008e565b6200007a6200010936600462000433565b620001f2565b6200007a620001203660046200049e565b620002a0565b6001600160a01b038116600090815260208190526040812080546200014e90600190620004cb565b81548110620001615762000161620004ed565b6000918252602090912001546001600160a01b031692915050565b6001600160a01b03811660009081526020818152604091829020805483518184028101840190945280845260609392830182828015620001e657602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311620001c7575b50505050509050919050565b60008083836040516200020590620002e9565b620002129291906200054b565b604051809103906000f0801580156200022f573d6000803e3d6000fd5b5033600081815260208181526040808320805460018101825590845291832090910180546001600160a01b0319166001600160a01b0386169081179091559051939450927f80108d1aca0caf8fcea04ffec0df23d37b689913b24cd81a4f6463c99b92f63e9190a390505b92915050565b6001600160a01b0382166000908152602081905260408120805483908110620002cd57620002cd620004ed565b6000918252602090912001546001600160a01b03169392505050565b61222f806200057e83390190565b80356001600160a01b03811681146200030f57600080fd5b919050565b6000602082840312156200032757600080fd5b6200033282620002f7565b9392505050565b6020808252825182820181905260009190848201906040850190845b818110156200037c5783516001600160a01b03168352928401929184019160010162000355565b50909695505050505050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620003b057600080fd5b813567ffffffffffffffff80821115620003ce57620003ce62000388565b604051601f8301601f19908116603f01168101908282118183101715620003f957620003f962000388565b816040528381528660208588010111156200041357600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080604083850312156200044757600080fd5b823567ffffffffffffffff808211156200046057600080fd5b6200046e868387016200039e565b935060208501359150808211156200048557600080fd5b5062000494858286016200039e565b9150509250929050565b60008060408385031215620004b257600080fd5b620004bd83620002f7565b946020939093013593505050565b818103818111156200029a57634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b6000815180845260005b818110156200052b576020818501810151868301820152016200050d565b506000602082860101526020601f19601f83011685010191505092915050565b60408152600062000560604083018562000503565b828103602084015262000574818562000503565b9594505050505056fe60806040523480156200001157600080fd5b506040516200222f3803806200222f833981016040819052620000349162000196565b8181620000413362000061565b6200004c82620000b1565b6200005781620000c3565b505050506200035b565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6006620000bf82826200028f565b5050565b6007620000bf82826200028f565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620000f957600080fd5b81516001600160401b0380821115620001165762000116620000d1565b604051601f8301601f19908116603f01168101908282118183101715620001415762000141620000d1565b816040528381526020925086838588010111156200015e57600080fd5b600091505b8382101562000182578582018301518183018401529082019062000163565b600093810190920192909252949350505050565b60008060408385031215620001aa57600080fd5b82516001600160401b0380821115620001c257600080fd5b620001d086838701620000e7565b93506020850151915080821115620001e757600080fd5b50620001f685828601620000e7565b9150509250929050565b600181811c908216806200021557607f821691505b6020821081036200023657634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200028a57600081815260208120601f850160051c81016020861015620002655750805b601f850160051c820191505b81811015620002865782815560010162000271565b5050505b505050565b81516001600160401b03811115620002ab57620002ab620000d1565b620002c381620002bc845462000200565b846200023c565b602080601f831160018114620002fb5760008415620002e25750858301515b600019600386901b1c1916600185901b17855562000286565b600085815260208120601f198616915b828110156200032c578886015182559484019460019091019084016200030b565b50858210156200034b5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b611ec4806200036b6000396000f3fe608060405234801561001057600080fd5b506004361061018e5760003560e01c8063867cc5c4116100de578063b9cd295911610097578063dc477d2f11610071578063dc477d2f14610361578063dcb79d561461038d578063f005548c146103a0578063f2fde38b146103b357600080fd5b8063b9cd295914610333578063ba146b2814610346578063d297ac431461034e57600080fd5b8063867cc5c4146102aa57806386a92af7146102bd5780638da5cb5b146102c55780638f7e7b49146102e057806396282ba3146103005780639806c6ec1461031357600080fd5b80636c508e661161014b578063750521f511610125578063750521f51461027157806379e8ca9e146102845780637aba6f37146102975780637e5852d91461029f57600080fd5b80636c508e66146102435780637084819a14610256578063715018a61461026957600080fd5b806301ffc9a714610193578063037dc677146101bb57806315dae03e146101db5780631d0d35f5146101f057806327a964841461021d5780636b27270214610232575b600080fd5b6101a66101a136600461150e565b6103c6565b60405190151581526020015b60405180910390f35b6101ce6101c936600461153f565b6103f1565b6040516101b29190611561565b6101e36104f3565b6040516101b291906115f4565b6101a66101fe366004611623565b6001600160a01b03166000908152600160208190526040909120541490565b61023061022b3660046118c6565b610585565b005b6005546040519081526020016101b2565b610230610251366004611902565b6105a1565b610230610264366004611902565b6105b2565b6102306105c3565b61023061027f36600461191d565b6105d7565b610230610292366004611951565b610614565b6102306106d1565b6002546001146101a6565b6102306102b836600461198d565b610709565b6101e3610722565b6000546040516001600160a01b0390911681526020016101b2565b6102f36102ee366004611a3d565b610731565b6040516101b29190611b1e565b61023061030e36600461191d565b61079f565b610326610321366004611b31565b6107ea565b6040516101b29190611bc8565b610230610341366004611c2a565b610a10565b6101ce610a26565b6102f361035c366004611902565b610aaf565b6101a661036f366004611902565b6001600160401b031660009081526004602052604090205460ff1690565b6101a661039b366004611c77565b610c2f565b6102306103ae366004611c2a565b610d59565b6102306103c1366004611623565b610d6b565b60006001600160e01b03198216635f0efda160e11b14806103eb57506103eb82610da3565b92915050565b600554606090831061040257600091505b60055461040f8385611cc0565b111561042657600554610423908490611cd3565b91505b816001600160401b0381111561043e5761043e61163e565b604051908082528060200260200182016040528015610467578160200160208202803683370190505b50905060005b828110156104ec5760056104818286611cc0565b8154811061049157610491611ce6565b90600052602060002090600491828204019190066008029054906101000a90046001600160401b03168282815181106104cc576104cc611ce6565b6001600160401b039092166020928302919091019091015260010161046d565b5092915050565b60606007805461050290611cfc565b80601f016020809104026020016040519081016040528092919081815260200182805461052e90611cfc565b801561057b5780601f106105505761010080835404028352916020019161057b565b820191906000526020600020905b81548152906001019060200180831161055e57829003601f168201915b5050505050905090565b61058d610dd9565b610595610e18565b61059e81610e3b565b50565b6105a9610dd9565b61059e8161107a565b6105ba610dd9565b61059e816110d1565b6105cb61115c565b6105d56000611187565b565b6105df610dd9565b6105e8816111d7565b6040517fa5d4097edda6d87cb9329af83fb3712ef77eeb13738ffe43cc35a4ce305ad96290600090a150565b61061c61115c565b6001600160a01b0382166106435760405163016b812760e71b815260040160405180910390fd5b80610668576001600160a01b0382166000908152600160205260408120819055610687565b6001600160a01b03821660009081526001602081905260409091208190555b50816001600160a01b03167f4b5657e84cf8a17ac5587bbeb3cc2bab9826c4c67b8bad81b4849de49d37aac2826040516106c5911515815260200190565b60405180910390a25050565b6106d961115c565b60016002556040517f3e423347941b5c6e8c727e4071ffeb6869244ce75121d6a56ba8356086851c6c90600090a1565b610711610dd9565b610719610e18565b61059e816111e3565b60606006805461050290611cfc565b61075b60408051608081019091528060008152600060208201526060604082018190529081015290565b6103eb6005838154811061077157610771611ce6565b90600052602060002090600491828204019190066008029054906101000a90046001600160401b0316610aaf565b6107a7610dd9565b6107b08161121f565b7f79cd875c1d0ea2b5f60c11bda8f3208f4b3c384cfe2504893653655cdedc82f9816040516107df91906115f4565b60405180910390a150565b8051606090806001600160401b038111156108075761080761163e565b60405190808252806020026020018201604052801561086257816020015b61084f60408051608081019091528060008152600060208201526060604082018190529081015290565b8152602001906001900390816108255790505b50915060005b81811015610a0957600084828151811061088457610884611ce6565b6020908102919091018101516001600160401b03811660009081526003909252604091829020825160808101909352805491935090829060ff1660028111156108cf576108cf611a56565b60028111156108e0576108e0611a56565b81528154610100900460ff16602080830191909152600183018054604080518285028101850182528281529401939283018282801561094857602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161092a575b5050505050815260200160028201805461096190611cfc565b80601f016020809104026020016040519081016040528092919081815260200182805461098d90611cfc565b80156109da5780601f106109af576101008083540402835291602001916109da565b820191906000526020600020905b8154815290600101906020018083116109bd57829003601f168201915b5050505050815250508483815181106109f5576109f5611ce6565b602090810291909101015250600101610868565b5050919050565b610a18610dd9565b610a22828261122b565b5050565b6060600580548060200260200160405190810160405280929190818152602001828054801561057b57602002820191906000526020600020906000905b82829054906101000a90046001600160401b03166001600160401b031681526020019060080190602082600701049283019260010382029150808411610a635790505050505050905090565b610ad960408051608081019091528060008152600060208201526060604082018190529081015290565b6001600160401b038216600090815260036020526040908190208151608081019092528054829060ff166002811115610b1457610b14611a56565b6002811115610b2557610b25611a56565b81528154610100900460ff166020808301919091526001830180546040805182850281018501825282815294019392830182828015610b8d57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610b6f575b50505050508152602001600282018054610ba690611cfc565b80601f0160208091040260200160405190810160405280929190818152602001828054610bd290611cfc565b8015610c1f5780601f10610bf457610100808354040283529160200191610c1f565b820191906000526020600020905b815481529060010190602001808311610c0257829003601f168201915b5050505050815250509050919050565b6001600160401b03821660009081526004602052604090205460ff1680158015610c85575060016001600160401b03841660009081526003602052604090205460ff166002811115610c8357610c83611a56565b145b156103eb576001600160401b038316600090815260036020908152604080832060010180548251818502810185019093528083529192909190830182828015610cf757602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610cd9575b505083519394506000925050505b81811015610d5057828181518110610d1f57610d1f611ce6565b60200260200101516001600160a01b0316856001600160a01b031603610d485760019350610d50565b600101610d05565b50505092915050565b610d61610dd9565b610a2282826112e4565b610d7361115c565b6001600160a01b038116610d9a57604051634ece6ecf60e01b815260040160405180910390fd5b61059e81611187565b60006001600160e01b031982166301ffc9a760e01b14806103eb57506001600160e01b0319821663d912401f60e01b1492915050565b6000546001600160a01b03163314801590610dfa5750610df8336101fe565b155b156105d5576040516301eca16760e41b815260040160405180910390fd5b6002546001036105d55760405163ed1fa96f60e01b815260040160405180910390fd5b805160208201516001600160401b038216610e69576040516312c33ce360e01b815260040160405180910390fd5b6001600160401b03821660009081526003602052604081205460ff166002811115610e9657610e96611a56565b14610eb457604051630fbdf8dd60e01b815260040160405180910390fd5b600081516002811115610ec957610ec9611a56565b03610ee757604051630b65407360e01b815260040160405180910390fd5b600281516002811115610efc57610efc611a56565b148015610f0d575060408101515115155b15610f2b57604051630b65407360e01b815260040160405180910390fd5b6001600160401b03821660009081526003602052604090208151815483929190829060ff19166001836002811115610f6557610f65611a56565b0217905550602082810151825460ff9091166101000261ff001990911617825560408301518051610f9c926001850192019061147a565b5060608201516002820190610fb19082611d84565b5050600580546001810182556000919091527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db06004820401805460039092166008026101000a6001600160401b038181021990931692861602919091179055508051600281111561102457611024611a56565b826001600160401b03167fc4715b52aed3b9dfb2fbdc63e39e234892ec1dd3811d2c671646dbfd3d32d92e83602001518460400151856060015160405161106d93929190611e43565b60405180910390a3505050565b80611084816113fb565b6001600160401b038216600081815260046020526040808220805460ff19166001179055517f540b0b22993accb6c2b7b0f4a5bd1b7e6419708ef2a68c39f09f01c848ba4fbc9190a25050565b806110db816113fb565b6001600160401b0382166000908152600360205260408120611102916001909101906114df565b6001600160401b0382166000818152600460209081526040808320805460ff191690558051928352908201908190527f507a75726ac34d3eb68ebf61f034616ee2030c6193bd4a9efb7e131de6c6adcc916106c591611e7b565b6000546001600160a01b031633146105d557604051631c62d58f60e11b815260040160405180910390fd5b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6006610a228282611d84565b805160005b8181101561121a5761121283828151811061120557611205611ce6565b6020026020010151610e3b565b6001016111e8565b505050565b6007610a228282611d84565b81611235816113fb565b600082511161125757604051631763fd3d60e21b815260040160405180910390fd5b6001600160401b038316600090815260036020908152604090912083516112869260019092019185019061147a565b506001600160401b03831660008181526004602052604090819020805460ff19169055517f507a75726ac34d3eb68ebf61f034616ee2030c6193bd4a9efb7e131de6c6adcc906112d7908590611e7b565b60405180910390a2505050565b816112ee816113fb565b600082511161131057604051631763fd3d60e21b815260040160405180910390fd5b815160005b8181101561139c5760036000866001600160401b03166001600160401b0316815260200190815260200160002060010184828151811061135757611357611ce6565b60209081029190910181015182546001808201855560009485529290932090920180546001600160a01b0319166001600160a01b039093169290921790915501611315565b506001600160401b03841660008181526004602052604090819020805460ff19169055517f379edf7304a765a58c7eba1fef9bc8675355bf31e276de44d60da39bb04c76ba906113ed908690611e7b565b60405180910390a250505050565b6001600160401b03811660009081526003602052604081205460ff169081600281111561142a5761142a611a56565b03611448576040516307ae018160e21b815260040160405180910390fd5b600281600281111561145c5761145c611a56565b03610a225760405163ae6a3b7760e01b815260040160405180910390fd5b8280548282559060005260206000209081019282156114cf579160200282015b828111156114cf57825182546001600160a01b0319166001600160a01b0390911617825560209092019160019091019061149a565b506114db9291506114f9565b5090565b508054600082559060005260206000209081019061059e91905b5b808211156114db57600081556001016114fa565b60006020828403121561152057600080fd5b81356001600160e01b03198116811461153857600080fd5b9392505050565b6000806040838503121561155257600080fd5b50508035926020909101359150565b6020808252825182820181905260009190848201906040850190845b818110156115a25783516001600160401b03168352928401929184019160010161157d565b50909695505050505050565b6000815180845260005b818110156115d4576020818501810151868301820152016115b8565b506000602082860101526020601f19601f83011685010191505092915050565b60208152600061153860208301846115ae565b80356001600160a01b038116811461161e57600080fd5b919050565b60006020828403121561163557600080fd5b61153882611607565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b03811182821017156116765761167661163e565b60405290565b604051608081016001600160401b03811182821017156116765761167661163e565b604051601f8201601f191681016001600160401b03811182821017156116c6576116c661163e565b604052919050565b80356001600160401b038116811461161e57600080fd5b60006001600160401b038211156116fe576116fe61163e565b5060051b60200190565b600082601f83011261171957600080fd5b8135602061172e611729836116e5565b61169e565b82815260059290921b8401810191818101908684111561174d57600080fd5b8286015b8481101561176f5761176281611607565b8352918301918301611751565b509695505050505050565b600082601f83011261178b57600080fd5b81356001600160401b038111156117a4576117a461163e565b6117b7601f8201601f191660200161169e565b8181528460208386010111156117cc57600080fd5b816020850160208301376000918101602001919091529392505050565b6000604082840312156117fb57600080fd5b611803611654565b905061180e826116ce565b815260208201356001600160401b038082111561182a57600080fd5b908301906080828603121561183e57600080fd5b61184661167c565b82356003811061185557600080fd5b8152602083013560ff8116811461186b57600080fd5b602082015260408301358281111561188257600080fd5b61188e87828601611708565b6040830152506060830135828111156118a657600080fd5b6118b28782860161177a565b606083015250602084015250909392505050565b6000602082840312156118d857600080fd5b81356001600160401b038111156118ee57600080fd5b6118fa848285016117e9565b949350505050565b60006020828403121561191457600080fd5b611538826116ce565b60006020828403121561192f57600080fd5b81356001600160401b0381111561194557600080fd5b6118fa8482850161177a565b6000806040838503121561196457600080fd5b61196d83611607565b91506020830135801515811461198257600080fd5b809150509250929050565b600060208083850312156119a057600080fd5b82356001600160401b03808211156119b757600080fd5b818501915085601f8301126119cb57600080fd5b81356119d9611729826116e5565b81815260059190911b830184019084810190888311156119f857600080fd5b8585015b83811015611a3057803585811115611a145760008081fd5b611a228b89838a01016117e9565b8452509186019186016119fc565b5098975050505050505050565b600060208284031215611a4f57600080fd5b5035919050565b634e487b7160e01b600052602160045260246000fd5b600081518084526020808501945080840160005b83811015611aa55781516001600160a01b031687529582019590820190600101611a80565b509495945050505050565b6000815160038110611ad257634e487b7160e01b600052602160045260246000fd5b8084525060ff6020830151166020840152604082015160806040850152611afc6080850182611a6c565b905060608301518482036060860152611b1582826115ae565b95945050505050565b6020815260006115386020830184611ab0565b60006020808385031215611b4457600080fd5b82356001600160401b03811115611b5a57600080fd5b8301601f81018513611b6b57600080fd5b8035611b79611729826116e5565b81815260059190911b82018301908381019087831115611b9857600080fd5b928401925b82841015611bbd57611bae846116ce565b82529284019290840190611b9d565b979650505050505050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b82811015611c1d57603f19888603018452611c0b858351611ab0565b94509285019290850190600101611bef565b5092979650505050505050565b60008060408385031215611c3d57600080fd5b611c46836116ce565b915060208301356001600160401b03811115611c6157600080fd5b611c6d85828601611708565b9150509250929050565b60008060408385031215611c8a57600080fd5b611c93836116ce565b9150611ca160208401611607565b90509250929050565b634e487b7160e01b600052601160045260246000fd5b808201808211156103eb576103eb611caa565b818103818111156103eb576103eb611caa565b634e487b7160e01b600052603260045260246000fd5b600181811c90821680611d1057607f821691505b602082108103611d3057634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111561121a57600081815260208120601f850160051c81016020861015611d5d5750805b601f850160051c820191505b81811015611d7c57828155600101611d69565b505050505050565b81516001600160401b03811115611d9d57611d9d61163e565b611db181611dab8454611cfc565b84611d36565b602080601f831160018114611de65760008415611dce5750858301515b600019600386901b1c1916600185901b178555611d7c565b600085815260208120601f198616915b82811015611e1557888601518255948401946001909101908401611df6565b5085821015611e335787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60ff84168152606060208201526000611e5f6060830185611a6c565b8281036040840152611e7181856115ae565b9695505050505050565b6020815260006115386020830184611a6c56fea26469706673582212207c3596ea6107c52ca4c6c3e1e5509f6de4763b0dcacd84a9faa44b7bbc3d30d964736f6c63430008150033a2646970667358221220ab379b819b8cf4743f0dfbdfc11ca4a7a21f5b23526a5bd2fbc9ade84f212d0164736f6c63430008150033

Deployed Bytecode

0x60806040523480156200001157600080fd5b50600436106200005e5760003560e01c806327126e6914620000635780634e89276214620000975780637c8f649a14620000bd578063a3911df114620000f8578063d9a8a509146200010f575b600080fd5b6200007a6200007436600462000314565b62000126565b6040516001600160a01b0390911681526020015b60405180910390f35b620000ae620000a836600462000314565b6200017c565b6040516200008e919062000339565b620000e9620000ce36600462000314565b6001600160a01b031660009081526020819052604090205490565b6040519081526020016200008e565b6200007a6200010936600462000433565b620001f2565b6200007a620001203660046200049e565b620002a0565b6001600160a01b038116600090815260208190526040812080546200014e90600190620004cb565b81548110620001615762000161620004ed565b6000918252602090912001546001600160a01b031692915050565b6001600160a01b03811660009081526020818152604091829020805483518184028101840190945280845260609392830182828015620001e657602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311620001c7575b50505050509050919050565b60008083836040516200020590620002e9565b620002129291906200054b565b604051809103906000f0801580156200022f573d6000803e3d6000fd5b5033600081815260208181526040808320805460018101825590845291832090910180546001600160a01b0319166001600160a01b0386169081179091559051939450927f80108d1aca0caf8fcea04ffec0df23d37b689913b24cd81a4f6463c99b92f63e9190a390505b92915050565b6001600160a01b0382166000908152602081905260408120805483908110620002cd57620002cd620004ed565b6000918252602090912001546001600160a01b03169392505050565b61222f806200057e83390190565b80356001600160a01b03811681146200030f57600080fd5b919050565b6000602082840312156200032757600080fd5b6200033282620002f7565b9392505050565b6020808252825182820181905260009190848201906040850190845b818110156200037c5783516001600160a01b03168352928401929184019160010162000355565b50909695505050505050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620003b057600080fd5b813567ffffffffffffffff80821115620003ce57620003ce62000388565b604051601f8301601f19908116603f01168101908282118183101715620003f957620003f962000388565b816040528381528660208588010111156200041357600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080604083850312156200044757600080fd5b823567ffffffffffffffff808211156200046057600080fd5b6200046e868387016200039e565b935060208501359150808211156200048557600080fd5b5062000494858286016200039e565b9150509250929050565b60008060408385031215620004b257600080fd5b620004bd83620002f7565b946020939093013593505050565b818103818111156200029a57634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b6000815180845260005b818110156200052b576020818501810151868301820152016200050d565b506000602082860101526020601f19601f83011685010191505092915050565b60408152600062000560604083018562000503565b828103602084015262000574818562000503565b9594505050505056fe60806040523480156200001157600080fd5b506040516200222f3803806200222f833981016040819052620000349162000196565b8181620000413362000061565b6200004c82620000b1565b6200005781620000c3565b505050506200035b565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6006620000bf82826200028f565b5050565b6007620000bf82826200028f565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620000f957600080fd5b81516001600160401b0380821115620001165762000116620000d1565b604051601f8301601f19908116603f01168101908282118183101715620001415762000141620000d1565b816040528381526020925086838588010111156200015e57600080fd5b600091505b8382101562000182578582018301518183018401529082019062000163565b600093810190920192909252949350505050565b60008060408385031215620001aa57600080fd5b82516001600160401b0380821115620001c257600080fd5b620001d086838701620000e7565b93506020850151915080821115620001e757600080fd5b50620001f685828601620000e7565b9150509250929050565b600181811c908216806200021557607f821691505b6020821081036200023657634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200028a57600081815260208120601f850160051c81016020861015620002655750805b601f850160051c820191505b81811015620002865782815560010162000271565b5050505b505050565b81516001600160401b03811115620002ab57620002ab620000d1565b620002c381620002bc845462000200565b846200023c565b602080601f831160018114620002fb5760008415620002e25750858301515b600019600386901b1c1916600185901b17855562000286565b600085815260208120601f198616915b828110156200032c578886015182559484019460019091019084016200030b565b50858210156200034b5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b611ec4806200036b6000396000f3fe608060405234801561001057600080fd5b506004361061018e5760003560e01c8063867cc5c4116100de578063b9cd295911610097578063dc477d2f11610071578063dc477d2f14610361578063dcb79d561461038d578063f005548c146103a0578063f2fde38b146103b357600080fd5b8063b9cd295914610333578063ba146b2814610346578063d297ac431461034e57600080fd5b8063867cc5c4146102aa57806386a92af7146102bd5780638da5cb5b146102c55780638f7e7b49146102e057806396282ba3146103005780639806c6ec1461031357600080fd5b80636c508e661161014b578063750521f511610125578063750521f51461027157806379e8ca9e146102845780637aba6f37146102975780637e5852d91461029f57600080fd5b80636c508e66146102435780637084819a14610256578063715018a61461026957600080fd5b806301ffc9a714610193578063037dc677146101bb57806315dae03e146101db5780631d0d35f5146101f057806327a964841461021d5780636b27270214610232575b600080fd5b6101a66101a136600461150e565b6103c6565b60405190151581526020015b60405180910390f35b6101ce6101c936600461153f565b6103f1565b6040516101b29190611561565b6101e36104f3565b6040516101b291906115f4565b6101a66101fe366004611623565b6001600160a01b03166000908152600160208190526040909120541490565b61023061022b3660046118c6565b610585565b005b6005546040519081526020016101b2565b610230610251366004611902565b6105a1565b610230610264366004611902565b6105b2565b6102306105c3565b61023061027f36600461191d565b6105d7565b610230610292366004611951565b610614565b6102306106d1565b6002546001146101a6565b6102306102b836600461198d565b610709565b6101e3610722565b6000546040516001600160a01b0390911681526020016101b2565b6102f36102ee366004611a3d565b610731565b6040516101b29190611b1e565b61023061030e36600461191d565b61079f565b610326610321366004611b31565b6107ea565b6040516101b29190611bc8565b610230610341366004611c2a565b610a10565b6101ce610a26565b6102f361035c366004611902565b610aaf565b6101a661036f366004611902565b6001600160401b031660009081526004602052604090205460ff1690565b6101a661039b366004611c77565b610c2f565b6102306103ae366004611c2a565b610d59565b6102306103c1366004611623565b610d6b565b60006001600160e01b03198216635f0efda160e11b14806103eb57506103eb82610da3565b92915050565b600554606090831061040257600091505b60055461040f8385611cc0565b111561042657600554610423908490611cd3565b91505b816001600160401b0381111561043e5761043e61163e565b604051908082528060200260200182016040528015610467578160200160208202803683370190505b50905060005b828110156104ec5760056104818286611cc0565b8154811061049157610491611ce6565b90600052602060002090600491828204019190066008029054906101000a90046001600160401b03168282815181106104cc576104cc611ce6565b6001600160401b039092166020928302919091019091015260010161046d565b5092915050565b60606007805461050290611cfc565b80601f016020809104026020016040519081016040528092919081815260200182805461052e90611cfc565b801561057b5780601f106105505761010080835404028352916020019161057b565b820191906000526020600020905b81548152906001019060200180831161055e57829003601f168201915b5050505050905090565b61058d610dd9565b610595610e18565b61059e81610e3b565b50565b6105a9610dd9565b61059e8161107a565b6105ba610dd9565b61059e816110d1565b6105cb61115c565b6105d56000611187565b565b6105df610dd9565b6105e8816111d7565b6040517fa5d4097edda6d87cb9329af83fb3712ef77eeb13738ffe43cc35a4ce305ad96290600090a150565b61061c61115c565b6001600160a01b0382166106435760405163016b812760e71b815260040160405180910390fd5b80610668576001600160a01b0382166000908152600160205260408120819055610687565b6001600160a01b03821660009081526001602081905260409091208190555b50816001600160a01b03167f4b5657e84cf8a17ac5587bbeb3cc2bab9826c4c67b8bad81b4849de49d37aac2826040516106c5911515815260200190565b60405180910390a25050565b6106d961115c565b60016002556040517f3e423347941b5c6e8c727e4071ffeb6869244ce75121d6a56ba8356086851c6c90600090a1565b610711610dd9565b610719610e18565b61059e816111e3565b60606006805461050290611cfc565b61075b60408051608081019091528060008152600060208201526060604082018190529081015290565b6103eb6005838154811061077157610771611ce6565b90600052602060002090600491828204019190066008029054906101000a90046001600160401b0316610aaf565b6107a7610dd9565b6107b08161121f565b7f79cd875c1d0ea2b5f60c11bda8f3208f4b3c384cfe2504893653655cdedc82f9816040516107df91906115f4565b60405180910390a150565b8051606090806001600160401b038111156108075761080761163e565b60405190808252806020026020018201604052801561086257816020015b61084f60408051608081019091528060008152600060208201526060604082018190529081015290565b8152602001906001900390816108255790505b50915060005b81811015610a0957600084828151811061088457610884611ce6565b6020908102919091018101516001600160401b03811660009081526003909252604091829020825160808101909352805491935090829060ff1660028111156108cf576108cf611a56565b60028111156108e0576108e0611a56565b81528154610100900460ff16602080830191909152600183018054604080518285028101850182528281529401939283018282801561094857602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161092a575b5050505050815260200160028201805461096190611cfc565b80601f016020809104026020016040519081016040528092919081815260200182805461098d90611cfc565b80156109da5780601f106109af576101008083540402835291602001916109da565b820191906000526020600020905b8154815290600101906020018083116109bd57829003601f168201915b5050505050815250508483815181106109f5576109f5611ce6565b602090810291909101015250600101610868565b5050919050565b610a18610dd9565b610a22828261122b565b5050565b6060600580548060200260200160405190810160405280929190818152602001828054801561057b57602002820191906000526020600020906000905b82829054906101000a90046001600160401b03166001600160401b031681526020019060080190602082600701049283019260010382029150808411610a635790505050505050905090565b610ad960408051608081019091528060008152600060208201526060604082018190529081015290565b6001600160401b038216600090815260036020526040908190208151608081019092528054829060ff166002811115610b1457610b14611a56565b6002811115610b2557610b25611a56565b81528154610100900460ff166020808301919091526001830180546040805182850281018501825282815294019392830182828015610b8d57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610b6f575b50505050508152602001600282018054610ba690611cfc565b80601f0160208091040260200160405190810160405280929190818152602001828054610bd290611cfc565b8015610c1f5780601f10610bf457610100808354040283529160200191610c1f565b820191906000526020600020905b815481529060010190602001808311610c0257829003601f168201915b5050505050815250509050919050565b6001600160401b03821660009081526004602052604090205460ff1680158015610c85575060016001600160401b03841660009081526003602052604090205460ff166002811115610c8357610c83611a56565b145b156103eb576001600160401b038316600090815260036020908152604080832060010180548251818502810185019093528083529192909190830182828015610cf757602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610cd9575b505083519394506000925050505b81811015610d5057828181518110610d1f57610d1f611ce6565b60200260200101516001600160a01b0316856001600160a01b031603610d485760019350610d50565b600101610d05565b50505092915050565b610d61610dd9565b610a2282826112e4565b610d7361115c565b6001600160a01b038116610d9a57604051634ece6ecf60e01b815260040160405180910390fd5b61059e81611187565b60006001600160e01b031982166301ffc9a760e01b14806103eb57506001600160e01b0319821663d912401f60e01b1492915050565b6000546001600160a01b03163314801590610dfa5750610df8336101fe565b155b156105d5576040516301eca16760e41b815260040160405180910390fd5b6002546001036105d55760405163ed1fa96f60e01b815260040160405180910390fd5b805160208201516001600160401b038216610e69576040516312c33ce360e01b815260040160405180910390fd5b6001600160401b03821660009081526003602052604081205460ff166002811115610e9657610e96611a56565b14610eb457604051630fbdf8dd60e01b815260040160405180910390fd5b600081516002811115610ec957610ec9611a56565b03610ee757604051630b65407360e01b815260040160405180910390fd5b600281516002811115610efc57610efc611a56565b148015610f0d575060408101515115155b15610f2b57604051630b65407360e01b815260040160405180910390fd5b6001600160401b03821660009081526003602052604090208151815483929190829060ff19166001836002811115610f6557610f65611a56565b0217905550602082810151825460ff9091166101000261ff001990911617825560408301518051610f9c926001850192019061147a565b5060608201516002820190610fb19082611d84565b5050600580546001810182556000919091527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db06004820401805460039092166008026101000a6001600160401b038181021990931692861602919091179055508051600281111561102457611024611a56565b826001600160401b03167fc4715b52aed3b9dfb2fbdc63e39e234892ec1dd3811d2c671646dbfd3d32d92e83602001518460400151856060015160405161106d93929190611e43565b60405180910390a3505050565b80611084816113fb565b6001600160401b038216600081815260046020526040808220805460ff19166001179055517f540b0b22993accb6c2b7b0f4a5bd1b7e6419708ef2a68c39f09f01c848ba4fbc9190a25050565b806110db816113fb565b6001600160401b0382166000908152600360205260408120611102916001909101906114df565b6001600160401b0382166000818152600460209081526040808320805460ff191690558051928352908201908190527f507a75726ac34d3eb68ebf61f034616ee2030c6193bd4a9efb7e131de6c6adcc916106c591611e7b565b6000546001600160a01b031633146105d557604051631c62d58f60e11b815260040160405180910390fd5b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6006610a228282611d84565b805160005b8181101561121a5761121283828151811061120557611205611ce6565b6020026020010151610e3b565b6001016111e8565b505050565b6007610a228282611d84565b81611235816113fb565b600082511161125757604051631763fd3d60e21b815260040160405180910390fd5b6001600160401b038316600090815260036020908152604090912083516112869260019092019185019061147a565b506001600160401b03831660008181526004602052604090819020805460ff19169055517f507a75726ac34d3eb68ebf61f034616ee2030c6193bd4a9efb7e131de6c6adcc906112d7908590611e7b565b60405180910390a2505050565b816112ee816113fb565b600082511161131057604051631763fd3d60e21b815260040160405180910390fd5b815160005b8181101561139c5760036000866001600160401b03166001600160401b0316815260200190815260200160002060010184828151811061135757611357611ce6565b60209081029190910181015182546001808201855560009485529290932090920180546001600160a01b0319166001600160a01b039093169290921790915501611315565b506001600160401b03841660008181526004602052604090819020805460ff19169055517f379edf7304a765a58c7eba1fef9bc8675355bf31e276de44d60da39bb04c76ba906113ed908690611e7b565b60405180910390a250505050565b6001600160401b03811660009081526003602052604081205460ff169081600281111561142a5761142a611a56565b03611448576040516307ae018160e21b815260040160405180910390fd5b600281600281111561145c5761145c611a56565b03610a225760405163ae6a3b7760e01b815260040160405180910390fd5b8280548282559060005260206000209081019282156114cf579160200282015b828111156114cf57825182546001600160a01b0319166001600160a01b0390911617825560209092019160019091019061149a565b506114db9291506114f9565b5090565b508054600082559060005260206000209081019061059e91905b5b808211156114db57600081556001016114fa565b60006020828403121561152057600080fd5b81356001600160e01b03198116811461153857600080fd5b9392505050565b6000806040838503121561155257600080fd5b50508035926020909101359150565b6020808252825182820181905260009190848201906040850190845b818110156115a25783516001600160401b03168352928401929184019160010161157d565b50909695505050505050565b6000815180845260005b818110156115d4576020818501810151868301820152016115b8565b506000602082860101526020601f19601f83011685010191505092915050565b60208152600061153860208301846115ae565b80356001600160a01b038116811461161e57600080fd5b919050565b60006020828403121561163557600080fd5b61153882611607565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b03811182821017156116765761167661163e565b60405290565b604051608081016001600160401b03811182821017156116765761167661163e565b604051601f8201601f191681016001600160401b03811182821017156116c6576116c661163e565b604052919050565b80356001600160401b038116811461161e57600080fd5b60006001600160401b038211156116fe576116fe61163e565b5060051b60200190565b600082601f83011261171957600080fd5b8135602061172e611729836116e5565b61169e565b82815260059290921b8401810191818101908684111561174d57600080fd5b8286015b8481101561176f5761176281611607565b8352918301918301611751565b509695505050505050565b600082601f83011261178b57600080fd5b81356001600160401b038111156117a4576117a461163e565b6117b7601f8201601f191660200161169e565b8181528460208386010111156117cc57600080fd5b816020850160208301376000918101602001919091529392505050565b6000604082840312156117fb57600080fd5b611803611654565b905061180e826116ce565b815260208201356001600160401b038082111561182a57600080fd5b908301906080828603121561183e57600080fd5b61184661167c565b82356003811061185557600080fd5b8152602083013560ff8116811461186b57600080fd5b602082015260408301358281111561188257600080fd5b61188e87828601611708565b6040830152506060830135828111156118a657600080fd5b6118b28782860161177a565b606083015250602084015250909392505050565b6000602082840312156118d857600080fd5b81356001600160401b038111156118ee57600080fd5b6118fa848285016117e9565b949350505050565b60006020828403121561191457600080fd5b611538826116ce565b60006020828403121561192f57600080fd5b81356001600160401b0381111561194557600080fd5b6118fa8482850161177a565b6000806040838503121561196457600080fd5b61196d83611607565b91506020830135801515811461198257600080fd5b809150509250929050565b600060208083850312156119a057600080fd5b82356001600160401b03808211156119b757600080fd5b818501915085601f8301126119cb57600080fd5b81356119d9611729826116e5565b81815260059190911b830184019084810190888311156119f857600080fd5b8585015b83811015611a3057803585811115611a145760008081fd5b611a228b89838a01016117e9565b8452509186019186016119fc565b5098975050505050505050565b600060208284031215611a4f57600080fd5b5035919050565b634e487b7160e01b600052602160045260246000fd5b600081518084526020808501945080840160005b83811015611aa55781516001600160a01b031687529582019590820190600101611a80565b509495945050505050565b6000815160038110611ad257634e487b7160e01b600052602160045260246000fd5b8084525060ff6020830151166020840152604082015160806040850152611afc6080850182611a6c565b905060608301518482036060860152611b1582826115ae565b95945050505050565b6020815260006115386020830184611ab0565b60006020808385031215611b4457600080fd5b82356001600160401b03811115611b5a57600080fd5b8301601f81018513611b6b57600080fd5b8035611b79611729826116e5565b81815260059190911b82018301908381019087831115611b9857600080fd5b928401925b82841015611bbd57611bae846116ce565b82529284019290840190611b9d565b979650505050505050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b82811015611c1d57603f19888603018452611c0b858351611ab0565b94509285019290850190600101611bef565b5092979650505050505050565b60008060408385031215611c3d57600080fd5b611c46836116ce565b915060208301356001600160401b03811115611c6157600080fd5b611c6d85828601611708565b9150509250929050565b60008060408385031215611c8a57600080fd5b611c93836116ce565b9150611ca160208401611607565b90509250929050565b634e487b7160e01b600052601160045260246000fd5b808201808211156103eb576103eb611caa565b818103818111156103eb576103eb611caa565b634e487b7160e01b600052603260045260246000fd5b600181811c90821680611d1057607f821691505b602082108103611d3057634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111561121a57600081815260208120601f850160051c81016020861015611d5d5750805b601f850160051c820191505b81811015611d7c57828155600101611d69565b505050505050565b81516001600160401b03811115611d9d57611d9d61163e565b611db181611dab8454611cfc565b84611d36565b602080601f831160018114611de65760008415611dce5750858301515b600019600386901b1c1916600185901b178555611d7c565b600085815260208120601f198616915b82811015611e1557888601518255948401946001909101908401611df6565b5085821015611e335787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60ff84168152606060208201526000611e5f6060830185611a6c565b8281036040840152611e7181856115ae565b9695505050505050565b6020815260006115386020830184611a6c56fea26469706673582212207c3596ea6107c52ca4c6c3e1e5509f6de4763b0dcacd84a9faa44b7bbc3d30d964736f6c63430008150033a2646970667358221220ab379b819b8cf4743f0dfbdfc11ca4a7a21f5b23526a5bd2fbc9ade84f212d0164736f6c63430008150033

Deployed Bytecode Sourcemap

269:2479:6:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2514:232;;;;;;:::i;:::-;;:::i;:::-;;;-1:-1:-1;;;;;547:32:11;;;529:51;;517:2;502:18;2514:232:6;;;;;;;;1272:151;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;1657:161::-;;;;;;:::i;:::-;-1:-1:-1;;;;;1777:27:6;1744:13;1777:27;;;;;;;;;;:34;;1657:161;;;;1400:25:11;;;1388:2;1373:18;1657:161:6;1254:177:11;696:355:6;;;;;;:::i;:::-;;:::i;2077:203::-;;;;;;:::i;:::-;;:::i;2514:232::-;-1:-1:-1;;;;;2650:27:6;;2599:22;2650:27;;;;;;;;;;2691:34;;:38;;2728:1;;2691:38;:::i;:::-;2650:89;;;;;;;;:::i;:::-;;;;;;;;;;;-1:-1:-1;;;;;2650:89:6;;2514:232;-1:-1:-1;;2514:232:6:o;1272:151::-;-1:-1:-1;;;;;1389:27:6;;:17;:27;;;;;;;;;;;;1382:34;;;;;;;;;;;;;;;;;1354:16;;1382:34;;;1389:27;1382:34;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;1382:34:6;;;;;;;;;;;;;;;;;;;;;;;1272:151;;;:::o;696:355::-;805:7;824:23;870:11;883:5;850:39;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;917:10:6;899:17;:29;;;;;;;;;;;:52;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;899:52:6;-1:-1:-1;;;;;899:52:6;;;;;;;;966:45;;899:52;;-1:-1:-1;899:52:6;966:45;;899:17;966:45;1036:7;-1:-1:-1;696:355:6;;;;;:::o;2077:203::-;-1:-1:-1;;;;;2239:27:6;;2188:22;2239:27;;;;;;;;;;:34;;2267:5;;2239:34;;;;;;:::i;:::-;;;;;;;;;;;-1:-1:-1;;;;;2239:34:6;;2077:203;-1:-1:-1;;;2077:203:6:o;-1:-1:-1:-;;;;;;;;:::o;14:173:11:-;82:20;;-1:-1:-1;;;;;131:31:11;;121:42;;111:70;;177:1;174;167:12;111:70;14:173;;;:::o;192:186::-;251:6;304:2;292:9;283:7;279:23;275:32;272:52;;;320:1;317;310:12;272:52;343:29;362:9;343:29;:::i;:::-;333:39;192:186;-1:-1:-1;;;192:186:11:o;591:658::-;762:2;814:21;;;884:13;;787:18;;;906:22;;;733:4;;762:2;985:15;;;;959:2;944:18;;;733:4;1028:195;1042:6;1039:1;1036:13;1028:195;;;1107:13;;-1:-1:-1;;;;;1103:39:11;1091:52;;1198:15;;;;1163:12;;;;1139:1;1057:9;1028:195;;;-1:-1:-1;1240:3:11;;591:658;-1:-1:-1;;;;;;591:658:11:o;1436:127::-;1497:10;1492:3;1488:20;1485:1;1478:31;1528:4;1525:1;1518:15;1552:4;1549:1;1542:15;1568:719;1611:5;1664:3;1657:4;1649:6;1645:17;1641:27;1631:55;;1682:1;1679;1672:12;1631:55;1718:6;1705:20;1744:18;1781:2;1777;1774:10;1771:36;;;1787:18;;:::i;:::-;1862:2;1856:9;1830:2;1916:13;;-1:-1:-1;;1912:22:11;;;1936:2;1908:31;1904:40;1892:53;;;1960:18;;;1980:22;;;1957:46;1954:72;;;2006:18;;:::i;:::-;2046:10;2042:2;2035:22;2081:2;2073:6;2066:18;2127:3;2120:4;2115:2;2107:6;2103:15;2099:26;2096:35;2093:55;;;2144:1;2141;2134:12;2093:55;2208:2;2201:4;2193:6;2189:17;2182:4;2174:6;2170:17;2157:54;2255:1;2248:4;2243:2;2235:6;2231:15;2227:26;2220:37;2275:6;2266:15;;;;;;1568:719;;;;:::o;2292:543::-;2380:6;2388;2441:2;2429:9;2420:7;2416:23;2412:32;2409:52;;;2457:1;2454;2447:12;2409:52;2497:9;2484:23;2526:18;2567:2;2559:6;2556:14;2553:34;;;2583:1;2580;2573:12;2553:34;2606:50;2648:7;2639:6;2628:9;2624:22;2606:50;:::i;:::-;2596:60;;2709:2;2698:9;2694:18;2681:32;2665:48;;2738:2;2728:8;2725:16;2722:36;;;2754:1;2751;2744:12;2722:36;;2777:52;2821:7;2810:8;2799:9;2795:24;2777:52;:::i;:::-;2767:62;;;2292:543;;;;;:::o;2840:254::-;2908:6;2916;2969:2;2957:9;2948:7;2944:23;2940:32;2937:52;;;2985:1;2982;2975:12;2937:52;3008:29;3027:9;3008:29;:::i;:::-;2998:39;3084:2;3069:18;;;;3056:32;;-1:-1:-1;;;2840:254:11:o;3099:225::-;3166:9;;;3187:11;;;3184:134;;;3240:10;3235:3;3231:20;3228:1;3221:31;3275:4;3272:1;3265:15;3303:4;3300:1;3293:15;3329:127;3390:10;3385:3;3381:20;3378:1;3371:31;3421:4;3418:1;3411:15;3445:4;3442:1;3435:15;3461:423;3503:3;3541:5;3535:12;3568:6;3563:3;3556:19;3593:1;3603:162;3617:6;3614:1;3611:13;3603:162;;;3679:4;3735:13;;;3731:22;;3725:29;3707:11;;;3703:20;;3696:59;3632:12;3603:162;;;3607:3;3810:1;3803:4;3794:6;3789:3;3785:16;3781:27;3774:38;3873:4;3866:2;3862:7;3857:2;3849:6;3845:15;3841:29;3836:3;3832:39;3828:50;3821:57;;;3461:423;;;;:::o;3889:383::-;4086:2;4075:9;4068:21;4049:4;4112:45;4153:2;4142:9;4138:18;4130:6;4112:45;:::i;:::-;4205:9;4197:6;4193:22;4188:2;4177:9;4173:18;4166:50;4233:33;4259:6;4251;4233:33;:::i;:::-;4225:41;3889:383;-1:-1:-1;;;;;3889:383:11:o

Swarm Source

ipfs://ab379b819b8cf4743f0dfbdfc11ca4a7a21f5b23526a5bd2fbc9ade84f212d01

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.