Sepolia Testnet

Contract

0xAAE8c724318D46bCFeB1c5686E1b13e22050283B

Overview

ETH Balance

0 ETH

Multichain Info

N/A
Transaction Hash
Method
Block
From
To
Deploy67041392024-09-16 17:40:2478 days ago1726508424IN
0xAAE8c724...22050283B
0 ETH0.0090902623.62506313
Deploy67033032024-09-16 14:30:0079 days ago1726497000IN
0xAAE8c724...22050283B
0 ETH0.002627536.82752752
Deploy66970352024-09-15 15:05:4880 days ago1726412748IN
0xAAE8c724...22050283B
0 ETH0.001294363.36334423
Deploy66970182024-09-15 15:02:1280 days ago1726412532IN
0xAAE8c724...22050283B
0 ETH0.001362483.54035736
Deploy66969672024-09-15 14:50:1280 days ago1726411812IN
0xAAE8c724...22050283B
0 ETH0.001254973.26100345
Deploy66968362024-09-15 14:20:0080 days ago1726410000IN
0xAAE8c724...22050283B
0 ETH0.001102782.86553418
Deploy66968082024-09-15 14:13:4880 days ago1726409628IN
0xAAE8c724...22050283B
0 ETH0.000850522.21006171
Deploy61841622024-06-25 14:41:24162 days ago1719326484IN
0xAAE8c724...22050283B
0 ETH0.04047184105.07583252
Deploy61496492024-06-20 19:30:24166 days ago1718911824IN
0xAAE8c724...22050283B
0 ETH0.000577751.50001818
Deploy60249062024-06-02 12:07:36185 days ago1717330056IN
0xAAE8c724...22050283B
0 ETH0.0041996410.91053858
Deploy Determini...58466962024-05-06 6:05:00212 days ago1714975500IN
0xAAE8c724...22050283B
0 ETH0.10715312119.60081995

Latest 12 internal transactions

Advanced mode:
Parent Transaction Hash Block From To
67041392024-09-16 17:40:2478 days ago1726508424
0xAAE8c724...22050283B
 Contract Creation0 ETH
67033032024-09-16 14:30:0079 days ago1726497000
0xAAE8c724...22050283B
 Contract Creation0 ETH
66970352024-09-15 15:05:4880 days ago1726412748
0xAAE8c724...22050283B
 Contract Creation0 ETH
66970182024-09-15 15:02:1280 days ago1726412532
0xAAE8c724...22050283B
 Contract Creation0 ETH
66969672024-09-15 14:50:1280 days ago1726411812
0xAAE8c724...22050283B
 Contract Creation0 ETH
66968362024-09-15 14:20:0080 days ago1726410000
0xAAE8c724...22050283B
 Contract Creation0 ETH
66968082024-09-15 14:13:4880 days ago1726409628
0xAAE8c724...22050283B
 Contract Creation0 ETH
61841622024-06-25 14:41:24162 days ago1719326484
0xAAE8c724...22050283B
 Contract Creation0 ETH
61496492024-06-20 19:30:24166 days ago1718911824
0xAAE8c724...22050283B
 Contract Creation0 ETH
60249062024-06-02 12:07:36185 days ago1717330056
0xAAE8c724...22050283B
 Contract Creation0 ETH
58466962024-05-06 6:05:00212 days ago1714975500
0xAAE8c724...22050283B
 Contract Creation0 ETH
58466602024-05-06 5:57:12212 days ago1714975032
0xAAE8c724...22050283B
 Contract Creation0 ETH
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
MiyaMints

Compiler Version
v0.8.23+commit.f704f362

Optimization Enabled:
Yes with 200 runs

Other Settings:
paris EvmVersion
File 1 of 21 : MiyaMints.sol
// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.23;

import {MiyaAVFactory, Ownable, LibClone, EnumerableSetLib} from "./MiyaAVFactory.sol";
import {IERC20} from "../lib/openzeppelin-contracts/contracts/interfaces/IERC20.sol";
import {IERC721} from "../lib/openzeppelin-contracts/contracts/interfaces/IERC721.sol";
import {IERC1155} from "../lib/openzeppelin-contracts/contracts/interfaces/IERC1155.sol";

interface IERC721MiyaInitialize {
    function initialize(
        string memory name, // NFT collection name
        string memory symbol, // NFT collection symbol/ticker
        string memory baseURI, // Base URI for NFT metadata, preferably on IPFS
        uint40 maxSupply, // Max mint supply
        uint16 royalty, // Percentage of royalty fees in basis points (0 - 10000)
        uint16 allocation, // Percentage of mint funds allocated to aligned collection in basis points (500 - 10000)
        address owner, // Collection owner
        address alignedNft, // Address of aligned NFT collection mint funds are being dedicated to
        uint80 price, // Standard mint price
        uint96 vaultId, // NFTX vault ID,
        bytes32 salt // AV deployment salt
    ) external;
    function disableInitializers() external;
}

contract MiyaMints is Ownable {
    using EnumerableSetLib for EnumerableSetLib.Uint256Set;

    error Invalid();
    error TransferFailed();

    event ERC721MiyaImplementation(address indexed implementation);
    event MiyaIdSet(address indexed erc721, uint256 indexed vaultId);
    event Deployed(address indexed deployer, address indexed collection, address indexed aligned, bytes32 salt);
    event OwnershipChanged(address indexed erc721m, address indexed oldOwner, address indexed newOwner);

    address public erc721MiyaImplementation;
    MiyaAVFactory public miyaAVFactory;
    mapping(address alignedNft => uint256 vaultId) public miyaIds;
    mapping(address erc721Miya => bool isMiyaMints) private isMiyaMintsContract;

    constructor(address newOwner, address newErc721MiyaImplementation, address newMiyaAVImplementation) payable {
        _initializeOwner(newOwner);
        erc721MiyaImplementation = newErc721MiyaImplementation;
        emit ERC721MiyaImplementation(newErc721MiyaImplementation);
        miyaAVFactory = new MiyaAVFactory(newOwner, newMiyaAVImplementation);
    }

    function renounceOwnership() public payable virtual override(Ownable) onlyOwner {}

    // Set preferred NFTX vault ID for a specific NFT to be used when vaultId 0 is specified for lazy deployments
    function setMiyaId(address alignedNft, uint256 vaultId) external onlyOwner {
        miyaIds[alignedNft] = vaultId;
        emit MiyaIdSet(alignedNft, vaultId);
    }

    // Update implementation address for new ERC721Miya clones
    // NOTE: Does not update implementation of prior clones
    function updateERC721MiyaImplementation(address newErc721MiyaImplementation) external onlyOwner {
        erc721MiyaImplementation = newErc721MiyaImplementation;
        emit ERC721MiyaImplementation(newErc721MiyaImplementation);
    }

    // Update implementation address for new MiyaAV clones
    // NOTE: Does not update implementation of prior clones
    function updateMiyaAVImplementation(address newMiyaAVImplementation) external onlyOwner {
        miyaAVFactory.updateImplementation(newMiyaAVImplementation);
    }

    function miyaAVImplementation() external view returns (address) {
        return miyaAVFactory.implementation();
    }

    // Helper functions to get vault info from MiyaAVFactory in MiyaMints
    function getVault(address alignedNft, uint256 vaultId) external view returns (address) {
        return miyaAVFactory.vaults(alignedNft, vaultId);
    }

    function getAlignedNfts() external view returns (address[] memory) {
        return miyaAVFactory.getAlignedNfts();
    }

    function getVaultIds(address alignedNft) external view returns (uint256[] memory) {
        return miyaAVFactory.getVaultIds(alignedNft);
    }

    // Deploy ERC721Miya collection and fully initialize it
    function deploy(
        string memory name, // NFT collection name
        string memory symbol, // NFT collection symbol/ticker
        string memory baseURI, // Base URI for NFT metadata, preferably on IPFS
        uint40 maxSupply, // Max mint supply
        uint16 royalty, // Percentage of royalty fees in basis points (0 - 10000)
        uint16 allocation, // Percentage of mint funds allocated to aligned collection in basis points (500 - 10000)
        address owner_, // Collection owner
        address alignedNft, // Address of aligned NFT collection mint funds are being dedicated to
        uint80 price, // Standard mint price
        uint96 vaultId, // NFTX vault ID
        bytes32 saltAlignmentVault // AV deployment salt
    ) external returns (address deployment) {
        deployment = LibClone.clone(erc721MiyaImplementation);
        isMiyaMintsContract[deployment] = true;
        IERC721MiyaInitialize(deployment).initialize(
            name,
            symbol,
            baseURI,
            maxSupply,
            royalty,
            allocation,
            owner_,
            alignedNft,
            price,
            vaultId,
            saltAlignmentVault
        );
        IERC721MiyaInitialize(deployment).disableInitializers();
        emit Deployed(msg.sender, deployment, alignedNft, bytes32(""));
    }

    // Deploy ERC721M collection to deterministic address
    function deployDeterministic(
        string memory name, // NFT collection name
        string memory symbol, // NFT collection symbol/ticker
        string memory baseURI, // Base URI for NFT metadata, preferably on IPFS
        uint40 maxSupply, // Max mint supply
        uint16 royalty, // Percentage of royalty fees in basis points (0 - 10000)
        uint16 allocation, // Percentage of mint funds allocated to aligned collection in basis points (500 - 10000)
        address owner_, // Collection owner
        address alignedNft, // Address of aligned NFT collection mint funds are being dedicated to
        uint80 price, // Standard mint price
        uint96 vaultId, // NFTX vault ID
        bytes32 saltAlignmentVault, // AV deployment salt
        bytes32 saltERC721Miya // ERC721Miya deployment salt
    ) external returns (address deployment) {
        deployment = LibClone.cloneDeterministic(erc721MiyaImplementation, saltERC721Miya);
        isMiyaMintsContract[deployment] = true;
        IERC721MiyaInitialize(deployment).initialize(
            name,
            symbol,
            baseURI,
            maxSupply,
            royalty,
            allocation,
            owner_,
            alignedNft,
            price,
            vaultId,
            saltAlignmentVault
        );
        IERC721MiyaInitialize(deployment).disableInitializers();
        emit Deployed(msg.sender, deployment, alignedNft, saltERC721Miya);
    }

    // Return initialization code hash of a clone of the current ERC721Miya implementation
    function initCodeHash() external view returns (bytes32 hash) {
        hash = LibClone.initCodeHash(erc721MiyaImplementation);
    }

    // Predict address of deterministic clone of the current ERC721Miya implementation
    function predictDeterministicAddress(bytes32 salt) external view returns (address predicted) {
        predicted = LibClone.predictDeterministicAddress(erc721MiyaImplementation, salt, address(this));
    }

    // Deploy vault if required, else return the already deployed vault
    function deployVault(address alignedNft, uint96 vaultId, bytes32 salt) external returns (address vault) {
        // If no vaultId is specified, overwrite with preferred, if any exists
        if (vaultId == 0) vaultId = uint96(miyaIds[alignedNft]);
        if (salt == bytes32("")) vault = miyaAVFactory.deploy(alignedNft, vaultId);
        else vault = miyaAVFactory.deployDeterministic(alignedNft, vaultId, salt);
    }

    // Allows deployed collections to update ownership status subgraph for frontend using events
    function ownershipChanged(address oldOwner, address newOwner) external {
        if (!isMiyaMintsContract[msg.sender]) revert Invalid();
        emit OwnershipChanged(msg.sender, oldOwner, newOwner);
    }

    function withdrawEth(address recipient) external payable virtual onlyOwner {
        if (recipient == address(0) || recipient == address(0xdead)) revert TransferFailed();
        (bool success,) = payable(recipient).call{value: address(this).balance}("");
        if (!success) revert TransferFailed();
    }

    function withdrawERC20(address token, address recipient) external payable virtual onlyOwner {
        if (recipient == address(0) || recipient == address(0xdead)) revert TransferFailed();
        IERC20(token).transfer(recipient, IERC20(token).balanceOf(address(this)));
    }

    function withdrawERC721(address token, uint256 tokenId, address recipient) external payable virtual onlyOwner {
        if (recipient == address(0) || recipient == address(0xdead)) revert TransferFailed();
        IERC721(token).transferFrom(address(this), recipient, tokenId);
    }

    function withdrawERC1155(
        address token,
        uint256 tokenId,
        uint256 amount,
        address recipient
    ) external payable virtual onlyOwner {
        if (recipient == address(0) || recipient == address(0xdead)) revert TransferFailed();
        IERC1155(token).safeTransferFrom(address(this), recipient, tokenId, amount, "");
    }

    function withdrawERC1155Batch(
        address token,
        uint256[] memory tokenIds,
        uint256[] memory amounts,
        address recipient
    ) external payable virtual onlyOwner {
        if (recipient == address(0) || recipient == address(0xdead)) revert TransferFailed();
        IERC1155(token).safeBatchTransferFrom(address(this), recipient, tokenIds, amounts, "");
    }
}

File 2 of 21 : MiyaAVFactory.sol
// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.23;

import {AlignmentVaultFactory, Ownable, LibClone, IInitialize} from "../lib/AlignmentVault/src/testnet/AlignmentVaultFactory.sol";
import {EnumerableSetLib} from "../lib/solady/src/utils/EnumerableSetLib.sol";

interface IMiyaAV {
    function vaultId() external view returns (uint96);
}

contract MiyaAVFactory is AlignmentVaultFactory {
    using EnumerableSetLib for EnumerableSetLib.Uint256Set;
    using EnumerableSetLib for EnumerableSetLib.AddressSet;

    event MAV_Deployed(address indexed vault, address indexed erc721, uint256 indexed vaultId, bytes32 salt);

    // ERC721 address => NFTX VaultID => MiyaAV address
    mapping(address => mapping(uint256 => address)) public vaults;
    mapping(address => EnumerableSetLib.Uint256Set) internal _vaultIds;
    EnumerableSetLib.AddressSet internal _alignedNfts;
    address public miyaMints;

    modifier onlyDeployer() {
        if (msg.sender != miyaMints) revert Unauthorized();
        _;
    }

    constructor(address owner_, address implementation_) AlignmentVaultFactory(owner_, implementation_) {
        miyaMints = msg.sender;
    }

    function _checkOwner() internal view override {
        if (msg.sender != owner()) revert Unauthorized();
    }

    function owner() public view override returns (address) {
        return Ownable(miyaMints).owner();
    }

    function renounceOwnership() public payable virtual override(Ownable) onlyOwner {}

    /**
     * @notice Deploys a new AlignmentVault and fully initializes it.
     * @param alignedNft Address of the ERC721 token associated with the vault.
     * @param vaultId NFTX Vault ID associated with alignedNft
     * @return deployment Address of the newly deployed AlignmentVault.
     */
    function deploy(address alignedNft, uint96 vaultId) external payable override onlyDeployer returns (address deployment) {
        // Return if a vault for this erc721 + vaultId combo already exists
        deployment = vaults[alignedNft][vaultId];
        if (deployment != address(0)) return deployment;
        // Otherwise deploy and initialize vault
        deployment = LibClone.clone(implementation);
        IInitialize(deployment).initialize(owner(), alignedNft, vaultId);
        IInitialize(deployment).disableInitializers();
        // Store enumerable vault metadata
        if (vaultId == 0) vaultId = IMiyaAV(deployment).vaultId();
        vaults[alignedNft][vaultId] = deployment;
        _alignedNfts.add(alignedNft);
        _vaultIds[alignedNft].add(vaultId);
        emit MAV_Deployed(deployment, alignedNft, vaultId, bytes32(""));
    }

    /**
     * @notice Deploys a new AlignmentVault to a deterministic address based on the provided salt.
     * @param alignedNft Address of the ERC721 token associated with the vault.
     * @param vaultId NFTX Vault ID associated with alignedNft
     * @param salt A unique salt to determine the address.
     * @return deployment Address of the newly deployed AlignmentVault.
     */
    function deployDeterministic(address alignedNft, uint96 vaultId, bytes32 salt)
        external
        payable
        override
        onlyDeployer
        returns (address deployment)
    {
        // Return if a vault for this erc721 + vaultId combo already exists
        deployment = vaults[alignedNft][vaultId];
        if (deployment != address(0)) return deployment;
        // Otherwise deploy and initialize vault
        deployment = LibClone.cloneDeterministic(implementation, salt);
        IInitialize(deployment).initialize(owner(), alignedNft, vaultId);
        IInitialize(deployment).disableInitializers();
        // Store enumerable vault metadata
        if (vaultId == 0) vaultId = IMiyaAV(deployment).vaultId();
        vaults[alignedNft][vaultId] = deployment;
        _alignedNfts.add(alignedNft);
        _vaultIds[alignedNft].add(vaultId);
        emit MAV_Deployed(deployment, alignedNft, vaultId, salt);
    }

    function updateImplementation(address newImplementation) external payable override onlyDeployer {
        if (newImplementation == implementation) return;
        implementation = newImplementation;
        emit AVF_ImplementationSet(newImplementation);
    }

    function getAlignedNfts() external view returns (address[] memory) {
        return _alignedNfts.values();
    }

    function getVaultIds(address alignedNft) external view returns (uint256[] memory) {
        return _vaultIds[alignedNft].values();
    }
}

File 3 of 21 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC20.sol)

pragma solidity ^0.8.20;

import {IERC20} from "../token/ERC20/IERC20.sol";

File 4 of 21 : IERC721.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC721.sol)

pragma solidity ^0.8.20;

import {IERC721} from "../token/ERC721/IERC721.sol";

File 5 of 21 : IERC1155.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC1155.sol)

pragma solidity ^0.8.20;

import {IERC1155} from "../token/ERC1155/IERC1155.sol";

File 6 of 21 : AlignmentVaultFactory.sol
// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.23;

// Inheritance and Libraries
import {Ownable} from "../../lib/solady/src/auth/Ownable.sol";
import {IAlignmentVaultFactory} from "../IAlignmentVaultFactory.sol";
import {LibClone} from "../../lib/solady/src/utils/LibClone.sol";

// Interfaces
import {IERC20} from "../../lib/openzeppelin-contracts-v5/contracts/interfaces/IERC20.sol";
import {IERC721} from "../../lib/openzeppelin-contracts-v5/contracts/interfaces/IERC721.sol";
import {IERC1155} from "../../lib/openzeppelin-contracts-v5/contracts/interfaces/IERC1155.sol";

interface IInitialize {
    function initialize(address owner, address alignedNft, uint96 vaultId) external payable;
    function disableInitializers() external payable;
}

/**
 * @title AlignmentVaultFactory
 * @notice This can be used by any EOA or contract to deploy an AlignmentVault owned by the deployer.
 * @dev deploy() will perform a normal deployment. deployDeterministic() allows you to mine a deployment address.
 * @author Zodomo.eth (X: @0xZodomo, Telegram: @zodomo, GitHub: Zodomo, Email: [email protected])
 * @custom:github https://github.com/Zodomo/AlignmentVault
 * @custom:miyamaker https://miyamaker.com
 */
contract AlignmentVaultFactory is Ownable, IAlignmentVaultFactory {
    // >>>>>>>>>>>> [ STORAGE VARIABLES ] <<<<<<<<<<<<

    address public implementation;

    // >>>>>>>>>>>> [ CONSTRUCTOR ] <<<<<<<<<<<<

    constructor(address owner_, address implementation_) payable {
        _initializeOwner(owner_);
        implementation = implementation_;
        emit AVF_ImplementationSet(implementation_);
    }

    // >>>>>>>>>>>> [ DEPLOYMENT FUNCTIONS ] <<<<<<<<<<<<

    /**
     * @notice Deploys a new AlignmentVault and fully initializes it.
     * @param alignedNft Address of the ERC721/1155 token associated with the vault.
     * @param vaultId NFTX Vault ID associated with alignedNft
     * @return deployment Address of the newly deployed AlignmentVault.
     */
    function deploy(address alignedNft, uint96 vaultId) external payable virtual returns (address deployment) {
        deployment = LibClone.clone(implementation);
        IInitialize(deployment).initialize(msg.sender, alignedNft, vaultId);
        IInitialize(deployment).disableInitializers();
        emit AVF_Deployed(msg.sender, deployment, alignedNft);
    }

    /**
     * @notice Deploys a new AlignmentVault to a deterministic address based on the provided salt.
     * @param alignedNft Address of the ERC721/1155 token associated with the vault.
     * @param vaultId NFTX Vault ID associated with alignedNft
     * @param salt A unique salt to determine the address.
     * @return deployment Address of the newly deployed AlignmentVault.
     */
    function deployDeterministic(
        address alignedNft,
        uint96 vaultId,
        bytes32 salt
    ) external payable virtual returns (address deployment) {
        deployment = LibClone.cloneDeterministic(implementation, salt);
        IInitialize(deployment).initialize(msg.sender, alignedNft, vaultId);
        IInitialize(deployment).disableInitializers();
        emit AVF_Deployed(msg.sender, deployment, alignedNft);
    }

    /**
     * @notice Returns the initialization code hash of the clone of the implementation.
     * @dev This is used primarily for tools like create2crunch to find vanity addresses.
     * @return codeHash The initialization code hash of the clone.
     */
    function initCodeHash() external view virtual returns (bytes32 codeHash) {
        return LibClone.initCodeHash(implementation);
    }

    /**
     * @notice Predicts the address of the deterministic clone with the given salt.
     * @param salt The unique salt used to determine the address.
     * @return addr Address of the deterministic clone.
     */
    function predictDeterministicAddress(bytes32 salt) external view virtual returns (address addr) {
        return LibClone.predictDeterministicAddress(implementation, salt, address(this));
    }

    // >>>>>>>>>>>> [ MANAGEMENT FUNCTIONS ] <<<<<<<<<<<<

    /**
     * @notice Updates the implementation address used for new clones.
     * @dev Does not affect previously deployed clones.
     * @param newImplementation The new implementation address for clones.
     */
    function updateImplementation(address newImplementation) external payable virtual onlyOwner {
        if (newImplementation == implementation) return;
        implementation = newImplementation;
        emit AVF_ImplementationSet(newImplementation);
    }

    /**
     * @notice Used to withdraw any ETH sent to the factory
     */
    function withdrawEth(address recipient) external payable virtual onlyOwner {
        if (recipient == address(0) || recipient == address(0xdead)) revert AVF_WithdrawalFailed();
        (bool success,) = payable(recipient).call{value: address(this).balance}("");
        if (!success) revert AVF_WithdrawalFailed();
    }

    /**
     * @notice Used to withdraw any ERC20 tokens sent to the factory
     */
    function withdrawERC20(address token, address recipient) external payable virtual onlyOwner {
        if (recipient == address(0) || recipient == address(0xdead)) revert AVF_WithdrawalFailed();
        IERC20(token).transfer(recipient, IERC20(token).balanceOf(address(this)));
    }

    /**
     * @notice Used to withdraw any ERC721 tokens sent to the factory
     */
    function withdrawERC721(address token, uint256 tokenId, address recipient) external payable virtual onlyOwner {
        if (recipient == address(0) || recipient == address(0xdead)) revert AVF_WithdrawalFailed();
        IERC721(token).transferFrom(address(this), recipient, tokenId);
    }

    /**
     * @notice Used to withdraw any ERC1155 tokens sent to the factory
     */
    function withdrawERC1155(
        address token,
        uint256 tokenId,
        uint256 amount,
        address recipient
    ) external payable virtual onlyOwner {
        if (recipient == address(0) || recipient == address(0xdead)) revert AVF_WithdrawalFailed();
        IERC1155(token).safeTransferFrom(address(this), recipient, tokenId, amount, "");
    }

    /**
     * @notice Used to batch withdraw any ERC1155 tokens sent to the factory
     */
    function withdrawERC1155Batch(
        address token,
        uint256[] calldata tokenIds,
        uint256[] calldata amounts,
        address recipient
    ) external payable virtual onlyOwner {
        if (recipient == address(0) || recipient == address(0xdead)) revert AVF_WithdrawalFailed();
        IERC1155(token).safeBatchTransferFrom(address(this), recipient, tokenIds, amounts, "");
    }
}

File 7 of 21 : 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/LibMap.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.
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;
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                     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 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 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)
                    sstore(add(rootSlot, n), shl(96, value))
                    sstore(p, add(1, n))
                    sstore(rootSlot, add(2, rootPacked))
                    result := 1
                    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 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))
                    sstore(add(rootSlot, n), 0)
                    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)
                    sstore(add(rootSlot, n), 0)
                    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 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 the element at index `i` in the set.
    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.
    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.
    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.
    function at(Int256Set storage set, uint256 i) internal view returns (int256 result) {
        result = int256(uint256(at(_toBytes32Set(set), i)));
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                      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
        }
    }
}

File 8 of 21 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC-20 standard as defined in the ERC.
 */
interface IERC20 {
    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);

    /**
     * @dev Returns the value of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the value of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves a `value` amount of tokens from the caller's account to `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, uint256 value) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the
     * caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 value) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to` using the
     * allowance mechanism. `value` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address from, address to, uint256 value) external returns (bool);
}

File 9 of 21 : IERC721.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/IERC721.sol)

pragma solidity ^0.8.20;

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

/**
 * @dev Required interface of an ERC-721 compliant contract.
 */
interface IERC721 is IERC165 {
    /**
     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.
     */
    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
     */
    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
     */
    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    /**
     * @dev Returns the number of tokens in ``owner``'s account.
     */
    function balanceOf(address owner) external view returns (uint256 balance);

    /**
     * @dev Returns the owner of the `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function ownerOf(uint256 tokenId) external view returns (address owner);

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon
     *   a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
     * are aware of the ERC-721 protocol to prevent tokens from being forever locked.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or
     *   {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon
     *   a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(address from, address to, uint256 tokenId) external;

    /**
     * @dev Transfers `tokenId` token from `from` to `to`.
     *
     * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC-721
     * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must
     * understand this adds an external call which potentially creates a reentrancy vulnerability.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address from, address to, uint256 tokenId) external;

    /**
     * @dev Gives permission to `to` to transfer `tokenId` token to another account.
     * The approval is cleared when the token is transferred.
     *
     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.
     *
     * Requirements:
     *
     * - The caller must own the token or be an approved operator.
     * - `tokenId` must exist.
     *
     * Emits an {Approval} event.
     */
    function approve(address to, uint256 tokenId) external;

    /**
     * @dev Approve or remove `operator` as an operator for the caller.
     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
     *
     * Requirements:
     *
     * - The `operator` cannot be the address zero.
     *
     * Emits an {ApprovalForAll} event.
     */
    function setApprovalForAll(address operator, bool approved) external;

    /**
     * @dev Returns the account approved for `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function getApproved(uint256 tokenId) external view returns (address operator);

    /**
     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
     *
     * See {setApprovalForAll}
     */
    function isApprovedForAll(address owner, address operator) external view returns (bool);
}

File 10 of 21 : IERC1155.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (token/ERC1155/IERC1155.sol)

pragma solidity ^0.8.20;

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

/**
 * @dev Required interface of an ERC-1155 compliant contract, as defined in the
 * https://eips.ethereum.org/EIPS/eip-1155[ERC].
 */
interface IERC1155 is IERC165 {
    /**
     * @dev Emitted when `value` amount of tokens of type `id` are transferred from `from` to `to` by `operator`.
     */
    event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);

    /**
     * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all
     * transfers.
     */
    event TransferBatch(
        address indexed operator,
        address indexed from,
        address indexed to,
        uint256[] ids,
        uint256[] values
    );

    /**
     * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to
     * `approved`.
     */
    event ApprovalForAll(address indexed account, address indexed operator, bool approved);

    /**
     * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.
     *
     * If an {URI} event was emitted for `id`, the standard
     * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value
     * returned by {IERC1155MetadataURI-uri}.
     */
    event URI(string value, uint256 indexed id);

    /**
     * @dev Returns the value of tokens of token type `id` owned by `account`.
     */
    function balanceOf(address account, uint256 id) external view returns (uint256);

    /**
     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.
     *
     * Requirements:
     *
     * - `accounts` and `ids` must have the same length.
     */
    function balanceOfBatch(
        address[] calldata accounts,
        uint256[] calldata ids
    ) external view returns (uint256[] memory);

    /**
     * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,
     *
     * Emits an {ApprovalForAll} event.
     *
     * Requirements:
     *
     * - `operator` cannot be the zero address.
     */
    function setApprovalForAll(address operator, bool approved) external;

    /**
     * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.
     *
     * See {setApprovalForAll}.
     */
    function isApprovedForAll(address account, address operator) external view returns (bool);

    /**
     * @dev Transfers a `value` amount of tokens of type `id` from `from` to `to`.
     *
     * WARNING: This function can potentially allow a reentrancy attack when transferring tokens
     * to an untrusted contract, when invoking {onERC1155Received} on the receiver.
     * Ensure to follow the checks-effects-interactions pattern and consider employing
     * reentrancy guards when interacting with untrusted contracts.
     *
     * Emits a {TransferSingle} event.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.
     * - `from` must have a balance of tokens of type `id` of at least `value` amount.
     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the
     * acceptance magic value.
     */
    function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes calldata data) external;

    /**
     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.
     *
     * WARNING: This function can potentially allow a reentrancy attack when transferring tokens
     * to an untrusted contract, when invoking {onERC1155BatchReceived} on the receiver.
     * Ensure to follow the checks-effects-interactions pattern and consider employing
     * reentrancy guards when interacting with untrusted contracts.
     *
     * Emits either a {TransferSingle} or a {TransferBatch} event, depending on the length of the array arguments.
     *
     * Requirements:
     *
     * - `ids` and `values` must have the same length.
     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the
     * acceptance magic value.
     */
    function safeBatchTransferFrom(
        address from,
        address to,
        uint256[] calldata ids,
        uint256[] calldata values,
        bytes calldata data
    ) external;
}

File 11 of 21 : Ownable.sol
// 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();
        _;
    }
}

File 12 of 21 : IAlignmentVaultFactory.sol
// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.23;

/**
 * @title IAlignmentVaultFactory
 * @notice This can be used by any EOA or contract to deploy an AlignmentVault owned by the deployer.
 * @dev deploy() will perform a normal deployment. deployDeterministic() allows you to mine a deployment address.
 * @author Zodomo.eth (X: @0xZodomo, Telegram: @zodomo, GitHub: Zodomo, Email: [email protected])
 * @custom:github https://github.com/Zodomo/AlignmentVault
 * @custom:miyamaker https://miyamaker.com
 */
interface IAlignmentVaultFactory {
    // >>>>>>>>>>>> [ ERRORS ] <<<<<<<<<<<<

    error AVF_WithdrawalFailed();

    // >>>>>>>>>>>> [ EVENTS ] <<<<<<<<<<<<

    event AVF_ImplementationSet(address indexed implementation);
    event AVF_Deployed(address indexed deployer, address indexed deployment, address indexed alignedNft);

    // >>>>>>>>>>>> [ STORAGE VARIABLES ] <<<<<<<<<<<<

    function implementation() external view returns (address);

    // >>>>>>>>>>>> [ DEPLOYMENT FUNCTIONS ] <<<<<<<<<<<<

    function deploy(address alignedNft, uint96 vaultId) external payable returns (address deployment);
    function deployDeterministic(
        address alignedNft,
        uint96 vaultId,
        bytes32 salt
    ) external payable returns (address deployment);

    function initCodeHash() external view returns (bytes32 codeHash);
    function predictDeterministicAddress(bytes32 salt) external view returns (address addr);

    // >>>>>>>>>>>> [ MANAGEMENT FUNCTIONS ] <<<<<<<<<<<<

    function updateImplementation(address newImplementation) external payable;
    function withdrawEth(address recipient) external payable;
    function withdrawERC20(address token, address recipient) external payable;
    function withdrawERC721(address token, uint256 tokenId, address recipient) external payable;
    function withdrawERC1155(address token, uint256 tokenId, uint256 amount, address recipient) external payable;
    function withdrawERC1155Batch(
        address token,
        uint256[] calldata tokenIds,
        uint256[] calldata amounts,
        address recipient
    ) external payable;
}

File 13 of 21 : LibClone.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/// @notice Minimal proxy library.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/LibClone.sol)
/// @author Minimal proxy by 0age (https://github.com/0age)
/// @author Clones with immutable args by wighawag, zefram.eth, Saw-mon & Natalie
/// (https://github.com/Saw-mon-and-Natalie/clones-with-immutable-args)
/// @author Minimal ERC1967 proxy by jtriley-eth (https://github.com/jtriley-eth/minimum-viable-proxy)
///
/// @dev Minimal proxy:
/// Although the sw0nt pattern saves 5 gas over the erc-1167 pattern during runtime,
/// it is not supported out-of-the-box on Etherscan. Hence, we choose to use the 0age pattern,
/// which saves 4 gas over the erc-1167 pattern during runtime, and has the smallest bytecode.
///
/// @dev Minimal proxy (PUSH0 variant):
/// This is a new minimal proxy that uses the PUSH0 opcode introduced during Shanghai.
/// It is optimized first for minimal runtime gas, then for minimal bytecode.
/// The PUSH0 clone functions are intentionally postfixed with a jarring "_PUSH0" as
/// many EVM chains may not support the PUSH0 opcode in the early months after Shanghai.
/// Please use with caution.
///
/// @dev Clones with immutable args (CWIA):
/// The implementation of CWIA here implements a `receive()` method that emits the
/// `ReceiveETH(uint256)` event. This skips the `DELEGATECALL` when there is no calldata,
/// enabling us to accept hard gas-capped `sends` & `transfers` for maximum backwards
/// composability. The minimal proxy implementation does not offer this feature.
///
/// @dev Minimal ERC1967 proxy:
/// An minimal ERC1967 proxy, intended to be upgraded with UUPS.
/// This is NOT the same as ERC1967Factory's transparent proxy, which includes admin logic.
///
/// @dev ERC1967I proxy:
/// An variant of the minimal ERC1967 proxy, with a special code path that activates
/// if `calldatasize() == 1`. This code path skips the delegatecall and directly returns the
/// `implementation` address. The returned implementation is guaranteed to be valid if the
/// keccak256 of the proxy's code is equal to `ERC1967I_CODE_HASH`.
library LibClone {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                         CONSTANTS                          */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The keccak256 of the deployed code for the ERC1967 proxy.
    bytes32 internal constant ERC1967_CODE_HASH =
        0xaaa52c8cc8a0e3fd27ce756cc6b4e70c51423e9b597b11f32d3e49f8b1fc890d;

    /// @dev The keccak256 of the deployed code for the ERC1967I proxy.
    bytes32 internal constant ERC1967I_CODE_HASH =
        0xce700223c0d4cea4583409accfc45adac4a093b3519998a9cbbe1504dadba6f7;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                       CUSTOM ERRORS                        */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Unable to deploy the clone.
    error DeploymentFailed();

    /// @dev The salt must start with either the zero address or `by`.
    error SaltDoesNotStartWith();

    /// @dev The ETH transfer has failed.
    error ETHTransferFailed();

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                  MINIMAL PROXY OPERATIONS                  */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Deploys a clone of `implementation`.
    function clone(address implementation) internal returns (address instance) {
        instance = clone(0, implementation);
    }

    /// @dev Deploys a clone of `implementation`.
    /// Deposits `value` ETH during deployment.
    function clone(uint256 value, address implementation) internal returns (address instance) {
        /// @solidity memory-safe-assembly
        assembly {
            /**
             * --------------------------------------------------------------------------+
             * CREATION (9 bytes)                                                        |
             * --------------------------------------------------------------------------|
             * Opcode     | Mnemonic          | Stack     | Memory                       |
             * --------------------------------------------------------------------------|
             * 60 runSize | PUSH1 runSize     | r         |                              |
             * 3d         | RETURNDATASIZE    | 0 r       |                              |
             * 81         | DUP2              | r 0 r     |                              |
             * 60 offset  | PUSH1 offset      | o r 0 r   |                              |
             * 3d         | RETURNDATASIZE    | 0 o r 0 r |                              |
             * 39         | CODECOPY          | 0 r       | [0..runSize): runtime code   |
             * f3         | RETURN            |           | [0..runSize): runtime code   |
             * --------------------------------------------------------------------------|
             * RUNTIME (44 bytes)                                                        |
             * --------------------------------------------------------------------------|
             * Opcode  | Mnemonic       | Stack                  | Memory                |
             * --------------------------------------------------------------------------|
             *                                                                           |
             * ::: keep some values in stack ::::::::::::::::::::::::::::::::::::::::::: |
             * 3d      | RETURNDATASIZE | 0                      |                       |
             * 3d      | RETURNDATASIZE | 0 0                    |                       |
             * 3d      | RETURNDATASIZE | 0 0 0                  |                       |
             * 3d      | RETURNDATASIZE | 0 0 0 0                |                       |
             *                                                                           |
             * ::: copy calldata to memory ::::::::::::::::::::::::::::::::::::::::::::: |
             * 36      | CALLDATASIZE   | cds 0 0 0 0            |                       |
             * 3d      | RETURNDATASIZE | 0 cds 0 0 0 0          |                       |
             * 3d      | RETURNDATASIZE | 0 0 cds 0 0 0 0        |                       |
             * 37      | CALLDATACOPY   | 0 0 0 0                | [0..cds): calldata    |
             *                                                                           |
             * ::: delegate call to the implementation contract :::::::::::::::::::::::: |
             * 36      | CALLDATASIZE   | cds 0 0 0 0            | [0..cds): calldata    |
             * 3d      | RETURNDATASIZE | 0 cds 0 0 0 0          | [0..cds): calldata    |
             * 73 addr | PUSH20 addr    | addr 0 cds 0 0 0 0     | [0..cds): calldata    |
             * 5a      | GAS            | gas addr 0 cds 0 0 0 0 | [0..cds): calldata    |
             * f4      | DELEGATECALL   | success 0 0            | [0..cds): calldata    |
             *                                                                           |
             * ::: copy return data to memory :::::::::::::::::::::::::::::::::::::::::: |
             * 3d      | RETURNDATASIZE | rds success 0 0        | [0..cds): calldata    |
             * 3d      | RETURNDATASIZE | rds rds success 0 0    | [0..cds): calldata    |
             * 93      | SWAP4          | 0 rds success 0 rds    | [0..cds): calldata    |
             * 80      | DUP1           | 0 0 rds success 0 rds  | [0..cds): calldata    |
             * 3e      | RETURNDATACOPY | success 0 rds          | [0..rds): returndata  |
             *                                                                           |
             * 60 0x2a | PUSH1 0x2a     | 0x2a success 0 rds     | [0..rds): returndata  |
             * 57      | JUMPI          | 0 rds                  | [0..rds): returndata  |
             *                                                                           |
             * ::: revert :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |
             * fd      | REVERT         |                        | [0..rds): returndata  |
             *                                                                           |
             * ::: return :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |
             * 5b      | JUMPDEST       | 0 rds                  | [0..rds): returndata  |
             * f3      | RETURN         |                        | [0..rds): returndata  |
             * --------------------------------------------------------------------------+
             */
            mstore(0x21, 0x5af43d3d93803e602a57fd5bf3)
            mstore(0x14, implementation)
            mstore(0x00, 0x602c3d8160093d39f33d3d3d3d363d3d37363d73)
            instance := create(value, 0x0c, 0x35)
            if iszero(instance) {
                mstore(0x00, 0x30116425) // `DeploymentFailed()`.
                revert(0x1c, 0x04)
            }
            mstore(0x21, 0) // Restore the overwritten part of the free memory pointer.
        }
    }

    /// @dev Deploys a deterministic clone of `implementation` with `salt`.
    function cloneDeterministic(address implementation, bytes32 salt)
        internal
        returns (address instance)
    {
        instance = cloneDeterministic(0, implementation, salt);
    }

    /// @dev Deploys a deterministic clone of `implementation` with `salt`.
    /// Deposits `value` ETH during deployment.
    function cloneDeterministic(uint256 value, address implementation, bytes32 salt)
        internal
        returns (address instance)
    {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x21, 0x5af43d3d93803e602a57fd5bf3)
            mstore(0x14, implementation)
            mstore(0x00, 0x602c3d8160093d39f33d3d3d3d363d3d37363d73)
            instance := create2(value, 0x0c, 0x35, salt)
            if iszero(instance) {
                mstore(0x00, 0x30116425) // `DeploymentFailed()`.
                revert(0x1c, 0x04)
            }
            mstore(0x21, 0) // Restore the overwritten part of the free memory pointer.
        }
    }

    /// @dev Returns the initialization code of the clone of `implementation`.
    function initCode(address implementation) internal pure returns (bytes memory result) {
        /// @solidity memory-safe-assembly
        assembly {
            result := mload(0x40)
            mstore(add(result, 0x40), 0x5af43d3d93803e602a57fd5bf30000000000000000000000)
            mstore(add(result, 0x28), implementation)
            mstore(add(result, 0x14), 0x602c3d8160093d39f33d3d3d3d363d3d37363d73)
            mstore(result, 0x35) // Store the length.
            mstore(0x40, add(result, 0x60)) // Allocate memory.
        }
    }

    /// @dev Returns the initialization code hash of the clone of `implementation`.
    /// Used for mining vanity addresses with create2crunch.
    function initCodeHash(address implementation) internal pure returns (bytes32 hash) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x21, 0x5af43d3d93803e602a57fd5bf3)
            mstore(0x14, implementation)
            mstore(0x00, 0x602c3d8160093d39f33d3d3d3d363d3d37363d73)
            hash := keccak256(0x0c, 0x35)
            mstore(0x21, 0) // Restore the overwritten part of the free memory pointer.
        }
    }

    /// @dev Returns the address of the deterministic clone of `implementation`,
    /// with `salt` by `deployer`.
    /// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.
    function predictDeterministicAddress(address implementation, bytes32 salt, address deployer)
        internal
        pure
        returns (address predicted)
    {
        bytes32 hash = initCodeHash(implementation);
        predicted = predictDeterministicAddress(hash, salt, deployer);
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*          MINIMAL PROXY OPERATIONS (PUSH0 VARIANT)          */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Deploys a PUSH0 clone of `implementation`.
    function clone_PUSH0(address implementation) internal returns (address instance) {
        instance = clone_PUSH0(0, implementation);
    }

    /// @dev Deploys a PUSH0 clone of `implementation`.
    /// Deposits `value` ETH during deployment.
    function clone_PUSH0(uint256 value, address implementation)
        internal
        returns (address instance)
    {
        /// @solidity memory-safe-assembly
        assembly {
            /**
             * --------------------------------------------------------------------------+
             * CREATION (9 bytes)                                                        |
             * --------------------------------------------------------------------------|
             * Opcode     | Mnemonic          | Stack     | Memory                       |
             * --------------------------------------------------------------------------|
             * 60 runSize | PUSH1 runSize     | r         |                              |
             * 5f         | PUSH0             | 0 r       |                              |
             * 81         | DUP2              | r 0 r     |                              |
             * 60 offset  | PUSH1 offset      | o r 0 r   |                              |
             * 5f         | PUSH0             | 0 o r 0 r |                              |
             * 39         | CODECOPY          | 0 r       | [0..runSize): runtime code   |
             * f3         | RETURN            |           | [0..runSize): runtime code   |
             * --------------------------------------------------------------------------|
             * RUNTIME (45 bytes)                                                        |
             * --------------------------------------------------------------------------|
             * Opcode  | Mnemonic       | Stack                  | Memory                |
             * --------------------------------------------------------------------------|
             *                                                                           |
             * ::: keep some values in stack ::::::::::::::::::::::::::::::::::::::::::: |
             * 5f      | PUSH0          | 0                      |                       |
             * 5f      | PUSH0          | 0 0                    |                       |
             *                                                                           |
             * ::: copy calldata to memory ::::::::::::::::::::::::::::::::::::::::::::: |
             * 36      | CALLDATASIZE   | cds 0 0                |                       |
             * 5f      | PUSH0          | 0 cds 0 0              |                       |
             * 5f      | PUSH0          | 0 0 cds 0 0            |                       |
             * 37      | CALLDATACOPY   | 0 0                    | [0..cds): calldata    |
             *                                                                           |
             * ::: delegate call to the implementation contract :::::::::::::::::::::::: |
             * 36      | CALLDATASIZE   | cds 0 0                | [0..cds): calldata    |
             * 5f      | PUSH0          | 0 cds 0 0              | [0..cds): calldata    |
             * 73 addr | PUSH20 addr    | addr 0 cds 0 0         | [0..cds): calldata    |
             * 5a      | GAS            | gas addr 0 cds 0 0     | [0..cds): calldata    |
             * f4      | DELEGATECALL   | success                | [0..cds): calldata    |
             *                                                                           |
             * ::: copy return data to memory :::::::::::::::::::::::::::::::::::::::::: |
             * 3d      | RETURNDATASIZE | rds success            | [0..cds): calldata    |
             * 5f      | PUSH0          | 0 rds success          | [0..cds): calldata    |
             * 5f      | PUSH0          | 0 0 rds success        | [0..cds): calldata    |
             * 3e      | RETURNDATACOPY | success                | [0..rds): returndata  |
             *                                                                           |
             * 60 0x29 | PUSH1 0x29     | 0x29 success           | [0..rds): returndata  |
             * 57      | JUMPI          |                        | [0..rds): returndata  |
             *                                                                           |
             * ::: revert :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |
             * 3d      | RETURNDATASIZE | rds                    | [0..rds): returndata  |
             * 5f      | PUSH0          | 0 rds                  | [0..rds): returndata  |
             * fd      | REVERT         |                        | [0..rds): returndata  |
             *                                                                           |
             * ::: return :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |
             * 5b      | JUMPDEST       |                        | [0..rds): returndata  |
             * 3d      | RETURNDATASIZE | rds                    | [0..rds): returndata  |
             * 5f      | PUSH0          | 0 rds                  | [0..rds): returndata  |
             * f3      | RETURN         |                        | [0..rds): returndata  |
             * --------------------------------------------------------------------------+
             */
            mstore(0x24, 0x5af43d5f5f3e6029573d5ffd5b3d5ff3) // 16
            mstore(0x14, implementation) // 20
            mstore(0x00, 0x602d5f8160095f39f35f5f365f5f37365f73) // 9 + 9
            instance := create(value, 0x0e, 0x36)
            if iszero(instance) {
                mstore(0x00, 0x30116425) // `DeploymentFailed()`.
                revert(0x1c, 0x04)
            }
            mstore(0x24, 0) // Restore the overwritten part of the free memory pointer.
        }
    }

    /// @dev Deploys a deterministic PUSH0 clone of `implementation` with `salt`.
    function cloneDeterministic_PUSH0(address implementation, bytes32 salt)
        internal
        returns (address instance)
    {
        instance = cloneDeterministic_PUSH0(0, implementation, salt);
    }

    /// @dev Deploys a deterministic PUSH0 clone of `implementation` with `salt`.
    /// Deposits `value` ETH during deployment.
    function cloneDeterministic_PUSH0(uint256 value, address implementation, bytes32 salt)
        internal
        returns (address instance)
    {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x24, 0x5af43d5f5f3e6029573d5ffd5b3d5ff3) // 16
            mstore(0x14, implementation) // 20
            mstore(0x00, 0x602d5f8160095f39f35f5f365f5f37365f73) // 9 + 9
            instance := create2(value, 0x0e, 0x36, salt)
            if iszero(instance) {
                mstore(0x00, 0x30116425) // `DeploymentFailed()`.
                revert(0x1c, 0x04)
            }
            mstore(0x24, 0) // Restore the overwritten part of the free memory pointer.
        }
    }

    /// @dev Returns the initialization code of the PUSH0 clone of `implementation`.
    function initCode_PUSH0(address implementation) internal pure returns (bytes memory result) {
        /// @solidity memory-safe-assembly
        assembly {
            result := mload(0x40)
            mstore(add(result, 0x40), 0x5af43d5f5f3e6029573d5ffd5b3d5ff300000000000000000000) // 16
            mstore(add(result, 0x26), implementation) // 20
            mstore(add(result, 0x12), 0x602d5f8160095f39f35f5f365f5f37365f73) // 9 + 9
            mstore(result, 0x36) // Store the length.
            mstore(0x40, add(result, 0x60)) // Allocate memory.
        }
    }

    /// @dev Returns the initialization code hash of the PUSH0 clone of `implementation`.
    /// Used for mining vanity addresses with create2crunch.
    function initCodeHash_PUSH0(address implementation) internal pure returns (bytes32 hash) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x24, 0x5af43d5f5f3e6029573d5ffd5b3d5ff3) // 16
            mstore(0x14, implementation) // 20
            mstore(0x00, 0x602d5f8160095f39f35f5f365f5f37365f73) // 9 + 9
            hash := keccak256(0x0e, 0x36)
            mstore(0x24, 0) // Restore the overwritten part of the free memory pointer.
        }
    }

    /// @dev Returns the address of the deterministic PUSH0 clone of `implementation`,
    /// with `salt` by `deployer`.
    /// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.
    function predictDeterministicAddress_PUSH0(
        address implementation,
        bytes32 salt,
        address deployer
    ) internal pure returns (address predicted) {
        bytes32 hash = initCodeHash_PUSH0(implementation);
        predicted = predictDeterministicAddress(hash, salt, deployer);
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*           CLONES WITH IMMUTABLE ARGS OPERATIONS            */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    // Note: This implementation of CWIA differs from the original implementation.
    // If the calldata is empty, it will emit a `ReceiveETH(uint256)` event and skip the `DELEGATECALL`.

    /// @dev Deploys a clone of `implementation` with immutable arguments encoded in `data`.
    function clone(address implementation, bytes memory data) internal returns (address instance) {
        instance = clone(0, implementation, data);
    }

    /// @dev Deploys a clone of `implementation` with immutable arguments encoded in `data`.
    /// Deposits `value` ETH during deployment.
    function clone(uint256 value, address implementation, bytes memory data)
        internal
        returns (address instance)
    {
        assembly {
            // Compute the boundaries of the data and cache the memory slots around it.
            let mBefore3 := mload(sub(data, 0x60))
            let mBefore2 := mload(sub(data, 0x40))
            let mBefore1 := mload(sub(data, 0x20))
            let dataLength := mload(data)
            let dataEnd := add(add(data, 0x20), dataLength)
            let mAfter1 := mload(dataEnd)

            // +2 bytes for telling how much data there is appended to the call.
            let extraLength := add(dataLength, 2)
            // The `creationSize` is `extraLength + 108`
            // The `runSize` is `creationSize - 10`.

            /**
             * ---------------------------------------------------------------------------------------------------+
             * CREATION (10 bytes)                                                                                |
             * ---------------------------------------------------------------------------------------------------|
             * Opcode     | Mnemonic          | Stack     | Memory                                                |
             * ---------------------------------------------------------------------------------------------------|
             * 61 runSize | PUSH2 runSize     | r         |                                                       |
             * 3d         | RETURNDATASIZE    | 0 r       |                                                       |
             * 81         | DUP2              | r 0 r     |                                                       |
             * 60 offset  | PUSH1 offset      | o r 0 r   |                                                       |
             * 3d         | RETURNDATASIZE    | 0 o r 0 r |                                                       |
             * 39         | CODECOPY          | 0 r       | [0..runSize): runtime code                            |
             * f3         | RETURN            |           | [0..runSize): runtime code                            |
             * ---------------------------------------------------------------------------------------------------|
             * RUNTIME (98 bytes + extraLength)                                                                   |
             * ---------------------------------------------------------------------------------------------------|
             * Opcode   | Mnemonic       | Stack                    | Memory                                      |
             * ---------------------------------------------------------------------------------------------------|
             *                                                                                                    |
             * ::: if no calldata, emit event & return w/o `DELEGATECALL` ::::::::::::::::::::::::::::::::::::::: |
             * 36       | CALLDATASIZE   | cds                      |                                             |
             * 60 0x2c  | PUSH1 0x2c     | 0x2c cds                 |                                             |
             * 57       | JUMPI          |                          |                                             |
             * 34       | CALLVALUE      | cv                       |                                             |
             * 3d       | RETURNDATASIZE | 0 cv                     |                                             |
             * 52       | MSTORE         |                          | [0..0x20): callvalue                        |
             * 7f sig   | PUSH32 0x9e..  | sig                      | [0..0x20): callvalue                        |
             * 59       | MSIZE          | 0x20 sig                 | [0..0x20): callvalue                        |
             * 3d       | RETURNDATASIZE | 0 0x20 sig               | [0..0x20): callvalue                        |
             * a1       | LOG1           |                          | [0..0x20): callvalue                        |
             * 00       | STOP           |                          | [0..0x20): callvalue                        |
             * 5b       | JUMPDEST       |                          |                                             |
             *                                                                                                    |
             * ::: copy calldata to memory :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |
             * 36       | CALLDATASIZE   | cds                      |                                             |
             * 3d       | RETURNDATASIZE | 0 cds                    |                                             |
             * 3d       | RETURNDATASIZE | 0 0 cds                  |                                             |
             * 37       | CALLDATACOPY   |                          | [0..cds): calldata                          |
             *                                                                                                    |
             * ::: keep some values in stack :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |
             * 3d       | RETURNDATASIZE | 0                        | [0..cds): calldata                          |
             * 3d       | RETURNDATASIZE | 0 0                      | [0..cds): calldata                          |
             * 3d       | RETURNDATASIZE | 0 0 0                    | [0..cds): calldata                          |
             * 3d       | RETURNDATASIZE | 0 0 0 0                  | [0..cds): calldata                          |
             * 61 extra | PUSH2 extra    | e 0 0 0 0                | [0..cds): calldata                          |
             *                                                                                                    |
             * ::: copy extra data to memory :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |
             * 80       | DUP1           | e e 0 0 0 0              | [0..cds): calldata                          |
             * 60 0x62  | PUSH1 0x62     | 0x62 e e 0 0 0 0         | [0..cds): calldata                          |
             * 36       | CALLDATASIZE   | cds 0x62 e e 0 0 0 0     | [0..cds): calldata                          |
             * 39       | CODECOPY       | e 0 0 0 0                | [0..cds): calldata, [cds..cds+e): extraData |
             *                                                                                                    |
             * ::: delegate call to the implementation contract ::::::::::::::::::::::::::::::::::::::::::::::::: |
             * 36       | CALLDATASIZE   | cds e 0 0 0 0            | [0..cds): calldata, [cds..cds+e): extraData |
             * 01       | ADD            | cds+e 0 0 0 0            | [0..cds): calldata, [cds..cds+e): extraData |
             * 3d       | RETURNDATASIZE | 0 cds+e 0 0 0 0          | [0..cds): calldata, [cds..cds+e): extraData |
             * 73 addr  | PUSH20 addr    | addr 0 cds+e 0 0 0 0     | [0..cds): calldata, [cds..cds+e): extraData |
             * 5a       | GAS            | gas addr 0 cds+e 0 0 0 0 | [0..cds): calldata, [cds..cds+e): extraData |
             * f4       | DELEGATECALL   | success 0 0              | [0..cds): calldata, [cds..cds+e): extraData |
             *                                                                                                    |
             * ::: copy return data to memory ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |
             * 3d       | RETURNDATASIZE | rds success 0 0          | [0..cds): calldata, [cds..cds+e): extraData |
             * 3d       | RETURNDATASIZE | rds rds success 0 0      | [0..cds): calldata, [cds..cds+e): extraData |
             * 93       | SWAP4          | 0 rds success 0 rds      | [0..cds): calldata, [cds..cds+e): extraData |
             * 80       | DUP1           | 0 0 rds success 0 rds    | [0..cds): calldata, [cds..cds+e): extraData |
             * 3e       | RETURNDATACOPY | success 0 rds            | [0..rds): returndata                        |
             *                                                                                                    |
             * 60 0x60  | PUSH1 0x60     | 0x60 success 0 rds       | [0..rds): returndata                        |
             * 57       | JUMPI          | 0 rds                    | [0..rds): returndata                        |
             *                                                                                                    |
             * ::: revert ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |
             * fd       | REVERT         |                          | [0..rds): returndata                        |
             *                                                                                                    |
             * ::: return ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |
             * 5b       | JUMPDEST       | 0 rds                    | [0..rds): returndata                        |
             * f3       | RETURN         |                          | [0..rds): returndata                        |
             * ---------------------------------------------------------------------------------------------------+
             */
            mstore(data, 0x5af43d3d93803e606057fd5bf3) // Write the bytecode before the data.
            mstore(sub(data, 0x0d), implementation) // Write the address of the implementation.
            // Write the rest of the bytecode.
            mstore(
                sub(data, 0x21),
                or(shl(0x48, extraLength), 0x593da1005b363d3d373d3d3d3d610000806062363936013d73)
            )
            // `keccak256("ReceiveETH(uint256)")`
            mstore(
                sub(data, 0x3a), 0x9e4ac34f21c619cefc926c8bd93b54bf5a39c7ab2127a895af1cc0691d7e3dff
            )
            mstore(
                // Do a out-of-gas revert if `extraLength` is too big. 0xffff - 0x62 + 0x01 = 0xff9e.
                // The actual EVM limit may be smaller and may change over time.
                sub(data, add(0x59, lt(extraLength, 0xff9e))),
                or(shl(0x78, add(extraLength, 0x62)), 0xfd6100003d81600a3d39f336602c57343d527f)
            )
            mstore(dataEnd, shl(0xf0, extraLength))

            instance := create(value, sub(data, 0x4c), add(extraLength, 0x6c))
            if iszero(instance) {
                mstore(0x00, 0x30116425) // `DeploymentFailed()`.
                revert(0x1c, 0x04)
            }

            // Restore the overwritten memory surrounding `data`.
            mstore(dataEnd, mAfter1)
            mstore(data, dataLength)
            mstore(sub(data, 0x20), mBefore1)
            mstore(sub(data, 0x40), mBefore2)
            mstore(sub(data, 0x60), mBefore3)
        }
    }

    /// @dev Deploys a deterministic clone of `implementation`
    /// with immutable arguments encoded in `data` and `salt`.
    function cloneDeterministic(address implementation, bytes memory data, bytes32 salt)
        internal
        returns (address instance)
    {
        instance = cloneDeterministic(0, implementation, data, salt);
    }

    /// @dev Deploys a deterministic clone of `implementation`
    /// with immutable arguments encoded in `data` and `salt`.
    function cloneDeterministic(
        uint256 value,
        address implementation,
        bytes memory data,
        bytes32 salt
    ) internal returns (address instance) {
        assembly {
            // Compute the boundaries of the data and cache the memory slots around it.
            let mBefore3 := mload(sub(data, 0x60))
            let mBefore2 := mload(sub(data, 0x40))
            let mBefore1 := mload(sub(data, 0x20))
            let dataLength := mload(data)
            let dataEnd := add(add(data, 0x20), dataLength)
            let mAfter1 := mload(dataEnd)

            // +2 bytes for telling how much data there is appended to the call.
            let extraLength := add(dataLength, 2)

            mstore(data, 0x5af43d3d93803e606057fd5bf3) // Write the bytecode before the data.
            mstore(sub(data, 0x0d), implementation) // Write the address of the implementation.
            // Write the rest of the bytecode.
            mstore(
                sub(data, 0x21),
                or(shl(0x48, extraLength), 0x593da1005b363d3d373d3d3d3d610000806062363936013d73)
            )
            // `keccak256("ReceiveETH(uint256)")`
            mstore(
                sub(data, 0x3a), 0x9e4ac34f21c619cefc926c8bd93b54bf5a39c7ab2127a895af1cc0691d7e3dff
            )
            mstore(
                // Do a out-of-gas revert if `extraLength` is too big. 0xffff - 0x62 + 0x01 = 0xff9e.
                // The actual EVM limit may be smaller and may change over time.
                sub(data, add(0x59, lt(extraLength, 0xff9e))),
                or(shl(0x78, add(extraLength, 0x62)), 0xfd6100003d81600a3d39f336602c57343d527f)
            )
            mstore(dataEnd, shl(0xf0, extraLength))

            instance := create2(value, sub(data, 0x4c), add(extraLength, 0x6c), salt)
            if iszero(instance) {
                mstore(0x00, 0x30116425) // `DeploymentFailed()`.
                revert(0x1c, 0x04)
            }

            // Restore the overwritten memory surrounding `data`.
            mstore(dataEnd, mAfter1)
            mstore(data, dataLength)
            mstore(sub(data, 0x20), mBefore1)
            mstore(sub(data, 0x40), mBefore2)
            mstore(sub(data, 0x60), mBefore3)
        }
    }

    /// @dev Returns the initialization code hash of the clone of `implementation`
    /// using immutable arguments encoded in `data`.
    function initCode(address implementation, bytes memory data)
        internal
        pure
        returns (bytes memory result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            result := mload(0x40)
            let dataLength := mload(data)

            // Do a out-of-gas revert if `dataLength` is too big. 0xffff - 0x02 - 0x62 = 0xff9b.
            // The actual EVM limit may be smaller and may change over time.
            returndatacopy(returndatasize(), returndatasize(), gt(dataLength, 0xff9b))

            let o := add(result, 0x8c)
            let end := add(o, dataLength)

            // Copy the `data` into `result`.
            for { let d := sub(add(data, 0x20), o) } 1 {} {
                mstore(o, mload(add(o, d)))
                o := add(o, 0x20)
                if iszero(lt(o, end)) { break }
            }

            // +2 bytes for telling how much data there is appended to the call.
            let extraLength := add(dataLength, 2)

            mstore(add(result, 0x6c), 0x5af43d3d93803e606057fd5bf3) // Write the bytecode before the data.
            mstore(add(result, 0x5f), implementation) // Write the address of the implementation.
            // Write the rest of the bytecode.
            mstore(
                add(result, 0x4b),
                or(shl(0x48, extraLength), 0x593da1005b363d3d373d3d3d3d610000806062363936013d73)
            )
            // `keccak256("ReceiveETH(uint256)")`
            mstore(
                add(result, 0x32),
                0x9e4ac34f21c619cefc926c8bd93b54bf5a39c7ab2127a895af1cc0691d7e3dff
            )
            mstore(
                add(result, 0x12),
                or(shl(0x78, add(extraLength, 0x62)), 0x6100003d81600a3d39f336602c57343d527f)
            )
            mstore(end, shl(0xf0, extraLength))
            mstore(add(end, 0x02), 0) // Zeroize the slot after the result.
            mstore(result, add(extraLength, 0x6c)) // Store the length.
            mstore(0x40, add(0x22, end)) // Allocate memory.
        }
    }

    /// @dev Returns the initialization code hash of the clone of `implementation`
    /// using immutable arguments encoded in `data`.
    /// Used for mining vanity addresses with create2crunch.
    function initCodeHash(address implementation, bytes memory data)
        internal
        pure
        returns (bytes32 hash)
    {
        assembly {
            // Compute the boundaries of the data and cache the memory slots around it.
            let mBefore3 := mload(sub(data, 0x60))
            let mBefore2 := mload(sub(data, 0x40))
            let mBefore1 := mload(sub(data, 0x20))
            let dataLength := mload(data)
            let dataEnd := add(add(data, 0x20), dataLength)
            let mAfter1 := mload(dataEnd)

            // Do a out-of-gas revert if `dataLength` is too big. 0xffff - 0x02 - 0x62 = 0xff9b.
            // The actual EVM limit may be smaller and may change over time.
            returndatacopy(returndatasize(), returndatasize(), gt(dataLength, 0xff9b))

            // +2 bytes for telling how much data there is appended to the call.
            let extraLength := add(dataLength, 2)

            mstore(data, 0x5af43d3d93803e606057fd5bf3) // Write the bytecode before the data.
            mstore(sub(data, 0x0d), implementation) // Write the address of the implementation.
            // Write the rest of the bytecode.
            mstore(
                sub(data, 0x21),
                or(shl(0x48, extraLength), 0x593da1005b363d3d373d3d3d3d610000806062363936013d73)
            )
            // `keccak256("ReceiveETH(uint256)")`
            mstore(
                sub(data, 0x3a), 0x9e4ac34f21c619cefc926c8bd93b54bf5a39c7ab2127a895af1cc0691d7e3dff
            )
            mstore(
                sub(data, 0x5a),
                or(shl(0x78, add(extraLength, 0x62)), 0x6100003d81600a3d39f336602c57343d527f)
            )
            mstore(dataEnd, shl(0xf0, extraLength))

            hash := keccak256(sub(data, 0x4c), add(extraLength, 0x6c))

            // Restore the overwritten memory surrounding `data`.
            mstore(dataEnd, mAfter1)
            mstore(data, dataLength)
            mstore(sub(data, 0x20), mBefore1)
            mstore(sub(data, 0x40), mBefore2)
            mstore(sub(data, 0x60), mBefore3)
        }
    }

    /// @dev Returns the address of the deterministic clone of
    /// `implementation` using immutable arguments encoded in `data`, with `salt`, by `deployer`.
    /// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.
    function predictDeterministicAddress(
        address implementation,
        bytes memory data,
        bytes32 salt,
        address deployer
    ) internal pure returns (address predicted) {
        bytes32 hash = initCodeHash(implementation, data);
        predicted = predictDeterministicAddress(hash, salt, deployer);
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*              MINIMAL ERC1967 PROXY OPERATIONS              */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    // Note: The ERC1967 proxy here is intended to be upgraded with UUPS.
    // This is NOT the same as ERC1967Factory's transparent proxy, which includes admin logic.

    /// @dev Deploys a minimal ERC1967 proxy with `implementation`.
    function deployERC1967(address implementation) internal returns (address instance) {
        instance = deployERC1967(0, implementation);
    }

    /// @dev Deploys a minimal ERC1967 proxy with `implementation`.
    /// Deposits `value` ETH during deployment.
    function deployERC1967(uint256 value, address implementation)
        internal
        returns (address instance)
    {
        /// @solidity memory-safe-assembly
        assembly {
            /**
             * ---------------------------------------------------------------------------------+
             * CREATION (34 bytes)                                                              |
             * ---------------------------------------------------------------------------------|
             * Opcode     | Mnemonic       | Stack            | Memory                          |
             * ---------------------------------------------------------------------------------|
             * 60 runSize | PUSH1 runSize  | r                |                                 |
             * 3d         | RETURNDATASIZE | 0 r              |                                 |
             * 81         | DUP2           | r 0 r            |                                 |
             * 60 offset  | PUSH1 offset   | o r 0 r          |                                 |
             * 3d         | RETURNDATASIZE | 0 o r 0 r        |                                 |
             * 39         | CODECOPY       | 0 r              | [0..runSize): runtime code      |
             * 73 impl    | PUSH20 impl    | impl 0 r         | [0..runSize): runtime code      |
             * 60 slotPos | PUSH1 slotPos  | slotPos impl 0 r | [0..runSize): runtime code      |
             * 51         | MLOAD          | slot impl 0 r    | [0..runSize): runtime code      |
             * 55         | SSTORE         | 0 r              | [0..runSize): runtime code      |
             * f3         | RETURN         |                  | [0..runSize): runtime code      |
             * ---------------------------------------------------------------------------------|
             * RUNTIME (61 bytes)                                                               |
             * ---------------------------------------------------------------------------------|
             * Opcode     | Mnemonic       | Stack            | Memory                          |
             * ---------------------------------------------------------------------------------|
             *                                                                                  |
             * ::: copy calldata to memory :::::::::::::::::::::::::::::::::::::::::::::::::::: |
             * 36         | CALLDATASIZE   | cds              |                                 |
             * 3d         | RETURNDATASIZE | 0 cds            |                                 |
             * 3d         | RETURNDATASIZE | 0 0 cds          |                                 |
             * 37         | CALLDATACOPY   |                  | [0..calldatasize): calldata     |
             *                                                                                  |
             * ::: delegatecall to implementation ::::::::::::::::::::::::::::::::::::::::::::: |
             * 3d         | RETURNDATASIZE | 0                |                                 |
             * 3d         | RETURNDATASIZE | 0 0              |                                 |
             * 36         | CALLDATASIZE   | cds 0 0          | [0..calldatasize): calldata     |
             * 3d         | RETURNDATASIZE | 0 cds 0 0        | [0..calldatasize): calldata     |
             * 7f slot    | PUSH32 slot    | s 0 cds 0 0      | [0..calldatasize): calldata     |
             * 54         | SLOAD          | i 0 cds 0 0      | [0..calldatasize): calldata     |
             * 5a         | GAS            | g i 0 cds 0 0    | [0..calldatasize): calldata     |
             * f4         | DELEGATECALL   | succ             | [0..calldatasize): calldata     |
             *                                                                                  |
             * ::: copy returndata to memory :::::::::::::::::::::::::::::::::::::::::::::::::: |
             * 3d         | RETURNDATASIZE | rds succ         | [0..calldatasize): calldata     |
             * 60 0x00    | PUSH1 0x00     | 0 rds succ       | [0..calldatasize): calldata     |
             * 80         | DUP1           | 0 0 rds succ     | [0..calldatasize): calldata     |
             * 3e         | RETURNDATACOPY | succ             | [0..returndatasize): returndata |
             *                                                                                  |
             * ::: branch on delegatecall status :::::::::::::::::::::::::::::::::::::::::::::: |
             * 60 0x38    | PUSH1 0x38     | dest succ        | [0..returndatasize): returndata |
             * 57         | JUMPI          |                  | [0..returndatasize): returndata |
             *                                                                                  |
             * ::: delegatecall failed, revert :::::::::::::::::::::::::::::::::::::::::::::::: |
             * 3d         | RETURNDATASIZE | rds              | [0..returndatasize): returndata |
             * 60 0x00    | PUSH1 0x00     | 0 rds            | [0..returndatasize): returndata |
             * fd         | REVERT         |                  | [0..returndatasize): returndata |
             *                                                                                  |
             * ::: delegatecall succeeded, return ::::::::::::::::::::::::::::::::::::::::::::: |
             * 5b         | JUMPDEST       |                  | [0..returndatasize): returndata |
             * 3d         | RETURNDATASIZE | rds              | [0..returndatasize): returndata |
             * 60 0x00    | PUSH1 0x00     | 0 rds            | [0..returndatasize): returndata |
             * f3         | RETURN         |                  | [0..returndatasize): returndata |
             * ---------------------------------------------------------------------------------+
             */
            let m := mload(0x40) // Cache the free memory pointer.
            mstore(0x60, 0xcc3735a920a3ca505d382bbc545af43d6000803e6038573d6000fd5b3d6000f3)
            mstore(0x40, 0x5155f3363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e2076)
            mstore(0x20, 0x6009)
            mstore(0x1e, implementation)
            mstore(0x0a, 0x603d3d8160223d3973)
            instance := create(value, 0x21, 0x5f)
            if iszero(instance) {
                mstore(0x00, 0x30116425) // `DeploymentFailed()`.
                revert(0x1c, 0x04)
            }
            mstore(0x40, m) // Restore the free memory pointer.
            mstore(0x60, 0) // Restore the zero slot.
        }
    }

    /// @dev Deploys a deterministic minimal ERC1967 proxy with `implementation` and `salt`.
    function deployDeterministicERC1967(address implementation, bytes32 salt)
        internal
        returns (address instance)
    {
        instance = deployDeterministicERC1967(0, implementation, salt);
    }

    /// @dev Deploys a deterministic minimal ERC1967 proxy with `implementation` and `salt`.
    /// Deposits `value` ETH during deployment.
    function deployDeterministicERC1967(uint256 value, address implementation, bytes32 salt)
        internal
        returns (address instance)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40) // Cache the free memory pointer.
            mstore(0x60, 0xcc3735a920a3ca505d382bbc545af43d6000803e6038573d6000fd5b3d6000f3)
            mstore(0x40, 0x5155f3363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e2076)
            mstore(0x20, 0x6009)
            mstore(0x1e, implementation)
            mstore(0x0a, 0x603d3d8160223d3973)
            instance := create2(value, 0x21, 0x5f, salt)
            if iszero(instance) {
                mstore(0x00, 0x30116425) // `DeploymentFailed()`.
                revert(0x1c, 0x04)
            }
            mstore(0x40, m) // Restore the free memory pointer.
            mstore(0x60, 0) // Restore the zero slot.
        }
    }

    /// @dev Creates a deterministic minimal ERC1967 proxy with `implementation` and `salt`.
    /// Note: This method is intended for use in ERC4337 factories,
    /// which are expected to NOT revert if the proxy is already deployed.
    function createDeterministicERC1967(address implementation, bytes32 salt)
        internal
        returns (bool alreadyDeployed, address instance)
    {
        return createDeterministicERC1967(0, implementation, salt);
    }

    /// @dev Creates a deterministic minimal ERC1967 proxy with `implementation` and `salt`.
    /// Deposits `value` ETH during deployment.
    /// Note: This method is intended for use in ERC4337 factories,
    /// which are expected to NOT revert if the proxy is already deployed.
    function createDeterministicERC1967(uint256 value, address implementation, bytes32 salt)
        internal
        returns (bool alreadyDeployed, address instance)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40) // Cache the free memory pointer.
            mstore(0x60, 0xcc3735a920a3ca505d382bbc545af43d6000803e6038573d6000fd5b3d6000f3)
            mstore(0x40, 0x5155f3363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e2076)
            mstore(0x20, 0x6009)
            mstore(0x1e, implementation)
            mstore(0x0a, 0x603d3d8160223d3973)
            // Compute and store the bytecode hash.
            mstore(add(m, 0x35), keccak256(0x21, 0x5f))
            mstore(m, shl(88, address()))
            mstore8(m, 0xff) // Write the prefix.
            mstore(add(m, 0x15), salt)
            instance := keccak256(m, 0x55)
            for {} 1 {} {
                if iszero(extcodesize(instance)) {
                    instance := create2(value, 0x21, 0x5f, salt)
                    if iszero(instance) {
                        mstore(0x00, 0x30116425) // `DeploymentFailed()`.
                        revert(0x1c, 0x04)
                    }
                    break
                }
                alreadyDeployed := 1
                if iszero(value) { break }
                if iszero(call(gas(), instance, value, codesize(), 0x00, codesize(), 0x00)) {
                    mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.
                    revert(0x1c, 0x04)
                }
                break
            }
            mstore(0x40, m) // Restore the free memory pointer.
            mstore(0x60, 0) // Restore the zero slot.
        }
    }

    /// @dev Returns the initialization code of the minimal ERC1967 proxy of `implementation`.
    function initCodeERC1967(address implementation) internal pure returns (bytes memory result) {
        /// @solidity memory-safe-assembly
        assembly {
            result := mload(0x40)
            mstore(
                add(result, 0x60),
                0x3735a920a3ca505d382bbc545af43d6000803e6038573d6000fd5b3d6000f300
            )
            mstore(
                add(result, 0x40),
                0x55f3363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e2076cc
            )
            mstore(add(result, 0x20), or(shl(24, implementation), 0x600951))
            mstore(add(result, 0x09), 0x603d3d8160223d3973)
            mstore(result, 0x5f) // Store the length.
            mstore(0x40, add(result, 0x80)) // Allocate memory.
        }
    }

    /// @dev Returns the initialization code hash of the minimal ERC1967 proxy of `implementation`.
    /// Used for mining vanity addresses with create2crunch.
    function initCodeHashERC1967(address implementation) internal pure returns (bytes32 hash) {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40) // Cache the free memory pointer.
            mstore(0x60, 0xcc3735a920a3ca505d382bbc545af43d6000803e6038573d6000fd5b3d6000f3)
            mstore(0x40, 0x5155f3363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e2076)
            mstore(0x20, 0x6009)
            mstore(0x1e, implementation)
            mstore(0x0a, 0x603d3d8160223d3973)
            hash := keccak256(0x21, 0x5f)
            mstore(0x40, m) // Restore the free memory pointer.
            mstore(0x60, 0) // Restore the zero slot.
        }
    }

    /// @dev Returns the address of the deterministic ERC1967 proxy of `implementation`,
    /// with `salt` by `deployer`.
    /// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.
    function predictDeterministicAddressERC1967(
        address implementation,
        bytes32 salt,
        address deployer
    ) internal pure returns (address predicted) {
        bytes32 hash = initCodeHashERC1967(implementation);
        predicted = predictDeterministicAddress(hash, salt, deployer);
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                 ERC1967I PROXY OPERATIONS                  */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    // Note: This proxy has a special code path that activates if `calldatasize() == 1`.
    // This code path skips the delegatecall and directly returns the `implementation` address.
    // The returned implementation is guaranteed to be valid if the keccak256 of the
    // proxy's code is equal to `ERC1967I_CODE_HASH`.

    /// @dev Deploys a minimal ERC1967I proxy with `implementation`.
    function deployERC1967I(address implementation) internal returns (address instance) {
        instance = deployERC1967I(0, implementation);
    }

    /// @dev Deploys a ERC1967I proxy with `implementation`.
    /// Deposits `value` ETH during deployment.
    function deployERC1967I(uint256 value, address implementation)
        internal
        returns (address instance)
    {
        /// @solidity memory-safe-assembly
        assembly {
            /**
             * ---------------------------------------------------------------------------------+
             * CREATION (34 bytes)                                                              |
             * ---------------------------------------------------------------------------------|
             * Opcode     | Mnemonic       | Stack            | Memory                          |
             * ---------------------------------------------------------------------------------|
             * 60 runSize | PUSH1 runSize  | r                |                                 |
             * 3d         | RETURNDATASIZE | 0 r              |                                 |
             * 81         | DUP2           | r 0 r            |                                 |
             * 60 offset  | PUSH1 offset   | o r 0 r          |                                 |
             * 3d         | RETURNDATASIZE | 0 o r 0 r        |                                 |
             * 39         | CODECOPY       | 0 r              | [0..runSize): runtime code      |
             * 73 impl    | PUSH20 impl    | impl 0 r         | [0..runSize): runtime code      |
             * 60 slotPos | PUSH1 slotPos  | slotPos impl 0 r | [0..runSize): runtime code      |
             * 51         | MLOAD          | slot impl 0 r    | [0..runSize): runtime code      |
             * 55         | SSTORE         | 0 r              | [0..runSize): runtime code      |
             * f3         | RETURN         |                  | [0..runSize): runtime code      |
             * ---------------------------------------------------------------------------------|
             * RUNTIME (82 bytes)                                                               |
             * ---------------------------------------------------------------------------------|
             * Opcode     | Mnemonic       | Stack            | Memory                          |
             * ---------------------------------------------------------------------------------|
             *                                                                                  |
             * ::: check calldatasize ::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |
             * 36         | CALLDATASIZE   | cds              |                                 |
             * 58         | PC             | 1 cds            |                                 |
             * 14         | EQ             | eqs              |                                 |
             * 60 0x43    | PUSH1 0x43     | dest eqs         |                                 |
             * 57         | JUMPI          |                  |                                 |
             *                                                                                  |
             * ::: copy calldata to memory :::::::::::::::::::::::::::::::::::::::::::::::::::: |
             * 36         | CALLDATASIZE   | cds              |                                 |
             * 3d         | RETURNDATASIZE | 0 cds            |                                 |
             * 3d         | RETURNDATASIZE | 0 0 cds          |                                 |
             * 37         | CALLDATACOPY   |                  | [0..calldatasize): calldata     |
             *                                                                                  |
             * ::: delegatecall to implementation ::::::::::::::::::::::::::::::::::::::::::::: |
             * 3d         | RETURNDATASIZE | 0                |                                 |
             * 3d         | RETURNDATASIZE | 0 0              |                                 |
             * 36         | CALLDATASIZE   | cds 0 0          | [0..calldatasize): calldata     |
             * 3d         | RETURNDATASIZE | 0 cds 0 0        | [0..calldatasize): calldata     |
             * 7f slot    | PUSH32 slot    | s 0 cds 0 0      | [0..calldatasize): calldata     |
             * 54         | SLOAD          | i 0 cds 0 0      | [0..calldatasize): calldata     |
             * 5a         | GAS            | g i 0 cds 0 0    | [0..calldatasize): calldata     |
             * f4         | DELEGATECALL   | succ             | [0..calldatasize): calldata     |
             *                                                                                  |
             * ::: copy returndata to memory :::::::::::::::::::::::::::::::::::::::::::::::::: |
             * 3d         | RETURNDATASIZE | rds succ         | [0..calldatasize): calldata     |
             * 60 0x00    | PUSH1 0x00     | 0 rds succ       | [0..calldatasize): calldata     |
             * 80         | DUP1           | 0 0 rds succ     | [0..calldatasize): calldata     |
             * 3e         | RETURNDATACOPY | succ             | [0..returndatasize): returndata |
             *                                                                                  |
             * ::: branch on delegatecall status :::::::::::::::::::::::::::::::::::::::::::::: |
             * 60 0x3E    | PUSH1 0x3E     | dest succ        | [0..returndatasize): returndata |
             * 57         | JUMPI          |                  | [0..returndatasize): returndata |
             *                                                                                  |
             * ::: delegatecall failed, revert :::::::::::::::::::::::::::::::::::::::::::::::: |
             * 3d         | RETURNDATASIZE | rds              | [0..returndatasize): returndata |
             * 60 0x00    | PUSH1 0x00     | 0 rds            | [0..returndatasize): returndata |
             * fd         | REVERT         |                  | [0..returndatasize): returndata |
             *                                                                                  |
             * ::: delegatecall succeeded, return ::::::::::::::::::::::::::::::::::::::::::::: |
             * 5b         | JUMPDEST       |                  | [0..returndatasize): returndata |
             * 3d         | RETURNDATASIZE | rds              | [0..returndatasize): returndata |
             * 60 0x00    | PUSH1 0x00     | 0 rds            | [0..returndatasize): returndata |
             * f3         | RETURN         |                  | [0..returndatasize): returndata |
             *                                                                                  |
             * ::: implementation , return :::::::::::::::::::::::::::::::::::::::::::::::::::: |
             * 5b         | JUMPDEST       |                  |                                 |
             * 60 0x20    | PUSH1 0x20     | 32               |                                 |
             * 60 0x0F    | PUSH1 0x0F     | o 32             |                                 |
             * 3d         | RETURNDATASIZE | 0 o 32           |                                 |
             * 39         | CODECOPY       |                  | [0..32): implementation slot    |
             * 3d         | RETURNDATASIZE | 0                | [0..32): implementation slot    |
             * 51         | MLOAD          | slot             | [0..32): implementation slot    |
             * 54         | SLOAD          | impl             | [0..32): implementation slot    |
             * 3d         | RETURNDATASIZE | 0 impl           | [0..32): implementation slot    |
             * 52         | MSTORE         |                  | [0..32): implementation address |
             * 59         | MSIZE          | 32               | [0..32): implementation address |
             * 3d         | RETURNDATASIZE | 0 32             | [0..32): implementation address |
             * f3         | RETURN         |                  | [0..32): implementation address |
             *                                                                                  |
             * ---------------------------------------------------------------------------------+
             */
            let m := mload(0x40) // Cache the free memory pointer.
            mstore(0x60, 0x3d6000803e603e573d6000fd5b3d6000f35b6020600f3d393d51543d52593df3)
            mstore(0x40, 0xa13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545af4)
            mstore(0x20, 0x600f5155f3365814604357363d3d373d3d363d7f360894)
            mstore(0x09, or(shl(160, 0x60523d8160223d3973), shr(96, shl(96, implementation))))
            instance := create(value, 0x0c, 0x74)
            if iszero(instance) {
                mstore(0x00, 0x30116425) // `DeploymentFailed()`.
                revert(0x1c, 0x04)
            }
            mstore(0x40, m) // Restore the free memory pointer.
            mstore(0x60, 0) // Restore the zero slot.
        }
    }

    /// @dev Deploys a deterministic ERC1967I proxy with `implementation` and `salt`.
    function deployDeterministicERC1967I(address implementation, bytes32 salt)
        internal
        returns (address instance)
    {
        instance = deployDeterministicERC1967I(0, implementation, salt);
    }

    /// @dev Deploys a deterministic ERC1967I proxy with `implementation` and `salt`.
    /// Deposits `value` ETH during deployment.
    function deployDeterministicERC1967I(uint256 value, address implementation, bytes32 salt)
        internal
        returns (address instance)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40) // Cache the free memory pointer.
            mstore(0x60, 0x3d6000803e603e573d6000fd5b3d6000f35b6020600f3d393d51543d52593df3)
            mstore(0x40, 0xa13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545af4)
            mstore(0x20, 0x600f5155f3365814604357363d3d373d3d363d7f360894)
            mstore(0x09, or(shl(160, 0x60523d8160223d3973), shr(96, shl(96, implementation))))
            instance := create2(value, 0x0c, 0x74, salt)
            if iszero(instance) {
                mstore(0x00, 0x30116425) // `DeploymentFailed()`.
                revert(0x1c, 0x04)
            }
            mstore(0x40, m) // Restore the free memory pointer.
            mstore(0x60, 0) // Restore the zero slot.
        }
    }

    /// @dev Creates a deterministic ERC1967I proxy with `implementation` and `salt`.
    /// Note: This method is intended for use in ERC4337 factories,
    /// which are expected to NOT revert if the proxy is already deployed.
    function createDeterministicERC1967I(address implementation, bytes32 salt)
        internal
        returns (bool alreadyDeployed, address instance)
    {
        return createDeterministicERC1967I(0, implementation, salt);
    }

    /// @dev Creates a deterministic ERC1967I proxy with `implementation` and `salt`.
    /// Deposits `value` ETH during deployment.
    /// Note: This method is intended for use in ERC4337 factories,
    /// which are expected to NOT revert if the proxy is already deployed.
    function createDeterministicERC1967I(uint256 value, address implementation, bytes32 salt)
        internal
        returns (bool alreadyDeployed, address instance)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40) // Cache the free memory pointer.
            mstore(0x60, 0x3d6000803e603e573d6000fd5b3d6000f35b6020600f3d393d51543d52593df3)
            mstore(0x40, 0xa13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545af4)
            mstore(0x20, 0x600f5155f3365814604357363d3d373d3d363d7f360894)
            mstore(0x09, or(shl(160, 0x60523d8160223d3973), shr(96, shl(96, implementation))))
            // Compute and store the bytecode hash.
            mstore(add(m, 0x35), keccak256(0x0c, 0x74))
            mstore(m, shl(88, address()))
            mstore8(m, 0xff) // Write the prefix.
            mstore(add(m, 0x15), salt)
            instance := keccak256(m, 0x55)
            for {} 1 {} {
                if iszero(extcodesize(instance)) {
                    instance := create2(value, 0x0c, 0x74, salt)
                    if iszero(instance) {
                        mstore(0x00, 0x30116425) // `DeploymentFailed()`.
                        revert(0x1c, 0x04)
                    }
                    break
                }
                alreadyDeployed := 1
                if iszero(value) { break }
                if iszero(call(gas(), instance, value, codesize(), 0x00, codesize(), 0x00)) {
                    mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.
                    revert(0x1c, 0x04)
                }
                break
            }
            mstore(0x40, m) // Restore the free memory pointer.
            mstore(0x60, 0) // Restore the zero slot.
        }
    }

    /// @dev Returns the initialization code of the minimal ERC1967 proxy of `implementation`.
    function initCodeERC1967I(address implementation) internal pure returns (bytes memory result) {
        /// @solidity memory-safe-assembly
        assembly {
            result := mload(0x40)
            mstore(
                add(result, 0x74),
                0x3d6000803e603e573d6000fd5b3d6000f35b6020600f3d393d51543d52593df3
            )
            mstore(
                add(result, 0x54),
                0xa13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545af4
            )
            mstore(add(result, 0x34), 0x600f5155f3365814604357363d3d373d3d363d7f360894)
            mstore(add(result, 0x1d), implementation)
            mstore(add(result, 0x09), 0x60523d8160223d3973)
            mstore(add(result, 0x94), 0)
            mstore(result, 0x74) // Store the length.
            mstore(0x40, add(result, 0xa0)) // Allocate memory.
        }
    }

    /// @dev Returns the initialization code hash of the minimal ERC1967 proxy of `implementation`.
    /// Used for mining vanity addresses with create2crunch.
    function initCodeHashERC1967I(address implementation) internal pure returns (bytes32 hash) {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40) // Cache the free memory pointer.
            mstore(0x60, 0x3d6000803e603e573d6000fd5b3d6000f35b6020600f3d393d51543d52593df3)
            mstore(0x40, 0xa13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545af4)
            mstore(0x20, 0x600f5155f3365814604357363d3d373d3d363d7f360894)
            mstore(0x09, or(shl(160, 0x60523d8160223d3973), shr(96, shl(96, implementation))))
            hash := keccak256(0x0c, 0x74)
            mstore(0x40, m) // Restore the free memory pointer.
            mstore(0x60, 0) // Restore the zero slot.
        }
    }

    /// @dev Returns the address of the deterministic ERC1967I proxy of `implementation`,
    /// with `salt` by `deployer`.
    /// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.
    function predictDeterministicAddressERC1967I(
        address implementation,
        bytes32 salt,
        address deployer
    ) internal pure returns (address predicted) {
        bytes32 hash = initCodeHashERC1967I(implementation);
        predicted = predictDeterministicAddress(hash, salt, deployer);
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*            CONSTANT ERC1967 BOOTSTRAP OPERATIONS           */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    // Note: This enables an ERC1967 proxy to be deployed at a deterministic address
    // independent of the implementation:
    // ```
    //     address bootstrap = LibClone.constantERC1967Bootstrap();
    //     address instance = LibClone.deployDeterministicERC1967(0, bootstrap, salt);
    //     LibClone.bootstrapConstantERC1967(bootstrap, implementation);
    // ```

    /// @dev Deploys the constant ERC1967 bootstrap if it has not been deployed.
    function constantERC1967Bootstrap() internal returns (address bootstrap) {
        bootstrap = constantERC1967BootstrapAddress();
        /// @solidity memory-safe-assembly
        assembly {
            if iszero(extcodesize(bootstrap)) {
                mstore(0x20, 0x0894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc55)
                mstore(0x00, 0x60258060093d393df358357f36)
                if iszero(create2(0, 0x13, 0x2e, 0)) {
                    mstore(0x00, 0x30116425) // `DeploymentFailed()`.
                    revert(0x1c, 0x04)
                }
            }
        }
    }

    /// @dev Returns the implementation address of the ERC1967 bootstrap for this contract.
    function constantERC1967BootstrapAddress() internal view returns (address bootstrap) {
        bytes32 hash = 0xfe1a42b9c571a6a8c083c94ac67b9cfd74e2582923426aa3b762e3431d717cd1;
        bootstrap = predictDeterministicAddress(hash, bytes32(0), address(this));
    }

    /// @dev Replaces the implementation at `instance`.
    function bootstrapERC1967(address instance, address implementation) internal {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, shr(96, shl(96, implementation)))
            if iszero(call(gas(), instance, 0, 0x00, 0x20, codesize(), 0x00)) {
                mstore(0x00, 0x30116425) // `DeploymentFailed()`.
                revert(0x1c, 0x04)
            }
        }
    }

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

    /// @dev Returns the address when a contract with initialization code hash,
    /// `hash`, is deployed with `salt`, by `deployer`.
    /// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.
    function predictDeterministicAddress(bytes32 hash, bytes32 salt, address deployer)
        internal
        pure
        returns (address predicted)
    {
        /// @solidity memory-safe-assembly
        assembly {
            // Compute and store the bytecode hash.
            mstore8(0x00, 0xff) // Write the prefix.
            mstore(0x35, hash)
            mstore(0x01, shl(96, deployer))
            mstore(0x15, salt)
            predicted := keccak256(0x00, 0x55)
            mstore(0x35, 0) // Restore the overwritten part of the free memory pointer.
        }
    }

    /// @dev Requires that `salt` starts with either the zero address or `by`.
    function checkStartsWith(bytes32 salt, address by) internal pure {
        /// @solidity memory-safe-assembly
        assembly {
            // If the salt does not start with the zero address or `by`.
            if iszero(or(iszero(shr(96, salt)), eq(shr(96, shl(96, by)), shr(96, salt)))) {
                mstore(0x00, 0x0c4549ef) // `SaltDoesNotStartWith()`.
                revert(0x1c, 0x04)
            }
        }
    }
}

File 14 of 21 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC20.sol)

pragma solidity ^0.8.20;

import {IERC20} from "../token/ERC20/IERC20.sol";

File 15 of 21 : IERC721.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC721.sol)

pragma solidity ^0.8.20;

import {IERC721} from "../token/ERC721/IERC721.sol";

File 16 of 21 : IERC1155.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC1155.sol)

pragma solidity ^0.8.20;

import {IERC1155} from "../token/ERC1155/IERC1155.sol";

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

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC-165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[ERC].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165 {
    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

File 18 of 21 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);

    /**
     * @dev Returns the value of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the value of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves a `value` amount of tokens from the caller's account to `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, uint256 value) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the
     * caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 value) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to` using the
     * allowance mechanism. `value` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address from, address to, uint256 value) external returns (bool);
}

File 19 of 21 : IERC721.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/IERC721.sol)

pragma solidity ^0.8.20;

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

/**
 * @dev Required interface of an ERC721 compliant contract.
 */
interface IERC721 is IERC165 {
    /**
     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.
     */
    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
     */
    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
     */
    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    /**
     * @dev Returns the number of tokens in ``owner``'s account.
     */
    function balanceOf(address owner) external view returns (uint256 balance);

    /**
     * @dev Returns the owner of the `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function ownerOf(uint256 tokenId) external view returns (address owner);

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon
     *   a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
     * are aware of the ERC721 protocol to prevent tokens from being forever locked.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or
     *   {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon
     *   a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(address from, address to, uint256 tokenId) external;

    /**
     * @dev Transfers `tokenId` token from `from` to `to`.
     *
     * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721
     * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must
     * understand this adds an external call which potentially creates a reentrancy vulnerability.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address from, address to, uint256 tokenId) external;

    /**
     * @dev Gives permission to `to` to transfer `tokenId` token to another account.
     * The approval is cleared when the token is transferred.
     *
     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.
     *
     * Requirements:
     *
     * - The caller must own the token or be an approved operator.
     * - `tokenId` must exist.
     *
     * Emits an {Approval} event.
     */
    function approve(address to, uint256 tokenId) external;

    /**
     * @dev Approve or remove `operator` as an operator for the caller.
     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
     *
     * Requirements:
     *
     * - The `operator` cannot be the address zero.
     *
     * Emits an {ApprovalForAll} event.
     */
    function setApprovalForAll(address operator, bool approved) external;

    /**
     * @dev Returns the account approved for `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function getApproved(uint256 tokenId) external view returns (address operator);

    /**
     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
     *
     * See {setApprovalForAll}
     */
    function isApprovedForAll(address owner, address operator) external view returns (bool);
}

File 20 of 21 : IERC1155.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (token/ERC1155/IERC1155.sol)

pragma solidity ^0.8.20;

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

/**
 * @dev Required interface of an ERC1155 compliant contract, as defined in the
 * https://eips.ethereum.org/EIPS/eip-1155[EIP].
 */
interface IERC1155 is IERC165 {
    /**
     * @dev Emitted when `value` amount of tokens of type `id` are transferred from `from` to `to` by `operator`.
     */
    event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);

    /**
     * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all
     * transfers.
     */
    event TransferBatch(
        address indexed operator,
        address indexed from,
        address indexed to,
        uint256[] ids,
        uint256[] values
    );

    /**
     * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to
     * `approved`.
     */
    event ApprovalForAll(address indexed account, address indexed operator, bool approved);

    /**
     * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.
     *
     * If an {URI} event was emitted for `id`, the standard
     * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value
     * returned by {IERC1155MetadataURI-uri}.
     */
    event URI(string value, uint256 indexed id);

    /**
     * @dev Returns the value of tokens of token type `id` owned by `account`.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     */
    function balanceOf(address account, uint256 id) external view returns (uint256);

    /**
     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.
     *
     * Requirements:
     *
     * - `accounts` and `ids` must have the same length.
     */
    function balanceOfBatch(
        address[] calldata accounts,
        uint256[] calldata ids
    ) external view returns (uint256[] memory);

    /**
     * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,
     *
     * Emits an {ApprovalForAll} event.
     *
     * Requirements:
     *
     * - `operator` cannot be the caller.
     */
    function setApprovalForAll(address operator, bool approved) external;

    /**
     * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.
     *
     * See {setApprovalForAll}.
     */
    function isApprovedForAll(address account, address operator) external view returns (bool);

    /**
     * @dev Transfers a `value` amount of tokens of type `id` from `from` to `to`.
     *
     * WARNING: This function can potentially allow a reentrancy attack when transferring tokens
     * to an untrusted contract, when invoking {onERC1155Received} on the receiver.
     * Ensure to follow the checks-effects-interactions pattern and consider employing
     * reentrancy guards when interacting with untrusted contracts.
     *
     * Emits a {TransferSingle} event.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.
     * - `from` must have a balance of tokens of type `id` of at least `value` amount.
     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the
     * acceptance magic value.
     */
    function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes calldata data) external;

    /**
     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.
     *
     * WARNING: This function can potentially allow a reentrancy attack when transferring tokens
     * to an untrusted contract, when invoking {onERC1155BatchReceived} on the receiver.
     * Ensure to follow the checks-effects-interactions pattern and consider employing
     * reentrancy guards when interacting with untrusted contracts.
     *
     * Emits either a {TransferSingle} or a {TransferBatch} event, depending on the length of the array arguments.
     *
     * Requirements:
     *
     * - `ids` and `values` must have the same length.
     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the
     * acceptance magic value.
     */
    function safeBatchTransferFrom(
        address from,
        address to,
        uint256[] calldata ids,
        uint256[] calldata values,
        bytes calldata data
    ) external;
}

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

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[EIP].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165 {
    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

Settings
{
  "remappings": [
    "@openzeppelin-upgradeable/=lib/AlignmentVault/lib/nftx-protocol-v3/lib/openzeppelin-contracts-upgradeable/",
    "@openzeppelin/=lib/AlignmentVault/lib/nftx-protocol-v3/lib/openzeppelin-contracts/",
    "@openzeppelin/contracts/=lib/AlignmentVault/lib/nftx-protocol-v3/lib/openzeppelin-contracts/contracts/",
    "@mocks/=lib/AlignmentVault/lib/nftx-protocol-v3/src/mocks/",
    "@openzeppelin/contracts-upgradeable/=lib/ERC721M/lib/ERC721x/lib/openzeppelin-contracts-upgradeable/contracts/",
    "@permit2/=lib/AlignmentVault/lib/nftx-protocol-v3/lib/permit2/src/",
    "@src/=lib/AlignmentVault/lib/nftx-protocol-v3/src/",
    "@test/=lib/AlignmentVault/lib/nftx-protocol-v3/test/",
    "@uni-core/=lib/AlignmentVault/lib/nftx-protocol-v3/src/uniswap/v3-core/",
    "@uni-periphery/=lib/AlignmentVault/lib/nftx-protocol-v3/src/uniswap/v3-periphery/",
    "@uniswap/lib/=lib/AlignmentVault/lib/nftx-protocol-v3/lib/solidity-lib/",
    "@uniswap/v2-core/=lib/AlignmentVault/lib/nftx-protocol-v3/lib/v2-core/",
    "@uniswap/v3-core/contracts/=lib/AlignmentVault/lib/nftx-protocol-v3/src/uniswap/v3-core/",
    "AlignmentVault/=lib/AlignmentVault/",
    "ERC721A-Upgradeable/=lib/ERC721M/lib/ERC721x/lib/ERC721A-Upgradeable/contracts/",
    "ERC721A/=lib/ERC721M/lib/ERC721x/lib/ERC721A/contracts/",
    "ERC721M/=lib/ERC721M/",
    "ERC721x/=lib/ERC721M/lib/ERC721x/",
    "base64-sol/=lib/AlignmentVault/lib/nftx-protocol-v3/src/uniswap/v3-periphery/libraries/",
    "delegate-registry/=lib/AlignmentVault/lib/delegate-registry/",
    "ds-test/=lib/AlignmentVault/lib/forge-std/lib/ds-test/src/",
    "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
    "forge-gas-snapshot/=lib/AlignmentVault/lib/nftx-protocol-v3/lib/permit2/lib/forge-gas-snapshot/src/",
    "forge-std/=lib/forge-std/src/",
    "murky/=lib/AlignmentVault/lib/delegate-registry/lib/murky/",
    "nftx-protocol-v3/=lib/AlignmentVault/lib/nftx-protocol-v3/src/",
    "openzeppelin-contracts-upgradeable/=lib/ERC721M/lib/ERC721x/lib/openzeppelin-contracts-upgradeable/",
    "openzeppelin-contracts-v5/=lib/AlignmentVault/lib/openzeppelin-contracts-v5/",
    "openzeppelin-contracts/=lib/openzeppelin-contracts/",
    "openzeppelin/=lib/AlignmentVault/lib/delegate-registry/lib/openzeppelin-contracts/contracts/",
    "permit2/=lib/AlignmentVault/lib/nftx-protocol-v3/lib/permit2/",
    "solady/=lib/solady/src/",
    "solidity-lib/=lib/AlignmentVault/lib/nftx-protocol-v3/lib/solidity-lib/contracts/",
    "solmate/=lib/AlignmentVault/lib/solmate/src/",
    "v2-core/=lib/AlignmentVault/lib/v2-core/contracts/",
    "v2-periphery/=lib/AlignmentVault/lib/v2-periphery/contracts/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "ipfs",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "paris",
  "viaIR": false,
  "libraries": {}
}

Contract ABI

[{"inputs":[{"internalType":"address","name":"newOwner","type":"address"},{"internalType":"address","name":"newErc721MiyaImplementation","type":"address"},{"internalType":"address","name":"newMiyaAVImplementation","type":"address"}],"stateMutability":"payable","type":"constructor"},{"inputs":[],"name":"AlreadyInitialized","type":"error"},{"inputs":[],"name":"Invalid","type":"error"},{"inputs":[],"name":"NewOwnerIsZeroAddress","type":"error"},{"inputs":[],"name":"NoHandoverRequest","type":"error"},{"inputs":[],"name":"TransferFailed","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"deployer","type":"address"},{"indexed":true,"internalType":"address","name":"collection","type":"address"},{"indexed":true,"internalType":"address","name":"aligned","type":"address"},{"indexed":false,"internalType":"bytes32","name":"salt","type":"bytes32"}],"name":"Deployed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"ERC721MiyaImplementation","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"erc721","type":"address"},{"indexed":true,"internalType":"uint256","name":"vaultId","type":"uint256"}],"name":"MiyaIdSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"erc721m","type":"address"},{"indexed":true,"internalType":"address","name":"oldOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipChanged","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"},{"inputs":[],"name":"cancelOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"pendingOwner","type":"address"}],"name":"completeOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"string","name":"baseURI","type":"string"},{"internalType":"uint40","name":"maxSupply","type":"uint40"},{"internalType":"uint16","name":"royalty","type":"uint16"},{"internalType":"uint16","name":"allocation","type":"uint16"},{"internalType":"address","name":"owner_","type":"address"},{"internalType":"address","name":"alignedNft","type":"address"},{"internalType":"uint80","name":"price","type":"uint80"},{"internalType":"uint96","name":"vaultId","type":"uint96"},{"internalType":"bytes32","name":"saltAlignmentVault","type":"bytes32"}],"name":"deploy","outputs":[{"internalType":"address","name":"deployment","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"string","name":"baseURI","type":"string"},{"internalType":"uint40","name":"maxSupply","type":"uint40"},{"internalType":"uint16","name":"royalty","type":"uint16"},{"internalType":"uint16","name":"allocation","type":"uint16"},{"internalType":"address","name":"owner_","type":"address"},{"internalType":"address","name":"alignedNft","type":"address"},{"internalType":"uint80","name":"price","type":"uint80"},{"internalType":"uint96","name":"vaultId","type":"uint96"},{"internalType":"bytes32","name":"saltAlignmentVault","type":"bytes32"},{"internalType":"bytes32","name":"saltERC721Miya","type":"bytes32"}],"name":"deployDeterministic","outputs":[{"internalType":"address","name":"deployment","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"alignedNft","type":"address"},{"internalType":"uint96","name":"vaultId","type":"uint96"},{"internalType":"bytes32","name":"salt","type":"bytes32"}],"name":"deployVault","outputs":[{"internalType":"address","name":"vault","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"erc721MiyaImplementation","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAlignedNfts","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"alignedNft","type":"address"},{"internalType":"uint256","name":"vaultId","type":"uint256"}],"name":"getVault","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"alignedNft","type":"address"}],"name":"getVaultIds","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"initCodeHash","outputs":[{"internalType":"bytes32","name":"hash","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"miyaAVFactory","outputs":[{"internalType":"contract MiyaAVFactory","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"miyaAVImplementation","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"alignedNft","type":"address"}],"name":"miyaIds","outputs":[{"internalType":"uint256","name":"vaultId","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"result","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"oldOwner","type":"address"},{"internalType":"address","name":"newOwner","type":"address"}],"name":"ownershipChanged","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"pendingOwner","type":"address"}],"name":"ownershipHandoverExpiresAt","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"salt","type":"bytes32"}],"name":"predictDeterministicAddress","outputs":[{"internalType":"address","name":"predicted","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"requestOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"alignedNft","type":"address"},{"internalType":"uint256","name":"vaultId","type":"uint256"}],"name":"setMiyaId","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"newErc721MiyaImplementation","type":"address"}],"name":"updateERC721MiyaImplementation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newMiyaAVImplementation","type":"address"}],"name":"updateMiyaAVImplementation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"}],"name":"withdrawERC1155","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"address","name":"recipient","type":"address"}],"name":"withdrawERC1155Batch","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"recipient","type":"address"}],"name":"withdrawERC20","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"}],"name":"withdrawERC721","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"}],"name":"withdrawEth","outputs":[],"stateMutability":"payable","type":"function"}]

60806040526040516200392a3803806200392a83398101604081905262000026916200014c565b6200003183620000e5565b600080546001600160a01b0319166001600160a01b038416908117825560405190917f86587754a7c1b5416d014e448fdb1d745a6f657dcbe010541f65993a7eccfee191a28281604051620000869062000121565b6001600160a01b03928316815291166020820152604001604051809103906000f080158015620000ba573d6000803e3d6000fd5b50600180546001600160a01b0319166001600160a01b03929092169190911790555062000196915050565b6001600160a01b0316638b78c6d8198190558060007f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08180a350565b611aee8062001e3c83390190565b80516001600160a01b03811681146200014757600080fd5b919050565b6000806000606084860312156200016257600080fd5b6200016d846200012f565b92506200017d602085016200012f565b91506200018d604085016200012f565b90509250925092565b611c9680620001a66000396000f3fe6080604052600436106101b75760003560e01c806375f0ebf4116100ec578063db4c545e1161008a578063f2fde38b11610064578063f2fde38b14610493578063f724fa6f146104a6578063fd8e2c84146104c6578063fee81cf4146104e657600080fd5b8063db4c545e14610417578063e98778841461046d578063f04e283e1461048057600080fd5b80639456fbcc116100c65780639456fbcc14610397578063c952c865146103aa578063cf4c3606146103ca578063d99d13f5146103f757600080fd5b806375f0ebf41461034b5780637b9f76b51461036b5780638da5cb5b1461037e57600080fd5b806354d1f13d116101595780635fa78f80116101335780635fa78f80146102c85780636149a6bc146102e85780636437a1aa14610308578063715018a61461034357600080fd5b806354d1f13d14610280578063565068a8146102885780635d92051b146102a857600080fd5b80632854f1b2116101955780632854f1b2146101ec5780632b002e731461021e57806334a365241461023e5780635414dff01461026057600080fd5b8063256451ac146101bc57806325692962146101d157806325e16063146101d9575b600080fd5b6101cf6101ca366004611347565b610519565b005b6101cf6105e3565b6101cf6101e7366004611391565b610633565b3480156101f857600080fd5b506102016106f1565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561022a57600080fd5b506101cf610239366004611391565b610764565b34801561024a57600080fd5b506102536107b4565b60405161021591906113ae565b34801561026c57600080fd5b5061020161027b3660046113fb565b610826565b6101cf610844565b34801561029457600080fd5b50600054610201906001600160a01b031681565b3480156102b457600080fd5b506101cf6102c3366004611414565b610880565b3480156102d457600080fd5b506102016102e3366004611464565b6108ef565b3480156102f457600080fd5b5061020161030336600461159a565b610a39565b34801561031457600080fd5b50610335610323366004611391565b60026020526000908152604090205481565b604051908152602001610215565b6101cf610b97565b34801561035757600080fd5b506101cf6103663660046116a5565b610ba1565b6101cf6103793660046116d1565b610bf0565b34801561038a57600080fd5b50638b78c6d81954610201565b6101cf6103a5366004611414565b610ca3565b3480156103b657600080fd5b506102016103c5366004611713565b610dcf565b3480156103d657600080fd5b506103ea6103e5366004611391565b610f52565b6040516102159190611871565b34801561040357600080fd5b506102016104123660046116a5565b610fc5565b34801561042357600080fd5b50600080546c5af43d3d93803e602a57fd5bf360219081526001600160a01b0390911660145273602c3d8160093d39f33d3d3d3d363d3d37363d7382526035600c20919052610335565b6101cf61047b366004611917565b61103b565b6101cf61048e366004611391565b6110b3565b6101cf6104a1366004611391565b6110f3565b3480156104b257600080fd5b506101cf6104c1366004611391565b61111a565b3480156104d257600080fd5b50600154610201906001600160a01b031681565b3480156104f257600080fd5b50610335610501366004611391565b63389a75e1600c908152600091909152602090205490565b610521611183565b6001600160a01b038116158061054157506001600160a01b03811661dead145b1561055f576040516312171d8360e31b815260040160405180910390fd5b604051637921219560e11b81523060048201526001600160a01b038281166024830152604482018590526064820184905260a06084830152600060a483015285169063f242432a9060c4015b600060405180830381600087803b1580156105c557600080fd5b505af11580156105d9573d6000803e3d6000fd5b5050505050505050565b60006202a30067ffffffffffffffff164201905063389a75e1600c5233600052806020600c2055337fdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d600080a250565b61063b611183565b6001600160a01b038116158061065b57506001600160a01b03811661dead145b15610679576040516312171d8360e31b815260040160405180910390fd5b6000816001600160a01b03164760405160006040518083038185875af1925050503d80600081146106c6576040519150601f19603f3d011682016040523d82523d6000602084013e6106cb565b606091505b50509050806106ed576040516312171d8360e31b815260040160405180910390fd5b5050565b60015460408051635c60da1b60e01b815290516000926001600160a01b031691635c60da1b9160048083019260209291908290030181865afa15801561073b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061075f9190611995565b905090565b61076c611183565b600080546001600160a01b0319166001600160a01b038316908117825560405190917f86587754a7c1b5416d014e448fdb1d745a6f657dcbe010541f65993a7eccfee191a250565b60015460408051630d28d94960e21b815290516060926001600160a01b0316916334a365249160048083019260009291908290030181865afa1580156107fe573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261075f91908101906119b2565b6000805461083e906001600160a01b0316833061119e565b92915050565b63389a75e1600c523360005260006020600c2055337ffa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c92600080a2565b3360009081526003602052604090205460ff166108b057604051636dac6a0960e01b815260040160405180910390fd5b6040516001600160a01b03808316919084169033907f60b760b15c562c07ca8faad5fab184dfc5d58d1e57d9f2fa4fd93b7380c9981b90600090a45050565b6000826001600160601b031660000361091e576001600160a01b03841660009081526002602052604090205492505b816109a957600154604051633b8cd70f60e01b81526001600160a01b0386811660048301526001600160601b038616602483015290911690633b8cd70f906044016020604051808303816000875af115801561097e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109a29190611995565b9050610a32565b60015460405163b1983f9360e01b81526001600160a01b0386811660048301526001600160601b0386166024830152604482018590529091169063b1983f93906064016020604051808303816000875af1158015610a0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a2f9190611995565b90505b9392505050565b60008054610a4f906001600160a01b03166111fb565b6001600160a01b03811660008181526003602052604090819020805460ff19166001179055516307e1fdd960e21b815291925090631f87f76490610aab908f908f908f908f908f908f908f908f908f908f908f90600401611a92565b600060405180830381600087803b158015610ac557600080fd5b505af1158015610ad9573d6000803e3d6000fd5b50505050806001600160a01b03166331f449006040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610b1857600080fd5b505af1158015610b2c573d6000803e3d6000fd5b50505050846001600160a01b0316816001600160a01b0316336001600160a01b03167ffe0b790c72ed3156887ce7a0bcfe2d4d72ecadef8a529eb9c8a40e7cff968b166000604051610b8091815260200190565b60405180910390a49b9a5050505050505050505050565b610b9f611183565b565b610ba9611183565b6001600160a01b038216600081815260026020526040808220849055518392917fecfc5799f71e577b2e57c8cec6535d089d0e392d1a5d0a704c8f327f55b0108d91a35050565b610bf8611183565b6001600160a01b0381161580610c1857506001600160a01b03811661dead145b15610c36576040516312171d8360e31b815260040160405180910390fd5b6040516323b872dd60e01b81523060048201526001600160a01b038281166024830152604482018490528416906323b872dd90606401600060405180830381600087803b158015610c8657600080fd5b505af1158015610c9a573d6000803e3d6000fd5b50505050505050565b610cab611183565b6001600160a01b0381161580610ccb57506001600160a01b03811661dead145b15610ce9576040516312171d8360e31b815260040160405180910390fd5b6040516370a0823160e01b81523060048201526001600160a01b0383169063a9059cbb90839083906370a0823190602401602060405180830381865afa158015610d37573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d5b9190611b44565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610da6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dca9190611b5d565b505050565b60008054610de6906001600160a01b031683611208565b9050600160036000836001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff021916908315150217905550806001600160a01b0316631f87f7648e8e8e8e8e8e8e8e8e8e8e6040518c63ffffffff1660e01b8152600401610e669b9a99989796959493929190611a92565b600060405180830381600087803b158015610e8057600080fd5b505af1158015610e94573d6000803e3d6000fd5b50505050806001600160a01b03166331f449006040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610ed357600080fd5b505af1158015610ee7573d6000803e3d6000fd5b50505050856001600160a01b0316816001600160a01b0316336001600160a01b03167ffe0b790c72ed3156887ce7a0bcfe2d4d72ecadef8a529eb9c8a40e7cff968b1685604051610f3a91815260200190565b60405180910390a49c9b505050505050505050505050565b6001546040516367a61b0360e11b81526001600160a01b038381166004830152606092169063cf4c360690602401600060405180830381865afa158015610f9d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261083e9190810190611b7f565b600154604051633ddfe34f60e11b81526001600160a01b038481166004830152602482018490526000921690637bbfc69e90604401602060405180830381865afa158015611017573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a329190611995565b611043611183565b6001600160a01b038116158061106357506001600160a01b03811661dead145b15611081576040516312171d8360e31b815260040160405180910390fd5b604051631759616b60e11b81526001600160a01b03851690632eb2c2d6906105ab903090859088908890600401611c05565b6110bb611183565b63389a75e1600c52806000526020600c2080544211156110e357636f5e88186000526004601cfd5b600090556110f081611216565b50565b6110fb611183565b8060601b61111157637448fbae6000526004601cfd5b6110f081611216565b611122611183565b6001546040516296c8af60e21b81526001600160a01b0383811660048301529091169063025b22bc90602401600060405180830381600087803b15801561116857600080fd5b505af115801561117c573d6000803e3d6000fd5b5050505050565b638b78c6d819543314610b9f576382b429006000526004601cfd5b6000806111e58560006c5af43d3d93803e602a57fd5bf36021528160145273602c3d8160093d39f33d3d3d3d363d3d37363d736000526035600c2090506000602152919050565b90506111f2818585611254565b95945050505050565b600061083e600083611276565b6000610a32600084846112cb565b638b78c6d81980546001600160a01b039092169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a355565b600060ff60005350603592835260601b60015260155260556000908120915290565b60006c5af43d3d93803e602a57fd5bf36021528160145273602c3d8160093d39f33d3d3d3d363d3d37363d736000526035600c84f09050806112c05763301164256000526004601cfd5b600060215292915050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c86f59050806113165763301164256000526004601cfd5b60006021529392505050565b6001600160a01b03811681146110f057600080fd5b803561134281611322565b919050565b6000806000806080858703121561135d57600080fd5b843561136881611322565b93506020850135925060408501359150606085013561138681611322565b939692955090935050565b6000602082840312156113a357600080fd5b8135610a3281611322565b6020808252825182820181905260009190848201906040850190845b818110156113ef5783516001600160a01b0316835292840192918401916001016113ca565b50909695505050505050565b60006020828403121561140d57600080fd5b5035919050565b6000806040838503121561142757600080fd5b823561143281611322565b9150602083013561144281611322565b809150509250929050565b80356001600160601b038116811461134257600080fd5b60008060006060848603121561147957600080fd5b833561148481611322565b92506114926020850161144d565b9150604084013590509250925092565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156114e1576114e16114a2565b604052919050565b600082601f8301126114fa57600080fd5b813567ffffffffffffffff811115611514576115146114a2565b611527601f8201601f19166020016114b8565b81815284602083860101111561153c57600080fd5b816020850160208301376000918101602001919091529392505050565b803564ffffffffff8116811461134257600080fd5b803561ffff8116811461134257600080fd5b803569ffffffffffffffffffff8116811461134257600080fd5b60008060008060008060008060008060006101608c8e0312156115bc57600080fd5b67ffffffffffffffff808d3511156115d357600080fd5b6115e08e8e358f016114e9565b9b508060208e013511156115f357600080fd5b6116038e60208f01358f016114e9565b9a508060408e0135111561161657600080fd5b506116278d60408e01358e016114e9565b985061163560608d01611559565b975061164360808d0161156e565b965061165160a08d0161156e565b955061165f60c08d01611337565b945061166d60e08d01611337565b935061167c6101008d01611580565b925061168b6101208d0161144d565b91506101408c013590509295989b509295989b9093969950565b600080604083850312156116b857600080fd5b82356116c381611322565b946020939093013593505050565b6000806000606084860312156116e657600080fd5b83356116f181611322565b925060208401359150604084013561170881611322565b809150509250925092565b6000806000806000806000806000806000806101808d8f03121561173657600080fd5b67ffffffffffffffff8d35111561174c57600080fd5b6117598e8e358f016114e9565b9b5067ffffffffffffffff60208e0135111561177457600080fd5b6117848e60208f01358f016114e9565b9a5067ffffffffffffffff60408e0135111561179f57600080fd5b6117af8e60408f01358f016114e9565b99506117bd60608e01611559565b98506117cb60808e0161156e565b97506117d960a08e0161156e565b96506117e760c08e01611337565b95506117f560e08e01611337565b94506118046101008e01611580565b93506118136101208e0161144d565b92506101408d013591506101608d013590509295989b509295989b509295989b565b60008151808452602080850194506020840160005b838110156118665781518752958201959082019060010161184a565b509495945050505050565b602081526000610a326020830184611835565b600067ffffffffffffffff82111561189e5761189e6114a2565b5060051b60200190565b600082601f8301126118b957600080fd5b813560206118ce6118c983611884565b6114b8565b8083825260208201915060208460051b8701019350868411156118f057600080fd5b602086015b8481101561190c57803583529183019183016118f5565b509695505050505050565b6000806000806080858703121561192d57600080fd5b843561193881611322565b9350602085013567ffffffffffffffff8082111561195557600080fd5b611961888389016118a8565b9450604087013591508082111561197757600080fd5b50611984878288016118a8565b925050606085013561138681611322565b6000602082840312156119a757600080fd5b8151610a3281611322565b600060208083850312156119c557600080fd5b825167ffffffffffffffff8111156119dc57600080fd5b8301601f810185136119ed57600080fd5b80516119fb6118c982611884565b81815260059190911b82018301908381019087831115611a1a57600080fd5b928401925b82841015611a41578351611a3281611322565b82529284019290840190611a1f565b979650505050505050565b6000815180845260005b81811015611a7257602081850181015186830182015201611a56565b506000602082860101526020601f19601f83011685010191505092915050565b6000610160808352611aa68184018f611a4c565b90508281036020840152611aba818e611a4c565b90508281036040840152611ace818d611a4c565b64ffffffffff8c16606085015261ffff8b811660808601528a1660a08501526001600160a01b0389811660c0860152881660e085015269ffffffffffffffffffff87166101008501529150611b209050565b6001600160601b039390931661012082015261014001529998505050505050505050565b600060208284031215611b5657600080fd5b5051919050565b600060208284031215611b6f57600080fd5b81518015158114610a3257600080fd5b60006020808385031215611b9257600080fd5b825167ffffffffffffffff811115611ba957600080fd5b8301601f81018513611bba57600080fd5b8051611bc86118c982611884565b81815260059190911b82018301908381019087831115611be757600080fd5b928401925b82841015611a4157835182529284019290840190611bec565b6001600160a01b0385811682528416602082015260a060408201819052600090611c3190830185611835565b8281036060840152611c438185611835565b83810360809094019390935250506000815260200194935050505056fea26469706673582212204ef33568a3b68d46eb14ee7632a349974e5102292c3f11e2779d9406f7d6a15a64736f6c6343000817003360806040523480156200001157600080fd5b5060405162001aee38038062001aee8339810160408190526200003491620000fc565b81816200004182620000a3565b600080546001600160a01b0319166001600160a01b038316908117825560405190917f1d83655f7ea9272ca6ce199d8142c5dd00133e0c1224729ef2a7b5058003030491a25050600480546001600160a01b0319163317905550620001349050565b6001600160a01b0316638b78c6d8198190558060007f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08180a350565b80516001600160a01b0381168114620000f757600080fd5b919050565b600080604083850312156200011057600080fd5b6200011b83620000df565b91506200012b60208401620000df565b90509250929050565b6119aa80620001446000396000f3fe6080604052600436106101355760003560e01c80637b9f76b5116100ab578063cf4c36061161006f578063cf4c3606146102d2578063db4c545e146102ff578063e98778841461035f578063f04e283e14610372578063f2fde38b14610385578063fee81cf41461039857600080fd5b80637b9f76b5146102435780637bbfc69e146102565780638da5cb5b146102975780639456fbcc146102ac578063b1983f93146102bf57600080fd5b80633b8cd70f116100fd5780633b8cd70f146101a85780635414dff0146101d357806354d1f13d146101f35780635c60da1b146101fb578063600041a01461021b578063715018a61461023b57600080fd5b8063025b22bc1461013a578063256451ac1461014f578063256929621461016257806325e160631461016a57806334a365241461017d575b600080fd5b61014d61014836600461155d565b6103cb565b005b61014d61015d36600461157a565b610453565b61014d61051c565b61014d61017836600461155d565b61056c565b34801561018957600080fd5b5061019261062a565b60405161019f91906115c4565b60405180910390f35b6101bb6101b6366004611626565b61063b565b6040516001600160a01b03909116815260200161019f565b3480156101df57600080fd5b506101bb6101ee36600461165f565b6108dd565b61014d6108f5565b34801561020757600080fd5b506000546101bb906001600160a01b031681565b34801561022757600080fd5b506004546101bb906001600160a01b031681565b61014d610931565b61014d610251366004611678565b61093b565b34801561026257600080fd5b506101bb6102713660046116ba565b60016020908152600092835260408084209091529082529020546001600160a01b031681565b3480156102a357600080fd5b506101bb6109ee565b61014d6102ba3660046116e6565b610a67565b6101bb6102cd366004611714565b610b93565b3480156102de57600080fd5b506102f26102ed36600461155d565b610e36565b60405161019f9190611755565b34801561030b57600080fd5b50600080546c5af43d3d93803e602a57fd5bf360219081526001600160a01b0390911660145273602c3d8160093d39f33d3d3d3d363d3d37363d7382526035600c209190525b60405190815260200161019f565b61014d61036d3660046117d9565b610e5a565b61014d61038036600461155d565b610f10565b61014d61039336600461155d565b610f4d565b3480156103a457600080fd5b506103516103b336600461155d565b63389a75e1600c908152600091909152602090205490565b6004546001600160a01b031633146103f5576040516282b42960e81b815260040160405180910390fd5b6000546001600160a01b0382811691161461045057600080546001600160a01b0319166001600160a01b038316908117825560405190917f1d83655f7ea9272ca6ce199d8142c5dd00133e0c1224729ef2a7b5058003030491a25b50565b61045b610f74565b6001600160a01b038116158061047b57506001600160a01b03811661dead145b156104995760405163dfad6a2360e01b815260040160405180910390fd5b604051637921219560e11b81523060048201526001600160a01b038281166024830152604482018590526064820184905260a06084830152600060a483015285169063f242432a9060c401600060405180830381600087803b1580156104fe57600080fd5b505af1158015610512573d6000803e3d6000fd5b5050505050505050565b60006202a30067ffffffffffffffff164201905063389a75e1600c5233600052806020600c2055337fdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d600080a250565b610574610f74565b6001600160a01b038116158061059457506001600160a01b03811661dead145b156105b25760405163dfad6a2360e01b815260040160405180910390fd5b6000816001600160a01b03164760405160006040518083038185875af1925050503d80600081146105ff576040519150601f19603f3d011682016040523d82523d6000602084013e610604565b606091505b50509050806106265760405163dfad6a2360e01b815260040160405180910390fd5b5050565b60606106366003610fac565b905090565b6004546000906001600160a01b03163314610668576040516282b42960e81b815260040160405180910390fd5b506001600160a01b0380831660009081526001602090815260408083206001600160601b038616845290915290205416806108d7576000546106b2906001600160a01b0316611081565b9050806001600160a01b031663c861c2506106cb6109ee565b6040516001600160e01b031960e084901b1681526001600160a01b03918216600482015290861660248201526001600160601b0385166044820152606401600060405180830381600087803b15801561072357600080fd5b505af1158015610737573d6000803e3d6000fd5b50505050806001600160a01b03166331f449006040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561077657600080fd5b505af115801561078a573d6000803e3d6000fd5b50505050816001600160601b031660000361080457806001600160a01b03166333194c0a6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156107dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610801919061186e565b91505b6001600160a01b0383811660009081526001602090815260408083206001600160601b0387168452909152902080546001600160a01b03191691831691909117905561085160038461108e565b506001600160a01b038316600090815260026020526040902061087d906001600160601b0384166111de565b50816001600160601b0316836001600160a01b0316826001600160a01b03167fe9c573b8597bcb5e44e22c9a179f71106bfd46ac62c1b933951c58891eee8f9460006040516108ce91815260200190565b60405180910390a45b92915050565b600080546108d7906001600160a01b031683306111ea565b63389a75e1600c523360005260006020600c2055337ffa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c92600080a2565b610939610f74565b565b610943610f74565b6001600160a01b038116158061096357506001600160a01b03811661dead145b156109815760405163dfad6a2360e01b815260040160405180910390fd5b6040516323b872dd60e01b81523060048201526001600160a01b038281166024830152604482018490528416906323b872dd90606401600060405180830381600087803b1580156109d157600080fd5b505af11580156109e5573d6000803e3d6000fd5b50505050505050565b6000600460009054906101000a90046001600160a01b03166001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a43573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610636919061188b565b610a6f610f74565b6001600160a01b0381161580610a8f57506001600160a01b03811661dead145b15610aad5760405163dfad6a2360e01b815260040160405180910390fd5b6040516370a0823160e01b81523060048201526001600160a01b0383169063a9059cbb90839083906370a0823190602401602060405180830381865afa158015610afb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b1f91906118a8565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610b6a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b8e91906118c1565b505050565b6004546000906001600160a01b03163314610bc0576040516282b42960e81b815260040160405180910390fd5b506001600160a01b0380841660009081526001602090815260408083206001600160601b03871684529091529020541680610e2f57600054610c0b906001600160a01b031683611247565b9050806001600160a01b031663c861c250610c246109ee565b6040516001600160e01b031960e084901b1681526001600160a01b03918216600482015290871660248201526001600160601b0386166044820152606401600060405180830381600087803b158015610c7c57600080fd5b505af1158015610c90573d6000803e3d6000fd5b50505050806001600160a01b03166331f449006040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610ccf57600080fd5b505af1158015610ce3573d6000803e3d6000fd5b50505050826001600160601b0316600003610d5d57806001600160a01b03166333194c0a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d5a919061186e565b92505b6001600160a01b0384811660009081526001602090815260408083206001600160601b0388168452909152902080546001600160a01b031916918316919091179055610daa60038561108e565b506001600160a01b0384166000908152600260205260409020610dd6906001600160601b0385166111de565b50826001600160601b0316846001600160a01b0316826001600160a01b03167fe9c573b8597bcb5e44e22c9a179f71106bfd46ac62c1b933951c58891eee8f9485604051610e2691815260200190565b60405180910390a45b9392505050565b6001600160a01b03811660009081526002602052604090206060906108d790611255565b610e62610f74565b6001600160a01b0381161580610e8257506001600160a01b03811661dead145b15610ea05760405163dfad6a2360e01b815260040160405180910390fd5b604051631759616b60e11b81526001600160a01b03871690632eb2c2d690610ed690309085908a908a908a908a90600401611915565b600060405180830381600087803b158015610ef057600080fd5b505af1158015610f04573d6000803e3d6000fd5b50505050505050505050565b610f18610f74565b63389a75e1600c52806000526020600c208054421115610f4057636f5e88186000526004601cfd5b6000905561045081611266565b610f55610f74565b8060601b610f6b57637448fbae6000526004601cfd5b61045081611266565b610f7c6109ee565b6001600160a01b0316336001600160a01b031614610939576040516282b42960e81b815260040160405180910390fd5b63978aab926004526000818152602481206060915068fbb67fda52d4bfb8bf81548060a01b60a01c6040519450846020018260601c925083831415830281528161103b57821561103657600191508185015460601c92508215611036578284141590920260208301525060028381015460601c918215611036576003915083831415830260408201525b61106b565b600191821c915b82811015611069578581015460601c858114158102600583901b8401529350600101611042565b505b8186528160051b81016040525050505050919050565b60006108d76000836112a4565b63978aab926004526000828152602481206001600160a01b03929092169168fbb67fda52d4bfb8be1983016110cb5763f5a267f16000526004601cfd5b826110dd5768fbb67fda52d4bfb8bf92505b80546001600160601b03811682602052806111a0578160601c8061110b578560601b845560019450506111d5565b85810361111857506111d5565b600184015460601c80611139578660601b60018601556001955050506111d5565b8681036111475750506111d5565b600285015460601c80611169578760601b6002870155600196505050506111d5565b878103611178575050506111d5565b6000928352604080842060019055918352818320600290558252902060039055506007908117905b84600052604060002080546111d3578160011c91508560601b8285015581600101815582600201845560019450506111d5565b505b50505092915050565b6000610e2f83836112f9565b6000806112318560006c5af43d3d93803e602a57fd5bf36021528160145273602c3d8160093d39f33d3d3d3d363d3d37363d736000526035600c2090506000602152919050565b905061123e818585611414565b95945050505050565b6000610e2f60008484611436565b60606108d76112638361148d565b90565b638b78c6d81980546001600160a01b039092169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a355565b60006c5af43d3d93803e602a57fd5bf36021528160145273602c3d8160093d39f33d3d3d3d363d3d37363d736000526035600c84f09050806112ee5763301164256000526004601cfd5b600060215292915050565b6318fb586460045260008281526024812068fbb67fda52d4bfb8bf83036113285763f5a267f16000526004601cfd5b8261133a5768fbb67fda52d4bfb8bf92505b80195481602052806113df5781548061135a57848355600193505061140c565b848103611367575061140c565b6001830154806113825785600185015560019450505061140c565b85810361139057505061140c565b6002840154806113ac578660028601556001955050505061140c565b8681036113bb5750505061140c565b60009283526040808420600190559183528183206002905582529020600390555060075b83600052604060002080546111d557600191821c8381018690558083019182905590821b82178319559092505b505092915050565b600060ff60005350603592835260601b60015260155260556000908120915290565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c86f59050806114815763301164256000526004601cfd5b60006021529392505050565b6318fb5864600452600081815260249020801954604051919068fbb67fda52d4bfb8bf90602084018161150757835480156115015780841415028152600184810154909250801561150157808414150260208201526002848101549092508015611501576003925083811415810260408301525b50611533565b8160011c915060005b8281101561153157848101548481141502600582901b830152600101611510565b505b8185528160051b810160405250505050919050565b6001600160a01b038116811461045057600080fd5b60006020828403121561156f57600080fd5b8135610e2f81611548565b6000806000806080858703121561159057600080fd5b843561159b81611548565b9350602085013592506040850135915060608501356115b981611548565b939692955090935050565b6020808252825182820181905260009190848201906040850190845b818110156116055783516001600160a01b0316835292840192918401916001016115e0565b50909695505050505050565b6001600160601b038116811461045057600080fd5b6000806040838503121561163957600080fd5b823561164481611548565b9150602083013561165481611611565b809150509250929050565b60006020828403121561167157600080fd5b5035919050565b60008060006060848603121561168d57600080fd5b833561169881611548565b92506020840135915060408401356116af81611548565b809150509250925092565b600080604083850312156116cd57600080fd5b82356116d881611548565b946020939093013593505050565b600080604083850312156116f957600080fd5b823561170481611548565b9150602083013561165481611548565b60008060006060848603121561172957600080fd5b833561173481611548565b9250602084013561174481611611565b929592945050506040919091013590565b6020808252825182820181905260009190848201906040850190845b8181101561160557835183529284019291840191600101611771565b60008083601f84011261179f57600080fd5b50813567ffffffffffffffff8111156117b757600080fd5b6020830191508360208260051b85010111156117d257600080fd5b9250929050565b600080600080600080608087890312156117f257600080fd5b86356117fd81611548565b9550602087013567ffffffffffffffff8082111561181a57600080fd5b6118268a838b0161178d565b9097509550604089013591508082111561183f57600080fd5b5061184c89828a0161178d565b909450925050606087013561186081611548565b809150509295509295509295565b60006020828403121561188057600080fd5b8151610e2f81611611565b60006020828403121561189d57600080fd5b8151610e2f81611548565b6000602082840312156118ba57600080fd5b5051919050565b6000602082840312156118d357600080fd5b81518015158114610e2f57600080fd5b81835260006001600160fb1b038311156118fc57600080fd5b8260051b80836020870137939093016020019392505050565b6001600160a01b0387811682528616602082015260a06040820181905260009061194290830186886118e3565b82810360608401526119558185876118e3565b838103608090940193909352505060008152602001969550505050505056fea2646970667358221220b8ab599890be8c29f239439c189b1da7626091d8a573fada4ce2c1dcae01dd5564736f6c63430008170033000000000000000000000000a779fc675db318dab004ab8d538cb320d0013f42000000000000000000000000c44b143c5abe84f418b50ad30be31afa7117a2b400000000000000000000000002d5af73501010cfc986045ff36c9ab3a4428787

Deployed Bytecode

0x6080604052600436106101b75760003560e01c806375f0ebf4116100ec578063db4c545e1161008a578063f2fde38b11610064578063f2fde38b14610493578063f724fa6f146104a6578063fd8e2c84146104c6578063fee81cf4146104e657600080fd5b8063db4c545e14610417578063e98778841461046d578063f04e283e1461048057600080fd5b80639456fbcc116100c65780639456fbcc14610397578063c952c865146103aa578063cf4c3606146103ca578063d99d13f5146103f757600080fd5b806375f0ebf41461034b5780637b9f76b51461036b5780638da5cb5b1461037e57600080fd5b806354d1f13d116101595780635fa78f80116101335780635fa78f80146102c85780636149a6bc146102e85780636437a1aa14610308578063715018a61461034357600080fd5b806354d1f13d14610280578063565068a8146102885780635d92051b146102a857600080fd5b80632854f1b2116101955780632854f1b2146101ec5780632b002e731461021e57806334a365241461023e5780635414dff01461026057600080fd5b8063256451ac146101bc57806325692962146101d157806325e16063146101d9575b600080fd5b6101cf6101ca366004611347565b610519565b005b6101cf6105e3565b6101cf6101e7366004611391565b610633565b3480156101f857600080fd5b506102016106f1565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561022a57600080fd5b506101cf610239366004611391565b610764565b34801561024a57600080fd5b506102536107b4565b60405161021591906113ae565b34801561026c57600080fd5b5061020161027b3660046113fb565b610826565b6101cf610844565b34801561029457600080fd5b50600054610201906001600160a01b031681565b3480156102b457600080fd5b506101cf6102c3366004611414565b610880565b3480156102d457600080fd5b506102016102e3366004611464565b6108ef565b3480156102f457600080fd5b5061020161030336600461159a565b610a39565b34801561031457600080fd5b50610335610323366004611391565b60026020526000908152604090205481565b604051908152602001610215565b6101cf610b97565b34801561035757600080fd5b506101cf6103663660046116a5565b610ba1565b6101cf6103793660046116d1565b610bf0565b34801561038a57600080fd5b50638b78c6d81954610201565b6101cf6103a5366004611414565b610ca3565b3480156103b657600080fd5b506102016103c5366004611713565b610dcf565b3480156103d657600080fd5b506103ea6103e5366004611391565b610f52565b6040516102159190611871565b34801561040357600080fd5b506102016104123660046116a5565b610fc5565b34801561042357600080fd5b50600080546c5af43d3d93803e602a57fd5bf360219081526001600160a01b0390911660145273602c3d8160093d39f33d3d3d3d363d3d37363d7382526035600c20919052610335565b6101cf61047b366004611917565b61103b565b6101cf61048e366004611391565b6110b3565b6101cf6104a1366004611391565b6110f3565b3480156104b257600080fd5b506101cf6104c1366004611391565b61111a565b3480156104d257600080fd5b50600154610201906001600160a01b031681565b3480156104f257600080fd5b50610335610501366004611391565b63389a75e1600c908152600091909152602090205490565b610521611183565b6001600160a01b038116158061054157506001600160a01b03811661dead145b1561055f576040516312171d8360e31b815260040160405180910390fd5b604051637921219560e11b81523060048201526001600160a01b038281166024830152604482018590526064820184905260a06084830152600060a483015285169063f242432a9060c4015b600060405180830381600087803b1580156105c557600080fd5b505af11580156105d9573d6000803e3d6000fd5b5050505050505050565b60006202a30067ffffffffffffffff164201905063389a75e1600c5233600052806020600c2055337fdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d600080a250565b61063b611183565b6001600160a01b038116158061065b57506001600160a01b03811661dead145b15610679576040516312171d8360e31b815260040160405180910390fd5b6000816001600160a01b03164760405160006040518083038185875af1925050503d80600081146106c6576040519150601f19603f3d011682016040523d82523d6000602084013e6106cb565b606091505b50509050806106ed576040516312171d8360e31b815260040160405180910390fd5b5050565b60015460408051635c60da1b60e01b815290516000926001600160a01b031691635c60da1b9160048083019260209291908290030181865afa15801561073b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061075f9190611995565b905090565b61076c611183565b600080546001600160a01b0319166001600160a01b038316908117825560405190917f86587754a7c1b5416d014e448fdb1d745a6f657dcbe010541f65993a7eccfee191a250565b60015460408051630d28d94960e21b815290516060926001600160a01b0316916334a365249160048083019260009291908290030181865afa1580156107fe573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261075f91908101906119b2565b6000805461083e906001600160a01b0316833061119e565b92915050565b63389a75e1600c523360005260006020600c2055337ffa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c92600080a2565b3360009081526003602052604090205460ff166108b057604051636dac6a0960e01b815260040160405180910390fd5b6040516001600160a01b03808316919084169033907f60b760b15c562c07ca8faad5fab184dfc5d58d1e57d9f2fa4fd93b7380c9981b90600090a45050565b6000826001600160601b031660000361091e576001600160a01b03841660009081526002602052604090205492505b816109a957600154604051633b8cd70f60e01b81526001600160a01b0386811660048301526001600160601b038616602483015290911690633b8cd70f906044016020604051808303816000875af115801561097e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109a29190611995565b9050610a32565b60015460405163b1983f9360e01b81526001600160a01b0386811660048301526001600160601b0386166024830152604482018590529091169063b1983f93906064016020604051808303816000875af1158015610a0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a2f9190611995565b90505b9392505050565b60008054610a4f906001600160a01b03166111fb565b6001600160a01b03811660008181526003602052604090819020805460ff19166001179055516307e1fdd960e21b815291925090631f87f76490610aab908f908f908f908f908f908f908f908f908f908f908f90600401611a92565b600060405180830381600087803b158015610ac557600080fd5b505af1158015610ad9573d6000803e3d6000fd5b50505050806001600160a01b03166331f449006040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610b1857600080fd5b505af1158015610b2c573d6000803e3d6000fd5b50505050846001600160a01b0316816001600160a01b0316336001600160a01b03167ffe0b790c72ed3156887ce7a0bcfe2d4d72ecadef8a529eb9c8a40e7cff968b166000604051610b8091815260200190565b60405180910390a49b9a5050505050505050505050565b610b9f611183565b565b610ba9611183565b6001600160a01b038216600081815260026020526040808220849055518392917fecfc5799f71e577b2e57c8cec6535d089d0e392d1a5d0a704c8f327f55b0108d91a35050565b610bf8611183565b6001600160a01b0381161580610c1857506001600160a01b03811661dead145b15610c36576040516312171d8360e31b815260040160405180910390fd5b6040516323b872dd60e01b81523060048201526001600160a01b038281166024830152604482018490528416906323b872dd90606401600060405180830381600087803b158015610c8657600080fd5b505af1158015610c9a573d6000803e3d6000fd5b50505050505050565b610cab611183565b6001600160a01b0381161580610ccb57506001600160a01b03811661dead145b15610ce9576040516312171d8360e31b815260040160405180910390fd5b6040516370a0823160e01b81523060048201526001600160a01b0383169063a9059cbb90839083906370a0823190602401602060405180830381865afa158015610d37573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d5b9190611b44565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610da6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dca9190611b5d565b505050565b60008054610de6906001600160a01b031683611208565b9050600160036000836001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff021916908315150217905550806001600160a01b0316631f87f7648e8e8e8e8e8e8e8e8e8e8e6040518c63ffffffff1660e01b8152600401610e669b9a99989796959493929190611a92565b600060405180830381600087803b158015610e8057600080fd5b505af1158015610e94573d6000803e3d6000fd5b50505050806001600160a01b03166331f449006040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610ed357600080fd5b505af1158015610ee7573d6000803e3d6000fd5b50505050856001600160a01b0316816001600160a01b0316336001600160a01b03167ffe0b790c72ed3156887ce7a0bcfe2d4d72ecadef8a529eb9c8a40e7cff968b1685604051610f3a91815260200190565b60405180910390a49c9b505050505050505050505050565b6001546040516367a61b0360e11b81526001600160a01b038381166004830152606092169063cf4c360690602401600060405180830381865afa158015610f9d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261083e9190810190611b7f565b600154604051633ddfe34f60e11b81526001600160a01b038481166004830152602482018490526000921690637bbfc69e90604401602060405180830381865afa158015611017573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a329190611995565b611043611183565b6001600160a01b038116158061106357506001600160a01b03811661dead145b15611081576040516312171d8360e31b815260040160405180910390fd5b604051631759616b60e11b81526001600160a01b03851690632eb2c2d6906105ab903090859088908890600401611c05565b6110bb611183565b63389a75e1600c52806000526020600c2080544211156110e357636f5e88186000526004601cfd5b600090556110f081611216565b50565b6110fb611183565b8060601b61111157637448fbae6000526004601cfd5b6110f081611216565b611122611183565b6001546040516296c8af60e21b81526001600160a01b0383811660048301529091169063025b22bc90602401600060405180830381600087803b15801561116857600080fd5b505af115801561117c573d6000803e3d6000fd5b5050505050565b638b78c6d819543314610b9f576382b429006000526004601cfd5b6000806111e58560006c5af43d3d93803e602a57fd5bf36021528160145273602c3d8160093d39f33d3d3d3d363d3d37363d736000526035600c2090506000602152919050565b90506111f2818585611254565b95945050505050565b600061083e600083611276565b6000610a32600084846112cb565b638b78c6d81980546001600160a01b039092169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a355565b600060ff60005350603592835260601b60015260155260556000908120915290565b60006c5af43d3d93803e602a57fd5bf36021528160145273602c3d8160093d39f33d3d3d3d363d3d37363d736000526035600c84f09050806112c05763301164256000526004601cfd5b600060215292915050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c86f59050806113165763301164256000526004601cfd5b60006021529392505050565b6001600160a01b03811681146110f057600080fd5b803561134281611322565b919050565b6000806000806080858703121561135d57600080fd5b843561136881611322565b93506020850135925060408501359150606085013561138681611322565b939692955090935050565b6000602082840312156113a357600080fd5b8135610a3281611322565b6020808252825182820181905260009190848201906040850190845b818110156113ef5783516001600160a01b0316835292840192918401916001016113ca565b50909695505050505050565b60006020828403121561140d57600080fd5b5035919050565b6000806040838503121561142757600080fd5b823561143281611322565b9150602083013561144281611322565b809150509250929050565b80356001600160601b038116811461134257600080fd5b60008060006060848603121561147957600080fd5b833561148481611322565b92506114926020850161144d565b9150604084013590509250925092565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156114e1576114e16114a2565b604052919050565b600082601f8301126114fa57600080fd5b813567ffffffffffffffff811115611514576115146114a2565b611527601f8201601f19166020016114b8565b81815284602083860101111561153c57600080fd5b816020850160208301376000918101602001919091529392505050565b803564ffffffffff8116811461134257600080fd5b803561ffff8116811461134257600080fd5b803569ffffffffffffffffffff8116811461134257600080fd5b60008060008060008060008060008060006101608c8e0312156115bc57600080fd5b67ffffffffffffffff808d3511156115d357600080fd5b6115e08e8e358f016114e9565b9b508060208e013511156115f357600080fd5b6116038e60208f01358f016114e9565b9a508060408e0135111561161657600080fd5b506116278d60408e01358e016114e9565b985061163560608d01611559565b975061164360808d0161156e565b965061165160a08d0161156e565b955061165f60c08d01611337565b945061166d60e08d01611337565b935061167c6101008d01611580565b925061168b6101208d0161144d565b91506101408c013590509295989b509295989b9093969950565b600080604083850312156116b857600080fd5b82356116c381611322565b946020939093013593505050565b6000806000606084860312156116e657600080fd5b83356116f181611322565b925060208401359150604084013561170881611322565b809150509250925092565b6000806000806000806000806000806000806101808d8f03121561173657600080fd5b67ffffffffffffffff8d35111561174c57600080fd5b6117598e8e358f016114e9565b9b5067ffffffffffffffff60208e0135111561177457600080fd5b6117848e60208f01358f016114e9565b9a5067ffffffffffffffff60408e0135111561179f57600080fd5b6117af8e60408f01358f016114e9565b99506117bd60608e01611559565b98506117cb60808e0161156e565b97506117d960a08e0161156e565b96506117e760c08e01611337565b95506117f560e08e01611337565b94506118046101008e01611580565b93506118136101208e0161144d565b92506101408d013591506101608d013590509295989b509295989b509295989b565b60008151808452602080850194506020840160005b838110156118665781518752958201959082019060010161184a565b509495945050505050565b602081526000610a326020830184611835565b600067ffffffffffffffff82111561189e5761189e6114a2565b5060051b60200190565b600082601f8301126118b957600080fd5b813560206118ce6118c983611884565b6114b8565b8083825260208201915060208460051b8701019350868411156118f057600080fd5b602086015b8481101561190c57803583529183019183016118f5565b509695505050505050565b6000806000806080858703121561192d57600080fd5b843561193881611322565b9350602085013567ffffffffffffffff8082111561195557600080fd5b611961888389016118a8565b9450604087013591508082111561197757600080fd5b50611984878288016118a8565b925050606085013561138681611322565b6000602082840312156119a757600080fd5b8151610a3281611322565b600060208083850312156119c557600080fd5b825167ffffffffffffffff8111156119dc57600080fd5b8301601f810185136119ed57600080fd5b80516119fb6118c982611884565b81815260059190911b82018301908381019087831115611a1a57600080fd5b928401925b82841015611a41578351611a3281611322565b82529284019290840190611a1f565b979650505050505050565b6000815180845260005b81811015611a7257602081850181015186830182015201611a56565b506000602082860101526020601f19601f83011685010191505092915050565b6000610160808352611aa68184018f611a4c565b90508281036020840152611aba818e611a4c565b90508281036040840152611ace818d611a4c565b64ffffffffff8c16606085015261ffff8b811660808601528a1660a08501526001600160a01b0389811660c0860152881660e085015269ffffffffffffffffffff87166101008501529150611b209050565b6001600160601b039390931661012082015261014001529998505050505050505050565b600060208284031215611b5657600080fd5b5051919050565b600060208284031215611b6f57600080fd5b81518015158114610a3257600080fd5b60006020808385031215611b9257600080fd5b825167ffffffffffffffff811115611ba957600080fd5b8301601f81018513611bba57600080fd5b8051611bc86118c982611884565b81815260059190911b82018301908381019087831115611be757600080fd5b928401925b82841015611a4157835182529284019290840190611bec565b6001600160a01b0385811682528416602082015260a060408201819052600090611c3190830185611835565b8281036060840152611c438185611835565b83810360809094019390935250506000815260200194935050505056fea26469706673582212204ef33568a3b68d46eb14ee7632a349974e5102292c3f11e2779d9406f7d6a15a64736f6c63430008170033

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

000000000000000000000000a779fc675db318dab004ab8d538cb320d0013f42000000000000000000000000c44b143c5abe84f418b50ad30be31afa7117a2b400000000000000000000000002d5af73501010cfc986045ff36c9ab3a4428787

-----Decoded View---------------
Arg [0] : newOwner (address): 0xA779fC675Db318dab004Ab8D538CB320D0013F42
Arg [1] : newErc721MiyaImplementation (address): 0xC44B143C5aBe84F418B50Ad30Be31aFA7117a2B4
Arg [2] : newMiyaAVImplementation (address): 0x02d5aF73501010CFC986045Ff36C9ab3a4428787

-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 000000000000000000000000a779fc675db318dab004ab8d538cb320d0013f42
Arg [1] : 000000000000000000000000c44b143c5abe84f418b50ad30be31afa7117a2b4
Arg [2] : 00000000000000000000000002d5af73501010cfc986045ff36c9ab3a4428787


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
[ Download: CSV Export  ]
[ 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.