ETH Price: $2,945.87 (-2.03%)

Contract

0x0d64E5D1BDC9DA3Af671b972C4D83BC863DB062f

Overview

ETH Balance

0 ETH

ETH Value

$0.00

More Info

Private Name Tags

Multichain Info

No addresses found
Transaction Hash
Block
From
To

There are no matching entries

1 Internal Transaction found.

Latest 1 internal transaction

Advanced mode:
Parent Transaction Hash Block From To
155523722025-07-29 13:35:01183 days ago1753796101  Contract Creation0 ETH
Cross-Chain Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
BlacksmithCrafting

Compiler Version
v0.8.30+commit.73712a01

ZkSolc Version
v1.5.15

Optimization Enabled:
Yes with Mode 3

Other Settings:
cancun EvmVersion
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.29;

import {Ownable} from "solady/auth/Ownable.sol";
import {UUPSUpgradeable} from "solady/utils/UUPSUpgradeable.sol";
import {EnumerableMapLib} from "solady/utils/EnumerableMapLib.sol";
import {IERC20} from "../interfaces/IERC20.sol";
import {IOCHItems} from "../interfaces/IOCHItems.sol";

/// @dev This contract is a proxy contract for BlacksmithCrafting.
/// @author Onchain-Heroes (https://www.onchainheroes.xyz/)
/// @author atarpara (https://www.github.com/atarpara)
contract BlacksmithCrafting is Ownable, UUPSUpgradeable {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                           ERRORS                           */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Revert if recipe is not running.
    error RecipeNotRunning();
    /// @dev Revert if length of itemId and qtys is not equal.
    error InvalidLength();
    /// @dev Revert if recipe is already running.
    error RecipeAlreadyRunning();
    /// @dev Revert if contract is paused.
    error Paused();
    /// @dev Revert if price is zero.
    error PriceIsZero();
    /// @dev Revert if length is zero.
    error LengthIsZero();
    /// @dev Revert if qty is zero.
    error QtyIsZero();
    /// @dev Revert if outputId is zero.
    error InvalidOutputId();

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                           EVENTS                           */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Emitted when recipes are cooked.
    event CookedRecipes(address owner, uint256 recipeId, uint256 price, uint256[] itemId, uint256[] qtys);
    /// @dev Emitted when recipe is added.
    event RecipeAdded(uint256 recipeId, uint256 recipePrice, uint256[] itemId, uint256[] qtys);
    /// @dev Emitted when recipe is updated.
    event RecipeUpdated(uint256 recipeId, uint256 recipePrice, uint256[] itemId, uint256[] qtys);

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                           CONSTANT                         */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Address of $HERO20 contract.
    IERC20 internal constant hero20 = IERC20(0x33EE11cE309854a45B65368C078616ABcb5c6e3d);

    /// @dev Address of OCHItems contract.
    IOCHItems internal constant items = IOCHItems(0x14f926D2751F4bb0200e9b016B6aE4A1E4B207Bd);

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                           STRUCT                           */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Recipe struct.
    struct Recipe {
        /// @dev Whether recipe is running or not.
        uint8 isRunning;
        /// @dev Price of recipe.
        uint248 price;
        /// @dev Item id array.
        uint256[] itemId;
        /// @dev Qtys array.
        uint256[] qty;
    }

    /// @dev BlacksmithCrafting storage.
    struct BlacksmithCraftingStorage {
        /// @dev Mapping of recipeId to Recipe.
        mapping(uint256 recipeId => Recipe) recipes;
        /// @dev Pause flag for contract.
        uint8 pauseFlag;
    }

    constructor(address _owner) {
        _initializeOwner(_owner);
    }

    /// @dev Init contract with `_owner`.
    function init(address _owner) external {
        if (owner() != address(0)) revert AlreadyInitialized();
        _initializeOwner(_owner);
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                           FUNCTIONS                        */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Cook recipes with `recipeId`.
    function cookRecipes(uint256[] calldata recipeId) external {
        // Get storage.
        BlacksmithCraftingStorage storage $ = _getStorage();

        // Check if contract is paused.
        if ($.pauseFlag != 0) revert Paused();

        uint256 len = recipeId.length;
        for (uint256 i = 0; i < len; ++i) {
            uint256 id = recipeId[i];
            // Get recipe.
            Recipe storage recipe = $.recipes[id];

            // Check if recipe is running.
            if (recipe.isRunning == 0) revert RecipeNotRunning();

            // Check if price is zero.
            if (recipe.price == 0) revert PriceIsZero();

            // Transfer $HERO20 to this contract.
            hero20.transferFrom(msg.sender, address(this), recipe.price);

            uint256 keyLen_ = recipe.itemId.length;

            uint256[] memory itemId = new uint256[](keyLen_);
            uint256[] memory qtys = new uint256[](keyLen_);

            for (uint256 z; z < keyLen_; ++z) {
                itemId[z] = recipe.itemId[z];
                qtys[z] = recipe.qty[z];
                // Burn items.
                items.burn(msg.sender, itemId[z], qtys[z]);
            }

            // Emit `CookedRecipes`.
            emit CookedRecipes(msg.sender, id, recipe.price, itemId, qtys);

            // Mint item.
            items.mint(msg.sender, id, 1);
        }
    }

    /// @dev Add recipe with `outputId`, `recipePrice`, `itemId` and `qtys`.
    function addRecipe(uint256 outputId, uint256 recipePrice, uint256[] calldata itemId, uint256[] calldata qtys)
        external
        onlyOwner
    {
        if (outputId == 0) revert InvalidOutputId();
        // Get storage.
        BlacksmithCraftingStorage storage $ = _getStorage();

        // Check if length of itemId and qtys is not equal.
        if (itemId.length != qtys.length) revert InvalidLength();

        // Get recipe.
        Recipe storage recipe = $.recipes[outputId];

        // Check if recipe is already running.
        if (recipe.isRunning != 0) revert RecipeAlreadyRunning();

        // Set recipe as running.
        recipe.isRunning = uint8(1);

        // Set recipe price.
        recipe.price = uint248(recipePrice);

        uint256 len = itemId.length;

        if (len == 0) revert LengthIsZero();

        recipe.itemId = new uint256[](len);
        recipe.qty = new uint256[](len);

        for (uint256 i = 0; i < len; ++i) {
            if (qtys[i] == 0) revert QtyIsZero();
            // Set itemId and qty.
            recipe.itemId[i] = itemId[i];
            recipe.qty[i] = qtys[i];
        }

        // Emit `RecipeAdded`.
        emit RecipeAdded(outputId, recipePrice, itemId, qtys);
    }

    /// @dev Update recipe with `outputId`, `recipePrice`, `itemId` and `qtys`.
    function updateRecipe(uint256 outputId, uint256 recipePrice, uint256[] calldata itemId, uint256[] calldata qtys)
        external
        onlyOwner
    {
        // Check if outputId is zero.
        if (outputId == 0) revert InvalidOutputId();
        // Get storage.
        BlacksmithCraftingStorage storage $ = _getStorage();

        // Check if length of itemId and qtys is not equal.
        if (itemId.length != qtys.length) revert InvalidLength();

        // Get recipe.
        Recipe storage recipe = $.recipes[outputId];

        // Set recipe price.
        recipe.price = uint248(recipePrice);

        uint256 len = itemId.length;

        if (len == 0) revert LengthIsZero();

        recipe.itemId = new uint256[](len);
        recipe.qty = new uint256[](len);

        for (uint256 i = 0; i < len; ++i) {
            if (qtys[i] == 0) revert QtyIsZero();
            // Set itemId and qty.
            recipe.itemId[i] = itemId[i];
            recipe.qty[i] = qtys[i];
        }

        // Emit `RecipeUpdated`.
        emit RecipeUpdated(outputId, recipePrice, itemId, qtys);
    }

    /// @dev Set recipe start flag.
    function setRecipeStartFlag(uint256 outputId, bool flag) external onlyOwner {
        BlacksmithCraftingStorage storage $ = _getStorage();
        $.recipes[outputId].isRunning = flag ? uint8(1) : uint8(0);
    }

    /// @dev Set pause flag.
    function setPauseFlag(bool flag) external onlyOwner {
        BlacksmithCraftingStorage storage $ = _getStorage();
        $.pauseFlag = flag ? uint8(1) : uint8(0);
    }

    /// @dev Withdraw $HERO20.
    function withdraw() external onlyOwner {
        uint256 balance = hero20.balanceOf(address(this));
        hero20.transfer(msg.sender, balance);
    }

    /// @dev Get storage pointer.
    function _getStorage() internal pure returns (BlacksmithCraftingStorage storage $) {
        uint256 s = uint72(bytes9(keccak256("BLACKSMITH_CRAFTING_STORAGE")));
        assembly ("memory-safe") {
            $.slot := s
        }
    }

    /// @dev Get recipe details.
    function getRecipe(uint256 outputId)
        external
        view
        returns (bool isRunning, uint256 price, uint256[] memory itemId, uint256[] memory qtys)
    {
        BlacksmithCraftingStorage storage $ = _getStorage();
        Recipe storage recipe = $.recipes[outputId];

        return (recipe.isRunning != 0, uint256(recipe.price), recipe.itemId, recipe.qty);
    }

    /// @dev Authorize upgrade.
    function _authorizeUpgrade(address newImplementation) internal override onlyOwner {}
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/// @notice Simple single owner authorization mixin.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/auth/Ownable.sol)
///
/// @dev Note:
/// This implementation does NOT auto-initialize the owner to `msg.sender`.
/// You MUST call the `_initializeOwner` in the constructor / initializer.
///
/// While the ownable portion follows
/// [EIP-173](https://eips.ethereum.org/EIPS/eip-173) for compatibility,
/// the nomenclature for the 2-step ownership handover may be unique to this codebase.
abstract contract Ownable {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                       CUSTOM ERRORS                        */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The caller is not authorized to call the function.
    error Unauthorized();

    /// @dev The `newOwner` cannot be the zero address.
    error NewOwnerIsZeroAddress();

    /// @dev The `pendingOwner` does not have a valid handover request.
    error NoHandoverRequest();

    /// @dev Cannot double-initialize.
    error AlreadyInitialized();

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                           EVENTS                           */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The ownership is transferred from `oldOwner` to `newOwner`.
    /// This event is intentionally kept the same as OpenZeppelin's Ownable to be
    /// compatible with indexers and [EIP-173](https://eips.ethereum.org/EIPS/eip-173),
    /// despite it not being as lightweight as a single argument event.
    event OwnershipTransferred(address indexed oldOwner, address indexed newOwner);

    /// @dev An ownership handover to `pendingOwner` has been requested.
    event OwnershipHandoverRequested(address indexed pendingOwner);

    /// @dev The ownership handover to `pendingOwner` has been canceled.
    event OwnershipHandoverCanceled(address indexed pendingOwner);

    /// @dev `keccak256(bytes("OwnershipTransferred(address,address)"))`.
    uint256 private constant _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE =
        0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0;

    /// @dev `keccak256(bytes("OwnershipHandoverRequested(address)"))`.
    uint256 private constant _OWNERSHIP_HANDOVER_REQUESTED_EVENT_SIGNATURE =
        0xdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d;

    /// @dev `keccak256(bytes("OwnershipHandoverCanceled(address)"))`.
    uint256 private constant _OWNERSHIP_HANDOVER_CANCELED_EVENT_SIGNATURE =
        0xfa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c92;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                          STORAGE                           */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The owner slot is given by:
    /// `bytes32(~uint256(uint32(bytes4(keccak256("_OWNER_SLOT_NOT")))))`.
    /// It is intentionally chosen to be a high value
    /// to avoid collision with lower slots.
    /// The choice of manual storage layout is to enable compatibility
    /// with both regular and upgradeable contracts.
    bytes32 internal constant _OWNER_SLOT =
        0xffffffffffffffffffffffffffffffffffffffffffffffffffffffff74873927;

    /// The ownership handover slot of `newOwner` is given by:
    /// ```
    ///     mstore(0x00, or(shl(96, user), _HANDOVER_SLOT_SEED))
    ///     let handoverSlot := keccak256(0x00, 0x20)
    /// ```
    /// It stores the expiry timestamp of the two-step ownership handover.
    uint256 private constant _HANDOVER_SLOT_SEED = 0x389a75e1;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                     INTERNAL FUNCTIONS                     */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Override to return true to make `_initializeOwner` prevent double-initialization.
    function _guardInitializeOwner() internal pure virtual returns (bool guard) {}

    /// @dev Initializes the owner directly without authorization guard.
    /// This function must be called upon initialization,
    /// regardless of whether the contract is upgradeable or not.
    /// This is to enable generalization to both regular and upgradeable contracts,
    /// and to save gas in case the initial owner is not the caller.
    /// For performance reasons, this function will not check if there
    /// is an existing owner.
    function _initializeOwner(address newOwner) internal virtual {
        if (_guardInitializeOwner()) {
            /// @solidity memory-safe-assembly
            assembly {
                let ownerSlot := _OWNER_SLOT
                if sload(ownerSlot) {
                    mstore(0x00, 0x0dc149f0) // `AlreadyInitialized()`.
                    revert(0x1c, 0x04)
                }
                // Clean the upper 96 bits.
                newOwner := shr(96, shl(96, newOwner))
                // Store the new value.
                sstore(ownerSlot, or(newOwner, shl(255, iszero(newOwner))))
                // Emit the {OwnershipTransferred} event.
                log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, 0, newOwner)
            }
        } else {
            /// @solidity memory-safe-assembly
            assembly {
                // Clean the upper 96 bits.
                newOwner := shr(96, shl(96, newOwner))
                // Store the new value.
                sstore(_OWNER_SLOT, newOwner)
                // Emit the {OwnershipTransferred} event.
                log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, 0, newOwner)
            }
        }
    }

    /// @dev Sets the owner directly without authorization guard.
    function _setOwner(address newOwner) internal virtual {
        if (_guardInitializeOwner()) {
            /// @solidity memory-safe-assembly
            assembly {
                let ownerSlot := _OWNER_SLOT
                // Clean the upper 96 bits.
                newOwner := shr(96, shl(96, newOwner))
                // Emit the {OwnershipTransferred} event.
                log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, sload(ownerSlot), newOwner)
                // Store the new value.
                sstore(ownerSlot, or(newOwner, shl(255, iszero(newOwner))))
            }
        } else {
            /// @solidity memory-safe-assembly
            assembly {
                let ownerSlot := _OWNER_SLOT
                // Clean the upper 96 bits.
                newOwner := shr(96, shl(96, newOwner))
                // Emit the {OwnershipTransferred} event.
                log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, sload(ownerSlot), newOwner)
                // Store the new value.
                sstore(ownerSlot, newOwner)
            }
        }
    }

    /// @dev Throws if the sender is not the owner.
    function _checkOwner() internal view virtual {
        /// @solidity memory-safe-assembly
        assembly {
            // If the caller is not the stored owner, revert.
            if iszero(eq(caller(), sload(_OWNER_SLOT))) {
                mstore(0x00, 0x82b42900) // `Unauthorized()`.
                revert(0x1c, 0x04)
            }
        }
    }

    /// @dev Returns how long a two-step ownership handover is valid for in seconds.
    /// Override to return a different value if needed.
    /// Made internal to conserve bytecode. Wrap it in a public function if needed.
    function _ownershipHandoverValidFor() internal view virtual returns (uint64) {
        return 48 * 3600;
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                  PUBLIC UPDATE FUNCTIONS                   */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Allows the owner to transfer the ownership to `newOwner`.
    function transferOwnership(address newOwner) public payable virtual onlyOwner {
        /// @solidity memory-safe-assembly
        assembly {
            if iszero(shl(96, newOwner)) {
                mstore(0x00, 0x7448fbae) // `NewOwnerIsZeroAddress()`.
                revert(0x1c, 0x04)
            }
        }
        _setOwner(newOwner);
    }

    /// @dev Allows the owner to renounce their ownership.
    function renounceOwnership() public payable virtual onlyOwner {
        _setOwner(address(0));
    }

    /// @dev Request a two-step ownership handover to the caller.
    /// The request will automatically expire in 48 hours (172800 seconds) by default.
    function requestOwnershipHandover() public payable virtual {
        unchecked {
            uint256 expires = block.timestamp + _ownershipHandoverValidFor();
            /// @solidity memory-safe-assembly
            assembly {
                // Compute and set the handover slot to `expires`.
                mstore(0x0c, _HANDOVER_SLOT_SEED)
                mstore(0x00, caller())
                sstore(keccak256(0x0c, 0x20), expires)
                // Emit the {OwnershipHandoverRequested} event.
                log2(0, 0, _OWNERSHIP_HANDOVER_REQUESTED_EVENT_SIGNATURE, caller())
            }
        }
    }

    /// @dev Cancels the two-step ownership handover to the caller, if any.
    function cancelOwnershipHandover() public payable virtual {
        /// @solidity memory-safe-assembly
        assembly {
            // Compute and set the handover slot to 0.
            mstore(0x0c, _HANDOVER_SLOT_SEED)
            mstore(0x00, caller())
            sstore(keccak256(0x0c, 0x20), 0)
            // Emit the {OwnershipHandoverCanceled} event.
            log2(0, 0, _OWNERSHIP_HANDOVER_CANCELED_EVENT_SIGNATURE, caller())
        }
    }

    /// @dev Allows the owner to complete the two-step ownership handover to `pendingOwner`.
    /// Reverts if there is no existing ownership handover requested by `pendingOwner`.
    function completeOwnershipHandover(address pendingOwner) public payable virtual onlyOwner {
        /// @solidity memory-safe-assembly
        assembly {
            // Compute and set the handover slot to 0.
            mstore(0x0c, _HANDOVER_SLOT_SEED)
            mstore(0x00, pendingOwner)
            let handoverSlot := keccak256(0x0c, 0x20)
            // If the handover does not exist, or has expired.
            if gt(timestamp(), sload(handoverSlot)) {
                mstore(0x00, 0x6f5e8818) // `NoHandoverRequest()`.
                revert(0x1c, 0x04)
            }
            // Set the handover slot to 0.
            sstore(handoverSlot, 0)
        }
        _setOwner(pendingOwner);
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                   PUBLIC READ FUNCTIONS                    */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns the owner of the contract.
    function owner() public view virtual returns (address result) {
        /// @solidity memory-safe-assembly
        assembly {
            result := sload(_OWNER_SLOT)
        }
    }

    /// @dev Returns the expiry timestamp for the two-step ownership handover to `pendingOwner`.
    function ownershipHandoverExpiresAt(address pendingOwner)
        public
        view
        virtual
        returns (uint256 result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            // Compute the handover slot.
            mstore(0x0c, _HANDOVER_SLOT_SEED)
            mstore(0x00, pendingOwner)
            // Load the handover slot.
            result := sload(keccak256(0x0c, 0x20))
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                         MODIFIERS                          */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Marks a function as only callable by the owner.
    modifier onlyOwner() virtual {
        _checkOwner();
        _;
    }
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/// @notice UUPS proxy mixin.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/UUPSUpgradeable.sol)
/// @author Modified from OpenZeppelin
/// (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/proxy/utils/UUPSUpgradeable.sol)
///
/// @dev Note:
/// - This implementation is intended to be used with ERC1967 proxies.
/// See: `LibClone.deployERC1967` and related functions.
/// - This implementation is NOT compatible with legacy OpenZeppelin proxies
/// which do not store the implementation at `_ERC1967_IMPLEMENTATION_SLOT`.
abstract contract UUPSUpgradeable {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                       CUSTOM ERRORS                        */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The upgrade failed.
    error UpgradeFailed();

    /// @dev The call is from an unauthorized call context.
    error UnauthorizedCallContext();

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                         IMMUTABLES                         */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev For checking if the context is a delegate call.
    uint256 private immutable __self = uint256(uint160(address(this)));

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                           EVENTS                           */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Emitted when the proxy's implementation is upgraded.
    event Upgraded(address indexed implementation);

    /// @dev `keccak256(bytes("Upgraded(address)"))`.
    uint256 private constant _UPGRADED_EVENT_SIGNATURE =
        0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                          STORAGE                           */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The ERC-1967 storage slot for the implementation in the proxy.
    /// `uint256(keccak256("eip1967.proxy.implementation")) - 1`.
    bytes32 internal constant _ERC1967_IMPLEMENTATION_SLOT =
        0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                      UUPS OPERATIONS                       */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Please override this function to check if `msg.sender` is authorized
    /// to upgrade the proxy to `newImplementation`, reverting if not.
    /// ```
    ///     function _authorizeUpgrade(address) internal override onlyOwner {}
    /// ```
    function _authorizeUpgrade(address newImplementation) internal virtual;

    /// @dev Returns the storage slot used by the implementation,
    /// as specified in [ERC1822](https://eips.ethereum.org/EIPS/eip-1822).
    ///
    /// Note: The `notDelegated` modifier prevents accidental upgrades to
    /// an implementation that is a proxy contract.
    function proxiableUUID() public view virtual notDelegated returns (bytes32) {
        // This function must always return `_ERC1967_IMPLEMENTATION_SLOT` to comply with ERC1967.
        return _ERC1967_IMPLEMENTATION_SLOT;
    }

    /// @dev Upgrades the proxy's implementation to `newImplementation`.
    /// Emits a {Upgraded} event.
    ///
    /// Note: Passing in empty `data` skips the delegatecall to `newImplementation`.
    function upgradeToAndCall(address newImplementation, bytes calldata data)
        public
        payable
        virtual
        onlyProxy
    {
        _authorizeUpgrade(newImplementation);
        /// @solidity memory-safe-assembly
        assembly {
            newImplementation := shr(96, shl(96, newImplementation)) // Clears upper 96 bits.
            mstore(0x00, returndatasize())
            mstore(0x01, 0x52d1902d) // `proxiableUUID()`.
            let s := _ERC1967_IMPLEMENTATION_SLOT
            // Check if `newImplementation` implements `proxiableUUID` correctly.
            if iszero(eq(mload(staticcall(gas(), newImplementation, 0x1d, 0x04, 0x01, 0x20)), s)) {
                mstore(0x01, 0x55299b49) // `UpgradeFailed()`.
                revert(0x1d, 0x04)
            }
            // Emit the {Upgraded} event.
            log2(codesize(), 0x00, _UPGRADED_EVENT_SIGNATURE, newImplementation)
            sstore(s, newImplementation) // Updates the implementation.

            // Perform a delegatecall to `newImplementation` if `data` is non-empty.
            if data.length {
                // Forwards the `data` to `newImplementation` via delegatecall.
                let m := mload(0x40)
                calldatacopy(m, data.offset, data.length)
                if iszero(delegatecall(gas(), newImplementation, m, data.length, codesize(), 0x00))
                {
                    // Bubble up the revert if the call reverts.
                    returndatacopy(m, 0x00, returndatasize())
                    revert(m, returndatasize())
                }
            }
        }
    }

    /// @dev Requires that the execution is performed through a proxy.
    modifier onlyProxy() {
        uint256 s = __self;
        /// @solidity memory-safe-assembly
        assembly {
            // To enable use cases with an immutable default implementation in the bytecode,
            // (see: ERC6551Proxy), we don't require that the proxy address must match the
            // value stored in the implementation slot, which may not be initialized.
            if eq(s, address()) {
                mstore(0x00, 0x9f03a026) // `UnauthorizedCallContext()`.
                revert(0x1c, 0x04)
            }
        }
        _;
    }

    /// @dev Requires that the execution is NOT performed via delegatecall.
    /// This is the opposite of `onlyProxy`.
    modifier notDelegated() {
        uint256 s = __self;
        /// @solidity memory-safe-assembly
        assembly {
            if iszero(eq(s, address())) {
                mstore(0x00, 0x9f03a026) // `UnauthorizedCallContext()`.
                revert(0x1c, 0x04)
            }
        }
        _;
    }
}

File 4 of 7 : EnumerableMapLib.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

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

/// @notice Library for managing enumerable maps in storage.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/EnumerableMapLib.sol)
/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/structs/EnumerableMap.sol)
library EnumerableMapLib {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                       CUSTOM ERRORS                        */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The key does not exist in the enumerable map.
    error EnumerableMapKeyNotFound();

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                          STRUCTS                           */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev A enumerable map of `bytes32` to `bytes32`.
    struct Bytes32ToBytes32Map {
        EnumerableSetLib.Bytes32Set _keys;
        mapping(bytes32 => bytes32) _values;
    }

    /// @dev A enumerable map of `bytes32` to `uint256`.
    struct Bytes32ToUint256Map {
        EnumerableSetLib.Bytes32Set _keys;
        mapping(bytes32 => uint256) _values;
    }

    /// @dev A enumerable map of `bytes32` to `address`.
    struct Bytes32ToAddressMap {
        EnumerableSetLib.Bytes32Set _keys;
        mapping(bytes32 => address) _values;
    }

    /// @dev A enumerable map of `uint256` to `bytes32`.
    struct Uint256ToBytes32Map {
        EnumerableSetLib.Uint256Set _keys;
        mapping(uint256 => bytes32) _values;
    }

    /// @dev A enumerable map of `uint256` to `uint256`.
    struct Uint256ToUint256Map {
        EnumerableSetLib.Uint256Set _keys;
        mapping(uint256 => uint256) _values;
    }

    /// @dev A enumerable map of `uint256` to `address`.
    struct Uint256ToAddressMap {
        EnumerableSetLib.Uint256Set _keys;
        mapping(uint256 => address) _values;
    }

    /// @dev A enumerable map of `address` to `bytes32`.
    struct AddressToBytes32Map {
        EnumerableSetLib.AddressSet _keys;
        mapping(address => bytes32) _values;
    }

    /// @dev A enumerable map of `address` to `uint256`.
    struct AddressToUint256Map {
        EnumerableSetLib.AddressSet _keys;
        mapping(address => uint256) _values;
    }

    /// @dev A enumerable map of `address` to `address`.
    struct AddressToAddressMap {
        EnumerableSetLib.AddressSet _keys;
        mapping(address => address) _values;
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                     GETTERS / SETTERS                      */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Adds a key-value pair to the map, or updates the value for an existing key.
    /// Returns true if `key` was added to the map, that is if it was not already present.
    function set(Bytes32ToBytes32Map storage map, bytes32 key, bytes32 value)
        internal
        returns (bool)
    {
        map._values[key] = value;
        return EnumerableSetLib.add(map._keys, key);
    }

    /// @dev Removes a key-value pair from the map.
    /// Returns true if `key` was removed from the map, that is if it was present.
    function remove(Bytes32ToBytes32Map storage map, bytes32 key) internal returns (bool) {
        delete map._values[key];
        return EnumerableSetLib.remove(map._keys, key);
    }

    /// @dev Returns true if the key is in the map.
    function contains(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bool) {
        return EnumerableSetLib.contains(map._keys, key);
    }

    /// @dev Returns the number of key-value pairs in the map.
    function length(Bytes32ToBytes32Map storage map) internal view returns (uint256) {
        return EnumerableSetLib.length(map._keys);
    }

    /// @dev Returns the key-value pair at index `i`. Reverts if `i` is out-of-bounds.
    function at(Bytes32ToBytes32Map storage map, uint256 i)
        internal
        view
        returns (bytes32 key, bytes32 value)
    {
        value = map._values[key = EnumerableSetLib.at(map._keys, i)];
    }

    /// @dev Tries to return the value associated with the key.
    function tryGet(Bytes32ToBytes32Map storage map, bytes32 key)
        internal
        view
        returns (bool exists, bytes32 value)
    {
        exists = (value = map._values[key]) != bytes32(0) || contains(map, key);
    }

    /// @dev Returns the value for the key. Reverts if the key is not found.
    function get(Bytes32ToBytes32Map storage map, bytes32 key)
        internal
        view
        returns (bytes32 value)
    {
        if ((value = map._values[key]) == bytes32(0)) if (!contains(map, key)) _revertNotFound();
    }

    /// @dev Returns the keys. May run out-of-gas if the map is too big.
    function keys(Bytes32ToBytes32Map storage map) internal view returns (bytes32[] memory) {
        return EnumerableSetLib.values(map._keys);
    }

    /// @dev Adds a key-value pair to the map, or updates the value for an existing key.
    /// Returns true if `key` was added to the map, that is if it was not already present.
    function set(Bytes32ToUint256Map storage map, bytes32 key, uint256 value)
        internal
        returns (bool)
    {
        map._values[key] = value;
        return EnumerableSetLib.add(map._keys, key);
    }

    /// @dev Removes a key-value pair from the map.
    /// Returns true if `key` was removed from the map, that is if it was present.
    function remove(Bytes32ToUint256Map storage map, bytes32 key) internal returns (bool) {
        delete map._values[key];
        return EnumerableSetLib.remove(map._keys, key);
    }

    /// @dev Returns true if the key is in the map.
    function contains(Bytes32ToUint256Map storage map, bytes32 key) internal view returns (bool) {
        return EnumerableSetLib.contains(map._keys, key);
    }

    /// @dev Returns the number of key-value pairs in the map.
    function length(Bytes32ToUint256Map storage map) internal view returns (uint256) {
        return EnumerableSetLib.length(map._keys);
    }

    /// @dev Returns the key-value pair at index `i`. Reverts if `i` is out-of-bounds.
    function at(Bytes32ToUint256Map storage map, uint256 i)
        internal
        view
        returns (bytes32 key, uint256 value)
    {
        value = map._values[key = EnumerableSetLib.at(map._keys, i)];
    }

    /// @dev Tries to return the value associated with the key.
    function tryGet(Bytes32ToUint256Map storage map, bytes32 key)
        internal
        view
        returns (bool exists, uint256 value)
    {
        exists = (value = map._values[key]) != uint256(0) || contains(map, key);
    }

    /// @dev Returns the value for the key. Reverts if the key is not found.
    function get(Bytes32ToUint256Map storage map, bytes32 key)
        internal
        view
        returns (uint256 value)
    {
        if ((value = map._values[key]) == uint256(0)) if (!contains(map, key)) _revertNotFound();
    }

    /// @dev Returns the keys. May run out-of-gas if the map is too big.
    function keys(Bytes32ToUint256Map storage map) internal view returns (bytes32[] memory) {
        return EnumerableSetLib.values(map._keys);
    }

    /// @dev Adds a key-value pair to the map, or updates the value for an existing key.
    /// Returns true if `key` was added to the map, that is if it was not already present.
    function set(Bytes32ToAddressMap storage map, bytes32 key, address value)
        internal
        returns (bool)
    {
        map._values[key] = value;
        return EnumerableSetLib.add(map._keys, key);
    }

    /// @dev Removes a key-value pair from the map.
    /// Returns true if `key` was removed from the map, that is if it was present.
    function remove(Bytes32ToAddressMap storage map, bytes32 key) internal returns (bool) {
        delete map._values[key];
        return EnumerableSetLib.remove(map._keys, key);
    }

    /// @dev Returns true if the key is in the map.
    function contains(Bytes32ToAddressMap storage map, bytes32 key) internal view returns (bool) {
        return EnumerableSetLib.contains(map._keys, key);
    }

    /// @dev Returns the number of key-value pairs in the map.
    function length(Bytes32ToAddressMap storage map) internal view returns (uint256) {
        return EnumerableSetLib.length(map._keys);
    }

    /// @dev Returns the key-value pair at index `i`. Reverts if `i` is out-of-bounds.
    function at(Bytes32ToAddressMap storage map, uint256 i)
        internal
        view
        returns (bytes32 key, address value)
    {
        value = map._values[key = EnumerableSetLib.at(map._keys, i)];
    }

    /// @dev Tries to return the value associated with the key.
    function tryGet(Bytes32ToAddressMap storage map, bytes32 key)
        internal
        view
        returns (bool exists, address value)
    {
        exists = (value = map._values[key]) != address(0) || contains(map, key);
    }

    /// @dev Returns the value for the key. Reverts if the key is not found.
    function get(Bytes32ToAddressMap storage map, bytes32 key)
        internal
        view
        returns (address value)
    {
        if ((value = map._values[key]) == address(0)) if (!contains(map, key)) _revertNotFound();
    }

    /// @dev Returns the keys. May run out-of-gas if the map is too big.
    function keys(Bytes32ToAddressMap storage map) internal view returns (bytes32[] memory) {
        return EnumerableSetLib.values(map._keys);
    }

    /// @dev Adds a key-value pair to the map, or updates the value for an existing key.
    /// Returns true if `key` was added to the map, that is if it was not already present.
    function set(Uint256ToBytes32Map storage map, uint256 key, bytes32 value)
        internal
        returns (bool)
    {
        map._values[key] = value;
        return EnumerableSetLib.add(map._keys, key);
    }

    /// @dev Removes a key-value pair from the map.
    /// Returns true if `key` was removed from the map, that is if it was present.
    function remove(Uint256ToBytes32Map storage map, uint256 key) internal returns (bool) {
        delete map._values[key];
        return EnumerableSetLib.remove(map._keys, key);
    }

    /// @dev Returns true if the key is in the map.
    function contains(Uint256ToBytes32Map storage map, uint256 key) internal view returns (bool) {
        return EnumerableSetLib.contains(map._keys, key);
    }

    /// @dev Returns the number of key-value pairs in the map.
    function length(Uint256ToBytes32Map storage map) internal view returns (uint256) {
        return EnumerableSetLib.length(map._keys);
    }

    /// @dev Returns the key-value pair at index `i`. Reverts if `i` is out-of-bounds.
    function at(Uint256ToBytes32Map storage map, uint256 i)
        internal
        view
        returns (uint256 key, bytes32 value)
    {
        value = map._values[key = EnumerableSetLib.at(map._keys, i)];
    }

    /// @dev Tries to return the value associated with the key.
    function tryGet(Uint256ToBytes32Map storage map, uint256 key)
        internal
        view
        returns (bool exists, bytes32 value)
    {
        exists = (value = map._values[key]) != bytes32(0) || contains(map, key);
    }

    /// @dev Returns the value for the key. Reverts if the key is not found.
    function get(Uint256ToBytes32Map storage map, uint256 key)
        internal
        view
        returns (bytes32 value)
    {
        if ((value = map._values[key]) == bytes32(0)) if (!contains(map, key)) _revertNotFound();
    }

    /// @dev Returns the keys. May run out-of-gas if the map is too big.
    function keys(Uint256ToBytes32Map storage map) internal view returns (uint256[] memory) {
        return EnumerableSetLib.values(map._keys);
    }

    /// @dev Adds a key-value pair to the map, or updates the value for an existing key.
    /// Returns true if `key` was added to the map, that is if it was not already present.
    function set(Uint256ToUint256Map storage map, uint256 key, uint256 value)
        internal
        returns (bool)
    {
        map._values[key] = value;
        return EnumerableSetLib.add(map._keys, key);
    }

    /// @dev Removes a key-value pair from the map.
    /// Returns true if `key` was removed from the map, that is if it was present.
    function remove(Uint256ToUint256Map storage map, uint256 key) internal returns (bool) {
        delete map._values[key];
        return EnumerableSetLib.remove(map._keys, key);
    }

    /// @dev Returns true if the key is in the map.
    function contains(Uint256ToUint256Map storage map, uint256 key) internal view returns (bool) {
        return EnumerableSetLib.contains(map._keys, key);
    }

    /// @dev Returns the number of key-value pairs in the map.
    function length(Uint256ToUint256Map storage map) internal view returns (uint256) {
        return EnumerableSetLib.length(map._keys);
    }

    /// @dev Returns the key-value pair at index `i`. Reverts if `i` is out-of-bounds.
    function at(Uint256ToUint256Map storage map, uint256 i)
        internal
        view
        returns (uint256 key, uint256 value)
    {
        value = map._values[key = EnumerableSetLib.at(map._keys, i)];
    }

    /// @dev Tries to return the value associated with the key.
    function tryGet(Uint256ToUint256Map storage map, uint256 key)
        internal
        view
        returns (bool exists, uint256 value)
    {
        exists = (value = map._values[key]) != uint256(0) || contains(map, key);
    }

    /// @dev Returns the value for the key. Reverts if the key is not found.
    function get(Uint256ToUint256Map storage map, uint256 key)
        internal
        view
        returns (uint256 value)
    {
        if ((value = map._values[key]) == uint256(0)) if (!contains(map, key)) _revertNotFound();
    }

    /// @dev Returns the keys. May run out-of-gas if the map is too big.
    function keys(Uint256ToUint256Map storage map) internal view returns (uint256[] memory) {
        return EnumerableSetLib.values(map._keys);
    }

    /// @dev Adds a key-value pair to the map, or updates the value for an existing key.
    /// Returns true if `key` was added to the map, that is if it was not already present.
    function set(Uint256ToAddressMap storage map, uint256 key, address value)
        internal
        returns (bool)
    {
        map._values[key] = value;
        return EnumerableSetLib.add(map._keys, key);
    }

    /// @dev Removes a key-value pair from the map.
    /// Returns true if `key` was removed from the map, that is if it was present.
    function remove(Uint256ToAddressMap storage map, uint256 key) internal returns (bool) {
        delete map._values[key];
        return EnumerableSetLib.remove(map._keys, key);
    }

    /// @dev Returns true if the key is in the map.
    function contains(Uint256ToAddressMap storage map, uint256 key) internal view returns (bool) {
        return EnumerableSetLib.contains(map._keys, key);
    }

    /// @dev Returns the number of key-value pairs in the map.
    function length(Uint256ToAddressMap storage map) internal view returns (uint256) {
        return EnumerableSetLib.length(map._keys);
    }

    /// @dev Returns the key-value pair at index `i`. Reverts if `i` is out-of-bounds.
    function at(Uint256ToAddressMap storage map, uint256 i)
        internal
        view
        returns (uint256 key, address value)
    {
        value = map._values[key = EnumerableSetLib.at(map._keys, i)];
    }

    /// @dev Tries to return the value associated with the key.
    function tryGet(Uint256ToAddressMap storage map, uint256 key)
        internal
        view
        returns (bool exists, address value)
    {
        exists = (value = map._values[key]) != address(0) || contains(map, key);
    }

    /// @dev Returns the value for the key. Reverts if the key is not found.
    function get(Uint256ToAddressMap storage map, uint256 key)
        internal
        view
        returns (address value)
    {
        if ((value = map._values[key]) == address(0)) if (!contains(map, key)) _revertNotFound();
    }

    /// @dev Returns the keys. May run out-of-gas if the map is too big.
    function keys(Uint256ToAddressMap storage map) internal view returns (uint256[] memory) {
        return EnumerableSetLib.values(map._keys);
    }

    /// @dev Adds a key-value pair to the map, or updates the value for an existing key.
    /// Returns true if `key` was added to the map, that is if it was not already present.
    function set(AddressToBytes32Map storage map, address key, bytes32 value)
        internal
        returns (bool)
    {
        map._values[key] = value;
        return EnumerableSetLib.add(map._keys, key);
    }

    /// @dev Removes a key-value pair from the map.
    /// Returns true if `key` was removed from the map, that is if it was present.
    function remove(AddressToBytes32Map storage map, address key) internal returns (bool) {
        delete map._values[key];
        return EnumerableSetLib.remove(map._keys, key);
    }

    /// @dev Returns true if the key is in the map.
    function contains(AddressToBytes32Map storage map, address key) internal view returns (bool) {
        return EnumerableSetLib.contains(map._keys, key);
    }

    /// @dev Returns the number of key-value pairs in the map.
    function length(AddressToBytes32Map storage map) internal view returns (uint256) {
        return EnumerableSetLib.length(map._keys);
    }

    /// @dev Returns the key-value pair at index `i`. Reverts if `i` is out-of-bounds.
    function at(AddressToBytes32Map storage map, uint256 i)
        internal
        view
        returns (address key, bytes32 value)
    {
        value = map._values[key = EnumerableSetLib.at(map._keys, i)];
    }

    /// @dev Tries to return the value associated with the key.
    function tryGet(AddressToBytes32Map storage map, address key)
        internal
        view
        returns (bool exists, bytes32 value)
    {
        exists = (value = map._values[key]) != bytes32(0) || contains(map, key);
    }

    /// @dev Returns the value for the key. Reverts if the key is not found.
    function get(AddressToBytes32Map storage map, address key)
        internal
        view
        returns (bytes32 value)
    {
        if ((value = map._values[key]) == bytes32(0)) if (!contains(map, key)) _revertNotFound();
    }

    /// @dev Returns the keys. May run out-of-gas if the map is too big.
    function keys(AddressToBytes32Map storage map) internal view returns (address[] memory) {
        return EnumerableSetLib.values(map._keys);
    }

    /// @dev Adds a key-value pair to the map, or updates the value for an existing key.
    /// Returns true if `key` was added to the map, that is if it was not already present.
    function set(AddressToUint256Map storage map, address key, uint256 value)
        internal
        returns (bool)
    {
        map._values[key] = value;
        return EnumerableSetLib.add(map._keys, key);
    }

    /// @dev Removes a key-value pair from the map.
    /// Returns true if `key` was removed from the map, that is if it was present.
    function remove(AddressToUint256Map storage map, address key) internal returns (bool) {
        delete map._values[key];
        return EnumerableSetLib.remove(map._keys, key);
    }

    /// @dev Returns true if the key is in the map.
    function contains(AddressToUint256Map storage map, address key) internal view returns (bool) {
        return EnumerableSetLib.contains(map._keys, key);
    }

    /// @dev Returns the number of key-value pairs in the map.
    function length(AddressToUint256Map storage map) internal view returns (uint256) {
        return EnumerableSetLib.length(map._keys);
    }

    /// @dev Returns the key-value pair at index `i`. Reverts if `i` is out-of-bounds.
    function at(AddressToUint256Map storage map, uint256 i)
        internal
        view
        returns (address key, uint256 value)
    {
        value = map._values[key = EnumerableSetLib.at(map._keys, i)];
    }

    /// @dev Tries to return the value associated with the key.
    function tryGet(AddressToUint256Map storage map, address key)
        internal
        view
        returns (bool exists, uint256 value)
    {
        exists = (value = map._values[key]) != uint256(0) || contains(map, key);
    }

    /// @dev Returns the value for the key. Reverts if the key is not found.
    function get(AddressToUint256Map storage map, address key)
        internal
        view
        returns (uint256 value)
    {
        if ((value = map._values[key]) == uint256(0)) if (!contains(map, key)) _revertNotFound();
    }

    /// @dev Returns the keys. May run out-of-gas if the map is too big.
    function keys(AddressToUint256Map storage map) internal view returns (address[] memory) {
        return EnumerableSetLib.values(map._keys);
    }

    /// @dev Adds a key-value pair to the map, or updates the value for an existing key.
    /// Returns true if `key` was added to the map, that is if it was not already present.
    function set(AddressToAddressMap storage map, address key, address value)
        internal
        returns (bool)
    {
        map._values[key] = value;
        return EnumerableSetLib.add(map._keys, key);
    }

    /// @dev Removes a key-value pair from the map.
    /// Returns true if `key` was removed from the map, that is if it was present.
    function remove(AddressToAddressMap storage map, address key) internal returns (bool) {
        delete map._values[key];
        return EnumerableSetLib.remove(map._keys, key);
    }

    /// @dev Returns true if the key is in the map.
    function contains(AddressToAddressMap storage map, address key) internal view returns (bool) {
        return EnumerableSetLib.contains(map._keys, key);
    }

    /// @dev Returns the number of key-value pairs in the map.
    function length(AddressToAddressMap storage map) internal view returns (uint256) {
        return EnumerableSetLib.length(map._keys);
    }

    /// @dev Returns the key-value pair at index `i`. Reverts if `i` is out-of-bounds.
    function at(AddressToAddressMap storage map, uint256 i)
        internal
        view
        returns (address key, address value)
    {
        value = map._values[key = EnumerableSetLib.at(map._keys, i)];
    }

    /// @dev Tries to return the value associated with the key.
    function tryGet(AddressToAddressMap storage map, address key)
        internal
        view
        returns (bool exists, address value)
    {
        exists = (value = map._values[key]) != address(0) || contains(map, key);
    }

    /// @dev Returns the value for the key. Reverts if the key is not found.
    function get(AddressToAddressMap storage map, address key)
        internal
        view
        returns (address value)
    {
        if ((value = map._values[key]) == address(0)) if (!contains(map, key)) _revertNotFound();
    }

    /// @dev Returns the keys. May run out-of-gas if the map is too big.
    function keys(AddressToAddressMap storage map) internal view returns (address[] memory) {
        return EnumerableSetLib.values(map._keys);
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                      PRIVATE HELPERS                       */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Reverts with `EnumerableMapKeyNotFound()`.
    function _revertNotFound() private pure {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, 0x88682bf3) // `EnumerableMapKeyNotFound()`.
            revert(0x1c, 0x04)
        }
    }
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface IERC20 {
    function mint(address to, uint256 amount) external;

    function transferFrom(address from, address to, uint256 amount) external returns (bool);

    function transfer(address to, uint256 amount) external returns (bool);

    function balanceOf(address to) external returns (uint256);

    function burn(uint256 amount) external;
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;

interface IOCHItems {
    function mint(address to, uint256 id, uint256 amount) external;
    function burn(address from, uint256 id, uint256 amount) external;
    function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes calldata data) external;
}

File 7 of 7 : EnumerableSetLib.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/// @notice Library for managing enumerable sets in storage.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/EnumerableSetLib.sol)
///
/// @dev Note:
/// In many applications, the number of elements in an enumerable set is small.
/// This enumerable set implementation avoids storing the length and indices
/// for up to 3 elements. Once the length exceeds 3 for the first time, the length
/// and indices will be initialized. The amortized cost of adding elements is O(1).
///
/// The AddressSet implementation packs the length with the 0th entry.
///
/// All enumerable sets except Uint8Set use a pop and swap mechanism to remove elements.
/// This means that the iteration order of elements can change between element removals.
library EnumerableSetLib {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                       CUSTOM ERRORS                        */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The index must be less than the length.
    error IndexOutOfBounds();

    /// @dev The value cannot be the zero sentinel.
    error ValueIsZeroSentinel();

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                         CONSTANTS                          */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev A sentinel value to denote the zero value in storage.
    /// No elements can be equal to this value.
    /// `uint72(bytes9(keccak256(bytes("_ZERO_SENTINEL"))))`.
    uint256 private constant _ZERO_SENTINEL = 0xfbb67fda52d4bfb8bf;

    /// @dev The storage layout is given by:
    /// ```
    ///     mstore(0x04, _ENUMERABLE_ADDRESS_SET_SLOT_SEED)
    ///     mstore(0x00, set.slot)
    ///     let rootSlot := keccak256(0x00, 0x24)
    ///     mstore(0x20, rootSlot)
    ///     mstore(0x00, shr(96, shl(96, value)))
    ///     let positionSlot := keccak256(0x00, 0x40)
    ///     let valueSlot := add(rootSlot, sload(positionSlot))
    ///     let valueInStorage := shr(96, sload(valueSlot))
    ///     let lazyLength := shr(160, shl(160, sload(rootSlot)))
    /// ```
    uint256 private constant _ENUMERABLE_ADDRESS_SET_SLOT_SEED = 0x978aab92;

    /// @dev The storage layout is given by:
    /// ```
    ///     mstore(0x04, _ENUMERABLE_WORD_SET_SLOT_SEED)
    ///     mstore(0x00, set.slot)
    ///     let rootSlot := keccak256(0x00, 0x24)
    ///     mstore(0x20, rootSlot)
    ///     mstore(0x00, value)
    ///     let positionSlot := keccak256(0x00, 0x40)
    ///     let valueSlot := add(rootSlot, sload(positionSlot))
    ///     let valueInStorage := sload(valueSlot)
    ///     let lazyLength := sload(not(rootSlot))
    /// ```
    uint256 private constant _ENUMERABLE_WORD_SET_SLOT_SEED = 0x18fb5864;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                          STRUCTS                           */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev An enumerable address set in storage.
    struct AddressSet {
        uint256 _spacer;
    }

    /// @dev An enumerable bytes32 set in storage.
    struct Bytes32Set {
        uint256 _spacer;
    }

    /// @dev An enumerable uint256 set in storage.
    struct Uint256Set {
        uint256 _spacer;
    }

    /// @dev An enumerable int256 set in storage.
    struct Int256Set {
        uint256 _spacer;
    }

    /// @dev An enumerable uint8 set in storage. Useful for enums.
    struct Uint8Set {
        uint256 data;
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                     GETTERS / SETTERS                      */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns the number of elements in the set.
    function length(AddressSet storage set) internal view returns (uint256 result) {
        bytes32 rootSlot = _rootSlot(set);
        /// @solidity memory-safe-assembly
        assembly {
            let rootPacked := sload(rootSlot)
            let n := shr(160, shl(160, rootPacked))
            result := shr(1, n)
            for {} iszero(or(iszero(shr(96, rootPacked)), n)) {} {
                result := 1
                if iszero(sload(add(rootSlot, result))) { break }
                result := 2
                if iszero(sload(add(rootSlot, result))) { break }
                result := 3
                break
            }
        }
    }

    /// @dev Returns the number of elements in the set.
    function length(Bytes32Set storage set) internal view returns (uint256 result) {
        bytes32 rootSlot = _rootSlot(set);
        /// @solidity memory-safe-assembly
        assembly {
            let n := sload(not(rootSlot))
            result := shr(1, n)
            for {} iszero(n) {} {
                result := 0
                if iszero(sload(add(rootSlot, result))) { break }
                result := 1
                if iszero(sload(add(rootSlot, result))) { break }
                result := 2
                if iszero(sload(add(rootSlot, result))) { break }
                result := 3
                break
            }
        }
    }

    /// @dev Returns the number of elements in the set.
    function length(Uint256Set storage set) internal view returns (uint256 result) {
        result = length(_toBytes32Set(set));
    }

    /// @dev Returns the number of elements in the set.
    function length(Int256Set storage set) internal view returns (uint256 result) {
        result = length(_toBytes32Set(set));
    }

    /// @dev Returns the number of elements in the set.
    function length(Uint8Set storage set) internal view returns (uint256 result) {
        /// @solidity memory-safe-assembly
        assembly {
            for { let packed := sload(set.slot) } packed { result := add(1, result) } {
                packed := xor(packed, and(packed, add(1, not(packed))))
            }
        }
    }

    /// @dev Returns whether `value` is in the set.
    function contains(AddressSet storage set, address value) internal view returns (bool result) {
        bytes32 rootSlot = _rootSlot(set);
        /// @solidity memory-safe-assembly
        assembly {
            value := shr(96, shl(96, value))
            if eq(value, _ZERO_SENTINEL) {
                mstore(0x00, 0xf5a267f1) // `ValueIsZeroSentinel()`.
                revert(0x1c, 0x04)
            }
            if iszero(value) { value := _ZERO_SENTINEL }
            let rootPacked := sload(rootSlot)
            for {} 1 {} {
                if iszero(shr(160, shl(160, rootPacked))) {
                    result := 1
                    if eq(shr(96, rootPacked), value) { break }
                    if eq(shr(96, sload(add(rootSlot, 1))), value) { break }
                    if eq(shr(96, sload(add(rootSlot, 2))), value) { break }
                    result := 0
                    break
                }
                mstore(0x20, rootSlot)
                mstore(0x00, value)
                result := iszero(iszero(sload(keccak256(0x00, 0x40))))
                break
            }
        }
    }

    /// @dev Returns whether `value` is in the set.
    function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool result) {
        bytes32 rootSlot = _rootSlot(set);
        /// @solidity memory-safe-assembly
        assembly {
            if eq(value, _ZERO_SENTINEL) {
                mstore(0x00, 0xf5a267f1) // `ValueIsZeroSentinel()`.
                revert(0x1c, 0x04)
            }
            if iszero(value) { value := _ZERO_SENTINEL }
            for {} 1 {} {
                if iszero(sload(not(rootSlot))) {
                    result := 1
                    if eq(sload(rootSlot), value) { break }
                    if eq(sload(add(rootSlot, 1)), value) { break }
                    if eq(sload(add(rootSlot, 2)), value) { break }
                    result := 0
                    break
                }
                mstore(0x20, rootSlot)
                mstore(0x00, value)
                result := iszero(iszero(sload(keccak256(0x00, 0x40))))
                break
            }
        }
    }

    /// @dev Returns whether `value` is in the set.
    function contains(Uint256Set storage set, uint256 value) internal view returns (bool result) {
        result = contains(_toBytes32Set(set), bytes32(value));
    }

    /// @dev Returns whether `value` is in the set.
    function contains(Int256Set storage set, int256 value) internal view returns (bool result) {
        result = contains(_toBytes32Set(set), bytes32(uint256(value)));
    }

    /// @dev Returns whether `value` is in the set.
    function contains(Uint8Set storage set, uint8 value) internal view returns (bool result) {
        /// @solidity memory-safe-assembly
        assembly {
            result := and(1, shr(and(0xff, value), sload(set.slot)))
        }
    }

    /// @dev Adds `value` to the set. Returns whether `value` was not in the set.
    function add(AddressSet storage set, address value) internal returns (bool result) {
        bytes32 rootSlot = _rootSlot(set);
        /// @solidity memory-safe-assembly
        assembly {
            value := shr(96, shl(96, value))
            if eq(value, _ZERO_SENTINEL) {
                mstore(0x00, 0xf5a267f1) // `ValueIsZeroSentinel()`.
                revert(0x1c, 0x04)
            }
            if iszero(value) { value := _ZERO_SENTINEL }
            let rootPacked := sload(rootSlot)
            for { let n := shr(160, shl(160, rootPacked)) } 1 {} {
                mstore(0x20, rootSlot)
                if iszero(n) {
                    let v0 := shr(96, rootPacked)
                    if iszero(v0) {
                        sstore(rootSlot, shl(96, value))
                        result := 1
                        break
                    }
                    if eq(v0, value) { break }
                    let v1 := shr(96, sload(add(rootSlot, 1)))
                    if iszero(v1) {
                        sstore(add(rootSlot, 1), shl(96, value))
                        result := 1
                        break
                    }
                    if eq(v1, value) { break }
                    let v2 := shr(96, sload(add(rootSlot, 2)))
                    if iszero(v2) {
                        sstore(add(rootSlot, 2), shl(96, value))
                        result := 1
                        break
                    }
                    if eq(v2, value) { break }
                    mstore(0x00, v0)
                    sstore(keccak256(0x00, 0x40), 1)
                    mstore(0x00, v1)
                    sstore(keccak256(0x00, 0x40), 2)
                    mstore(0x00, v2)
                    sstore(keccak256(0x00, 0x40), 3)
                    rootPacked := or(rootPacked, 7)
                    n := 7
                }
                mstore(0x00, value)
                let p := keccak256(0x00, 0x40)
                if iszero(sload(p)) {
                    n := shr(1, n)
                    result := 1
                    sstore(p, add(1, n))
                    if iszero(n) {
                        sstore(rootSlot, or(3, shl(96, value)))
                        break
                    }
                    sstore(add(rootSlot, n), shl(96, value))
                    sstore(rootSlot, add(2, rootPacked))
                    break
                }
                break
            }
        }
    }

    /// @dev Adds `value` to the set. Returns whether `value` was not in the set.
    function add(Bytes32Set storage set, bytes32 value) internal returns (bool result) {
        bytes32 rootSlot = _rootSlot(set);
        /// @solidity memory-safe-assembly
        assembly {
            if eq(value, _ZERO_SENTINEL) {
                mstore(0x00, 0xf5a267f1) // `ValueIsZeroSentinel()`.
                revert(0x1c, 0x04)
            }
            if iszero(value) { value := _ZERO_SENTINEL }
            for { let n := sload(not(rootSlot)) } 1 {} {
                mstore(0x20, rootSlot)
                if iszero(n) {
                    let v0 := sload(rootSlot)
                    if iszero(v0) {
                        sstore(rootSlot, value)
                        result := 1
                        break
                    }
                    if eq(v0, value) { break }
                    let v1 := sload(add(rootSlot, 1))
                    if iszero(v1) {
                        sstore(add(rootSlot, 1), value)
                        result := 1
                        break
                    }
                    if eq(v1, value) { break }
                    let v2 := sload(add(rootSlot, 2))
                    if iszero(v2) {
                        sstore(add(rootSlot, 2), value)
                        result := 1
                        break
                    }
                    if eq(v2, value) { break }
                    mstore(0x00, v0)
                    sstore(keccak256(0x00, 0x40), 1)
                    mstore(0x00, v1)
                    sstore(keccak256(0x00, 0x40), 2)
                    mstore(0x00, v2)
                    sstore(keccak256(0x00, 0x40), 3)
                    n := 7
                }
                mstore(0x00, value)
                let p := keccak256(0x00, 0x40)
                if iszero(sload(p)) {
                    n := shr(1, n)
                    sstore(add(rootSlot, n), value)
                    sstore(p, add(1, n))
                    sstore(not(rootSlot), or(1, shl(1, add(1, n))))
                    result := 1
                    break
                }
                break
            }
        }
    }

    /// @dev Adds `value` to the set. Returns whether `value` was not in the set.
    function add(Uint256Set storage set, uint256 value) internal returns (bool result) {
        result = add(_toBytes32Set(set), bytes32(value));
    }

    /// @dev Adds `value` to the set. Returns whether `value` was not in the set.
    function add(Int256Set storage set, int256 value) internal returns (bool result) {
        result = add(_toBytes32Set(set), bytes32(uint256(value)));
    }

    /// @dev Adds `value` to the set. Returns whether `value` was not in the set.
    function add(Uint8Set storage set, uint8 value) internal returns (bool result) {
        /// @solidity memory-safe-assembly
        assembly {
            result := sload(set.slot)
            let mask := shl(and(0xff, value), 1)
            sstore(set.slot, or(result, mask))
            result := iszero(and(result, mask))
        }
    }

    /// @dev Removes `value` from the set. Returns whether `value` was in the set.
    function remove(AddressSet storage set, address value) internal returns (bool result) {
        bytes32 rootSlot = _rootSlot(set);
        /// @solidity memory-safe-assembly
        assembly {
            value := shr(96, shl(96, value))
            if eq(value, _ZERO_SENTINEL) {
                mstore(0x00, 0xf5a267f1) // `ValueIsZeroSentinel()`.
                revert(0x1c, 0x04)
            }
            if iszero(value) { value := _ZERO_SENTINEL }
            let rootPacked := sload(rootSlot)
            for { let n := shr(160, shl(160, rootPacked)) } 1 {} {
                if iszero(n) {
                    result := 1
                    if eq(shr(96, rootPacked), value) {
                        sstore(rootSlot, sload(add(rootSlot, 1)))
                        sstore(add(rootSlot, 1), sload(add(rootSlot, 2)))
                        sstore(add(rootSlot, 2), 0)
                        break
                    }
                    if eq(shr(96, sload(add(rootSlot, 1))), value) {
                        sstore(add(rootSlot, 1), sload(add(rootSlot, 2)))
                        sstore(add(rootSlot, 2), 0)
                        break
                    }
                    if eq(shr(96, sload(add(rootSlot, 2))), value) {
                        sstore(add(rootSlot, 2), 0)
                        break
                    }
                    result := 0
                    break
                }
                mstore(0x20, rootSlot)
                mstore(0x00, value)
                let p := keccak256(0x00, 0x40)
                let position := sload(p)
                if iszero(position) { break }
                n := sub(shr(1, n), 1)
                if iszero(eq(sub(position, 1), n)) {
                    let lastValue := shr(96, sload(add(rootSlot, n)))
                    sstore(add(rootSlot, sub(position, 1)), shl(96, lastValue))
                    mstore(0x00, lastValue)
                    sstore(keccak256(0x00, 0x40), position)
                }
                sstore(rootSlot, or(shl(96, shr(96, sload(rootSlot))), or(shl(1, n), 1)))
                sstore(p, 0)
                result := 1
                break
            }
        }
    }

    /// @dev Removes `value` from the set. Returns whether `value` was in the set.
    function remove(Bytes32Set storage set, bytes32 value) internal returns (bool result) {
        bytes32 rootSlot = _rootSlot(set);
        /// @solidity memory-safe-assembly
        assembly {
            if eq(value, _ZERO_SENTINEL) {
                mstore(0x00, 0xf5a267f1) // `ValueIsZeroSentinel()`.
                revert(0x1c, 0x04)
            }
            if iszero(value) { value := _ZERO_SENTINEL }
            for { let n := sload(not(rootSlot)) } 1 {} {
                if iszero(n) {
                    result := 1
                    if eq(sload(rootSlot), value) {
                        sstore(rootSlot, sload(add(rootSlot, 1)))
                        sstore(add(rootSlot, 1), sload(add(rootSlot, 2)))
                        sstore(add(rootSlot, 2), 0)
                        break
                    }
                    if eq(sload(add(rootSlot, 1)), value) {
                        sstore(add(rootSlot, 1), sload(add(rootSlot, 2)))
                        sstore(add(rootSlot, 2), 0)
                        break
                    }
                    if eq(sload(add(rootSlot, 2)), value) {
                        sstore(add(rootSlot, 2), 0)
                        break
                    }
                    result := 0
                    break
                }
                mstore(0x20, rootSlot)
                mstore(0x00, value)
                let p := keccak256(0x00, 0x40)
                let position := sload(p)
                if iszero(position) { break }
                n := sub(shr(1, n), 1)
                if iszero(eq(sub(position, 1), n)) {
                    let lastValue := sload(add(rootSlot, n))
                    sstore(add(rootSlot, sub(position, 1)), lastValue)
                    mstore(0x00, lastValue)
                    sstore(keccak256(0x00, 0x40), position)
                }
                sstore(not(rootSlot), or(shl(1, n), 1))
                sstore(p, 0)
                result := 1
                break
            }
        }
    }

    /// @dev Removes `value` from the set. Returns whether `value` was in the set.
    function remove(Uint256Set storage set, uint256 value) internal returns (bool result) {
        result = remove(_toBytes32Set(set), bytes32(value));
    }

    /// @dev Removes `value` from the set. Returns whether `value` was in the set.
    function remove(Int256Set storage set, int256 value) internal returns (bool result) {
        result = remove(_toBytes32Set(set), bytes32(uint256(value)));
    }

    /// @dev Removes `value` from the set. Returns whether `value` was in the set.
    function remove(Uint8Set storage set, uint8 value) internal returns (bool result) {
        /// @solidity memory-safe-assembly
        assembly {
            result := sload(set.slot)
            let mask := shl(and(0xff, value), 1)
            sstore(set.slot, and(result, not(mask)))
            result := iszero(iszero(and(result, mask)))
        }
    }

    /// @dev Returns all of the values in the set.
    /// Note: This can consume more gas than the block gas limit for large sets.
    function values(AddressSet storage set) internal view returns (address[] memory result) {
        bytes32 rootSlot = _rootSlot(set);
        /// @solidity memory-safe-assembly
        assembly {
            let zs := _ZERO_SENTINEL
            let rootPacked := sload(rootSlot)
            let n := shr(160, shl(160, rootPacked))
            result := mload(0x40)
            let o := add(0x20, result)
            let v := shr(96, rootPacked)
            mstore(o, mul(v, iszero(eq(v, zs))))
            for {} 1 {} {
                if iszero(n) {
                    if v {
                        n := 1
                        v := shr(96, sload(add(rootSlot, n)))
                        if v {
                            n := 2
                            mstore(add(o, 0x20), mul(v, iszero(eq(v, zs))))
                            v := shr(96, sload(add(rootSlot, n)))
                            if v {
                                n := 3
                                mstore(add(o, 0x40), mul(v, iszero(eq(v, zs))))
                            }
                        }
                    }
                    break
                }
                n := shr(1, n)
                for { let i := 1 } lt(i, n) { i := add(i, 1) } {
                    v := shr(96, sload(add(rootSlot, i)))
                    mstore(add(o, shl(5, i)), mul(v, iszero(eq(v, zs))))
                }
                break
            }
            mstore(result, n)
            mstore(0x40, add(o, shl(5, n)))
        }
    }

    /// @dev Returns all of the values in the set.
    /// Note: This can consume more gas than the block gas limit for large sets.
    function values(Bytes32Set storage set) internal view returns (bytes32[] memory result) {
        bytes32 rootSlot = _rootSlot(set);
        /// @solidity memory-safe-assembly
        assembly {
            let zs := _ZERO_SENTINEL
            let n := sload(not(rootSlot))
            result := mload(0x40)
            let o := add(0x20, result)
            for {} 1 {} {
                if iszero(n) {
                    let v := sload(rootSlot)
                    if v {
                        n := 1
                        mstore(o, mul(v, iszero(eq(v, zs))))
                        v := sload(add(rootSlot, n))
                        if v {
                            n := 2
                            mstore(add(o, 0x20), mul(v, iszero(eq(v, zs))))
                            v := sload(add(rootSlot, n))
                            if v {
                                n := 3
                                mstore(add(o, 0x40), mul(v, iszero(eq(v, zs))))
                            }
                        }
                    }
                    break
                }
                n := shr(1, n)
                for { let i := 0 } lt(i, n) { i := add(i, 1) } {
                    let v := sload(add(rootSlot, i))
                    mstore(add(o, shl(5, i)), mul(v, iszero(eq(v, zs))))
                }
                break
            }
            mstore(result, n)
            mstore(0x40, add(o, shl(5, n)))
        }
    }

    /// @dev Returns all of the values in the set.
    /// Note: This can consume more gas than the block gas limit for large sets.
    function values(Uint256Set storage set) internal view returns (uint256[] memory result) {
        result = _toUints(values(_toBytes32Set(set)));
    }

    /// @dev Returns all of the values in the set.
    /// Note: This can consume more gas than the block gas limit for large sets.
    function values(Int256Set storage set) internal view returns (int256[] memory result) {
        result = _toInts(values(_toBytes32Set(set)));
    }

    /// @dev Returns all of the values in the set.
    function values(Uint8Set storage set) internal view returns (uint8[] memory result) {
        /// @solidity memory-safe-assembly
        assembly {
            result := mload(0x40)
            let ptr := add(result, 0x20)
            let o := 0
            for { let packed := sload(set.slot) } packed {} {
                if iszero(and(packed, 0xffff)) {
                    o := add(o, 16)
                    packed := shr(16, packed)
                    continue
                }
                mstore(ptr, o)
                ptr := add(ptr, shl(5, and(packed, 1)))
                o := add(o, 1)
                packed := shr(1, packed)
            }
            mstore(result, shr(5, sub(ptr, add(result, 0x20))))
            mstore(0x40, ptr)
        }
    }

    /// @dev Returns the element at index `i` in the set. Reverts if `i` is out-of-bounds.
    function at(AddressSet storage set, uint256 i) internal view returns (address result) {
        bytes32 rootSlot = _rootSlot(set);
        /// @solidity memory-safe-assembly
        assembly {
            result := shr(96, sload(add(rootSlot, i)))
            result := mul(result, iszero(eq(result, _ZERO_SENTINEL)))
        }
        if (i >= length(set)) revert IndexOutOfBounds();
    }

    /// @dev Returns the element at index `i` in the set. Reverts if `i` is out-of-bounds.
    function at(Bytes32Set storage set, uint256 i) internal view returns (bytes32 result) {
        result = _rootSlot(set);
        /// @solidity memory-safe-assembly
        assembly {
            result := sload(add(result, i))
            result := mul(result, iszero(eq(result, _ZERO_SENTINEL)))
        }
        if (i >= length(set)) revert IndexOutOfBounds();
    }

    /// @dev Returns the element at index `i` in the set. Reverts if `i` is out-of-bounds.
    function at(Uint256Set storage set, uint256 i) internal view returns (uint256 result) {
        result = uint256(at(_toBytes32Set(set), i));
    }

    /// @dev Returns the element at index `i` in the set. Reverts if `i` is out-of-bounds.
    function at(Int256Set storage set, uint256 i) internal view returns (int256 result) {
        result = int256(uint256(at(_toBytes32Set(set), i)));
    }

    /// @dev Returns the element at index `i` in the set. Reverts if `i` is out-of-bounds.
    function at(Uint8Set storage set, uint256 i) internal view returns (uint8 result) {
        /// @solidity memory-safe-assembly
        assembly {
            let packed := sload(set.slot)
            for {} 1 {
                mstore(0x00, 0x4e23d035) // `IndexOutOfBounds()`.
                revert(0x1c, 0x04)
            } {
                if iszero(lt(i, 256)) { continue }
                for { let j := 0 } iszero(eq(i, j)) {} {
                    packed := xor(packed, and(packed, add(1, not(packed))))
                    j := add(j, 1)
                }
                if iszero(packed) { continue }
                break
            }
            // Find first set subroutine, optimized for smaller bytecode size.
            let x := and(packed, add(1, not(packed)))
            let r := shl(7, iszero(iszero(shr(128, x))))
            r := or(r, shl(6, iszero(iszero(shr(64, shr(r, x))))))
            r := or(r, shl(5, lt(0xffffffff, shr(r, x))))
            // For the lower 5 bits of the result, use a De Bruijn lookup.
            // forgefmt: disable-next-item
            result := or(r, byte(and(div(0xd76453e0, shr(r, x)), 0x1f),
                0x001f0d1e100c1d070f090b19131c1706010e11080a1a141802121b1503160405))
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                      PRIVATE HELPERS                       */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns the root slot.
    function _rootSlot(AddressSet storage s) private pure returns (bytes32 r) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x04, _ENUMERABLE_ADDRESS_SET_SLOT_SEED)
            mstore(0x00, s.slot)
            r := keccak256(0x00, 0x24)
        }
    }

    /// @dev Returns the root slot.
    function _rootSlot(Bytes32Set storage s) private pure returns (bytes32 r) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x04, _ENUMERABLE_WORD_SET_SLOT_SEED)
            mstore(0x00, s.slot)
            r := keccak256(0x00, 0x24)
        }
    }

    /// @dev Casts to a Bytes32Set.
    function _toBytes32Set(Uint256Set storage s) private pure returns (Bytes32Set storage c) {
        /// @solidity memory-safe-assembly
        assembly {
            c.slot := s.slot
        }
    }

    /// @dev Casts to a Bytes32Set.
    function _toBytes32Set(Int256Set storage s) private pure returns (Bytes32Set storage c) {
        /// @solidity memory-safe-assembly
        assembly {
            c.slot := s.slot
        }
    }

    /// @dev Casts to a uint256 array.
    function _toUints(bytes32[] memory a) private pure returns (uint256[] memory c) {
        /// @solidity memory-safe-assembly
        assembly {
            c := a
        }
    }

    /// @dev Casts to a int256 array.
    function _toInts(bytes32[] memory a) private pure returns (int256[] memory c) {
        /// @solidity memory-safe-assembly
        assembly {
            c := a
        }
    }
}

Settings
{
  "viaIR": false,
  "codegen": "yul",
  "remappings": [
    "@limitbreak/permit-c/=lib/creator-token-standards/lib/PermitC/src/",
    "@opensea/tstorish/=lib/creator-token-standards/lib/tstorish/src/",
    "@openzeppelin/=lib/creator-token-standards/lib/openzeppelin-contracts/",
    "@rari-capital/solmate/=lib/creator-token-standards/lib/PermitC/lib/solmate/",
    "ERC721A/=lib/ERC721A/contracts/",
    "PermitC/=lib/creator-token-standards/lib/PermitC/",
    "creator-token-standards/=lib/creator-token-standards/",
    "delegate-registry/=lib/delegate-registry/",
    "ds-test/=lib/delegate-registry/lib/forge-std/lib/ds-test/src/",
    "erc4626-tests/=lib/delegate-registry/lib/openzeppelin-contracts/lib/erc4626-tests/",
    "erc721a/=lib/creator-token-standards/lib/ERC721A/",
    "forge-gas-metering/=lib/creator-token-standards/lib/PermitC/lib/forge-gas-metering/",
    "forge-std/=lib/forge-std/src/",
    "forge-zksync-std/=lib/forge-zksync-std/src/",
    "murky/=lib/creator-token-standards/lib/murky/",
    "openzeppelin-contracts/=lib/creator-token-standards/lib/openzeppelin-contracts/",
    "openzeppelin/=lib/delegate-registry/lib/openzeppelin-contracts/contracts/",
    "solady/=lib/solady/src/",
    "solmate/=lib/creator-token-standards/lib/PermitC/lib/solmate/src/",
    "tstorish/=lib/creator-token-standards/lib/tstorish/src/"
  ],
  "evmVersion": "cancun",
  "outputSelection": {
    "*": {
      "*": [
        "abi"
      ]
    }
  },
  "optimizer": {
    "enabled": true,
    "mode": "3",
    "size_fallback": false,
    "disable_system_request_memoization": true
  },
  "metadata": {},
  "libraries": {},
  "enableEraVMExtensions": false,
  "forceEVMLA": false
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyInitialized","type":"error"},{"inputs":[],"name":"InvalidLength","type":"error"},{"inputs":[],"name":"InvalidOutputId","type":"error"},{"inputs":[],"name":"LengthIsZero","type":"error"},{"inputs":[],"name":"NewOwnerIsZeroAddress","type":"error"},{"inputs":[],"name":"NoHandoverRequest","type":"error"},{"inputs":[],"name":"Paused","type":"error"},{"inputs":[],"name":"PriceIsZero","type":"error"},{"inputs":[],"name":"QtyIsZero","type":"error"},{"inputs":[],"name":"RecipeAlreadyRunning","type":"error"},{"inputs":[],"name":"RecipeNotRunning","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"inputs":[],"name":"UnauthorizedCallContext","type":"error"},{"inputs":[],"name":"UpgradeFailed","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"recipeId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"price","type":"uint256"},{"indexed":false,"internalType":"uint256[]","name":"itemId","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"qtys","type":"uint256[]"}],"name":"CookedRecipes","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pendingOwner","type":"address"}],"name":"OwnershipHandoverCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pendingOwner","type":"address"}],"name":"OwnershipHandoverRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"recipeId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"recipePrice","type":"uint256"},{"indexed":false,"internalType":"uint256[]","name":"itemId","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"qtys","type":"uint256[]"}],"name":"RecipeAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"recipeId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"recipePrice","type":"uint256"},{"indexed":false,"internalType":"uint256[]","name":"itemId","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"qtys","type":"uint256[]"}],"name":"RecipeUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"inputs":[{"internalType":"uint256","name":"outputId","type":"uint256"},{"internalType":"uint256","name":"recipePrice","type":"uint256"},{"internalType":"uint256[]","name":"itemId","type":"uint256[]"},{"internalType":"uint256[]","name":"qtys","type":"uint256[]"}],"name":"addRecipe","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"cancelOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"pendingOwner","type":"address"}],"name":"completeOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"recipeId","type":"uint256[]"}],"name":"cookRecipes","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"outputId","type":"uint256"}],"name":"getRecipe","outputs":[{"internalType":"bool","name":"isRunning","type":"bool"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"uint256[]","name":"itemId","type":"uint256[]"},{"internalType":"uint256[]","name":"qtys","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"init","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"result","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pendingOwner","type":"address"}],"name":"ownershipHandoverExpiresAt","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proxiableUUID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"requestOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bool","name":"flag","type":"bool"}],"name":"setPauseFlag","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"outputId","type":"uint256"},{"internalType":"bool","name":"flag","type":"bool"}],"name":"setRecipeStartFlag","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"outputId","type":"uint256"},{"internalType":"uint256","name":"recipePrice","type":"uint256"},{"internalType":"uint256[]","name":"itemId","type":"uint256[]"},{"internalType":"uint256[]","name":"qtys","type":"uint256[]"}],"name":"updateRecipe","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"upgradeToAndCall","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]

9c4d535b00000000000000000000000000000000000000000000000000000000000000000100028db759cf39cc34156f866b5caf35b5a08eb0965502ce143062a6a231b5000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000200000000000000000000000001b2c84dd7957b1e207cd7b01ded77984ec16fdef

Deployed Bytecode

0x0003000000000002000f00000000000200020000000103550000006003100270000002320030019d000002320330019700000001002001900000002d0000c13d0000008002000039000000400020043f000000040030008c000004cc0000413d000000000201043b000000e0022002700000023a0020009c000000690000a13d0000023b0020009c000000980000a13d0000023c0020009c000001d00000a13d0000023d0020009c0000037c0000613d0000023e0020009c0000038d0000613d0000023f0020009c000004cc0000c13d0000000002000416000000000002004b000004cc0000c13d000000240030008c000004cc0000413d0000000401100370000000000101043b000002350010009c000004cc0000213d00000252020000410000000c0020043f000000000010043f0000000c01000039000000200200003908c508a10000040f000000000101041a000000800010043f0000025301000041000008c60001042e0000000002000416000000000002004b000004cc0000c13d0000001f023000390000023302200197000000a002200039000000400020043f0000001f0430018f0000023405300198000000a0025000390000003e0000613d000000a006000039000000000701034f000000007807043c0000000006860436000000000026004b0000003a0000c13d000000000004004b0000004b0000613d000000000151034f0000000304400210000000000502043300000000054501cf000000000545022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000151019f0000000000120435000000200030008c000004cc0000413d000000a00600043d000002350060009c000004cc0000213d0000000001000410000000800010043f0000023601000041000000000061041b0000000001000414000002320010009c0000023201008041000000c00110021000000237011001c70000800d0200003900000003030000390000023804000041000000000500001908c508b60000040f0000000100200190000004cc0000613d000000800100043d0000014000000443000001600010044300000020010000390000010000100443000000010100003900000120001004430000023901000041000008c60001042e000002470020009c000000ad0000213d0000024d0020009c000000ee0000213d000002500020009c000003c60000613d000002510020009c000004cc0000c13d00000252010000410000000c0010043f0000000001000411000000000010043f000002580100004100000000001004430000000001000414000002320010009c0000023201008041000000c00110021000000259011001c70000800b0200003908c508bb0000040f0000000100200190000006880000613d000000000101043b000f00000001001d0000000001000414000002320010009c0000023201008041000000c00110021000000257011001c7000080100200003908c508bb0000040f0000000100200190000004cc0000613d000000000101043b0000000f02000029000002840220009a000000000021041b0000000001000414000002320010009c0000023201008041000000c00110021000000237011001c70000800d0200003900000002030000390000028504000041000000ca0000013d000002420020009c000000d00000213d000002450020009c000002030000613d000002460020009c000004cc0000c13d0000000002000416000000000002004b000004cc0000c13d000000240030008c000004cc0000413d0000000401100370000000000101043b000f00000001001d000000010010008c000004cc0000213d08c508800000040f0000025c01000041000000000201041a0000028702200197000000ea0000013d000002480020009c000001b70000213d0000024b0020009c000003e10000613d0000024c0020009c000004cc0000c13d00000252010000410000000c0010043f0000000001000411000000000010043f0000000001000414000002320010009c0000023201008041000000c00110021000000257011001c7000080100200003908c508bb0000040f0000000100200190000004cc0000613d000000000101043b000000000001041b0000000001000414000002320010009c0000023201008041000000c00110021000000237011001c70000800d0200003900000002030000390000027604000041000000000500041108c508b60000040f0000000100200190000004cc0000613d0000000001000019000008c60001042e000002430020009c0000020c0000613d000002440020009c000004cc0000c13d0000000002000416000000000002004b000004cc0000c13d000000440030008c000004cc0000413d0000002401100370000000000101043b000f00000001001d000000010010008c000004cc0000213d08c508800000040f00000004010000390000000201100367000000000101043b000000000010043f0000025401000041000000200010043f0000004002000039000000000100001908c508a10000040f000000000301041a00000287023001970000000f022001af000000000021041b0000000001000019000008c60001042e0000024e0020009c000003fe0000613d0000024f0020009c000004cc0000c13d000000440030008c000004cc0000413d0000000402100370000000000202043b000f00000002001d000002350020009c000004cc0000213d0000002402100370000000000202043b0000025b0020009c000004cc0000213d0000002304200039000000000034004b000004cc0000813d000d00040020003d0000000d01100360000000000101043b000e00000001001d0000025b0010009c000004cc0000213d0000000e012000290000002401100039000000000031004b000004cc0000213d000002770100004100000000001004430000000001000412000000040010044300000024000004430000000001000414000002320010009c0000023201008041000000c00110021000000278011001c7000080050200003908c508bb0000040f0000000100200190000006880000613d000000000101043b0000000002000410000000000021004b000004ce0000613d0000023601000041000000000101041a0000000002000411000000000012004b000004b00000c13d0000000101000031000000000010043f0000024b01000041000000010010043f0000000001000414000002320010009c0000023201008041000000c0011002100000027b011001c70000000f0200002908c508bb0000040f00000060031002700000023203300197000000200030008c000000200400003900000000040340190000001f0540018f000000200640019000000001046001bf0000013b0000613d0000000107000039000000000801034f000000008908043c0000000007970436000000000047004b000001370000c13d000000010220018f000000000005004b000001490000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f0000000000140435000100000003001f0000000001020433000002790010009c0000069f0000c13d0000000001000414000002320010009c0000023201008041000000c00110021000000237011001c70000800d0200003900000002030000390000027d040000410000000f0500002908c508b60000040f0000000100200190000004cc0000613d00000279010000410000000f02000029000000000021041b0000000e0000006b000000ce0000613d0000000e0300002900000288023001980000001f0330018f000000400100043d000c00000001001d00000000012100190000000d04000029000000200440003900000002044003670000016e0000613d000000000504034f0000000c06000029000000005705043c0000000006760436000000000016004b0000016a0000c13d000000000003004b0000017b0000613d000000000224034f0000000303300210000000000401043300000000043401cf000000000434022f000000000202043b0000010003300089000000000232022f00000000023201cf000000000242019f000000000021043500000265010000410000000000100443000000000100041200000004001004430000000001000414000002320010009c0000023201008041000000c00110021000000267011001c7000080020200003908c508bb0000040f0000000100200190000006880000613d0000000e01000029000002320010009c000002320100804100000060011002100000000002000414000002320020009c0000023202008041000000c002200210000000000112019f0000000c02000029000002320020009c0000023202008041000e0040002002180000000e011001af0000000f0200002908c508c00000040f0000006003100270000102320030019d0000000100200190000000ce0000c13d00000232023001970000001f0420018f00000234052001980000000c080000290000000003580019000001a70000613d000000000601034f000000006706043c0000000008780436000000000038004b000001a30000c13d000000000004004b000001b40000613d000000000151034f0000000304400210000000000503043300000000054501cf000000000545022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000151019f000000000013043500000060012002100000000e011001af000008c700010430000002490020009c000004720000613d0000024a0020009c000004cc0000c13d0000023601000041000000000501041a0000000001000411000000000051004b000004b00000c13d0000000001000414000002320010009c0000023201008041000000c00110021000000237011001c70000800d0200003900000003030000390000023804000041000000000600001908c508b60000040f0000000100200190000004cc0000613d0000023601000041000000000001041b0000000001000019000008c60001042e000002400020009c000004b40000613d000002410020009c000004cc0000c13d000000240030008c000004cc0000413d0000000401100370000000000101043b000f00000001001d000002350010009c000004cc0000213d0000023601000041000000000101041a0000000002000411000000000012004b000004b00000c13d00000252010000410000000c0010043f0000000f01000029000000000010043f0000000001000414000002320010009c0000023201008041000000c00110021000000257011001c7000080100200003908c508bb0000040f0000000100200190000004cc0000613d000000000101043b000d00000001001d000000000101041a000e00000001001d000002580100004100000000001004430000000001000414000002320010009c0000023201008041000000c00110021000000259011001c70000800b0200003908c508bb0000040f0000000100200190000006880000613d000000000101043b0000000e0010006c000006990000a13d0000025a01000041000000000010043f0000025601000041000008c7000104300000000001000416000000000001004b000004cc0000c13d0000023601000041000000000101041a0000023501100197000000800010043f0000025301000041000008c60001042e0000000002000416000000000002004b000004cc0000c13d000000840030008c000004cc0000413d0000002402100370000000000202043b000c00000002001d0000000402100370000000000202043b000d00000002001d0000004402100370000000000202043b0000025b0020009c000004cc0000213d0000002304200039000000000034004b000004cc0000813d0000000404200039000000000441034f000000000404043b000f00000004001d0000025b0040009c000004cc0000213d00000024042000390000000f020000290000000502200210000700000004001d000500000002001d0000000002420019000000000032004b000004cc0000213d0000006402100370000000000202043b0000025b0020009c000004cc0000213d0000002304200039000000000034004b000004cc0000813d0000000404200039000000000141034f000000000101043b0000025b0010009c000004cc0000213d00000024042000390000000502100210000400000002001d000600000004001d0000000002420019000000000032004b000004cc0000213d0000023602000041000000000202041a0000000003000411000000000023004b000004b00000c13d0000000d0000006b000004ac0000613d0000000f0010006b000006c00000c13d0000000d01000029000000000010043f0000025401000041000000200010043f0000000001000414000002320010009c0000023201008041000000c0011002100000025f011001c7000080100200003908c508bb0000040f0000000100200190000004cc0000613d000000000101043b000e00000001001d000000000101041a000000ff00100190000006d10000c13d0000000c01000029000000080110021000000001011001bf0000000e02000029000000000012041b0000000f0000006b000006bc0000613d00000005010000290000003f01100039000a02630010019b000000400100043d0000000a02100029000000000012004b000000000300003900000001030040390000025b0020009c000006f60000213d0000000100300190000006f60000c13d000000400020043f0000000f020000290000000002210436000800000002001d00000005020000290003001f00200193000000000002004b0000027d0000613d0000000804000029000000050240002900000000030000310000000203300367000000003503043c0000000004540436000000000024004b000002790000c13d000000030000006b0000000001010433000900000001001d0000025b0010009c000006f60000213d0000000e010000290000000101100039000000000301041a000b00000001001d0000000902000029000000000021041b000200000003001d000000000032004b0000029f0000813d0000000b01000029000000000010043f0000000001000414000002320010009c0000023201008041000000c00110021000000264011001c7000080100200003908c508bb0000040f0000000100200190000004cc0000613d000000000201043b00000009012000290000000202200029000000000021004b0000029f0000813d000000000001041b0000000101100039000000000021004b0000029b0000413d0000000b01000029000000000010043f0000000001000414000002320010009c0000023201008041000000c00110021000000264011001c7000080100200003908c508bb0000040f0000000100200190000004cc0000613d000000000101043b0000000906000029000000000006004b0000000805000029000002b60000613d000000000200001900000000031200190000000054050434000000000043041b0000000102200039000000000062004b000002b00000413d000000400100043d0000000a02100029000000000012004b000000000300003900000001030040390000025b0020009c000006f60000213d0000000100300190000006f60000c13d000000400020043f0000000f020000290000000002210436000800000002001d000000050000006b000002cd0000613d0000000804000029000000050240002900000000030000310000000203300367000000003503043c0000000004540436000000000024004b000002c90000c13d000000030000006b0000000001010433000900000001001d0000025b0010009c000006f60000213d0000000e010000290000000201100039000000000301041a000a00000001001d0000000902000029000000000021041b000e00000003001d000000000032004b000002ef0000813d0000000a01000029000000000010043f0000000001000414000002320010009c0000023201008041000000c00110021000000264011001c7000080100200003908c508bb0000040f0000000100200190000004cc0000613d000000000201043b00000009012000290000000e02200029000000000021004b000002ef0000813d000000000001041b0000000101100039000000000021004b000002eb0000413d0000000a01000029000000000010043f0000000001000414000002320010009c0000023201008041000000c00110021000000264011001c7000080100200003908c508bb0000040f0000000100200190000004cc0000613d000000000101043b0000000906000029000000000006004b0000000805000029000003060000613d000000000200001900000000031200190000000054050434000000000043041b0000000102200039000000000062004b000003000000413d0000000004000019000000050140021000000006031000290000000202300367000000000202043b000000000002004b0000081d0000613d000900000003001d00000007011000290000000201100367000000000101043b000800000001001d0000000b01000029000000000101041a000e00000004001d000000000041004b000008170000a13d0000000b01000029000000000010043f0000000001000414000002320010009c0000023201008041000000c00110021000000264011001c7000080100200003908c508bb0000040f0000000100200190000004cc0000613d000000000101043b0000000e011000290000000803000029000000000031041b00000009010000290000000201100367000000000101043b000900000001001d0000000a01000029000000000101041a0000000e0010006c000008170000a13d0000000a01000029000000000010043f0000000001000414000002320010009c0000023201008041000000c00110021000000264011001c7000080100200003908c508bb0000040f00000001002001900000008003000039000004cc0000613d000000000101043b0000000e0400002900000000014100190000000902000029000000000021041b00000001044000390000000f0040006c000003070000413d000000400100043d00000080021000390000000f0400002900000000004204350000004002100039000000000032043500000020021000390000000c0300002900000000003204350000000d020000290000000000210435000000a00410003900000005034000290000000202000367000000050000006b000003570000613d0000000705200360000000005605043c0000000004640436000000000034004b000003530000c13d000000030000006b0000000004130049000000600510003900000000004504350000000f04000029000000000343043600000004050000290000001f0450018f000000000005004b000003680000613d000000060220036000000004053000290000000006030019000000002702043c0000000006760436000000000056004b000003640000c13d000000000004004b00000004021000690000000002320019000002320020009c00000232020080410000006002200210000002320010009c00000232010080410000004001100210000000000112019f0000000002000414000002320020009c0000023202008041000000c002200210000000000112019f00000237011001c70000800d0200003900000001030000390000026e04000041000008160000013d000000240030008c000004cc0000413d0000000401100370000000000101043b000002350010009c000004cc0000213d0000023602000041000000000202041a0000000003000411000000000023004b000004b00000c13d000000000001004b0000069c0000c13d0000025501000041000000000010043f0000025601000041000008c7000104300000000002000416000000000002004b000004cc0000c13d000000240030008c000004cc0000413d0000000401100370000000000101043b000000000010043f0000025401000041000000200010043f0000004002000039000000000100001908c508a10000040f0000000002010019000f00000001001d000000000101041a000d00000001001d000000010120003908c5084b0000040f000e00000001001d0000000f01000029000000020110003908c5084b0000040f0000000d050000290000000802500270000000400400043d000f00000004001d00000020034000390000000000230435000000400240003900000080030000390000000000320435000000ff005001900000000002000039000000010200c0390000000000240435000d00000001001d00000080024000390000000e0100002908c508210000040f00000000020100190000000f030000290000000001310049000000600330003900000000001304350000000d0100002908c508210000040f0000000f020000290000000001210049000002320020009c00000232020080410000004002200210000002320010009c00000232010080410000006001100210000000000121019f000008c60001042e0000000002000416000000000002004b000004cc0000c13d000000240030008c000004cc0000413d0000000401100370000000000601043b000002350060009c000004cc0000213d0000023601000041000000000201041a0000023500200198000004f00000c13d000000000061041b0000000001000414000002320010009c0000023201008041000000c00110021000000237011001c70000800d0200003900000003030000390000023804000041000000000500001908c508b60000040f0000000100200190000004cc0000613d000000ce0000013d0000000001000416000000000001004b000004cc0000c13d000002770100004100000000001004430000000001000412000000040010044300000024000004430000000001000414000002320010009c0000023201008041000000c00110021000000278011001c7000080050200003908c508bb0000040f0000000100200190000006880000613d000000000101043b0000000002000410000000000021004b000004ce0000c13d000000400100043d00000279020000410000000000210435000002320010009c000002320100804100000040011002100000027a011001c7000008c60001042e0000000001000416000000000001004b000004cc0000c13d0000023601000041000000000201041a0000000001000411000000000021004b000004b00000c13d000e00000002001d0000028001000041000000800010043f0000000001000410000000840010043f0000000001000414000002320010009c0000023201008041000000c00110021000000281011001c7000002620200004108c508b60000040f000000800a00003900000060031002700000023203300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000080057001bf000004210000613d000000000801034f000000008908043c000000000a9a043600000000005a004b0000041d0000c13d000000000006004b0000042e0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000100000003001f0000000100200190000004d20000613d0000001f01400039000000600110018f00000080021001bf000f00000002001d000000400020043f000000200030008c000004cc0000413d000000800200043d00000282030000410000000f05000029000000000035043500000084031001bf0000000e040000290000000000430435000000a40110003900000000002104350000000001000414000002320010009c0000023201008041000000c0011002100000004002500210000000000121019f00000283011001c7000002620200004108c508b60000040f00000060031002700000023203300197000000200030008c000000200a000039000000000a0340190000001f05a0018f0000002006a001900000000f04600029000004590000613d000000000701034f0000000f08000029000000007907043c0000000008980436000000000048004b000004550000c13d000000000005004b000004660000613d000000000661034f0000000305500210000000000704043300000000075701cf000000000757022f000000000606043b0000010005500089000000000656022f00000000055601cf000000000575019f0000000000540435000100000003001f0000000100200190000006890000613d0000000f0100002900000000020a0019000e0000000a001d08c5082e0000040f0000000f010000290000000e0210002908c508400000040f0000000001000019000008c60001042e0000000002000416000000000002004b000004cc0000c13d000000840030008c000004cc0000413d0000002402100370000000000202043b000800000002001d0000000402100370000000000202043b000900000002001d0000004402100370000000000202043b0000025b0020009c000004cc0000213d0000002304200039000000000034004b000004cc0000813d0000000404200039000000000441034f000000000404043b000e00000004001d0000025b0040009c000004cc0000213d00000024042000390000000e020000290000000502200210000700000004001d000500000002001d0000000002420019000000000032004b000004cc0000213d0000006402100370000000000202043b0000025b0020009c000004cc0000213d0000002304200039000000000034004b000004cc0000813d0000000404200039000000000141034f000000000101043b0000025b0010009c000004cc0000213d00000024042000390000000502100210000400000002001d000600000004001d0000000002420019000000000032004b000004cc0000213d0000023602000041000000000202041a0000000003000411000000000023004b000004b00000c13d000000090000006b000006a30000c13d0000027501000041000000000010043f0000025e01000041000008c7000104300000027f01000041000000000010043f0000025601000041000008c7000104300000000002000416000000000002004b000004cc0000c13d000000240030008c000004cc0000413d0000000402100370000000000202043b0000025b0020009c000004cc0000213d0000002304200039000000000034004b000004cc0000813d0000000404200039000000000141034f000000000101043b000200000001001d0000025b0010009c000004cc0000213d000100240020003d000000020100002900000005011002100000000101100029000000000031004b000004f40000a13d0000000001000019000008c7000104300000027e01000041000000000010043f0000025601000041000008c7000104300000001f0530018f0000023406300198000000400200043d0000000004620019000004dd0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000004d90000c13d000000000005004b000004ea0000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f00000000001404350000006001300210000002320020009c00000232020080410000004002200210000000000112019f000008c7000104300000028601000041000000000010043f0000025e01000041000008c7000104300000025c01000041000000000101041a000000ff00100190000006950000c13d000000020000006b000000ce0000613d000400000000001d0000000401000029000000050110021000000001011000290000000201100367000000000101043b000300000001001d000000000010043f0000025401000041000000200010043f0000000001000414000002320010009c0000023201008041000000c0011002100000025f011001c7000080100200003908c508bb0000040f0000000100200190000004cc0000613d000000000101043b000500000001001d000000000101041a000000ff00100190000006fc0000613d0000000801100272000007000000613d000000400300043d000f00000003001d0000004402300039000000000012043500000024013000390000000002000410000000000021043500000260010000410000000000130435000000040130003900000000020004110000000000210435000002320030009c0000023201000041000000000103401900000040011002100000000002000414000002320020009c0000023202008041000000c002200210000000000112019f00000261011001c7000002620200004108c508b60000040f0000000f0a00002900000060031002700000023203300197000000200030008c00000020040000390000000004034019000000200640019000000000056a00190000053b0000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b000005370000c13d0000001f07400190000005480000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000100000003001f0000000100200190000007040000613d0000001f01400039000000600110018f0000000002a10019000000000012004b00000000010000390000000101004039000e00000002001d0000025b0020009c000006f60000213d0000000100100190000006f60000c13d0000000e01000029000000400010043f000000200030008c000004cc0000413d00000000010a0433000000010010008c000004cc0000213d00000005010000290000000101100039000c00000001001d000000000101041a000800000001001d0000025b0010009c000006f60000213d000000080100002900000005021002100000003f0120003900000263041001970000000e014000290000025b0010009c000006f60000213d000000400010043f0000000e0100002900000008030000290000000001310436000700000001001d00000000010000310000000201100367000000000002004b0000057b0000613d00000007060000290000000003260019000000000501034f000000005705043c0000000006760436000000000036004b000005770000c13d0000001f03200190000000400500043d0000000004450019000d00000005001d000000000054004b000000000500003900000001050040390000025b0040009c000006f60000213d0000000100500190000006f60000c13d000000400040043f0000000d0400002900000008050000290000000004540436000600000004001d000000000002004b000005930000613d00000006040000290000000002240019000000001501043c0000000004540436000000000024004b0000058f0000c13d000000000003004b000000080000006b000006120000613d0000000501000029000b00020010003d00000000020000190000000c01000029000000000101041a000000000021004b000008170000a13d000f00000002001d0000000c01000029000000000010043f0000000001000414000002320010009c0000023201008041000000c00110021000000264011001c7000080100200003908c508bb0000040f0000000100200190000004cc0000613d0000000e0200002900000000020204330000000f03000029000000000032004b000008170000a13d0000000504300210000a00000004001d0000000702400029000000000101043b0000000001310019000000000101041a000900000002001d00000000001204350000000b01000029000000000101041a000000000031004b000008170000a13d0000000b01000029000000000010043f0000000001000414000002320010009c0000023201008041000000c00110021000000264011001c7000080100200003908c508bb0000040f0000000100200190000004cc0000613d000000000101043b0000000d0200002900000000020204330000000f03000029000000000032004b000008170000a13d0000000001310019000000000201041a0000000a040000290000000601400029000a00000002001d00000000002104350000000e010000290000000001010433000000000031004b000008170000a13d0000000d010000290000000001010433000000000031004b000008170000a13d00000009010000290000000001010433000900000001001d00000265010000410000000000100443000002660100004100000004001004430000000001000414000002320010009c0000023201008041000000c00110021000000267011001c7000080020200003908c508bb0000040f0000000100200190000006880000613d000000000101043b000000000001004b000004cc0000613d000000400300043d00000044013000390000000a02000029000000000021043500000024013000390000000902000029000000000021043500000268010000410000000000130435000000040130003900000000020004110000000000210435000002320030009c000a00000003001d0000023201000041000000000103401900000040011002100000000002000414000002320020009c0000023202008041000000c002200210000000000112019f00000261011001c7000002660200004108c508b60000040f0000006003100270000102320030019d0000000100200190000006c40000613d0000000a060000290000025b0060009c000006f60000213d000000400060043f0000000f020000290000000102200039000000080020006c000005990000413d000006130000013d000000400600043d0000000501000029000000000101041a000000000200041100000000002604350000006002600039000000a00300003900000000003204350000000801100270000000400260003900000000001204350000002001600039000000030200002900000000002104350000000e050000290000000002050433000000a0016000390000000000210435000000c001600039000000000002004b0000062e0000613d00000000030000190000002005500039000000000405043300000000014104360000000103300039000000000023004b000006280000413d0000000002610049000000800360003900000000002304350000000d0500002900000000020504330000000001210436000000000002004b0000063d0000613d00000000030000190000002005500039000000000405043300000000014104360000000103300039000000000023004b000006370000413d0000000001610049000002320010009c00000232010080410000006001100210000002320060009c00000232060080410000004002600210000000000121019f0000000002000414000002320020009c0000023202008041000000c002200210000000000121019f00000237011001c70000800d020000390000000103000039000002690400004108c508b60000040f0000000100200190000004cc0000613d00000265010000410000000000100443000002660100004100000004001004430000000001000414000002320010009c0000023201008041000000c00110021000000267011001c7000080020200003908c508bb0000040f0000000100200190000006880000613d000000000101043b000000000001004b000004cc0000613d000000400300043d0000004401300039000000010200003900000000002104350000002401300039000000030200002900000000002104350000026a010000410000000000130435000000040130003900000000020004110000000000210435000002320030009c000f00000003001d0000023201000041000000000103401900000040011002100000000002000414000002320020009c0000023202008041000000c002200210000000000112019f00000261011001c7000002660200004108c508b60000040f0000006003100270000102320030019d0000000100200190000007100000613d0000000f010000290000025b0010009c000006f60000213d000000400010043f00000004020000290000000102200039000400000002001d000000020020006c000004fb0000413d000000ce0000013d000000000001042f0000001f0530018f0000023406300198000000400200043d0000000004620019000004dd0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000006900000c13d000004dd0000013d0000025d01000041000000000010043f0000025e01000041000008c7000104300000000d01000029000000000001041b0000000f0100002908c5088a0000040f0000000001000019000008c60001042e0000027c01000041000000010010043f0000027b01000041000008c7000104300000000e0010006b000006c00000c13d0000000901000029000000000010043f0000025401000041000000200010043f0000000001000414000002320010009c0000023201008041000000c0011002100000025f011001c7000080100200003908c508bb0000040f0000000100200190000004cc0000613d00000008020000290000000802200210000000000301043b000000000103041a000000ff0110018f000000000121019f000f00000003001d000000000013041b0000000e0000006b000006d50000c13d0000027401000041000000000010043f0000025e01000041000008c7000104300000026f01000041000000000010043f0000025e01000041000008c70001043000000232033001970000001f0530018f0000023406300198000000400200043d0000000004620019000004dd0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000006cc0000c13d000004dd0000013d0000026d01000041000000000010043f0000025e01000041000008c70001043000000005010000290000003f01100039000c02630010019b000000400100043d0000000c02100029000000000012004b000000000300003900000001030040390000025b0020009c000006f60000213d0000000100300190000006f60000c13d000000400020043f0000000e020000290000000002210436000a00000002001d00000005020000290003001f00200193000000000002004b000006f10000613d0000000a04000029000000050240002900000000030000310000000203300367000000003503043c0000000004540436000000000024004b000006ed0000c13d000000030000006b0000000001010433000b00000001001d0000025b0010009c0000071d0000a13d0000027001000041000000000010043f0000004101000039000000040010043f0000027101000041000008c7000104300000026c01000041000000000010043f0000025e01000041000008c7000104300000026b01000041000000000010043f0000025e01000041000008c7000104300000001f0530018f0000023406300198000000400200043d0000000004620019000004dd0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000070b0000c13d000004dd0000013d00000232033001970000001f0530018f0000023406300198000000400200043d0000000004620019000004dd0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000007180000c13d000004dd0000013d0000000f010000290000000101100039000000000301041a000d00000001001d0000000b02000029000000000021041b000200000003001d000000000032004b0000073a0000813d0000000d01000029000000000010043f0000000001000414000002320010009c0000023201008041000000c00110021000000264011001c7000080100200003908c508bb0000040f0000000100200190000004cc0000613d000000000201043b0000000b012000290000000202200029000000000021004b0000073a0000813d000000000001041b0000000101100039000000000021004b000007360000413d0000000d01000029000000000010043f0000000001000414000002320010009c0000023201008041000000c00110021000000264011001c7000080100200003908c508bb0000040f0000000100200190000004cc0000613d000000000101043b0000000b06000029000000000006004b0000000a05000029000007510000613d000000000200001900000000031200190000000054050434000000000043041b0000000102200039000000000062004b0000074b0000413d000000400100043d0000000c02100029000000000012004b000000000300003900000001030040390000025b0020009c000006f60000213d0000000100300190000006f60000c13d000000400020043f0000000e020000290000000002210436000a00000002001d000000050000006b000007680000613d0000000a04000029000000050240002900000000030000310000000203300367000000003503043c0000000004540436000000000024004b000007640000c13d000000030000006b0000000001010433000b00000001001d0000025b0010009c000006f60000213d0000000f010000290000000201100039000000000301041a000c00000001001d0000000b02000029000000000021041b000f00000003001d000000000032004b0000078a0000813d0000000c01000029000000000010043f0000000001000414000002320010009c0000023201008041000000c00110021000000264011001c7000080100200003908c508bb0000040f0000000100200190000004cc0000613d000000000201043b0000000b012000290000000f02200029000000000021004b0000078a0000813d000000000001041b0000000101100039000000000021004b000007860000413d0000000c01000029000000000010043f0000000001000414000002320010009c0000023201008041000000c00110021000000264011001c7000080100200003908c508bb0000040f0000000100200190000004cc0000613d000000000101043b0000000b06000029000000000006004b0000000a05000029000007a10000613d000000000200001900000000031200190000000054050434000000000043041b0000000102200039000000000062004b0000079b0000413d0000000004000019000000050140021000000006031000290000000202300367000000000202043b000000000002004b0000081d0000613d000b00000003001d00000007011000290000000201100367000000000101043b000a00000001001d0000000d01000029000000000101041a000f00000004001d000000000041004b000008170000a13d0000000d01000029000000000010043f0000000001000414000002320010009c0000023201008041000000c00110021000000264011001c7000080100200003908c508bb0000040f0000000100200190000004cc0000613d000000000101043b0000000f011000290000000a03000029000000000031041b0000000b010000290000000201100367000000000101043b000b00000001001d0000000c01000029000000000101041a0000000f0010006c000008170000a13d0000000c01000029000000000010043f0000000001000414000002320010009c0000023201008041000000c00110021000000264011001c7000080100200003908c508bb0000040f00000001002001900000008003000039000004cc0000613d000000000101043b0000000f0400002900000000014100190000000b02000029000000000021041b00000001044000390000000e0040006c000007a20000413d000000400100043d00000080021000390000000e0400002900000000004204350000004002100039000000000032043500000020021000390000000803000029000000000032043500000009020000290000000000210435000000a00410003900000005034000290000000202000367000000050000006b000007f20000613d0000000705200360000000005605043c0000000004640436000000000034004b000007ee0000c13d000000030000006b0000000004130049000000600510003900000000004504350000000e04000029000000000343043600000004050000290000001f0450018f000000000005004b000008030000613d000000060220036000000004053000290000000006030019000000002702043c0000000006760436000000000056004b000007ff0000c13d000000000004004b00000004021000690000000002320019000002320020009c00000232020080410000006002200210000002320010009c00000232010080410000004001100210000000000112019f0000000002000414000002320020009c0000023202008041000000c002200210000000000112019f00000237011001c70000800d0200003900000001030000390000027204000041000000cb0000013d0000027001000041000000000010043f0000003201000039000000040010043f0000027101000041000008c7000104300000027301000041000000000010043f0000025e01000041000008c700010430000000000301001900000000040104330000000001420436000000000004004b0000082d0000613d00000000020000190000002003300039000000000503043300000000015104360000000102200039000000000042004b000008270000413d000000000001042d0000001f0220003900000288022001970000000001120019000000000021004b000000000200003900000001020040390000025b0010009c0000083a0000213d00000001002001900000083a0000c13d000000400010043f000000000001042d0000027001000041000000000010043f0000004101000039000000040010043f0000027101000041000008c7000104300000000002120049000002890020009c000008490000213d0000001f0020008c000008490000a13d0000000001010433000000010010008c000008490000213d000000000001042d0000000001000019000008c7000104300003000000000002000000000301041a000000400200043d000300000002001d000100000003001d0000000002320436000200000002001d000000000010043f0000000001000414000002320010009c0000023201008041000000c00110021000000264011001c7000080100200003908c508bb0000040f0000000100200190000008780000613d0000000105000029000000000005004b000008690000613d000000000101043b00000000020000190000000204000029000000000301041a000000000434043600000001011000390000000102200039000000000052004b000008620000413d0000086a0000013d0000000204000029000000030100002900000000021400490000001f0320003900000288023001970000000003120019000000000023004b000000000200003900000001020040390000025b0030009c0000087a0000213d00000001002001900000087a0000c13d000000400030043f000000000001042d0000000001000019000008c7000104300000027001000041000000000010043f0000004101000039000000040010043f0000027101000041000008c7000104300000023601000041000000000101041a0000000002000411000000000012004b000008860000c13d000000000001042d0000027f01000041000000000010043f0000025601000041000008c70001043000010000000000020000023602000041000000000502041a00000000020004140000023506100197000002320020009c0000023202008041000000c00120021000000237011001c70000800d0200003900000003030000390000023804000041000100000006001d08c508b60000040f00000001002001900000089e0000613d00000236010000410000000102000029000000000021041b000000000001042d0000000001000019000008c700010430000000000001042f000002320010009c00000232010080410000004001100210000002320020009c00000232020080410000006002200210000000000112019f0000000002000414000002320020009c0000023202008041000000c002200210000000000112019f00000237011001c7000080100200003908c508bb0000040f0000000100200190000008b40000613d000000000101043b000000000001042d0000000001000019000008c700010430000008b9002104210000000102000039000000000001042d0000000002000019000000000001042d000008be002104230000000102000039000000000001042d0000000002000019000000000001042d000008c3002104250000000102000039000000000001042d0000000002000019000000000001042d000008c500000432000008c60001042e000008c70001043000000000000000000000000000000000000000000000000000000000ffffffff00000000000000000000000000000000000000000000000000000001ffffffe000000000000000000000000000000000000000000000000000000000ffffffe0000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7487392702000000000000000000000000000000000000000000000000000000000000008be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e00000000200000000000000000000000000000080000001000000000000000000000000000000000000000000000000000000000000000000000000008da5cb5a00000000000000000000000000000000000000000000000000000000eb62ce8500000000000000000000000000000000000000000000000000000000f2fde38a00000000000000000000000000000000000000000000000000000000f2fde38b00000000000000000000000000000000000000000000000000000000f8d12a4100000000000000000000000000000000000000000000000000000000fee81cf400000000000000000000000000000000000000000000000000000000eb62ce8600000000000000000000000000000000000000000000000000000000f04e283e00000000000000000000000000000000000000000000000000000000ad428ba900000000000000000000000000000000000000000000000000000000ad428baa00000000000000000000000000000000000000000000000000000000df7a4b9a000000000000000000000000000000000000000000000000000000008da5cb5b000000000000000000000000000000000000000000000000000000008da92e710000000000000000000000000000000000000000000000000000000052d1902c0000000000000000000000000000000000000000000000000000000064ae249d0000000000000000000000000000000000000000000000000000000064ae249e00000000000000000000000000000000000000000000000000000000715018a60000000000000000000000000000000000000000000000000000000052d1902d0000000000000000000000000000000000000000000000000000000054d1f13d000000000000000000000000000000000000000000000000000000003ccfd60a000000000000000000000000000000000000000000000000000000003ccfd60b000000000000000000000000000000000000000000000000000000004f1ef2860000000000000000000000000000000000000000000000000000000019ab453c000000000000000000000000000000000000000000000000000000002569296200000000000000000000000000000000000000000000000000000000389a75e10000000000000000000000000000000000000020000000800000000000000000000000000000000000000000000000000000000000000059500cb63f71b71a86000000000000000000000000000000000000000000000000000000007448fbae00000000000000000000000000000000000000040000001c000000000000000002000000000000000000000000000000000000200000000c0000000000000000796b89b91644bc98cd93958e4c9038275d622183e25ac5af08cc6b5d955391320200000200000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000006f5e8818000000000000000000000000000000000000000000000000ffffffffffffffff000000000000000000000000000000000000000000000059500cb63f71b71a879e87fac8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000020000000000000000000000000000000000004000000000000000000000000023b872dd00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000033ee11ce309854a45b65368c078616abcb5c6e3d00000000000000000000000000000000000000000000003fffffffffffffffe002000000000000000000000000000000000000200000000000000000000000001806aa1896bbf26568e884a7374b41e002500962caba6a15023a8d90e8508b8300000000000000000000000014f926d2751f4bb0200e9b016b6ae4a1e4b207bd0200000200000000000000000000000000000024000000000000000000000000f5298aca00000000000000000000000000000000000000000000000000000000c259359a889be310ee009908708eb5cf8b76b6a87d85a5f2feaa2cc35d43ca0a156e29f600000000000000000000000000000000000000000000000000000000907adecd000000000000000000000000000000000000000000000000000000001a9e6e1500000000000000000000000000000000000000000000000000000000ed17b0ac000000000000000000000000000000000000000000000000000000002679c8af4390c9ade41a4ccdb614490d83c940b6f84c746d29765c3dcc45f513947d5a84000000000000000000000000000000000000000000000000000000004e487b710000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000240000000000000000000000007d9b171d1be5a58940ea2f76358ecf144e532d6d156e16496f0f316b5c19dff64c233bda000000000000000000000000000000000000000000000000000000000c71ec17000000000000000000000000000000000000000000000000000000002f97ff7a00000000000000000000000000000000000000000000000000000000fa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c92310ab089e4439a4c15d089f94afb7896ff553aecb10793d0ab882de59d99a32e0200000200000000000000000000000000000044000000000000000000000000360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000040000001d00000000000000000000000000000000000000000000000000000000000000000000000055299b49bc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b000000000000000000000000000000000000000000000000000000009f03a0260000000000000000000000000000000000000000000000000000000082b4290070a08231000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024000000800000000000000000a9059cbb000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044000000000000000000000000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd5d00dbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d0dc149f000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000a26469706673582212200fb530da0837a6bf82a167cb4634253da8be16415ce6ebcdfc83e8634aff315a64736f6c6378247a6b736f6c633a312e352e31353b736f6c633a302e382e33303b6c6c766d3a312e302e320055

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

0000000000000000000000001b2c84dd7957b1e207cd7b01ded77984ec16fdef

-----Decoded View---------------
Arg [0] : _owner (address): 0x1B2C84dd7957b1e207Cd7b01Ded77984eC16fDEf

-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 0000000000000000000000001b2c84dd7957b1e207cd7b01ded77984ec16fdef


Block Transaction Gas Used Reward
view all blocks produced

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

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
[ Download: CSV Export  ]

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.