creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "src/Presale.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.24;\n\nimport {MerkleProof} from \"lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol\";\nimport {ECDSA} from \"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\";\nimport {MessageHashUtils} from \"lib/openzeppelin-contracts/contracts/utils/cryptography/MessageHashUtils.sol\";\nimport {IERC721} from \"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721.sol\";\nimport {ReentrancyGuard} from \"lib/openzeppelin-contracts/contracts/utils/ReentrancyGuard.sol\";\nimport {Ownable2Step, Ownable} from \"lib/openzeppelin-contracts/contracts/access/Ownable2Step.sol\";\nimport {Pausable} from \"lib/openzeppelin-contracts/contracts/utils/Pausable.sol\";\nimport {IDelegationRegistry} from \"src/lib/IDelegationRegistry.sol\";\nimport {IDelegateRegistry} from \"lib/delegate-registry/src/IDelegateRegistry.sol\";\n\n/// @title Presale\n/// @notice Block Games presale contract\n/// @author karooolis\ncontract Presale is Ownable2Step, Pausable, ReentrancyGuard {\n    /*==============================================================\n                      CONSTANTS & IMMUTABLES\n    ==============================================================*/\n\n    /// @notice Event emitted when the merkle root for the allowed wallets is set\n    bytes32 public constant DOMAIN_TYPEHASH = keccak256(\"EIP712Domain(uint256 chainId,address verifyingContract)\");\n\n    /// @notice Event emitted when the merkle root for the allowed wallets is set\n    bytes32 public immutable cachedDomainSeparator;\n\n    /// @notice Chain ID of the contract\n    uint256 public immutable cachedChainId;\n\n    // @notice Address of the contract\n    address public immutable cachedThis;\n\n    /// @notice Address of the Dice NFT\n    address public immutable diceNFT;\n\n    /// @notice Address of the wallet that will receive the funds\n    address public immutable treasury;\n\n    /// @notice Address of the delegate registry v1\n    IDelegationRegistry public immutable delegateRegistryV1;\n\n    /// @notice Address of the delegate registry v2\n    IDelegateRegistry public immutable delegateRegistryV2;\n\n    /*==============================================================\n                            STRUCTS\n    ==============================================================*/\n\n    struct BuyWithDiceNFTParams {\n        bytes32[] proof;\n        uint256 tokenId;\n        uint256 amount;\n        uint256 maxAmount;\n    }\n\n    struct BuyWithAllowedNFTParams {\n        bytes32[] proof;\n        address collection;\n        uint256 tokenId;\n        uint256 amount;\n        uint256 maxAmount;\n    }\n\n    struct AllowedWalletParams {\n        bytes32[] proof;\n        uint256 amount;\n        uint256 maxAmount;\n    }\n\n    /*==============================================================\n                       STORAGE VARIABLES\n    ==============================================================*/\n\n    enum Phase {\n        Guaranteed,\n        Lucky,\n        Open\n    }\n\n    /// @notice Merkle root for the allowed wallets, and their caps (wallet + ETH amount)\n    bytes32 public allowedWalletsMerkleRoot;\n\n    /// @notice Merkle root for the Dice NFTs, and their caps (tokenId + ETH amount)\n    bytes32 public diceNFTsMerkleRoot;\n\n    /// @notice Merkle root for the allowed NFT collections, and their caps (collection + ETH amount)\n    bytes32 public allowedNFTsMerkleRoot;\n\n    /// @notice Merkle root for Open phase alocations (wallet + ETH amount + tokens amount)\n    bytes32 public openPhaseAllocationsMerkleRoot;\n\n    /// @notice Merkle root for Dice NFT eligible tokens (tokenId + tokens amount)\n    bytes32 public diceNFTsTokensEligibleMerkleRoot;\n\n    /// @notice Guaranteed allocation (ETH)\n    uint256 public guaranteedAllocation;\n\n    /// @notice Lucky allocation for each Lucky Tier 1 (ETH)\n    uint256 public luckyAllocationTier1;\n\n    /// @notice Lucky allocation for each Lucky Tier 2 (ETH)\n    uint256 public luckyAllocationTier2;\n\n    /// @notice Lucky allocation for each Lucky Tier 3 (ETH)\n    uint256 public luckyAllocationTier3;\n\n    /// @notice Signer of lucky signatures\n    address public luckySigner;\n\n    /// @notice Guaranteed phase start\n    uint256 public guaranteedStart;\n\n    /// @notice Guaranteed phase end\n    uint256 public guaranteedEnd;\n\n    /// @notice Lucky phase start\n    uint256 public luckyStart;\n\n    /// @notice Lucky phase end\n    uint256 public luckyEnd;\n\n    /// @notice Open phase start\n    uint256 public openStart;\n\n    /// @notice Open phase end\n    uint256 public openEnd;\n\n    /// @notice Wallet cap for the Open phase\n    uint256 public openPhaseWalletCap;\n\n    /// @notice Contribution step for the Open phase\n    uint256 public openPhaseContributionStep;\n\n    /// @notice Guaranteed phase exchange rate\n    uint256 public guaranteedExchangeRate;\n\n    /// @notice Lucky phase Tier 1 exchange rate\n    uint256 public luckyExchangeRate1;\n\n    /// @notice Lucky phase Tier 2 exchange rate\n    uint256 public luckyExchangeRate2;\n\n    /// @notice Lucky phase Tier 3 exchange rate\n    uint256 public luckyExchangeRate3;\n\n    /// @notice Guaranteed phase raised ETH\n    uint256 public guaranteedRaisedETH;\n\n    /// @notice Lucky phase raised ETH\n    uint256 public luckyRaisedETH;\n\n    /// @notice Open phase raised ETH\n    uint256 public openRaisedETH;\n\n    /// @notice Contributed ETH in allowed NFTs (tokenId => amount)\n    mapping(uint256 => uint256) public diceNFTContributed;\n\n    /// @notice Contributed in allowed wallets (wallet => amount)\n    mapping(address => uint256) public allowedWalletContributed;\n\n    /// @notice Contributed in allowed NFTs (collection => (tokenId => amount)\n    mapping(address => mapping(uint256 => uint256)) public allowedNFTContributed;\n\n    /// @notice Contributed in Lucky phase (wallet => amount)\n    mapping(address => uint256) public luckyPhaseContributed;\n\n    /// @notice Contributed in Lucky phase with signature (signature => amount)\n    mapping(bytes => uint256) public raffleTicketContributed;\n\n    /// @notice Contributed in Open phase (wallet => amount)\n    mapping(address => uint256) public openPhaseContributed;\n\n    /// @notice Tokens vestable after contribution (wallet => amount)\n    mapping(address => uint256) public tokensEligible;\n\n    /*==============================================================\n                            MODIFIERS\n    ==============================================================*/\n\n    /// @notice Modifier to check if the phase is active\n    /// @param _phase The phase to check\n    modifier phaseGuard(Phase _phase) {\n        bool isPhaseActive = isPhaseActive(_phase);\n        if (!isPhaseActive) {\n            revert PhaseNotActive(_phase);\n        }\n        _;\n    }\n\n    /// @notice Check if the presale has not started\n    modifier onlyBeforePresale() {\n        if (\n            (guaranteedStart != 0 && block.timestamp > guaranteedStart)\n                || (luckyStart != 0 && block.timestamp > luckyStart) || (openStart != 0 && block.timestamp > openStart)\n        ) {\n            revert OnlyBeforePresale();\n        }\n        _;\n    }\n\n    /// @notice Check if the presale has ended\n    modifier onlyAfterPresale() {\n        if (\n            (guaranteedEnd != 0 && block.timestamp < guaranteedEnd) || (luckyEnd != 0 && block.timestamp < luckyEnd)\n                || (openEnd != 0 && block.timestamp < openEnd)\n        ) {\n            revert OnlyAfterPresale();\n        }\n        _;\n    }\n\n    /*==============================================================\n                            FUNCTIONS\n    ==============================================================*/\n\n    /// @param _diceNFT Address of the Dice NFT\n    /// @param _treasury Address of the wallet that will receive the funds\n    /// @param _initialOwner Address of the initial owner\n    /// @param _delegateRegistryV1 Address of the delegate registry v1\n    /// @param _delegateRegistryV2 Address of the delegate registry v2\n    constructor(\n        address _diceNFT,\n        address _treasury,\n        address _initialOwner,\n        address _delegateRegistryV1,\n        address _delegateRegistryV2\n    ) Ownable(_initialOwner) {\n        diceNFT = _diceNFT;\n        treasury = _treasury;\n        delegateRegistryV1 = IDelegationRegistry(_delegateRegistryV1);\n        delegateRegistryV2 = IDelegateRegistry(_delegateRegistryV2);\n\n        // Domain separator for EIP-712\n        cachedChainId = block.chainid;\n        cachedDomainSeparator = _constructDomainSeparator();\n        cachedThis = address(this);\n    }\n\n    /// @notice Buy tokens with Dice NFTs\n    /// @dev This function allows users to buy tokens with Dice NFTs during the guaranteed phase\n    /// @param _params Array of BuyWithDiceNFTParams\n    function buyWithDiceNFTs(BuyWithDiceNFTParams[] calldata _params) public payable {\n        uint256 ethContributed;\n        for (uint256 i = 0; i < _params.length; i++) {\n            _buyWithDiceNFT(_params[i].amount, _params[i].proof, _params[i].tokenId, _params[i].maxAmount);\n            ethContributed += _params[i].amount;\n        }\n\n        if (ethContributed != msg.value) {\n            revert ContributionAmountMismatch();\n        }\n    }\n\n    /// @notice Buy tokens with a Dice NFT\n    /// @dev This function allows users to buy tokens with a Dice NFT during the guaranteed phase\n    /// @param _proof Merkle proof\n    /// @param _tokenId ID of the NFT\n    /// @param _maxAmount Maximum amount of ETH that can be contributed\n    function buyWithDiceNFT(bytes32[] calldata _proof, uint256 _tokenId, uint256 _maxAmount) external payable {\n        _buyWithDiceNFT(msg.value, _proof, _tokenId, _maxAmount);\n    }\n\n    /// @notice Buy tokens with an allowlisted wallet\n    /// @dev This function relies on the merkle proof to verify the caller's eligibility\n    /// @param _proof Merkle proof\n    /// @param _maxAmount Maximum amount of ETH that can be contributed\n    function buyWithAllowedWallet(bytes32[] calldata _proof, uint256 _maxAmount) external payable {\n        _buyWithAllowedWallet(msg.value, _proof, _maxAmount);\n    }\n\n    /// @notice Buy tokens with an allowlisted wallet\n    /// @param _params AllowedWalletParams\n    function buyWithAllowedNFTs(BuyWithAllowedNFTParams[] calldata _params) external payable {\n        uint256 ethContributed;\n        for (uint256 i = 0; i < _params.length; i++) {\n            _buyWithAllowedNFT(\n                _params[i].amount, _params[i].proof, _params[i].collection, _params[i].tokenId, _params[i].maxAmount\n            );\n            ethContributed += _params[i].amount;\n        }\n\n        if (ethContributed != msg.value) {\n            revert ContributionAmountMismatch();\n        }\n    }\n\n    /// @notice Buy tokens with an allowlisted NFT\n    /// @dev This function allows users to buy tokens with an allowlisted NFT\n    /// @param _proof Merkle proof\n    /// @param _collection Address of the NFT collection\n    /// @param _tokenId ID of the NFT\n    /// @param _maxAmount Maximum amount of ETH that can be contributed\n    function buyWithAllowedNFT(bytes32[] calldata _proof, address _collection, uint256 _tokenId, uint256 _maxAmount)\n        external\n        payable\n    {\n        _buyWithAllowedNFT(msg.value, _proof, _collection, _tokenId, _maxAmount);\n    }\n\n    /// @notice Buy tokens in the Lucky phase\n    /// @dev This function uses a signature to verify the maximum investment amount\n    /// @param _maxAmount Maximum amount of ETH that can be contributed\n    /// @param _signature Signature of the maximum amount and the sender's address\n    function buyLuckyTier(uint256 _maxAmount, bytes calldata _signature) external payable {\n        _buyLuckyTier(msg.value, _maxAmount, _signature);\n    }\n\n    /// @notice Buy tokens in the Open phase\n    function buyOpenPhase() external payable {\n        _buyOpenPhase(msg.value);\n    }\n\n    /// @notice Buy tokens in all phases\n    /// @param _diceNFTParams Array of BuyWithDiceNFTParams\n    /// @param _allowedNFTParams Array of BuyWithAllowedNFTParams\n    /// @param _allowedWalletParams AllowedWalletParams\n    /// @param _luckyPhaseSignature Signature of the maximum amount and the sender's address\n    /// @param _luckyPhaseAmount Amount of ETH to contribute in the lucky phase\n    /// @param _luckyPhaseMaxAmount Maximum amount of ETH that can be contributed in the lucky phase\n    /// @param _openPhaseAmount Amount of ETH to contribute in the open phase\n    function buyAllPhases(\n        BuyWithDiceNFTParams[] calldata _diceNFTParams,\n        BuyWithAllowedNFTParams[] calldata _allowedNFTParams,\n        AllowedWalletParams calldata _allowedWalletParams,\n        bytes calldata _luckyPhaseSignature,\n        uint256 _luckyPhaseAmount,\n        uint256 _luckyPhaseMaxAmount,\n        uint256 _openPhaseAmount\n    ) external payable {\n        uint256 ethContributed;\n\n        uint256 diceNFTParamsLength = _diceNFTParams.length;\n        for (uint256 i = 0; i < diceNFTParamsLength; i++) {\n            BuyWithDiceNFTParams memory param = _diceNFTParams[i];\n            _buyWithDiceNFT(param.amount, _diceNFTParams[i].proof, param.tokenId, param.maxAmount);\n            ethContributed += param.amount;\n        }\n\n        uint256 allowedNFTParamsLength = _allowedNFTParams.length;\n        for (uint256 i = 0; i < allowedNFTParamsLength; i++) {\n            BuyWithAllowedNFTParams memory param = _allowedNFTParams[i];\n            _buyWithAllowedNFT(\n                param.amount, _allowedNFTParams[i].proof, param.collection, param.tokenId, param.maxAmount\n            );\n            ethContributed += param.amount;\n        }\n\n        if (_allowedWalletParams.proof.length > 0) {\n            _buyWithAllowedWallet(\n                _allowedWalletParams.amount, _allowedWalletParams.proof, _allowedWalletParams.maxAmount\n            );\n            ethContributed += _allowedWalletParams.amount;\n        }\n\n        if (_luckyPhaseSignature.length > 0) {\n            _buyLuckyTier(_luckyPhaseAmount, _luckyPhaseMaxAmount, _luckyPhaseSignature);\n            ethContributed += _luckyPhaseAmount;\n        }\n\n        if (_openPhaseAmount > 0) {\n            _buyOpenPhase(_openPhaseAmount);\n            ethContributed += _openPhaseAmount;\n        }\n\n        if (ethContributed != msg.value) {\n            revert ContributionAmountMismatch();\n        }\n    }\n\n    /*==============================================================\n                            VIEW FUNCTIONS\n    ==============================================================*/\n\n    /// @notice Calculate the amount of tokens for a given amount and phase\n    /// @param _amount Amount of ETH to calculate tokens for\n    /// @param _phase Phase to calculate tokens for\n    function calculateTokens(uint256 _amount, Phase _phase) public view returns (uint256 tokens) {\n        if (_phase == Phase.Guaranteed) {\n            tokens = _amount * guaranteedExchangeRate;\n        } else {\n            uint256 remainingETH = _amount;\n            uint256 luckyRaisedETH_ = luckyRaisedETH;\n            uint256 tier1Space = luckyAllocationTier1 > luckyRaisedETH_ ? luckyAllocationTier1 - luckyRaisedETH_ : 0;\n\n            if (tier1Space > 0) {\n                uint256 tier1ETH = remainingETH > tier1Space ? tier1Space : remainingETH;\n                tokens = tier1ETH * luckyExchangeRate1;\n                remainingETH -= tier1ETH;\n                luckyRaisedETH_ += tier1Space;\n            }\n\n            if (remainingETH > 0) {\n                uint256 tier2Space = luckyAllocationTier1 + luckyAllocationTier2 > luckyRaisedETH_\n                    ? luckyAllocationTier1 + luckyAllocationTier2 - luckyRaisedETH_\n                    : 0;\n\n                if (tier2Space > 0) {\n                    uint256 tier2ETH = remainingETH > tier2Space ? tier2Space : remainingETH;\n                    tokens += tier2ETH * luckyExchangeRate2;\n                    remainingETH -= tier2ETH;\n                }\n            }\n\n            if (remainingETH > 0) {\n                tokens += remainingETH * luckyExchangeRate3;\n            }\n        }\n    }\n\n    /// @notice Check if a phase is active\n    /// @param _phase Phase to check\n    /// @return bool\n    function isPhaseActive(Phase _phase) public view returns (bool) {\n        if (_phase == Phase.Guaranteed) {\n            if (\n                guaranteedRaisedETH > guaranteedAllocation\n                    || (block.timestamp < guaranteedStart || block.timestamp > guaranteedEnd)\n            ) {\n                return false;\n            }\n        } else if (_phase == Phase.Lucky) {\n            if (\n                luckyRaisedETH > luckyAllocationTier1 + luckyAllocationTier2 + luckyAllocationTier3\n                    || (block.timestamp < luckyStart || block.timestamp > luckyEnd)\n            ) {\n                return false;\n            }\n        } else if (_phase == Phase.Open) {\n            if (block.timestamp < openStart || block.timestamp > openEnd) {\n                return false;\n            }\n        }\n\n        return true;\n    }\n\n    /*==============================================================\n                       ADMIN FUNCTIONS\n    ==============================================================*/\n\n    /// @notice Set the merkle root for the allowed wallets\n    /// @param _allowedWalletsMerkleRoot Merkle root for the allowed wallets\n    function setAllowedWalletsMerkleRoot(bytes32 _allowedWalletsMerkleRoot) external onlyOwner onlyBeforePresale {\n        allowedWalletsMerkleRoot = _allowedWalletsMerkleRoot;\n        emit AllowedWalletsMerkleRootSet(_allowedWalletsMerkleRoot);\n    }\n\n    /// @notice Set the merkle root for the Dice NFTs\n    /// @param _diceNFTsMerkleRoot Merkle root for the Dice NFTs\n    function setDiceNFTsMerkleRoot(bytes32 _diceNFTsMerkleRoot) external onlyOwner onlyBeforePresale {\n        diceNFTsMerkleRoot = _diceNFTsMerkleRoot;\n        emit DiceNFTsMerkleRootSet(_diceNFTsMerkleRoot);\n    }\n\n    /// @notice Set the merkle root for the allowed NFTs\n    /// @param _allowedNFTsMerkleRoot Merkle root for the allowed NFTs\n    function setAllowedNFTsMerkleRoot(bytes32 _allowedNFTsMerkleRoot) external onlyOwner onlyBeforePresale {\n        allowedNFTsMerkleRoot = _allowedNFTsMerkleRoot;\n        emit AllowedNFTsMerkleRootSet(_allowedNFTsMerkleRoot);\n    }\n\n    /// @notice Set the merkle root for the Open phase allocations\n    /// @param _openPhaseAllocationsMerkleRoot Merkle root for the Open phase allocations\n    function setOpenPhaseAllocationsMerkleRoot(bytes32 _openPhaseAllocationsMerkleRoot)\n        external\n        onlyOwner\n        onlyAfterPresale\n    {\n        openPhaseAllocationsMerkleRoot = _openPhaseAllocationsMerkleRoot;\n        emit OpenPhaseAllocationsMerkleRootSet(_openPhaseAllocationsMerkleRoot);\n    }\n\n    /// @notice Sets the merkle root for the Dice NFTs tokens eligible\n    /// @param _diceNFTsTokensEligibleMerkleRoot Merkle root for the Dice NFTs tokens eligible\n    function setDiceNFTsTokensEligibleMerkleRoot(bytes32 _diceNFTsTokensEligibleMerkleRoot)\n        external\n        onlyOwner\n        onlyAfterPresale\n    {\n        diceNFTsTokensEligibleMerkleRoot = _diceNFTsTokensEligibleMerkleRoot;\n        emit DiceNFTsTokensEligibleMerkleRootSet(_diceNFTsTokensEligibleMerkleRoot);\n    }\n\n    /// @notice Set guaranteed phase start, end and allocation\n    /// @param _guaranteedStart Start time of the guaranteed phase\n    /// @param _guaranteedEnd End time of the guaranteed phase\n    /// @param _guaranteedAllocation Allocation for the guaranteed phase\n    function setGuaranteedPhase(uint256 _guaranteedStart, uint256 _guaranteedEnd, uint256 _guaranteedAllocation)\n        external\n        onlyOwner\n        onlyBeforePresale\n    {\n        guaranteedStart = _guaranteedStart;\n        guaranteedEnd = _guaranteedEnd;\n        guaranteedAllocation = _guaranteedAllocation;\n\n        emit GuaranteedPhaseSet(guaranteedStart, guaranteedEnd, guaranteedAllocation);\n    }\n\n    /// @notice Set Lucky phase start, end, allocations per tier, and wallet cap\n    /// @param _luckyStart Start time of the Lucky phase\n    /// @param _luckyEnd End time of the Lucky phase\n    /// @param _luckyAllocationTier1 Allocation for the first lucky tier1\n    /// @param _luckyAllocationTier2 Allocation for the second lucky tier2\n    /// @param _luckyAllocationTier3 Allocation for the third lucky tier3\n    /// @param _luckySigner Signer of lucky signatures\n    function setLuckyPhase(\n        uint256 _luckyStart,\n        uint256 _luckyEnd,\n        uint256 _luckyAllocationTier1,\n        uint256 _luckyAllocationTier2,\n        uint256 _luckyAllocationTier3,\n        address _luckySigner\n    ) external onlyOwner onlyBeforePresale {\n        luckyStart = _luckyStart;\n        luckyEnd = _luckyEnd;\n        luckyAllocationTier1 = _luckyAllocationTier1;\n        luckyAllocationTier2 = _luckyAllocationTier2;\n        luckyAllocationTier3 = _luckyAllocationTier3;\n        luckySigner = _luckySigner;\n\n        emit LuckyPhaseSet(\n            _luckyStart, _luckyEnd, _luckyAllocationTier1, _luckyAllocationTier2, _luckyAllocationTier3, _luckySigner\n        );\n    }\n\n    /// @notice Set Open phase start, end and allocation\n    /// @param _openStart Start time of the open phase\n    /// @param _openEnd End time of the open phase\n    function setOpenPhase(\n        uint256 _openStart,\n        uint256 _openEnd,\n        uint256 _openPhaseWalletCap,\n        uint256 _openPhaseContributionStep\n    ) external onlyOwner onlyBeforePresale {\n        openStart = _openStart;\n        openEnd = _openEnd;\n        openPhaseWalletCap = _openPhaseWalletCap;\n        openPhaseContributionStep = _openPhaseContributionStep;\n\n        emit OpenPhaseSet(_openStart, _openEnd, _openPhaseWalletCap, _openPhaseContributionStep);\n    }\n\n    /// @notice Set the exchange rates for each phase\n    /// @param _guaranteedExchangeRate Exchange rate for the guaranteed phase\n    /// @param _luckyExchangeRate1 Exchange rate for the first lucky phase\n    /// @param _luckyExchangeRate2 Exchange rate for the second lucky phase\n    /// @param _luckyExchangeRate3 Exchange rate for the third lucky phase\n    function setExchangeRates(\n        uint256 _guaranteedExchangeRate,\n        uint256 _luckyExchangeRate1,\n        uint256 _luckyExchangeRate2,\n        uint256 _luckyExchangeRate3\n    ) external onlyOwner onlyBeforePresale {\n        guaranteedExchangeRate = _guaranteedExchangeRate;\n        luckyExchangeRate1 = _luckyExchangeRate1;\n        luckyExchangeRate2 = _luckyExchangeRate2;\n        luckyExchangeRate3 = _luckyExchangeRate3;\n\n        emit ExchangeRatesSet(_guaranteedExchangeRate, _luckyExchangeRate1, _luckyExchangeRate2, _luckyExchangeRate3);\n    }\n\n    /// @notice Pause the purchase functions, only owner can call this function\n    function pause() external onlyOwner {\n        _pause();\n    }\n\n    /// @notice Unpause the purchase functions, only owner can call this function\n    function unpause() external onlyOwner {\n        _unpause();\n    }\n\n    /*==============================================================\n                       INTERNAL FUNCTIONS\n    ==============================================================*/\n\n    function _buyWithDiceNFT(uint256 _amount, bytes32[] calldata _proof, uint256 _tokenId, uint256 _maxAmount)\n        internal\n        nonReentrant\n        whenNotPaused\n        phaseGuard(Phase.Guaranteed)\n    {\n        _verifyTokenOwner(diceNFT, _tokenId);\n        _verifyDiceNFTProof(_proof, _tokenId, _maxAmount);\n\n        // check if contribution cap is not exceeded\n        if (diceNFTContributed[_tokenId] + _amount > _maxAmount) {\n            revert ExceededDiceNFTCap(_tokenId);\n        }\n\n        // check if total contribution cap is not exceeded\n        if (guaranteedRaisedETH + _amount > guaranteedAllocation) {\n            revert ExceededGuaranteedAllocation();\n        }\n\n        // update contributed amount, tokens eligible & total sold\n        uint256 tokensAmount = calculateTokens(_amount, Phase.Guaranteed);\n        tokensEligible[msg.sender] += tokensAmount;\n        diceNFTContributed[_tokenId] += _amount;\n        guaranteedRaisedETH += _amount;\n\n        // transfer ETH to receiver wallet\n        (bool success,) = treasury.call{value: _amount}(\"\");\n        if (!success) {\n            revert TransferFailed(treasury, _amount);\n        }\n\n        emit ContributedDiceNFT(msg.sender, _amount, tokensAmount, _tokenId);\n    }\n\n    /// @notice Buy tokens with an allowlisted NFT\n    /// @param _amount Amount of ETH to contribute\n    /// @param _proof Merkle proof\n    /// @param _collection Address of the NFT collection\n    /// @param _tokenId ID of the NFT\n    /// @param _maxAmount Maximum amount of ETH that can be contributed\n    function _buyWithAllowedNFT(\n        uint256 _amount,\n        bytes32[] calldata _proof,\n        address _collection,\n        uint256 _tokenId,\n        uint256 _maxAmount\n    ) internal nonReentrant whenNotPaused phaseGuard(Phase.Guaranteed) {\n        _verifyTokenOwner(_collection, _tokenId);\n        _verifyAllowedNFTProof(_proof, _collection, _maxAmount);\n\n        // check if total contribution cap is not exceeded\n        if (guaranteedRaisedETH + _amount > guaranteedAllocation) {\n            revert ExceededGuaranteedAllocation();\n        }\n\n        // check if NFT cap is not exceeded\n        if (allowedNFTContributed[_collection][_tokenId] + _amount > _maxAmount) {\n            revert ExceededNFTCap(_collection, _tokenId);\n        }\n\n        // update contributed amount, tokens eligible & total sold\n        uint256 tokensAmount = calculateTokens(_amount, Phase.Guaranteed);\n        tokensEligible[msg.sender] += tokensAmount;\n        allowedNFTContributed[_collection][_tokenId] += _amount;\n        guaranteedRaisedETH += _amount;\n\n        // transfer ETH to receiver wallet\n        (bool success,) = treasury.call{value: _amount}(\"\");\n        if (!success) {\n            revert TransferFailed(treasury, _amount);\n        }\n\n        emit ContributedAllowedNFT(msg.sender, _amount, tokensAmount, _collection, _tokenId);\n    }\n\n    /// @notice Buy tokens with an allowlisted wallet\n    /// @param _amount Amount of ETH to contribute\n    /// @param _proof Merkle proof\n    /// @param _maxAmount Maximum amount of ETH that can be contributed\n    function _buyWithAllowedWallet(uint256 _amount, bytes32[] calldata _proof, uint256 _maxAmount)\n        internal\n        nonReentrant\n        whenNotPaused\n        phaseGuard(Phase.Guaranteed)\n    {\n        _verifyAllowedWalletProof(_proof, _maxAmount);\n\n        // check if contribution cap is not exceeded\n        if (allowedWalletContributed[msg.sender] + _amount > _maxAmount) {\n            revert ExceededAllowedWalletCap(msg.sender);\n        }\n\n        // check if total contribution cap is not exceeded\n        if (guaranteedRaisedETH + _amount > guaranteedAllocation) {\n            revert ExceededGuaranteedAllocation();\n        }\n\n        // Update contributed amount, tokens eligible & total sold\n        uint256 tokensAmount = calculateTokens(_amount, Phase.Guaranteed);\n        tokensEligible[msg.sender] += tokensAmount;\n        allowedWalletContributed[msg.sender] += _amount;\n        guaranteedRaisedETH += _amount;\n\n        // Transfer ETH to receiver wallet\n        (bool success,) = treasury.call{value: _amount}(\"\");\n        if (!success) {\n            revert TransferFailed(treasury, _amount);\n        }\n\n        emit ContributedAllowedWallet(msg.sender, _amount, tokensAmount);\n    }\n\n    /// @notice Buy tokens in the Lucky phase\n    /// @param _amount Amount of ETH to contribute\n    /// @param _maxAmount Maximum amount of ETH that can be contributed\n    /// @param _signature Signature of the maximum amount and the sender's address\n    function _buyLuckyTier(uint256 _amount, uint256 _maxAmount, bytes calldata _signature)\n        internal\n        nonReentrant\n        whenNotPaused\n        phaseGuard(Phase.Lucky)\n    {\n        _verifyLuckySignature(_maxAmount, _signature);\n\n        if (raffleTicketContributed[_signature] + _amount > _maxAmount) {\n            revert ExceededRaffleTicketContribution();\n        } else if (luckyRaisedETH + _amount > luckyAllocationTier1 + luckyAllocationTier2 + luckyAllocationTier3) {\n            revert ExceededLuckyAllocation();\n        }\n\n        // update contributed amounts for raffle ticket and per-wallet, tokens eligible & total sold\n        uint256 tokensAmount = calculateTokens(_amount, Phase.Lucky);\n        tokensEligible[msg.sender] += tokensAmount;\n        raffleTicketContributed[_signature] += _amount;\n        luckyPhaseContributed[msg.sender] += _amount;\n        luckyRaisedETH += _amount;\n\n        // transfer ETH to receiver wallet\n        (bool success,) = treasury.call{value: _amount}(\"\");\n        if (!success) {\n            revert TransferFailed(treasury, _amount);\n        }\n\n        emit ContributedLuckyPhase(msg.sender, _amount, tokensAmount);\n    }\n\n    /// @notice Buy tokens in the Open phase\n    /// @param _amount Amount of ETH to contribute\n    function _buyOpenPhase(uint256 _amount) internal nonReentrant whenNotPaused phaseGuard(Phase.Open) {\n        if (_amount % openPhaseContributionStep != 0) {\n            revert IncorrectContributionStep();\n        }\n\n        if (openPhaseContributed[msg.sender] + _amount > openPhaseWalletCap) {\n            revert ExceededOpenPhaseWalletCap(msg.sender);\n        }\n\n        openPhaseContributed[msg.sender] += _amount;\n        openRaisedETH += _amount;\n\n        // transfer ETH to receiver wallet\n        (bool success,) = treasury.call{value: _amount}(\"\");\n        if (!success) {\n            revert TransferFailed(treasury, _amount);\n        }\n\n        emit ContributedOpenPhase(msg.sender, _amount);\n    }\n\n    /// @notice Verifies if the sender is the owner of a given token or a valid delegate.\n    /// @param _collection The address of the collection contract.\n    /// @param _tokenId The token ID to verify ownership or delegation for.\n    function _verifyTokenOwner(address _collection, uint256 _tokenId) internal view {\n        address _tokenOwner = IERC721(_collection).ownerOf(_tokenId);\n\n        // Check sender is owner\n        if (_tokenOwner == msg.sender) {\n            return;\n        }\n\n        // Check with delegate registry v2\n        if (delegateRegistryV2.checkDelegateForERC721(msg.sender, _tokenOwner, _collection, _tokenId, \"\")) {\n            return;\n        }\n\n        // Check with delegate registry v1\n        if (delegateRegistryV1.checkDelegateForToken(msg.sender, _tokenOwner, _collection, _tokenId)) {\n            return;\n        }\n\n        // Revert if not owner or delegate\n        revert NotTokenOwner(_collection, _tokenId);\n    }\n\n    /// @notice Verify the signature of the maximum amount and the sender's address\n    /// @param _maxAmount Maximum amount of ETH that can be contributed\n    /// @param _signature Signature of the maximum amount and the sender's address\n    function _verifyLuckySignature(uint256 _maxAmount, bytes calldata _signature) internal view {\n        bytes32 signedMessageHash = MessageHashUtils.toEthSignedMessageHash(\n            keccak256(abi.encode(_getDomainSeparator(), _maxAmount, msg.sender))\n        );\n        address recoveredOwner = ECDSA.recover(signedMessageHash, _signature);\n\n        if (recoveredOwner != luckySigner) {\n            revert InvalidSignature();\n        }\n    }\n\n    /// @notice Verify the merkle proof\n    /// @param _proof The merkle proof\n    /// @param _maxAmount The amount to verify\n    function _verifyAllowedWalletProof(bytes32[] calldata _proof, uint256 _maxAmount) internal view {\n        bytes32 leaf = keccak256(bytes.concat(keccak256(abi.encode(msg.sender, _maxAmount))));\n        if (!MerkleProof.verify(_proof, allowedWalletsMerkleRoot, leaf)) {\n            revert InvalidAllowedWalletProof();\n        }\n    }\n\n    /// @notice Verify the merkle proof\n    /// @param _proof The merkle proof\n    /// @param _tokenId The token ID to verify\n    /// @param _maxAmount The amount to verify\n    function _verifyDiceNFTProof(bytes32[] calldata _proof, uint256 _tokenId, uint256 _maxAmount) internal view {\n        bytes32 leaf = keccak256(bytes.concat(keccak256(abi.encode(_tokenId, _maxAmount))));\n        if (!MerkleProof.verify(_proof, diceNFTsMerkleRoot, leaf)) {\n            revert InvalidDiceNFTProof();\n        }\n    }\n\n    /// @notice Verify the merkle proof\n    /// @param _proof The merkle proof\n    /// @param _collection Collection address\n    /// @param _maxAmount The amount to verify\n    function _verifyAllowedNFTProof(bytes32[] calldata _proof, address _collection, uint256 _maxAmount) internal view {\n        bytes32 leaf = keccak256(bytes.concat(keccak256(abi.encode(_collection, _maxAmount))));\n        if (!MerkleProof.verify(_proof, allowedNFTsMerkleRoot, leaf)) {\n            revert InvalidAllowedNFTProof();\n        }\n    }\n\n    /// @notice Get the domain separator\n    function _getDomainSeparator() internal view returns (bytes32) {\n        if (address(this) == cachedThis && block.chainid == cachedChainId) {\n            return cachedDomainSeparator;\n        } else {\n            return _constructDomainSeparator();\n        }\n    }\n\n    /// @notice Construct the domain separator\n    function _constructDomainSeparator() internal view returns (bytes32) {\n        return keccak256(abi.encode(DOMAIN_TYPEHASH, block.chainid, address(this)));\n    }\n\n    /*==============================================================\n                            EVENTS\n    ==============================================================*/\n\n    /// @notice Emitted when the merkle root for the allowed wallets is set\n    /// @param allowedWalletsMerkleRoot The merkle root for the allowed wallets\n    event AllowedWalletsMerkleRootSet(bytes32 indexed allowedWalletsMerkleRoot);\n\n    /// @notice Emitted when the merkle root for the Dice NFTs is set\n    /// @param diceNFTsMerkleRoot The merkle root for the Dice NFTs\n    event DiceNFTsMerkleRootSet(bytes32 indexed diceNFTsMerkleRoot);\n\n    /// @notice Emitted when the merkle root for the allowed NFTs is set\n    /// @param allowedNFTsMerkleRoot The merkle root for the allowed NFTs\n    event AllowedNFTsMerkleRootSet(bytes32 indexed allowedNFTsMerkleRoot);\n\n    /// @notice Emitted when the merkle root for the open phase allocations is set\n    /// @param openPhaseAllocationsMerkleRoot The merkle root for the open phase allocations\n    event OpenPhaseAllocationsMerkleRootSet(bytes32 indexed openPhaseAllocationsMerkleRoot);\n\n    /// @notice Emitted when the merkle root for the Dice NFTs tokens eligible is set\n    /// @param diceNFTsTokensEligibleMerkleRootSet The merkle root for the Dice NFTs tokens eligible\n    event DiceNFTsTokensEligibleMerkleRootSet(bytes32 indexed diceNFTsTokensEligibleMerkleRootSet);\n\n    /// @notice Emitted when the exchange rates for each phase are set\n    event ExchangeRatesSet(\n        uint256 guaranteedExchangeRate,\n        uint256 luckyExchangeRate1,\n        uint256 luckyExchangeRate2,\n        uint256 luckyExchangeRate3\n    );\n\n    /// @notice Emitted when the allocations for the guaranteed phase are set\n    /// @param guaranteedStart Start time of the guaranteed phase\n    /// @param guaranteedEnd End time of the guaranteed phase\n    /// @param guaranteedAllocation Allocation for the guaranteed phase\n    event GuaranteedPhaseSet(\n        uint256 indexed guaranteedStart, uint256 indexed guaranteedEnd, uint256 indexed guaranteedAllocation\n    );\n\n    /// @notice Emitted when the allocations for the lucky phase are set\n    /// @param luckyStart Start time of the Lucky phase\n    /// @param luckyEnd End time of the Lucky phase\n    /// @param luckyAllocationTier1 Allocation for the first lucky tier1\n    /// @param luckyAllocationTier2 Allocation for the second lucky tier2\n    /// @param luckyAllocationTier3 Allocation for the third lucky tier3\n    /// @param luckySigner Signer of lucky signatures\n    event LuckyPhaseSet(\n        uint256 luckyStart,\n        uint256 luckyEnd,\n        uint256 luckyAllocationTier1,\n        uint256 luckyAllocationTier2,\n        uint256 luckyAllocationTier3,\n        address luckySigner\n    );\n\n    /// @notice Emitted when the allocations for the open phase are set\n    /// @param openStart Start time of the Open phase\n    /// @param openEnd End time of the Open phase\n    /// @param openPhaseWalletCap Wallet cap for the Open phase\n    /// @param openPhaseContributionStep Contribution step for the Open phase\n    event OpenPhaseSet(\n        uint256 openStart, uint256 openEnd, uint256 openPhaseWalletCap, uint256 openPhaseContributionStep\n    );\n\n    /// @notice Emitted when a contributor buys tokens\n    /// @param contributor The address of the contributor\n    /// @param amount The amount of ETH contributed\n    event Contributed(address indexed contributor, uint256 indexed amount);\n\n    /// @notice Emitted when a contributor buys tokens with allowed wallet\n    /// @param contributor The address of the contributor\n    /// @param amount The amount of ETH contributed\n    /// @param tokensAmount The amount of tokens contributed\n    event ContributedAllowedWallet(address indexed contributor, uint256 indexed amount, uint256 indexed tokensAmount);\n\n    /// @notice Emitted when a contributor buys tokens with a Dice NFT\n    /// @param contributor The address of the contributor\n    /// @param amount The amount of ETH contributed\n    /// @param tokensAmount The amount of tokens contributed\n    /// @param tokenId The token ID contributed for\n    event ContributedDiceNFT(\n        address indexed contributor, uint256 indexed amount, uint256 indexed tokensAmount, uint256 tokenId\n    );\n\n    /// @notice Emitted when a contributor buys tokens with an allowlisted NFT\n    /// @param contributor The address of the contributor\n    /// @param amount The amount of ETH contributed\n    /// @param tokensAmount The amount of tokens contributed\n    /// @param collection The address of the NFT collection\n    /// @param tokenId The token ID contributed for\n    event ContributedAllowedNFT(\n        address indexed contributor,\n        uint256 indexed amount,\n        uint256 indexed tokensAmount,\n        address collection,\n        uint256 tokenId\n    );\n\n    /// @notice Emitted when a contributor buys tokens in the Lucky phase\n    /// @param contributor The address of the contributor\n    /// @param amount The amount of ETH contributed\n    /// @param tokensAmount The amount of tokens contributed\n    event ContributedLuckyPhase(address indexed contributor, uint256 indexed amount, uint256 indexed tokensAmount);\n\n    /// @notice Emitted when a contributor buys tokens in the Open phase\n    /// @param contributor The address of the contributor\n    /// @param amount The amount of ETH contributed\n    event ContributedOpenPhase(address indexed contributor, uint256 indexed amount);\n\n    /*==============================================================\n                            ERRORS\n    ==============================================================*/\n\n    /// @notice Revert if the transfer of funds fails\n    /// @param recipient The address of the recipient\n    /// @param amount The amount of funds refunded\n    error TransferFailed(address recipient, uint256 amount);\n\n    /// @notice Reverse if the signature is invalid\n    error InvalidSignature();\n\n    /// @notice Revert if the merkle proof for allowed wallet is invalid\n    error InvalidAllowedWalletProof();\n\n    /// @notice Revert if the merkle proof for Dice NFT is invalid\n    error InvalidDiceNFTProof();\n\n    /// @notice Revert if the merkle proof for allowed NFT is invalid\n    error InvalidAllowedNFTProof();\n\n    /// @notice Revert if the Dice NFT cap is exceeded\n    error ExceededDiceNFTCap(uint256 tokenId);\n\n    /// @notice Revert if the NFT cap is exceeded\n    error ExceededNFTCap(address collection, uint256 tokenId);\n\n    /// @notice Revert if the guaranteed allocation is exceeded\n    error ExceededGuaranteedAllocation();\n\n    /// @notice Revert if the contribution amount is incorrect\n    error ContributionAmountMismatch();\n\n    /// @notice Revert if the lucky allocation is exceeded\n    error ExceededLuckyAllocation();\n\n    /// @notice Revert if the wallet cap is exceeded\n    error ExceededAllowedWalletCap(address wallet);\n\n    /// @notice Revert if the raffle ticket contribution is exceeded\n    error ExceededOpenPhaseWalletCap(address wallet);\n\n    /// @notice Revert if the contribution is not divisible by the step\n    error IncorrectContributionStep();\n\n    /// @notice Revert if the raffle ticket contribution is exceeded\n    error ExceededRaffleTicketContribution();\n\n    /// @notice Revert if the phase is not active\n    error PhaseNotActive(Phase phase);\n\n    /// @notice Revert if the caller is not the owner of the token or a valid delegate.\n    /// @param collection The address of the collection contract.\n    /// @param tokenId The token ID to verify ownership or delegation for.\n    error NotTokenOwner(address collection, uint256 tokenId);\n\n    /// @notice Revert if presale has started\n    error OnlyBeforePresale();\n\n    /// @notice Revert if presale has ended\n    error OnlyAfterPresale();\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/MerkleProof.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev These functions deal with verification of Merkle Tree proofs.\n *\n * The tree and the proofs can be generated using our\n * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].\n * You will find a quickstart guide in the readme.\n *\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\n * hashing, or use a hash function other than keccak256 for hashing leaves.\n * This is because the concatenation of a sorted pair of internal nodes in\n * the Merkle tree could be reinterpreted as a leaf value.\n * OpenZeppelin's JavaScript library generates Merkle trees that are safe\n * against this attack out of the box.\n */\nlibrary MerkleProof {\n    /**\n     *@dev The multiproof provided is not valid.\n     */\n    error MerkleProofInvalidMultiproof();\n\n    /**\n     * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\n     * defined by `root`. For this, a `proof` must be provided, containing\n     * sibling hashes on the branch from the leaf to the root of the tree. Each\n     * pair of leaves and each pair of pre-images are assumed to be sorted.\n     */\n    function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n        return processProof(proof, leaf) == root;\n    }\n\n    /**\n     * @dev Calldata version of {verify}\n     */\n    function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n        return processProofCalldata(proof, leaf) == root;\n    }\n\n    /**\n     * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\n     * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\n     * hash matches the root of the tree. When processing the proof, the pairs\n     * of leafs & pre-images are assumed to be sorted.\n     */\n    function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\n        bytes32 computedHash = leaf;\n        for (uint256 i = 0; i < proof.length; i++) {\n            computedHash = _hashPair(computedHash, proof[i]);\n        }\n        return computedHash;\n    }\n\n    /**\n     * @dev Calldata version of {processProof}\n     */\n    function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {\n        bytes32 computedHash = leaf;\n        for (uint256 i = 0; i < proof.length; i++) {\n            computedHash = _hashPair(computedHash, proof[i]);\n        }\n        return computedHash;\n    }\n\n    /**\n     * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a Merkle tree defined by\n     * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.\n     *\n     * CAUTION: Not all Merkle trees admit multiproofs. See {processMultiProof} for details.\n     */\n    function multiProofVerify(\n        bytes32[] memory proof,\n        bool[] memory proofFlags,\n        bytes32 root,\n        bytes32[] memory leaves\n    ) internal pure returns (bool) {\n        return processMultiProof(proof, proofFlags, leaves) == root;\n    }\n\n    /**\n     * @dev Calldata version of {multiProofVerify}\n     *\n     * CAUTION: Not all Merkle trees admit multiproofs. See {processMultiProof} for details.\n     */\n    function multiProofVerifyCalldata(\n        bytes32[] calldata proof,\n        bool[] calldata proofFlags,\n        bytes32 root,\n        bytes32[] memory leaves\n    ) internal pure returns (bool) {\n        return processMultiProofCalldata(proof, proofFlags, leaves) == root;\n    }\n\n    /**\n     * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction\n     * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another\n     * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false\n     * respectively.\n     *\n     * CAUTION: Not all Merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree\n     * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the\n     * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).\n     */\n    function processMultiProof(\n        bytes32[] memory proof,\n        bool[] memory proofFlags,\n        bytes32[] memory leaves\n    ) internal pure returns (bytes32 merkleRoot) {\n        // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n        // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n        // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n        // the Merkle tree.\n        uint256 leavesLen = leaves.length;\n        uint256 proofLen = proof.length;\n        uint256 totalHashes = proofFlags.length;\n\n        // Check proof validity.\n        if (leavesLen + proofLen != totalHashes + 1) {\n            revert MerkleProofInvalidMultiproof();\n        }\n\n        // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n        // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n        bytes32[] memory hashes = new bytes32[](totalHashes);\n        uint256 leafPos = 0;\n        uint256 hashPos = 0;\n        uint256 proofPos = 0;\n        // At each step, we compute the next hash using two values:\n        // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n        //   get the next hash.\n        // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n        //   `proof` array.\n        for (uint256 i = 0; i < totalHashes; i++) {\n            bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n            bytes32 b = proofFlags[i]\n                ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n                : proof[proofPos++];\n            hashes[i] = _hashPair(a, b);\n        }\n\n        if (totalHashes > 0) {\n            if (proofPos != proofLen) {\n                revert MerkleProofInvalidMultiproof();\n            }\n            unchecked {\n                return hashes[totalHashes - 1];\n            }\n        } else if (leavesLen > 0) {\n            return leaves[0];\n        } else {\n            return proof[0];\n        }\n    }\n\n    /**\n     * @dev Calldata version of {processMultiProof}.\n     *\n     * CAUTION: Not all Merkle trees admit multiproofs. See {processMultiProof} for details.\n     */\n    function processMultiProofCalldata(\n        bytes32[] calldata proof,\n        bool[] calldata proofFlags,\n        bytes32[] memory leaves\n    ) internal pure returns (bytes32 merkleRoot) {\n        // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n        // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n        // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n        // the Merkle tree.\n        uint256 leavesLen = leaves.length;\n        uint256 proofLen = proof.length;\n        uint256 totalHashes = proofFlags.length;\n\n        // Check proof validity.\n        if (leavesLen + proofLen != totalHashes + 1) {\n            revert MerkleProofInvalidMultiproof();\n        }\n\n        // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n        // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n        bytes32[] memory hashes = new bytes32[](totalHashes);\n        uint256 leafPos = 0;\n        uint256 hashPos = 0;\n        uint256 proofPos = 0;\n        // At each step, we compute the next hash using two values:\n        // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n        //   get the next hash.\n        // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n        //   `proof` array.\n        for (uint256 i = 0; i < totalHashes; i++) {\n            bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n            bytes32 b = proofFlags[i]\n                ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n                : proof[proofPos++];\n            hashes[i] = _hashPair(a, b);\n        }\n\n        if (totalHashes > 0) {\n            if (proofPos != proofLen) {\n                revert MerkleProofInvalidMultiproof();\n            }\n            unchecked {\n                return hashes[totalHashes - 1];\n            }\n        } else if (leavesLen > 0) {\n            return leaves[0];\n        } else {\n            return proof[0];\n        }\n    }\n\n    /**\n     * @dev Sorts the pair (a, b) and hashes the result.\n     */\n    function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {\n        return a < b ? _efficientHash(a, b) : _efficientHash(b, a);\n    }\n\n    /**\n     * @dev Implementation of keccak256(abi.encode(a, b)) that doesn't allocate or expand memory.\n     */\n    function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            mstore(0x00, a)\n            mstore(0x20, b)\n            value := keccak256(0x00, 0x40)\n        }\n    }\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/ECDSA.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n    enum RecoverError {\n        NoError,\n        InvalidSignature,\n        InvalidSignatureLength,\n        InvalidSignatureS\n    }\n\n    /**\n     * @dev The signature derives the `address(0)`.\n     */\n    error ECDSAInvalidSignature();\n\n    /**\n     * @dev The signature has an invalid length.\n     */\n    error ECDSAInvalidSignatureLength(uint256 length);\n\n    /**\n     * @dev The signature has an S value that is in the upper half order.\n     */\n    error ECDSAInvalidSignatureS(bytes32 s);\n\n    /**\n     * @dev Returns the address that signed a hashed message (`hash`) with `signature` or an error. This will not\n     * return address(0) without also returning an error description. Errors are documented using an enum (error type)\n     * and a bytes32 providing additional information about the error.\n     *\n     * If no error is returned, then the address can be used for verification purposes.\n     *\n     * The `ecrecover` EVM precompile allows for malleable (non-unique) signatures:\n     * this function rejects them by requiring the `s` value to be in the lower\n     * half order, and the `v` value to be either 27 or 28.\n     *\n     * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n     * verification to be secure: it is possible to craft signatures that\n     * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n     * this is by receiving a hash of the original message (which may otherwise\n     * be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it.\n     *\n     * Documentation for signature generation:\n     * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n     * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n     */\n    function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError, bytes32) {\n        if (signature.length == 65) {\n            bytes32 r;\n            bytes32 s;\n            uint8 v;\n            // ecrecover takes the signature parameters, and the only way to get them\n            // currently is to use assembly.\n            /// @solidity memory-safe-assembly\n            assembly {\n                r := mload(add(signature, 0x20))\n                s := mload(add(signature, 0x40))\n                v := byte(0, mload(add(signature, 0x60)))\n            }\n            return tryRecover(hash, v, r, s);\n        } else {\n            return (address(0), RecoverError.InvalidSignatureLength, bytes32(signature.length));\n        }\n    }\n\n    /**\n     * @dev Returns the address that signed a hashed message (`hash`) with\n     * `signature`. This address can then be used for verification purposes.\n     *\n     * The `ecrecover` EVM precompile allows for malleable (non-unique) signatures:\n     * this function rejects them by requiring the `s` value to be in the lower\n     * half order, and the `v` value to be either 27 or 28.\n     *\n     * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n     * verification to be secure: it is possible to craft signatures that\n     * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n     * this is by receiving a hash of the original message (which may otherwise\n     * be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it.\n     */\n    function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n        (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, signature);\n        _throwError(error, errorArg);\n        return recovered;\n    }\n\n    /**\n     * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n     *\n     * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n     */\n    function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError, bytes32) {\n        unchecked {\n            bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n            // We do not check for an overflow here since the shift operation results in 0 or 1.\n            uint8 v = uint8((uint256(vs) >> 255) + 27);\n            return tryRecover(hash, v, r, s);\n        }\n    }\n\n    /**\n     * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n     */\n    function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n        (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, r, vs);\n        _throwError(error, errorArg);\n        return recovered;\n    }\n\n    /**\n     * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n     * `r` and `s` signature fields separately.\n     */\n    function tryRecover(\n        bytes32 hash,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) internal pure returns (address, RecoverError, bytes32) {\n        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n        // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n        // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n        // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n        //\n        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n        // these malleable signatures as well.\n        if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n            return (address(0), RecoverError.InvalidSignatureS, s);\n        }\n\n        // If the signature is valid (and not malleable), return the signer address\n        address signer = ecrecover(hash, v, r, s);\n        if (signer == address(0)) {\n            return (address(0), RecoverError.InvalidSignature, bytes32(0));\n        }\n\n        return (signer, RecoverError.NoError, bytes32(0));\n    }\n\n    /**\n     * @dev Overload of {ECDSA-recover} that receives the `v`,\n     * `r` and `s` signature fields separately.\n     */\n    function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n        (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, v, r, s);\n        _throwError(error, errorArg);\n        return recovered;\n    }\n\n    /**\n     * @dev Optionally reverts with the corresponding custom error according to the `error` argument provided.\n     */\n    function _throwError(RecoverError error, bytes32 errorArg) private pure {\n        if (error == RecoverError.NoError) {\n            return; // no error: do nothing\n        } else if (error == RecoverError.InvalidSignature) {\n            revert ECDSAInvalidSignature();\n        } else if (error == RecoverError.InvalidSignatureLength) {\n            revert ECDSAInvalidSignatureLength(uint256(errorArg));\n        } else if (error == RecoverError.InvalidSignatureS) {\n            revert ECDSAInvalidSignatureS(errorArg);\n        }\n    }\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/utils/cryptography/MessageHashUtils.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/MessageHashUtils.sol)\n\npragma solidity ^0.8.20;\n\nimport {Strings} from \"../Strings.sol\";\n\n/**\n * @dev Signature message hash utilities for producing digests to be consumed by {ECDSA} recovery or signing.\n *\n * The library provides methods for generating a hash of a message that conforms to the\n * https://eips.ethereum.org/EIPS/eip-191[EIP 191] and https://eips.ethereum.org/EIPS/eip-712[EIP 712]\n * specifications.\n */\nlibrary MessageHashUtils {\n    /**\n     * @dev Returns the keccak256 digest of an EIP-191 signed data with version\n     * `0x45` (`personal_sign` messages).\n     *\n     * The digest is calculated by prefixing a bytes32 `messageHash` with\n     * `\"\\x19Ethereum Signed Message:\\n32\"` and hashing the result. It corresponds with the\n     * hash signed when using the https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] JSON-RPC method.\n     *\n     * NOTE: The `messageHash` parameter is intended to be the result of hashing a raw message with\n     * keccak256, although any bytes32 value can be safely used because the final digest will\n     * be re-hashed.\n     *\n     * See {ECDSA-recover}.\n     */\n    function toEthSignedMessageHash(bytes32 messageHash) internal pure returns (bytes32 digest) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            mstore(0x00, \"\\x19Ethereum Signed Message:\\n32\") // 32 is the bytes-length of messageHash\n            mstore(0x1c, messageHash) // 0x1c (28) is the length of the prefix\n            digest := keccak256(0x00, 0x3c) // 0x3c is the length of the prefix (0x1c) + messageHash (0x20)\n        }\n    }\n\n    /**\n     * @dev Returns the keccak256 digest of an EIP-191 signed data with version\n     * `0x45` (`personal_sign` messages).\n     *\n     * The digest is calculated by prefixing an arbitrary `message` with\n     * `\"\\x19Ethereum Signed Message:\\n\" + len(message)` and hashing the result. It corresponds with the\n     * hash signed when using the https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] JSON-RPC method.\n     *\n     * See {ECDSA-recover}.\n     */\n    function toEthSignedMessageHash(bytes memory message) internal pure returns (bytes32) {\n        return\n            keccak256(bytes.concat(\"\\x19Ethereum Signed Message:\\n\", bytes(Strings.toString(message.length)), message));\n    }\n\n    /**\n     * @dev Returns the keccak256 digest of an EIP-191 signed data with version\n     * `0x00` (data with intended validator).\n     *\n     * The digest is calculated by prefixing an arbitrary `data` with `\"\\x19\\x00\"` and the intended\n     * `validator` address. Then hashing the result.\n     *\n     * See {ECDSA-recover}.\n     */\n    function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {\n        return keccak256(abi.encodePacked(hex\"19_00\", validator, data));\n    }\n\n    /**\n     * @dev Returns the keccak256 digest of an EIP-712 typed data (EIP-191 version `0x01`).\n     *\n     * The digest is calculated from a `domainSeparator` and a `structHash`, by prefixing them with\n     * `\\x19\\x01` and hashing the result. It corresponds to the hash signed by the\n     * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] JSON-RPC method as part of EIP-712.\n     *\n     * See {ECDSA-recover}.\n     */\n    function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 digest) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let ptr := mload(0x40)\n            mstore(ptr, hex\"19_01\")\n            mstore(add(ptr, 0x02), domainSeparator)\n            mstore(add(ptr, 0x22), structHash)\n            digest := keccak256(ptr, 0x42)\n        }\n    }\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/IERC721.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC165} from \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC721 compliant contract.\n */\ninterface IERC721 is IERC165 {\n    /**\n     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n    /**\n     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n     */\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n    /**\n     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n     */\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n    /**\n     * @dev Returns the number of tokens in ``owner``'s account.\n     */\n    function balanceOf(address owner) external view returns (uint256 balance);\n\n    /**\n     * @dev Returns the owner of the `tokenId` token.\n     *\n     * Requirements:\n     *\n     * - `tokenId` must exist.\n     */\n    function ownerOf(uint256 tokenId) external view returns (address owner);\n\n    /**\n     * @dev Safely transfers `tokenId` token from `from` to `to`.\n     *\n     * Requirements:\n     *\n     * - `from` cannot be the zero address.\n     * - `to` cannot be the zero address.\n     * - `tokenId` token must exist and be owned by `from`.\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon\n     *   a safe transfer.\n     *\n     * Emits a {Transfer} event.\n     */\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\n\n    /**\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n     *\n     * Requirements:\n     *\n     * - `from` cannot be the zero address.\n     * - `to` cannot be the zero address.\n     * - `tokenId` token must exist and be owned by `from`.\n     * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or\n     *   {setApprovalForAll}.\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon\n     *   a safe transfer.\n     *\n     * Emits a {Transfer} event.\n     */\n    function safeTransferFrom(address from, address to, uint256 tokenId) external;\n\n    /**\n     * @dev Transfers `tokenId` token from `from` to `to`.\n     *\n     * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\n     * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\n     * understand this adds an external call which potentially creates a reentrancy vulnerability.\n     *\n     * Requirements:\n     *\n     * - `from` cannot be the zero address.\n     * - `to` cannot be the zero address.\n     * - `tokenId` token must be owned by `from`.\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(address from, address to, uint256 tokenId) external;\n\n    /**\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n     * The approval is cleared when the token is transferred.\n     *\n     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n     *\n     * Requirements:\n     *\n     * - The caller must own the token or be an approved operator.\n     * - `tokenId` must exist.\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address to, uint256 tokenId) external;\n\n    /**\n     * @dev Approve or remove `operator` as an operator for the caller.\n     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\n     *\n     * Requirements:\n     *\n     * - The `operator` cannot be the address zero.\n     *\n     * Emits an {ApprovalForAll} event.\n     */\n    function setApprovalForAll(address operator, bool approved) external;\n\n    /**\n     * @dev Returns the account approved for `tokenId` token.\n     *\n     * Requirements:\n     *\n     * - `tokenId` must exist.\n     */\n    function getApproved(uint256 tokenId) external view returns (address operator);\n\n    /**\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n     *\n     * See {setApprovalForAll}\n     */\n    function isApprovedForAll(address owner, address operator) external view returns (bool);\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/utils/ReentrancyGuard.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/ReentrancyGuard.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuard {\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant NOT_ENTERED = 1;\n    uint256 private constant ENTERED = 2;\n\n    uint256 private _status;\n\n    /**\n     * @dev Unauthorized reentrant call.\n     */\n    error ReentrancyGuardReentrantCall();\n\n    constructor() {\n        _status = NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and making it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        _nonReentrantBefore();\n        _;\n        _nonReentrantAfter();\n    }\n\n    function _nonReentrantBefore() private {\n        // On the first call to nonReentrant, _status will be NOT_ENTERED\n        if (_status == ENTERED) {\n            revert ReentrancyGuardReentrantCall();\n        }\n\n        // Any calls to nonReentrant after this point will fail\n        _status = ENTERED;\n    }\n\n    function _nonReentrantAfter() private {\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        _status = NOT_ENTERED;\n    }\n\n    /**\n     * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n     * `nonReentrant` function in the call stack.\n     */\n    function _reentrancyGuardEntered() internal view returns (bool) {\n        return _status == ENTERED;\n    }\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/access/Ownable2Step.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable2Step.sol)\n\npragma solidity ^0.8.20;\n\nimport {Ownable} from \"./Ownable.sol\";\n\n/**\n * @dev Contract module which provides access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * The initial owner is specified at deployment time in the constructor for `Ownable`. This\n * can later be changed with {transferOwnership} and {acceptOwnership}.\n *\n * This module is used through inheritance. It will make available all functions\n * from parent (Ownable).\n */\nabstract contract Ownable2Step is Ownable {\n    address private _pendingOwner;\n\n    event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Returns the address of the pending owner.\n     */\n    function pendingOwner() public view virtual returns (address) {\n        return _pendingOwner;\n    }\n\n    /**\n     * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual override onlyOwner {\n        _pendingOwner = newOwner;\n        emit OwnershipTransferStarted(owner(), newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual override {\n        delete _pendingOwner;\n        super._transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev The new owner accepts the ownership transfer.\n     */\n    function acceptOwnership() public virtual {\n        address sender = _msgSender();\n        if (pendingOwner() != sender) {\n            revert OwnableUnauthorizedAccount(sender);\n        }\n        _transferOwnership(sender);\n    }\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/utils/Pausable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Pausable.sol)\n\npragma solidity ^0.8.20;\n\nimport {Context} from \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\nabstract contract Pausable is Context {\n    bool private _paused;\n\n    /**\n     * @dev Emitted when the pause is triggered by `account`.\n     */\n    event Paused(address account);\n\n    /**\n     * @dev Emitted when the pause is lifted by `account`.\n     */\n    event Unpaused(address account);\n\n    /**\n     * @dev The operation failed because the contract is paused.\n     */\n    error EnforcedPause();\n\n    /**\n     * @dev The operation failed because the contract is not paused.\n     */\n    error ExpectedPause();\n\n    /**\n     * @dev Initializes the contract in unpaused state.\n     */\n    constructor() {\n        _paused = false;\n    }\n\n    /**\n     * @dev Modifier to make a function callable only when the contract is not paused.\n     *\n     * Requirements:\n     *\n     * - The contract must not be paused.\n     */\n    modifier whenNotPaused() {\n        _requireNotPaused();\n        _;\n    }\n\n    /**\n     * @dev Modifier to make a function callable only when the contract is paused.\n     *\n     * Requirements:\n     *\n     * - The contract must be paused.\n     */\n    modifier whenPaused() {\n        _requirePaused();\n        _;\n    }\n\n    /**\n     * @dev Returns true if the contract is paused, and false otherwise.\n     */\n    function paused() public view virtual returns (bool) {\n        return _paused;\n    }\n\n    /**\n     * @dev Throws if the contract is paused.\n     */\n    function _requireNotPaused() internal view virtual {\n        if (paused()) {\n            revert EnforcedPause();\n        }\n    }\n\n    /**\n     * @dev Throws if the contract is not paused.\n     */\n    function _requirePaused() internal view virtual {\n        if (!paused()) {\n            revert ExpectedPause();\n        }\n    }\n\n    /**\n     * @dev Triggers stopped state.\n     *\n     * Requirements:\n     *\n     * - The contract must not be paused.\n     */\n    function _pause() internal virtual whenNotPaused {\n        _paused = true;\n        emit Paused(_msgSender());\n    }\n\n    /**\n     * @dev Returns to normal state.\n     *\n     * Requirements:\n     *\n     * - The contract must be paused.\n     */\n    function _unpause() internal virtual whenPaused {\n        _paused = false;\n        emit Unpaused(_msgSender());\n    }\n}\n"
      },
      "src/lib/IDelegationRegistry.sol": {
        "content": "// SPDX-License-Identifier: CC0-1.0\npragma solidity ^0.8.17;\n\n/**\n * @title An immutable registry contract to be deployed as a standalone primitive\n * @dev See EIP-5639, new project launches can read previous cold wallet -> hot wallet delegations\n * from here and integrate those permissions into their flow\n */\ninterface IDelegationRegistry {\n    /// @notice Delegation type\n    enum DelegationType {\n        NONE,\n        ALL,\n        CONTRACT,\n        TOKEN\n    }\n\n    /// @notice Info about a single delegation, used for onchain enumeration\n    struct DelegationInfo {\n        DelegationType type_;\n        address vault;\n        address delegate;\n        address contract_;\n        uint256 tokenId;\n    }\n\n    /// @notice Info about a single contract-level delegation\n    struct ContractDelegation {\n        address contract_;\n        address delegate;\n    }\n\n    /// @notice Info about a single token-level delegation\n    struct TokenDelegation {\n        address contract_;\n        uint256 tokenId;\n        address delegate;\n    }\n\n    /// @notice Emitted when a user delegates their entire wallet\n    event DelegateForAll(address vault, address delegate, bool value);\n\n    /// @notice Emitted when a user delegates a specific contract\n    event DelegateForContract(\n        address vault,\n        address delegate,\n        address contract_,\n        bool value\n    );\n\n    /// @notice Emitted when a user delegates a specific token\n    event DelegateForToken(\n        address vault,\n        address delegate,\n        address contract_,\n        uint256 tokenId,\n        bool value\n    );\n\n    /// @notice Emitted when a user revokes all delegations\n    event RevokeAllDelegates(address vault);\n\n    /// @notice Emitted when a user revoes all delegations for a given delegate\n    event RevokeDelegate(address vault, address delegate);\n\n    /**\n     * -----------  WRITE -----------\n     */\n\n    /**\n     * @notice Allow the delegate to act on your behalf for all contracts\n     * @param delegate The hotwallet to act on your behalf\n     * @param value Whether to enable or disable delegation for this address, true for setting and false for revoking\n     */\n    function delegateForAll(address delegate, bool value) external;\n\n    /**\n     * @notice Allow the delegate to act on your behalf for a specific contract\n     * @param delegate The hotwallet to act on your behalf\n     * @param contract_ The address for the contract you're delegating\n     * @param value Whether to enable or disable delegation for this address, true for setting and false for revoking\n     */\n    function delegateForContract(\n        address delegate,\n        address contract_,\n        bool value\n    ) external;\n\n    /**\n     * @notice Allow the delegate to act on your behalf for a specific token\n     * @param delegate The hotwallet to act on your behalf\n     * @param contract_ The address for the contract you're delegating\n     * @param tokenId The token id for the token you're delegating\n     * @param value Whether to enable or disable delegation for this address, true for setting and false for revoking\n     */\n    function delegateForToken(\n        address delegate,\n        address contract_,\n        uint256 tokenId,\n        bool value\n    ) external;\n\n    /**\n     * @notice Revoke all delegates\n     */\n    function revokeAllDelegates() external;\n\n    /**\n     * @notice Revoke a specific delegate for all their permissions\n     * @param delegate The hotwallet to revoke\n     */\n    function revokeDelegate(address delegate) external;\n\n    /**\n     * @notice Remove yourself as a delegate for a specific vault\n     * @param vault The vault which delegated to the msg.sender, and should be removed\n     */\n    function revokeSelf(address vault) external;\n\n    /**\n     * -----------  READ -----------\n     */\n\n    /**\n     * @notice Returns all active delegations a given delegate is able to claim on behalf of\n     * @param delegate The delegate that you would like to retrieve delegations for\n     * @return info Array of DelegationInfo structs\n     */\n    function getDelegationsByDelegate(\n        address delegate\n    ) external view returns (DelegationInfo[] memory);\n\n    /**\n     * @notice Returns an array of wallet-level delegates for a given vault\n     * @param vault The cold wallet who issued the delegation\n     * @return addresses Array of wallet-level delegates for a given vault\n     */\n    function getDelegatesForAll(\n        address vault\n    ) external view returns (address[] memory);\n\n    /**\n     * @notice Returns an array of contract-level delegates for a given vault and contract\n     * @param vault The cold wallet who issued the delegation\n     * @param contract_ The address for the contract you're delegating\n     * @return addresses Array of contract-level delegates for a given vault and contract\n     */\n    function getDelegatesForContract(\n        address vault,\n        address contract_\n    ) external view returns (address[] memory);\n\n    /**\n     * @notice Returns an array of contract-level delegates for a given vault's token\n     * @param vault The cold wallet who issued the delegation\n     * @param contract_ The address for the contract holding the token\n     * @param tokenId The token id for the token you're delegating\n     * @return addresses Array of contract-level delegates for a given vault's token\n     */\n    function getDelegatesForToken(\n        address vault,\n        address contract_,\n        uint256 tokenId\n    ) external view returns (address[] memory);\n\n    /**\n     * @notice Returns all contract-level delegations for a given vault\n     * @param vault The cold wallet who issued the delegations\n     * @return delegations Array of ContractDelegation structs\n     */\n    function getContractLevelDelegations(\n        address vault\n    ) external view returns (ContractDelegation[] memory delegations);\n\n    /**\n     * @notice Returns all token-level delegations for a given vault\n     * @param vault The cold wallet who issued the delegations\n     * @return delegations Array of TokenDelegation structs\n     */\n    function getTokenLevelDelegations(\n        address vault\n    ) external view returns (TokenDelegation[] memory delegations);\n\n    /**\n     * @notice Returns true if the address is delegated to act on the entire vault\n     * @param delegate The hotwallet to act on your behalf\n     * @param vault The cold wallet who issued the delegation\n     */\n    function checkDelegateForAll(\n        address delegate,\n        address vault\n    ) external view returns (bool);\n\n    /**\n     * @notice Returns true if the address is delegated to act on your behalf for a token contract or an entire vault\n     * @param delegate The hotwallet to act on your behalf\n     * @param contract_ The address for the contract you're delegating\n     * @param vault The cold wallet who issued the delegation\n     */\n    function checkDelegateForContract(\n        address delegate,\n        address vault,\n        address contract_\n    ) external view returns (bool);\n\n    /**\n     * @notice Returns true if the address is delegated to act on your behalf for a specific token, the token's contract or an entire vault\n     * @param delegate The hotwallet to act on your behalf\n     * @param contract_ The address for the contract you're delegating\n     * @param tokenId The token id for the token you're delegating\n     * @param vault The cold wallet who issued the delegation\n     */\n    function checkDelegateForToken(\n        address delegate,\n        address vault,\n        address contract_,\n        uint256 tokenId\n    ) external view returns (bool);\n}\n"
      },
      "lib/delegate-registry/src/IDelegateRegistry.sol": {
        "content": "// SPDX-License-Identifier: CC0-1.0\npragma solidity >=0.8.13;\n\n/**\n * @title IDelegateRegistry\n * @custom:version 2.0\n * @custom:author foobar (0xfoobar)\n * @notice A standalone immutable registry storing delegated permissions from one address to another\n */\ninterface IDelegateRegistry {\n    /// @notice Delegation type, NONE is used when a delegation does not exist or is revoked\n    enum DelegationType {\n        NONE,\n        ALL,\n        CONTRACT,\n        ERC721,\n        ERC20,\n        ERC1155\n    }\n\n    /// @notice Struct for returning delegations\n    struct Delegation {\n        DelegationType type_;\n        address to;\n        address from;\n        bytes32 rights;\n        address contract_;\n        uint256 tokenId;\n        uint256 amount;\n    }\n\n    /// @notice Emitted when an address delegates or revokes rights for their entire wallet\n    event DelegateAll(address indexed from, address indexed to, bytes32 rights, bool enable);\n\n    /// @notice Emitted when an address delegates or revokes rights for a contract address\n    event DelegateContract(address indexed from, address indexed to, address indexed contract_, bytes32 rights, bool enable);\n\n    /// @notice Emitted when an address delegates or revokes rights for an ERC721 tokenId\n    event DelegateERC721(address indexed from, address indexed to, address indexed contract_, uint256 tokenId, bytes32 rights, bool enable);\n\n    /// @notice Emitted when an address delegates or revokes rights for an amount of ERC20 tokens\n    event DelegateERC20(address indexed from, address indexed to, address indexed contract_, bytes32 rights, uint256 amount);\n\n    /// @notice Emitted when an address delegates or revokes rights for an amount of an ERC1155 tokenId\n    event DelegateERC1155(address indexed from, address indexed to, address indexed contract_, uint256 tokenId, bytes32 rights, uint256 amount);\n\n    /// @notice Thrown if multicall calldata is malformed\n    error MulticallFailed();\n\n    /**\n     * -----------  WRITE -----------\n     */\n\n    /**\n     * @notice Call multiple functions in the current contract and return the data from all of them if they all succeed\n     * @param data The encoded function data for each of the calls to make to this contract\n     * @return results The results from each of the calls passed in via data\n     */\n    function multicall(bytes[] calldata data) external payable returns (bytes[] memory results);\n\n    /**\n     * @notice Allow the delegate to act on behalf of `msg.sender` for all contracts\n     * @param to The address to act as delegate\n     * @param rights Specific subdelegation rights granted to the delegate, pass an empty bytestring to encompass all rights\n     * @param enable Whether to enable or disable this delegation, true delegates and false revokes\n     * @return delegationHash The unique identifier of the delegation\n     */\n    function delegateAll(address to, bytes32 rights, bool enable) external payable returns (bytes32 delegationHash);\n\n    /**\n     * @notice Allow the delegate to act on behalf of `msg.sender` for a specific contract\n     * @param to The address to act as delegate\n     * @param contract_ The contract whose rights are being delegated\n     * @param rights Specific subdelegation rights granted to the delegate, pass an empty bytestring to encompass all rights\n     * @param enable Whether to enable or disable this delegation, true delegates and false revokes\n     * @return delegationHash The unique identifier of the delegation\n     */\n    function delegateContract(address to, address contract_, bytes32 rights, bool enable) external payable returns (bytes32 delegationHash);\n\n    /**\n     * @notice Allow the delegate to act on behalf of `msg.sender` for a specific ERC721 token\n     * @param to The address to act as delegate\n     * @param contract_ The contract whose rights are being delegated\n     * @param tokenId The token id to delegate\n     * @param rights Specific subdelegation rights granted to the delegate, pass an empty bytestring to encompass all rights\n     * @param enable Whether to enable or disable this delegation, true delegates and false revokes\n     * @return delegationHash The unique identifier of the delegation\n     */\n    function delegateERC721(address to, address contract_, uint256 tokenId, bytes32 rights, bool enable) external payable returns (bytes32 delegationHash);\n\n    /**\n     * @notice Allow the delegate to act on behalf of `msg.sender` for a specific amount of ERC20 tokens\n     * @dev The actual amount is not encoded in the hash, just the existence of a amount (since it is an upper bound)\n     * @param to The address to act as delegate\n     * @param contract_ The address for the fungible token contract\n     * @param rights Specific subdelegation rights granted to the delegate, pass an empty bytestring to encompass all rights\n     * @param amount The amount to delegate, > 0 delegates and 0 revokes\n     * @return delegationHash The unique identifier of the delegation\n     */\n    function delegateERC20(address to, address contract_, bytes32 rights, uint256 amount) external payable returns (bytes32 delegationHash);\n\n    /**\n     * @notice Allow the delegate to act on behalf of `msg.sender` for a specific amount of ERC1155 tokens\n     * @dev The actual amount is not encoded in the hash, just the existence of a amount (since it is an upper bound)\n     * @param to The address to act as delegate\n     * @param contract_ The address of the contract that holds the token\n     * @param tokenId The token id to delegate\n     * @param rights Specific subdelegation rights granted to the delegate, pass an empty bytestring to encompass all rights\n     * @param amount The amount of that token id to delegate, > 0 delegates and 0 revokes\n     * @return delegationHash The unique identifier of the delegation\n     */\n    function delegateERC1155(address to, address contract_, uint256 tokenId, bytes32 rights, uint256 amount) external payable returns (bytes32 delegationHash);\n\n    /**\n     * ----------- CHECKS -----------\n     */\n\n    /**\n     * @notice Check if `to` is a delegate of `from` for the entire wallet\n     * @param to The potential delegate address\n     * @param from The potential address who delegated rights\n     * @param rights Specific rights to check for, pass the zero value to ignore subdelegations and check full delegations only\n     * @return valid Whether delegate is granted to act on the from's behalf\n     */\n    function checkDelegateForAll(address to, address from, bytes32 rights) external view returns (bool);\n\n    /**\n     * @notice Check if `to` is a delegate of `from` for the specified `contract_` or the entire wallet\n     * @param to The delegated address to check\n     * @param contract_ The specific contract address being checked\n     * @param from The cold wallet who issued the delegation\n     * @param rights Specific rights to check for, pass the zero value to ignore subdelegations and check full delegations only\n     * @return valid Whether delegate is granted to act on from's behalf for entire wallet or that specific contract\n     */\n    function checkDelegateForContract(address to, address from, address contract_, bytes32 rights) external view returns (bool);\n\n    /**\n     * @notice Check if `to` is a delegate of `from` for the specific `contract` and `tokenId`, the entire `contract_`, or the entire wallet\n     * @param to The delegated address to check\n     * @param contract_ The specific contract address being checked\n     * @param tokenId The token id for the token to delegating\n     * @param from The wallet that issued the delegation\n     * @param rights Specific rights to check for, pass the zero value to ignore subdelegations and check full delegations only\n     * @return valid Whether delegate is granted to act on from's behalf for entire wallet, that contract, or that specific tokenId\n     */\n    function checkDelegateForERC721(address to, address from, address contract_, uint256 tokenId, bytes32 rights) external view returns (bool);\n\n    /**\n     * @notice Returns the amount of ERC20 tokens the delegate is granted rights to act on the behalf of\n     * @param to The delegated address to check\n     * @param contract_ The address of the token contract\n     * @param from The cold wallet who issued the delegation\n     * @param rights Specific rights to check for, pass the zero value to ignore subdelegations and check full delegations only\n     * @return balance The delegated balance, which will be 0 if the delegation does not exist\n     */\n    function checkDelegateForERC20(address to, address from, address contract_, bytes32 rights) external view returns (uint256);\n\n    /**\n     * @notice Returns the amount of a ERC1155 tokens the delegate is granted rights to act on the behalf of\n     * @param to The delegated address to check\n     * @param contract_ The address of the token contract\n     * @param tokenId The token id to check the delegated amount of\n     * @param from The cold wallet who issued the delegation\n     * @param rights Specific rights to check for, pass the zero value to ignore subdelegations and check full delegations only\n     * @return balance The delegated balance, which will be 0 if the delegation does not exist\n     */\n    function checkDelegateForERC1155(address to, address from, address contract_, uint256 tokenId, bytes32 rights) external view returns (uint256);\n\n    /**\n     * ----------- ENUMERATIONS -----------\n     */\n\n    /**\n     * @notice Returns all enabled delegations a given delegate has received\n     * @param to The address to retrieve delegations for\n     * @return delegations Array of Delegation structs\n     */\n    function getIncomingDelegations(address to) external view returns (Delegation[] memory delegations);\n\n    /**\n     * @notice Returns all enabled delegations an address has given out\n     * @param from The address to retrieve delegations for\n     * @return delegations Array of Delegation structs\n     */\n    function getOutgoingDelegations(address from) external view returns (Delegation[] memory delegations);\n\n    /**\n     * @notice Returns all hashes associated with enabled delegations an address has received\n     * @param to The address to retrieve incoming delegation hashes for\n     * @return delegationHashes Array of delegation hashes\n     */\n    function getIncomingDelegationHashes(address to) external view returns (bytes32[] memory delegationHashes);\n\n    /**\n     * @notice Returns all hashes associated with enabled delegations an address has given out\n     * @param from The address to retrieve outgoing delegation hashes for\n     * @return delegationHashes Array of delegation hashes\n     */\n    function getOutgoingDelegationHashes(address from) external view returns (bytes32[] memory delegationHashes);\n\n    /**\n     * @notice Returns the delegations for a given array of delegation hashes\n     * @param delegationHashes is an array of hashes that correspond to delegations\n     * @return delegations Array of Delegation structs, return empty structs for nonexistent or revoked delegations\n     */\n    function getDelegationsFromHashes(bytes32[] calldata delegationHashes) external view returns (Delegation[] memory delegations);\n\n    /**\n     * ----------- STORAGE ACCESS -----------\n     */\n\n    /**\n     * @notice Allows external contracts to read arbitrary storage slots\n     */\n    function readSlot(bytes32 location) external view returns (bytes32);\n\n    /**\n     * @notice Allows external contracts to read an arbitrary array of storage slots\n     */\n    function readSlots(bytes32[] calldata locations) external view returns (bytes32[] memory);\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/utils/Strings.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Strings.sol)\n\npragma solidity ^0.8.20;\n\nimport {Math} from \"./math/Math.sol\";\nimport {SignedMath} from \"./math/SignedMath.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n    bytes16 private constant HEX_DIGITS = \"0123456789abcdef\";\n    uint8 private constant ADDRESS_LENGTH = 20;\n\n    /**\n     * @dev The `value` string doesn't fit in the specified `length`.\n     */\n    error StringsInsufficientHexLength(uint256 value, uint256 length);\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n     */\n    function toString(uint256 value) internal pure returns (string memory) {\n        unchecked {\n            uint256 length = Math.log10(value) + 1;\n            string memory buffer = new string(length);\n            uint256 ptr;\n            /// @solidity memory-safe-assembly\n            assembly {\n                ptr := add(buffer, add(32, length))\n            }\n            while (true) {\n                ptr--;\n                /// @solidity memory-safe-assembly\n                assembly {\n                    mstore8(ptr, byte(mod(value, 10), HEX_DIGITS))\n                }\n                value /= 10;\n                if (value == 0) break;\n            }\n            return buffer;\n        }\n    }\n\n    /**\n     * @dev Converts a `int256` to its ASCII `string` decimal representation.\n     */\n    function toStringSigned(int256 value) internal pure returns (string memory) {\n        return string.concat(value < 0 ? \"-\" : \"\", toString(SignedMath.abs(value)));\n    }\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n     */\n    function toHexString(uint256 value) internal pure returns (string memory) {\n        unchecked {\n            return toHexString(value, Math.log256(value) + 1);\n        }\n    }\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n     */\n    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n        uint256 localValue = value;\n        bytes memory buffer = new bytes(2 * length + 2);\n        buffer[0] = \"0\";\n        buffer[1] = \"x\";\n        for (uint256 i = 2 * length + 1; i > 1; --i) {\n            buffer[i] = HEX_DIGITS[localValue & 0xf];\n            localValue >>= 4;\n        }\n        if (localValue != 0) {\n            revert StringsInsufficientHexLength(value, length);\n        }\n        return string(buffer);\n    }\n\n    /**\n     * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal\n     * representation.\n     */\n    function toHexString(address addr) internal pure returns (string memory) {\n        return toHexString(uint256(uint160(addr)), ADDRESS_LENGTH);\n    }\n\n    /**\n     * @dev Returns true if the two strings are equal.\n     */\n    function equal(string memory a, string memory b) internal pure returns (bool) {\n        return bytes(a).length == bytes(b).length && keccak256(bytes(a)) == keccak256(bytes(b));\n    }\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n    /**\n     * @dev Returns true if this contract implements the interface defined by\n     * `interfaceId`. See the corresponding\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n     * to learn more about how these ids are created.\n     *\n     * This function call must use less than 30 000 gas.\n     */\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/access/Ownable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)\n\npragma solidity ^0.8.20;\n\nimport {Context} from \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * The initial owner is set to the address provided by the deployer. This can\n * later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n    address private _owner;\n\n    /**\n     * @dev The caller account is not authorized to perform an operation.\n     */\n    error OwnableUnauthorizedAccount(address account);\n\n    /**\n     * @dev The owner is not a valid owner account. (eg. `address(0)`)\n     */\n    error OwnableInvalidOwner(address owner);\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the address provided by the deployer as the initial owner.\n     */\n    constructor(address initialOwner) {\n        if (initialOwner == address(0)) {\n            revert OwnableInvalidOwner(address(0));\n        }\n        _transferOwnership(initialOwner);\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        _checkOwner();\n        _;\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view virtual returns (address) {\n        return _owner;\n    }\n\n    /**\n     * @dev Throws if the sender is not the owner.\n     */\n    function _checkOwner() internal view virtual {\n        if (owner() != _msgSender()) {\n            revert OwnableUnauthorizedAccount(_msgSender());\n        }\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby disabling any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual onlyOwner {\n        _transferOwnership(address(0));\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual onlyOwner {\n        if (newOwner == address(0)) {\n            revert OwnableInvalidOwner(address(0));\n        }\n        _transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual {\n        address oldOwner = _owner;\n        _owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/utils/Context.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n\n    function _contextSuffixLength() internal view virtual returns (uint256) {\n        return 0;\n    }\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/utils/math/Math.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n    /**\n     * @dev Muldiv operation overflow.\n     */\n    error MathOverflowedMulDiv();\n\n    enum Rounding {\n        Floor, // Toward negative infinity\n        Ceil, // Toward positive infinity\n        Trunc, // Toward zero\n        Expand // Away from zero\n    }\n\n    /**\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\n     */\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            uint256 c = a + b;\n            if (c < a) return (false, 0);\n            return (true, c);\n        }\n    }\n\n    /**\n     * @dev Returns the subtraction of two unsigned integers, with an overflow flag.\n     */\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            if (b > a) return (false, 0);\n            return (true, a - b);\n        }\n    }\n\n    /**\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\n     */\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\n            // benefit is lost if 'b' is also tested.\n            // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\n            if (a == 0) return (true, 0);\n            uint256 c = a * b;\n            if (c / a != b) return (false, 0);\n            return (true, c);\n        }\n    }\n\n    /**\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\n     */\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            if (b == 0) return (false, 0);\n            return (true, a / b);\n        }\n    }\n\n    /**\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\n     */\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            if (b == 0) return (false, 0);\n            return (true, a % b);\n        }\n    }\n\n    /**\n     * @dev Returns the largest of two numbers.\n     */\n    function max(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a > b ? a : b;\n    }\n\n    /**\n     * @dev Returns the smallest of two numbers.\n     */\n    function min(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a < b ? a : b;\n    }\n\n    /**\n     * @dev Returns the average of two numbers. The result is rounded towards\n     * zero.\n     */\n    function average(uint256 a, uint256 b) internal pure returns (uint256) {\n        // (a + b) / 2 can overflow.\n        return (a & b) + (a ^ b) / 2;\n    }\n\n    /**\n     * @dev Returns the ceiling of the division of two numbers.\n     *\n     * This differs from standard division with `/` in that it rounds towards infinity instead\n     * of rounding towards zero.\n     */\n    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n        if (b == 0) {\n            // Guarantee the same behavior as in a regular Solidity division.\n            return a / b;\n        }\n\n        // (a + b - 1) / b can overflow on addition, so we distribute.\n        return a == 0 ? 0 : (a - 1) / b + 1;\n    }\n\n    /**\n     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or\n     * denominator == 0.\n     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by\n     * Uniswap Labs also under MIT license.\n     */\n    function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n        unchecked {\n            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n            // variables such that product = prod1 * 2^256 + prod0.\n            uint256 prod0 = x * y; // Least significant 256 bits of the product\n            uint256 prod1; // Most significant 256 bits of the product\n            assembly {\n                let mm := mulmod(x, y, not(0))\n                prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n            }\n\n            // Handle non-overflow cases, 256 by 256 division.\n            if (prod1 == 0) {\n                // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n                // The surrounding unchecked block does not change this fact.\n                // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n                return prod0 / denominator;\n            }\n\n            // Make sure the result is less than 2^256. Also prevents denominator == 0.\n            if (denominator <= prod1) {\n                revert MathOverflowedMulDiv();\n            }\n\n            ///////////////////////////////////////////////\n            // 512 by 256 division.\n            ///////////////////////////////////////////////\n\n            // Make division exact by subtracting the remainder from [prod1 prod0].\n            uint256 remainder;\n            assembly {\n                // Compute remainder using mulmod.\n                remainder := mulmod(x, y, denominator)\n\n                // Subtract 256 bit number from 512 bit number.\n                prod1 := sub(prod1, gt(remainder, prod0))\n                prod0 := sub(prod0, remainder)\n            }\n\n            // Factor powers of two out of denominator and compute largest power of two divisor of denominator.\n            // Always >= 1. See https://cs.stackexchange.com/q/138556/92363.\n\n            uint256 twos = denominator & (0 - denominator);\n            assembly {\n                // Divide denominator by twos.\n                denominator := div(denominator, twos)\n\n                // Divide [prod1 prod0] by twos.\n                prod0 := div(prod0, twos)\n\n                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n                twos := add(div(sub(0, twos), twos), 1)\n            }\n\n            // Shift in bits from prod1 into prod0.\n            prod0 |= prod1 * twos;\n\n            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n            // four bits. That is, denominator * inv = 1 mod 2^4.\n            uint256 inverse = (3 * denominator) ^ 2;\n\n            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also\n            // works in modular arithmetic, doubling the correct bits in each step.\n            inverse *= 2 - denominator * inverse; // inverse mod 2^8\n            inverse *= 2 - denominator * inverse; // inverse mod 2^16\n            inverse *= 2 - denominator * inverse; // inverse mod 2^32\n            inverse *= 2 - denominator * inverse; // inverse mod 2^64\n            inverse *= 2 - denominator * inverse; // inverse mod 2^128\n            inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n            // is no longer required.\n            result = prod0 * inverse;\n            return result;\n        }\n    }\n\n    /**\n     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n     */\n    function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n        uint256 result = mulDiv(x, y, denominator);\n        if (unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0) {\n            result += 1;\n        }\n        return result;\n    }\n\n    /**\n     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded\n     * towards zero.\n     *\n     * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n     */\n    function sqrt(uint256 a) internal pure returns (uint256) {\n        if (a == 0) {\n            return 0;\n        }\n\n        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n        //\n        // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n        // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n        //\n        // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n        // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n        // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n        //\n        // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n        uint256 result = 1 << (log2(a) >> 1);\n\n        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n        // into the expected uint128 result.\n        unchecked {\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            return min(result, a / result);\n        }\n    }\n\n    /**\n     * @notice Calculates sqrt(a), following the selected rounding direction.\n     */\n    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = sqrt(a);\n            return result + (unsignedRoundsUp(rounding) && result * result < a ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 2 of a positive value rounded towards zero.\n     * Returns 0 if given 0.\n     */\n    function log2(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >> 128 > 0) {\n                value >>= 128;\n                result += 128;\n            }\n            if (value >> 64 > 0) {\n                value >>= 64;\n                result += 64;\n            }\n            if (value >> 32 > 0) {\n                value >>= 32;\n                result += 32;\n            }\n            if (value >> 16 > 0) {\n                value >>= 16;\n                result += 16;\n            }\n            if (value >> 8 > 0) {\n                value >>= 8;\n                result += 8;\n            }\n            if (value >> 4 > 0) {\n                value >>= 4;\n                result += 4;\n            }\n            if (value >> 2 > 0) {\n                value >>= 2;\n                result += 2;\n            }\n            if (value >> 1 > 0) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log2(value);\n            return result + (unsignedRoundsUp(rounding) && 1 << result < value ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 10 of a positive value rounded towards zero.\n     * Returns 0 if given 0.\n     */\n    function log10(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >= 10 ** 64) {\n                value /= 10 ** 64;\n                result += 64;\n            }\n            if (value >= 10 ** 32) {\n                value /= 10 ** 32;\n                result += 32;\n            }\n            if (value >= 10 ** 16) {\n                value /= 10 ** 16;\n                result += 16;\n            }\n            if (value >= 10 ** 8) {\n                value /= 10 ** 8;\n                result += 8;\n            }\n            if (value >= 10 ** 4) {\n                value /= 10 ** 4;\n                result += 4;\n            }\n            if (value >= 10 ** 2) {\n                value /= 10 ** 2;\n                result += 2;\n            }\n            if (value >= 10 ** 1) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log10(value);\n            return result + (unsignedRoundsUp(rounding) && 10 ** result < value ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 256 of a positive value rounded towards zero.\n     * Returns 0 if given 0.\n     *\n     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n     */\n    function log256(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >> 128 > 0) {\n                value >>= 128;\n                result += 16;\n            }\n            if (value >> 64 > 0) {\n                value >>= 64;\n                result += 8;\n            }\n            if (value >> 32 > 0) {\n                value >>= 32;\n                result += 4;\n            }\n            if (value >> 16 > 0) {\n                value >>= 16;\n                result += 2;\n            }\n            if (value >> 8 > 0) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log256(value);\n            return result + (unsignedRoundsUp(rounding) && 1 << (result << 3) < value ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.\n     */\n    function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {\n        return uint8(rounding) % 2 == 1;\n    }\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n    /**\n     * @dev Returns the largest of two signed numbers.\n     */\n    function max(int256 a, int256 b) internal pure returns (int256) {\n        return a > b ? a : b;\n    }\n\n    /**\n     * @dev Returns the smallest of two signed numbers.\n     */\n    function min(int256 a, int256 b) internal pure returns (int256) {\n        return a < b ? a : b;\n    }\n\n    /**\n     * @dev Returns the average of two signed numbers without overflow.\n     * The result is rounded towards zero.\n     */\n    function average(int256 a, int256 b) internal pure returns (int256) {\n        // Formula from the book \"Hacker's Delight\"\n        int256 x = (a & b) + ((a ^ b) >> 1);\n        return x + (int256(uint256(x) >> 255) & (a ^ b));\n    }\n\n    /**\n     * @dev Returns the absolute unsigned value of a signed value.\n     */\n    function abs(int256 n) internal pure returns (uint256) {\n        unchecked {\n            // must be unchecked in order to support `n = type(int256).min`\n            return uint256(n >= 0 ? n : -n);\n        }\n    }\n}\n"
      }
    },
    "settings": {
      "remappings": [
        "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
        "LayerZero-v2/=lib/LayerZero-v2/",
        "delegate-registry/=lib/delegate-registry/src/",
        "ds-test/=lib/forge-std/lib/ds-test/src/",
        "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
        "forge-std/=lib/forge-std/src/",
        "murky/=lib/delegate-registry/lib/murky/src/",
        "openzeppelin-contracts/=lib/openzeppelin-contracts/",
        "openzeppelin/=lib/delegate-registry/lib/openzeppelin-contracts/contracts/"
      ],
      "optimizer": {
        "enabled": true,
        "runs": 10000000
      },
      "metadata": {
        "useLiteralContent": false,
        "bytecodeHash": "ipfs",
        "appendCBOR": true
      },
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "evmVersion": "paris",
      "viaIR": false,
      "libraries": {}
    }
  }}