ETH Price: $2,056.18 (-2.96%)

Token

SoundCreator ()
 

Overview

Max Total Supply

0 SoundCreator

Holders

0

Transfers

-
0 (0%)

Market

Onchain Market Cap

-

Circulating Supply Market Cap

-

Other Info

Token Contract (WITH 0 Decimals)

Loading...
Loading
Loading...
Loading
Loading...
Loading

Click here to update the token information / general information
# Exchange Pair Price  24H Volume % Volume
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.

Contract Source Code Verified (Exact Match)

Contract Name:
SoundCreatorV2

Compiler Version
v0.8.19+commit.7dd6d404

Optimization Enabled:
Yes with 200 runs

Other Settings:
paris EvmVersion, MIT license
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.16;

import { Clones } from "openzeppelin/proxy/Clones.sol";
import { ReentrancyGuard } from "openzeppelin/security/ReentrancyGuard.sol";
import { ISoundCreatorV2 } from "./interfaces/ISoundCreatorV2.sol";
import { LibMulticaller } from "multicaller/LibMulticaller.sol";
import { Ownable } from "solady/auth/Ownable.sol";
import { EIP712 } from "solady/utils/EIP712.sol";
import { LibZip } from "solady/utils/LibZip.sol";
import { LibBitmap } from "solady/utils/LibBitmap.sol";
import { SafeTransferLib } from "solady/utils/SafeTransferLib.sol";
import { SignatureCheckerLib } from "solady/utils/SignatureCheckerLib.sol";

/**
 * @title SoundCreatorV1
 * @notice A factory that deploys minimal proxies of SoundEditions.
 * @dev The proxies are OpenZeppelin's Clones implementation of https://eips.ethereum.org/EIPS/eip-1167
 */
contract SoundCreatorV2 is ISoundCreatorV2, EIP712, ReentrancyGuard {
    using LibBitmap for LibBitmap.Bitmap;

    // =============================================================
    //                           CONSTANTS
    // =============================================================

    /**
     * @dev For EIP-712 signature digest calculation.
     */
    bytes32 public constant SOUND_CREATION_TYPEHASH =
        // prettier-ignore
        keccak256(
            "SoundCreation("
                "address implementation,"
                "address owner,"
                "bytes32 salt,"
                "bytes initData,"
                "address[] contracts,"
                "bytes[] data,"
                "uint256 nonce"
            ")"
        );

    /**
     * @dev For EIP-712 signature digest calculation.
     */
    bytes32 public constant DOMAIN_TYPEHASH = _DOMAIN_TYPEHASH;

    // =============================================================
    //                            STORAGE
    // =============================================================

    /**
     * @dev For storing the invalidated nonces.
     */
    mapping(address => LibBitmap.Bitmap) internal _invalidatedNonces;

    // =============================================================
    //               PUBLIC / EXTERNAL WRITE FUNCTIONS
    // =============================================================

    /**
     * @inheritdoc ISoundCreatorV2
     */
    function create(SoundCreation calldata c) external nonReentrant returns (address edition, bytes[] memory results) {
        if (c.owner != LibMulticaller.sender()) revert Unauthorized();
        (edition, results) = _create(c);
    }

    /**
     * @inheritdoc ISoundCreatorV2
     */
    function createWithSignature(SoundCreation calldata creation, bytes calldata signature)
        external
        nonReentrant
        returns (address soundEdition, bytes[] memory results)
    {
        (soundEdition, results) = _createWithSignature(creation, signature);
    }

    /**
     * @inheritdoc ISoundCreatorV2
     */
    function mint(
        address minter,
        bytes calldata mintData,
        address refundTo
    ) external payable nonReentrant {
        _mint(minter, mintData, refundTo);
    }

    /**
     * @inheritdoc ISoundCreatorV2
     */
    function createWithSignatureAndMint(
        SoundCreation calldata c,
        bytes calldata signature,
        address minter,
        bytes calldata mintData,
        address refundTo
    ) external payable nonReentrant returns (address edition, bytes[] memory results) {
        // We will skip the `createWithSignature` if the SoundEdtion already exists.
        (, bool exists) = soundEditionAddress(c.implementation, c.owner, c.salt);
        if (!exists) (edition, results) = _createWithSignature(c, signature);
        _mint(minter, mintData, refundTo);
    }

    /**
     * @inheritdoc ISoundCreatorV2
     */
    function invalidateNonces(uint256[] calldata nonces) external {
        unchecked {
            address sender = LibMulticaller.sender();
            LibBitmap.Bitmap storage s = _invalidatedNonces[sender];
            for (uint256 i; i != nonces.length; ++i) {
                s.set(nonces[i]);
            }
            emit NoncesInvalidated(sender, nonces);
        }
    }

    /**
     * @dev For compressed calldata calling.
     */
    fallback() external payable {
        LibZip.cdFallback();
    }

    /**
     * @dev For compressed calldata calling.
     */
    receive() external payable {
        LibZip.cdFallback();
    }

    // =============================================================
    //               PUBLIC / EXTERNAL VIEW FUNCTIONS
    // =============================================================

    /**
     * @inheritdoc ISoundCreatorV2
     */
    function soundEditionAddress(
        address implementation,
        address owner,
        bytes32 salt
    ) public view returns (address addr, bool exists) {
        addr = Clones.predictDeterministicAddress(implementation, _saltedSalt(owner, salt), address(this));
        exists = addr.code.length != 0;
    }

    /**
     * @inheritdoc ISoundCreatorV2
     */
    function isValidSignature(SoundCreation calldata c, bytes calldata signature) public view returns (bool) {
        return
            // Whether the signature is correctly signed. Will revert if recovery fails.
            SignatureCheckerLib.isValidSignatureNowCalldata(c.owner, computeDigest(c), signature) &&
            // And whether the creation's nonce is not invalidated.
            !_invalidatedNonces[c.owner].get(c.nonce);
    }

    /**
     * @inheritdoc ISoundCreatorV2
     */
    function computeDigest(SoundCreation calldata c) public view returns (bytes32) {
        bytes32 encodedDataHash;
        unchecked {
            bytes[] calldata cData = c.data;
            uint256 n = cData.length;
            bytes32[] memory encodedData = new bytes32[](n);
            for (uint256 i = 0; i != n; ++i) {
                encodedData[i] = keccak256(cData[i]);
            }
            encodedDataHash = keccak256(abi.encodePacked(encodedData));
        }
        return
            _hashTypedData(
                keccak256(
                    abi.encode(
                        SOUND_CREATION_TYPEHASH,
                        c.implementation, // address
                        c.owner, // address
                        c.salt, // bytes32
                        keccak256(c.initData), // bytes
                        keccak256(abi.encodePacked(c.contracts)), // address[]
                        encodedDataHash, // bytes[]
                        c.nonce // uint256
                    )
                )
            );
    }

    /**
     * @inheritdoc ISoundCreatorV2
     */
    function noncesInvalidated(address signer, uint256[] calldata nonces) external view returns (bool[] memory result) {
        unchecked {
            result = new bool[](nonces.length);
            LibBitmap.Bitmap storage s = _invalidatedNonces[signer];
            for (uint256 i; i != nonces.length; ++i) {
                result[i] = s.get(nonces[i]);
            }
        }
    }

    // EIP712 parameters.

    /**
     * @inheritdoc ISoundCreatorV2
     */
    function name() external pure returns (string memory name_) {
        (name_, ) = _domainNameAndVersion();
    }

    /**
     * @inheritdoc ISoundCreatorV2
     */
    function version() external pure returns (string memory version_) {
        (, version_) = _domainNameAndVersion();
    }

    /**
     * @inheritdoc ISoundCreatorV2
     */
    function domainSeparator() external view returns (bytes32 separator) {
        separator = _domainSeparator();
    }

    // =============================================================
    //                  INTERNAL / PRIVATE HELPERS
    // =============================================================

    /**
     * @dev Override for EIP-712.
     * @return name_    The EIP-712 name.
     * @return version_ The EIP-712 version.
     */
    function _domainNameAndVersion()
        internal
        pure
        virtual
        override
        returns (string memory name_, string memory version_)
    {
        name_ = "SoundCreator";
        version_ = "2";
    }

    /**
     * @dev Call the `contracts` in order with `data`.
     * @param contracts The addresses of the contracts.
     * @param data      The `abi.encodeWithSelector` calldata for each of the contracts.
     * @return results The results of calling the contracts.
     */
    function _callContracts(address[] calldata contracts, bytes[] calldata data)
        internal
        returns (bytes[] memory results)
    {
        if (contracts.length != data.length) revert ArrayLengthsMismatch();

        assembly {
            // Grab the free memory pointer.
            // We will use the free memory to construct the `results` array,
            // and also as a temporary space for the calldata.
            results := mload(0x40)
            // Set `results.length` to be equal to `data.length`.
            mstore(results, data.length)
            // Skip the first word, which is used to store the length
            let resultsOffsets := add(results, 0x20)
            // Compute the location of the last calldata offset in `data`.
            // `shl(5, n)` is a gas-saving shorthand for `mul(0x20, n)`.
            let dataOffsetsEnd := add(data.offset, shl(5, data.length))
            // This is the start of the unused free memory.
            // We use it to temporarily store the calldata to call the contracts.
            let m := add(resultsOffsets, shl(5, data.length))

            // Loop through `contacts` and `data` together.
            // prettier-ignore
            for { let i := data.offset } iszero(eq(i, dataOffsetsEnd)) { i := add(i, 0x20) } {
                // Location of `bytes[i]` in calldata.
                let o := add(data.offset, calldataload(i))
                // Copy `bytes[i]` from calldata to the free memory.
                calldatacopy(
                    m, // Start of the unused free memory.
                    add(o, 0x20), // Location of starting byte of `data[i]` in calldata.
                    calldataload(o) // The length of the `bytes[i]`.
                )
                // Grab `contracts[i]` from the calldata.
                // As `contracts` is the same length as `data`,
                // `sub(i, data.offset)` gives the relative offset to apply to
                // `contracts.offset` for `contracts[i]` to match `data[i]`.
                let c := calldataload(add(contracts.offset, sub(i, data.offset)))
                // Call the contract, and revert if the call fails.
                if iszero(
                    call(
                        gas(), // Gas remaining.
                        c, // `contracts[i]`.
                        0, // `msg.value` of the call: 0 ETH.
                        m, // Start of the copy of `bytes[i]` in memory.
                        calldataload(o), // The length of the `bytes[i]`.
                        0x00, // Start of output. Not used.
                        0x00 // Size of output. Not used.
                    )
                ) {
                    // Bubble up the revert if the call reverts.
                    returndatacopy(0x00, 0x00, returndatasize())
                    revert(0x00, returndatasize())
                }
                // Append the current `m` into `resultsOffsets`.
                mstore(resultsOffsets, m)
                resultsOffsets := add(resultsOffsets, 0x20)

                // Append the `returndatasize()` to `results`.
                mstore(m, returndatasize())
                // Append the return data to `results`.
                returndatacopy(add(m, 0x20), 0x00, returndatasize())
                // Advance `m` by `returndatasize() + 0x20`,
                // rounded up to the next multiple of 32.
                // `0x3f = 32 + 31`. The mask is `type(uint64).max & ~31`,
                // which is big enough for all purposes (see memory expansion costs).
                m := and(add(add(m, returndatasize()), 0x3f), 0xffffffffffffffe0)
            }
            // Allocate the memory for `results` by updating the free memory pointer.
            mstore(0x40, m)
        }
    }

    /**
     * @dev Returns the salted salt.
     *      To prevent griefing and accidental collisions from clients that don't
     *      generate their salt properly.
     * @param owner The initial owner of the SoundEdition.
     * @param salt  The salt, generated on the client side.
     * @return result The computed value.
     */
    function _saltedSalt(address owner, bytes32 salt) internal view returns (bytes32 result) {
        assembly {
            mstore(0x20, owner)
            mstore(0x0c, chainid())
            mstore(0x00, salt)
            result := keccak256(0x00, 0x40)
        }
    }

    /**
     * @dev Creates a new SoundEdtion via `c.soundCreator`, and a new split contract if needed.
     * @param c The SoundCreation struct.
     * @return edition The address of the created SoundEdition contract.
     * @return results      The results of calling the contracts.
     *                      Use `abi.decode` to decode them.
     */
    function _create(SoundCreation calldata c) internal returns (address edition, bytes[] memory results) {
        if (c.implementation == address(0)) revert ImplementationAddressCantBeZero();

        // Create Sound Edition proxy.
        edition = payable(Clones.cloneDeterministic(c.implementation, _saltedSalt(c.owner, c.salt)));

        bytes calldata initData = c.initData;
        // Initialize proxy.
        assembly {
            // Grab the free memory pointer.
            let m := mload(0x40)
            // Copy the `initData` to the free memory.
            calldatacopy(m, initData.offset, initData.length)
            // Call the initializer, and revert if the call fails.
            if iszero(
                call(
                    gas(), // Gas remaining.
                    edition, // Address of the edition.
                    0, // `msg.value` of the call: 0 ETH.
                    m, // Start of input.
                    initData.length, // Length of input.
                    0x00, // Start of output. Not used.
                    0x00 // Size of output. Not used.
                )
            ) {
                // Bubble up the revert if the call reverts.
                returndatacopy(0x00, 0x00, returndatasize())
                revert(0x00, returndatasize())
            }
        }

        results = _callContracts(c.contracts, c.data);

        Ownable(edition).transferOwnership(c.owner);

        emit Created(c.implementation, edition, c.owner, c.initData, c.contracts, c.data, results);
    }

    /**
     * @dev Creates a SoundEdition on behalf of `c.owner`.
     * @param c  The SoundCreation struct.
     * @param signature The signature for the SoundCreation struct, by `c.owner`.
     * @return edition The address of the created SoundEdition contract.
     * @return results      The results of calling the contracts.
     *                      Use `abi.decode` to decode them.
     */
    function _createWithSignature(SoundCreation calldata c, bytes calldata signature)
        internal
        returns (address edition, bytes[] memory results)
    {
        if (!isValidSignature(c, signature)) revert InvalidSignature();
        (edition, results) = _create(c);

        // Invalidate the nonce and emit the event.
        _invalidatedNonces[c.owner].set(c.nonce);
        uint256[] memory nonces = new uint256[](1);
        nonces[0] = c.nonce;
        emit NoncesInvalidated(c.owner, nonces);
    }

    /**
     * @dev Calls `minter` with `mintData`.
     *      After which, refunds any remaining ETH balance in the adapter contract.
     *      If `minter` is the zero address, the function is a no-op.
     * @param minter   The minter contract to call, SAM included.
     * @param mintData The abi encoded calldata to the minter contract.
     * @param refundTo The address to transfer any remaining ETH in the contract after the calls.
     *                 If `address(0)`, remaining ETH will NOT be refunded.
     *                 If `address(1)`, remaining ETH will be refunded to `msg.sender`.
     *                 If anything else, remaining ETH will be refunded to `refundTo`.
     */
    function _mint(
        address minter,
        bytes calldata mintData,
        address refundTo
    ) internal {
        if (minter == address(0)) return;
        assembly {
            // Grab the free memory pointer.
            let m := mload(0x40)
            // Copy the `mintData` into the free memory.
            calldatacopy(m, mintData.offset, mintData.length)
            // Make a call to `minter` with `mintData`, reverting if the call fails.
            if iszero(
                call(
                    gas(), // Gas remaining.
                    minter, // Address of the minter.
                    callvalue(), // All the ETH sent to this function.
                    m, // Start of the `mintData` in memory.
                    mintData.length, // Length of `mintData`.
                    0x00, // We'll use returndatasize instead.
                    0x00 // We'll use returndatasize instead.
                )
            ) {
                // If the call fails, bubble up the revert.
                returndatacopy(0x00, 0x00, returndatasize())
                revert(0x00, returndatasize())
            }
        }
        if (refundTo != address(0)) {
            // Refund any ETH in this contract. In the unlikely case where ETH is
            // mistakenly sent to this contract, it will be combined into the refund.
            if (address(this).balance != 0) {
                if (refundTo == address(1)) refundTo = msg.sender;
                SafeTransferLib.forceSafeTransferAllETH(refundTo);
            }
        }
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (proxy/Clones.sol)

pragma solidity ^0.8.0;

/**
 * @dev https://eips.ethereum.org/EIPS/eip-1167[EIP 1167] is a standard for
 * deploying minimal proxy contracts, also known as "clones".
 *
 * > To simply and cheaply clone contract functionality in an immutable way, this standard specifies
 * > a minimal bytecode implementation that delegates all calls to a known, fixed address.
 *
 * The library includes functions to deploy a proxy using either `create` (traditional deployment) or `create2`
 * (salted deterministic deployment). It also includes functions to predict the addresses of clones deployed using the
 * deterministic method.
 *
 * _Available since v3.4._
 */
library Clones {
    /**
     * @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`.
     *
     * This function uses the create opcode, which should never revert.
     */
    function clone(address implementation) internal returns (address instance) {
        /// @solidity memory-safe-assembly
        assembly {
            let ptr := mload(0x40)
            mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)
            mstore(add(ptr, 0x14), shl(0x60, implementation))
            mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)
            instance := create(0, ptr, 0x37)
        }
        require(instance != address(0), "ERC1167: create failed");
    }

    /**
     * @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`.
     *
     * This function uses the create2 opcode and a `salt` to deterministically deploy
     * the clone. Using the same `implementation` and `salt` multiple time will revert, since
     * the clones cannot be deployed twice at the same address.
     */
    function cloneDeterministic(address implementation, bytes32 salt) internal returns (address instance) {
        /// @solidity memory-safe-assembly
        assembly {
            let ptr := mload(0x40)
            mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)
            mstore(add(ptr, 0x14), shl(0x60, implementation))
            mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)
            instance := create2(0, ptr, 0x37, salt)
        }
        require(instance != address(0), "ERC1167: create2 failed");
    }

    /**
     * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.
     */
    function predictDeterministicAddress(
        address implementation,
        bytes32 salt,
        address deployer
    ) internal pure returns (address predicted) {
        /// @solidity memory-safe-assembly
        assembly {
            let ptr := mload(0x40)
            mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)
            mstore(add(ptr, 0x14), shl(0x60, implementation))
            mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf3ff00000000000000000000000000000000)
            mstore(add(ptr, 0x38), shl(0x60, deployer))
            mstore(add(ptr, 0x4c), salt)
            mstore(add(ptr, 0x6c), keccak256(ptr, 0x37))
            predicted := keccak256(add(ptr, 0x37), 0x55)
        }
    }

    /**
     * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.
     */
    function predictDeterministicAddress(address implementation, bytes32 salt)
        internal
        view
        returns (address predicted)
    {
        return predictDeterministicAddress(implementation, salt, address(this));
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)

pragma solidity ^0.8.0;

/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
 * available, which can be applied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 *
 * TIP: If you would like to learn more about reentrancy and alternative ways
 * to protect against it, check out our blog post
 * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
 */
abstract contract ReentrancyGuard {
    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

    // The values being non-zero value makes deployment a bit more expensive,
    // but in exchange the refund on every call to nonReentrant will be lower in
    // amount. Since refunds are capped to a percentage of the total
    // transaction's gas, it is best to keep them low in cases like this one, to
    // increase the likelihood of the full refund coming into effect.
    uint256 private constant _NOT_ENTERED = 1;
    uint256 private constant _ENTERED = 2;

    uint256 private _status;

    constructor() {
        _status = _NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and making it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        _nonReentrantBefore();
        _;
        _nonReentrantAfter();
    }

    function _nonReentrantBefore() private {
        // On the first call to nonReentrant, _notEntered will be true
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

        // Any calls to nonReentrant after this point will fail
        _status = _ENTERED;
    }

    function _nonReentrantAfter() private {
        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        _status = _NOT_ENTERED;
    }
}

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

/**
 * @title ISoundCreatorV2
 * @notice The interface for the Sound edition factory.
 */
interface ISoundCreatorV2 {
    // =============================================================
    //                            STRUCTS
    // =============================================================

    /**
     * @dev A struct containing all the data required for creating a SoundEdition
     *      and setting up all other relevant contracts.
     */
    struct SoundCreation {
        // The address of the SoundEdition implementation.
        address implementation;
        // The initial owner of the deployed SoundEdition.
        address owner;
        // The salt used for deploying the SoundEdition via the SoundCreator factory.
        bytes32 salt;
        // The calldata passed to the SoundEdition to initialize it.
        bytes initData;
        // Array of contracts to call after initializing the SoundEdition.
        address[] contracts;
        // Array of abi encoded calldata to pass to each entry in `contracts`.
        bytes[] data;
        // The current nonce used to sign the SoundCreation struct, if required.
        // Just generate some really random number on the client side for this.
        uint256 nonce;
    }

    // =============================================================
    //                            EVENTS
    // =============================================================

    /**
     * @dev Emitted when an edition is created.
     * @param implementation The address of the SoundEdition implementation.
     * @param edition        The address of the deployed SoundEdition.
     * @param owner          The address of the owner.
     * @param initData       The calldata to initialize SoundEdition via `abi.encodeWithSelector`.
     * @param contracts      The list of contracts called.
     * @param data           The list of calldata created via `abi.encodeWithSelector`
     * @param results        The results of calling the contracts. Use `abi.decode` to decode them.
     */
    event Created(
        address indexed implementation,
        address indexed edition,
        address indexed owner,
        bytes initData,
        address[] contracts,
        bytes[] data,
        bytes[] results
    );

    /**
     * @dev Emitted when the `nonces` of `signer` are invalidated.
     * @param signer  The signer of the nonces.
     * @param nonces The nonces.
     */
    event NoncesInvalidated(address indexed signer, uint256[] nonces);

    // =============================================================
    //                            ERRORS
    // =============================================================

    /**
     * @dev Thrown if the implementation address is zero.
     */
    error ImplementationAddressCantBeZero();

    /**
     * @dev Thrown if the lengths of the input arrays are not equal.
     */
    error ArrayLengthsMismatch();

    /**
     * @dev Not authorized to perfrom the action.
     */
    error Unauthorized();

    /**
     * @dev The signature for the SoundCreation struct is invalid.
     *      This could be caused be an invalid parameter, signer, or invalidated nonce.
     */
    error InvalidSignature();

    // =============================================================
    //               PUBLIC / EXTERNAL WRITE FUNCTIONS
    // =============================================================

    /**
     * @dev Creates a SoundEdition and sets up all other relevant contracts.
     * @param creation The SoundCreation struct.
     * @return soundEdition The address of the created SoundEdition contract.
     * @return results      The results of calling the contracts.
     *                      Use `abi.decode` to decode them.
     */
    function create(SoundCreation calldata creation) external returns (address soundEdition, bytes[] memory results);

    /**
     * @dev Creates a SoundEdition on behalf of `creation.owner`.
     * @param creation  The SoundCreation struct.
     * @param signature The signature for the SoundCreation struct, by `creation.owner`.
     * @return soundEdition The address of the created SoundEdition contract.
     * @return results      The results of calling the contracts.
     *                      Use `abi.decode` to decode them.
     */
    function createWithSignature(SoundCreation calldata creation, bytes calldata signature)
        external
        returns (address soundEdition, bytes[] memory results);

    /**
     * @dev Calls `minter` with `mintData`.
     *      After which, refunds any remaining ETH balance in the adapter contract.
     *      If `minter` is the zero address, the function is a no-op.
     * @param minter   The minter contract to call, SAM included.
     * @param mintData The abi encoded calldata to the minter contract.
     * @param refundTo The address to transfer any remaining ETH in the contract after the calls.
     *                 If `address(0)`, remaining ETH will NOT be refunded.
     *                 If `address(1)`, remaining ETH will be refunded to `msg.sender`.
     *                 If anything else, remaining ETH will be refunded to `refundTo`.
     */
    function mint(
        address minter,
        bytes calldata mintData,
        address refundTo
    ) external payable;

    /**
     * @dev Equivalent to calling {createWithSignature}, followed by {mint}.
     * @param creation  The SoundCreation struct.
     * @param signature The signature for the SoundCreation struct, by `creation.owner`.
     * @param minter    The minter contract to call, SAM included.
     * @param mintData  The calldata to the minter contract.
     * @param refundTo  The address to transfer any remaining ETH in the contract after the calls.
     *                  If `address(0)`, remaining ETH will NOT be refunded.
     *                  If `address(1)`, remaining ETH will be refunded to `msg.sender`.
     *                  If anything else, remaining ETH will be refunded to `refundTo`.
     * @return soundEdition The address of the created SoundEdition contract.
     * @return results      The results of calling the contracts.
     *                      Use `abi.decode` to decode them.
     */
    function createWithSignatureAndMint(
        SoundCreation calldata creation,
        bytes calldata signature,
        address minter,
        bytes calldata mintData,
        address refundTo
    ) external payable returns (address soundEdition, bytes[] memory results);

    /**
     * @dev Invalidates the nonces for the `msg.sender`.
     * @param nonces The nonces.
     */
    function invalidateNonces(uint256[] calldata nonces) external;

    // =============================================================
    //               PUBLIC / EXTERNAL VIEW FUNCTIONS
    // =============================================================

    /**
     * @dev Returns whether each of the `nonces` of `signer` has been invalidated.
     * @param signer The signer of the signature.
     * @param nonces An array of nonces.
     * @return A bool array representing whether each nonce has been invalidated.
     */
    function noncesInvalidated(address signer, uint256[] calldata nonces) external view returns (bool[] memory);

    /**
     * @dev Returns the deterministic address for the SoundEdition clone.
     * @param implementation The implementation of the SoundEdition.
     * @param owner          The initial owner of the SoundEdition.
     * @param salt           The salt, generated on the client side.
     * @return addr The computed address.
     * @return exists Whether the contract exists.
     */
    function soundEditionAddress(
        address implementation,
        address owner,
        bytes32 salt
    ) external view returns (address addr, bool exists);

    /**
     * @dev Returns if the signature for the creation struct is correctly signed,
     *      as well as the creation's nonce is still valid.
     * @param creation  The SoundCreation struct.
     * @param signature The signature for the SoundCreation struct.
     * @return isValid The computed result.
     */
    function isValidSignature(SoundCreation calldata creation, bytes calldata signature) external view returns (bool);

    /**
     * @dev Computes the EIP-712 hash of the SoundCreation struct.
     * @param creation The SoundCreation struct.
     * @return digest The computed result.
     */
    function computeDigest(SoundCreation calldata creation) external view returns (bytes32 digest);

    /**
     * @dev Returns the SoundCreation struct's EIP-712 typehash.
     * @return The constant value.
     */
    function SOUND_CREATION_TYPEHASH() external view returns (bytes32);

    /**
     * @dev Returns the EIP-712 domain typehash.
     * @return The constant value.
     */
    function DOMAIN_TYPEHASH() external view returns (bytes32);

    /**
     * @dev Returns the EIP-712 domain name.
     * @return name_ The constant value.
     */
    function name() external pure returns (string memory name_);

    /**
     * @dev Returns the EIP-712 domain version.
     * @return version_ The constant value.
     */
    function version() external pure returns (string memory version_);

    /**
     * @dev Returns the EIP-712 domain separator.
     * @return The current value.
     */
    function domainSeparator() external view returns (bytes32);
}

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

/**
 * @title LibMulticaller
 * @author vectorized.eth
 * @notice Library to read the `msg.sender` of the multicaller with sender contract.
 */
library LibMulticaller {
    /**
     * @dev The address of the multicaller contract.
     */
    address internal constant MULTICALLER = 0x0000000000009448722dAF1A55EF6D1E71FB162d;

    /**
     * @dev The address of the multicaller with sender contract.
     */
    address internal constant MULTICALLER_WITH_SENDER = 0x00000000002Fd5Aeb385D324B580FCa7c83823A0;

    /**
     * @dev The address of the multicaller with signer contract.
     */
    address internal constant MULTICALLER_WITH_SIGNER = 0x000000000000a89360A6a4786b9B33266F208AF4;

    /**
     * @dev Returns the caller of `aggregateWithSender` on `MULTICALLER_WITH_SENDER`.
     */
    function multicallerSender() internal view returns (address result) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, 0x00)
            if iszero(staticcall(gas(), MULTICALLER_WITH_SENDER, 0x00, 0x00, 0x00, 0x20)) {
                revert(0x00, 0x00) // For better gas estimation.
            }
            result := mload(0x00)
        }
    }

    /**
     * @dev Returns the signer of `aggregateWithSigner` on `MULTICALLER_WITH_SIGNER`.
     */
    function multicallerSigner() internal view returns (address result) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, 0x00)
            if iszero(staticcall(gas(), MULTICALLER_WITH_SIGNER, 0x00, 0x00, 0x00, 0x20)) {
                revert(0x00, 0x00) // For better gas estimation.
            }
            result := mload(0x00)
        }
    }

    /**
     * @dev Returns the caller of `aggregateWithSender` on `MULTICALLER_WITH_SENDER`,
     *      if the current context's `msg.sender` is `MULTICALLER_WITH_SENDER`.
     *      Otherwise, returns `msg.sender`.
     */
    function sender() internal view returns (address result) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, caller())
            let withSender := MULTICALLER_WITH_SENDER
            if eq(caller(), withSender) {
                if iszero(staticcall(gas(), withSender, 0x00, 0x00, 0x00, 0x20)) {
                    revert(0x00, 0x00) // For better gas estimation.
                }
            }
            result := mload(0x00)
        }
    }

    /**
     * @dev Returns the caller of `aggregateWithSender` on `MULTICALLER_WITH_SENDER`,
     *      if the current context's `msg.sender` is `MULTICALLER_WITH_SENDER`.
     *      Returns the signer of `aggregateWithSigner` on `MULTICALLER_WITH_SIGNER`,
     *      if the current context's `msg.sender` is `MULTICALLER_WITH_SIGNER`.
     *      Otherwise, returns `msg.sender`.
     */
    function senderOrSigner() internal view returns (address result) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, caller())
            let withSender := MULTICALLER_WITH_SENDER
            if eq(caller(), withSender) {
                if iszero(staticcall(gas(), withSender, 0x00, 0x00, 0x00, 0x20)) {
                    revert(0x00, 0x00) // For better gas estimation.
                }
            }
            let withSigner := MULTICALLER_WITH_SIGNER
            if eq(caller(), withSigner) {
                if iszero(staticcall(gas(), withSigner, 0x00, 0x00, 0x00, 0x20)) {
                    revert(0x00, 0x00) // For better gas estimation.
                }
            }
            result := mload(0x00)
        }
    }
}

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

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

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

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

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

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

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

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

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

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

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

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

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

    /// @dev The owner slot is given by: `not(_OWNER_SLOT_NOT)`.
    /// It is intentionally chosen to be a high value
    /// to avoid collision with lower slots.
    /// The choice of manual storage layout is to enable compatibility
    /// with both regular and upgradeable contracts.
    uint256 private constant _OWNER_SLOT_NOT = 0x8b78c6d8;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

/// @notice Contract for EIP-712 typed structured data hashing and signing.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/EIP712.sol)
/// @author Modified from Solbase (https://github.com/Sol-DAO/solbase/blob/main/src/utils/EIP712.sol)
/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/EIP712.sol)
///
/// @dev Note, this implementation:
/// - Uses `address(this)` for the `verifyingContract` field.
/// - Does NOT use the optional EIP-712 salt.
/// - Does NOT use any EIP-712 extensions.
/// This is for simplicity and to save gas.
/// If you need to customize, please fork / modify accordingly.
abstract contract EIP712 {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                  CONSTANTS AND IMMUTABLES                  */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev `keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)")`.
    bytes32 internal constant _DOMAIN_TYPEHASH =
        0x8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f;

    address private immutable _cachedThis;
    uint256 private immutable _cachedChainId;
    bytes32 private immutable _cachedNameHash;
    bytes32 private immutable _cachedVersionHash;
    bytes32 private immutable _cachedDomainSeparator;

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

    /// @dev Cache the hashes for cheaper runtime gas costs.
    /// In the case of upgradeable contracts (i.e. proxies),
    /// or if the chain id changes due to a hard fork,
    /// the domain separator will be seamlessly calculated on-the-fly.
    constructor() {
        _cachedThis = address(this);
        _cachedChainId = block.chainid;

        string memory name;
        string memory version;
        if (!_domainNameAndVersionMayChange()) (name, version) = _domainNameAndVersion();
        bytes32 nameHash = _domainNameAndVersionMayChange() ? bytes32(0) : keccak256(bytes(name));
        bytes32 versionHash =
            _domainNameAndVersionMayChange() ? bytes32(0) : keccak256(bytes(version));
        _cachedNameHash = nameHash;
        _cachedVersionHash = versionHash;

        bytes32 separator;
        if (!_domainNameAndVersionMayChange()) {
            /// @solidity memory-safe-assembly
            assembly {
                let m := mload(0x40) // Load the free memory pointer.
                mstore(m, _DOMAIN_TYPEHASH)
                mstore(add(m, 0x20), nameHash)
                mstore(add(m, 0x40), versionHash)
                mstore(add(m, 0x60), chainid())
                mstore(add(m, 0x80), address())
                separator := keccak256(m, 0xa0)
            }
        }
        _cachedDomainSeparator = separator;
    }

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

    /// @dev Please override this function to return the domain name and version.
    /// ```
    ///     function _domainNameAndVersion()
    ///         internal
    ///         pure
    ///         virtual
    ///         returns (string memory name, string memory version)
    ///     {
    ///         name = "Solady";
    ///         version = "1";
    ///     }
    /// ```
    ///
    /// Note: If the returned result may change after the contract has been deployed,
    /// you must override `_domainNameAndVersionMayChange()` to return true.
    function _domainNameAndVersion()
        internal
        view
        virtual
        returns (string memory name, string memory version);

    /// @dev Returns if `_domainNameAndVersion()` may change
    /// after the contract has been deployed (i.e. after the constructor).
    /// Default: false.
    function _domainNameAndVersionMayChange() internal pure virtual returns (bool result) {}

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

    /// @dev Returns the EIP-712 domain separator.
    function _domainSeparator() internal view virtual returns (bytes32 separator) {
        if (_domainNameAndVersionMayChange()) {
            separator = _buildDomainSeparator();
        } else {
            separator = _cachedDomainSeparator;
            if (_cachedDomainSeparatorInvalidated()) separator = _buildDomainSeparator();
        }
    }

    /// @dev Returns the hash of the fully encoded EIP-712 message for this domain,
    /// given `structHash`, as defined in
    /// https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct.
    ///
    /// The hash can be used together with {ECDSA-recover} to obtain the signer of a message:
    /// ```
    ///     bytes32 digest = _hashTypedData(keccak256(abi.encode(
    ///         keccak256("Mail(address to,string contents)"),
    ///         mailTo,
    ///         keccak256(bytes(mailContents))
    ///     )));
    ///     address signer = ECDSA.recover(digest, signature);
    /// ```
    function _hashTypedData(bytes32 structHash) internal view virtual returns (bytes32 digest) {
        bytes32 separator;
        if (_domainNameAndVersionMayChange()) {
            separator = _buildDomainSeparator();
        } else {
            separator = _cachedDomainSeparator;
            if (_cachedDomainSeparatorInvalidated()) separator = _buildDomainSeparator();
        }
        /// @solidity memory-safe-assembly
        assembly {
            // Compute the digest.
            mstore(0x00, 0x1901000000000000) // Store "\x19\x01".
            mstore(0x1a, separator) // Store the domain separator.
            mstore(0x3a, structHash) // Store the struct hash.
            digest := keccak256(0x18, 0x42)
            // Restore the part of the free memory slot that was overwritten.
            mstore(0x3a, 0)
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                    EIP-5267 OPERATIONS                     */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev See: https://eips.ethereum.org/EIPS/eip-5267
    function eip712Domain()
        public
        view
        virtual
        returns (
            bytes1 fields,
            string memory name,
            string memory version,
            uint256 chainId,
            address verifyingContract,
            bytes32 salt,
            uint256[] memory extensions
        )
    {
        fields = hex"0f"; // `0b01111`.
        (name, version) = _domainNameAndVersion();
        chainId = block.chainid;
        verifyingContract = address(this);
        salt = salt; // `bytes32(0)`.
        extensions = extensions; // `new uint256[](0)`.
    }

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

    /// @dev Returns the EIP-712 domain separator.
    function _buildDomainSeparator() private view returns (bytes32 separator) {
        bytes32 nameHash;
        bytes32 versionHash;
        if (_domainNameAndVersionMayChange()) {
            (string memory name, string memory version) = _domainNameAndVersion();
            nameHash = keccak256(bytes(name));
            versionHash = keccak256(bytes(version));
        } else {
            nameHash = _cachedNameHash;
            versionHash = _cachedVersionHash;
        }
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40) // Load the free memory pointer.
            mstore(m, _DOMAIN_TYPEHASH)
            mstore(add(m, 0x20), nameHash)
            mstore(add(m, 0x40), versionHash)
            mstore(add(m, 0x60), chainid())
            mstore(add(m, 0x80), address())
            separator := keccak256(m, 0xa0)
        }
    }

    /// @dev Returns if the cached domain separator has been invalidated.
    function _cachedDomainSeparatorInvalidated() private view returns (bool result) {
        uint256 cachedChainId = _cachedChainId;
        address cachedThis = _cachedThis;
        /// @solidity memory-safe-assembly
        assembly {
            result := iszero(and(eq(chainid(), cachedChainId), eq(address(), cachedThis)))
        }
    }
}

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

/// @notice Library for compressing and decompressing bytes.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/LibZip.sol)
/// @author Calldata compression by clabby (https://github.com/clabby/op-kompressor)
/// @author FastLZ by ariya (https://github.com/ariya/FastLZ)
///
/// @dev Note:
/// The accompanying solady.js library includes implementations of
/// FastLZ and calldata operations for convenience.
library LibZip {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                     FAST LZ OPERATIONS                     */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    // LZ77 implementation based on FastLZ.
    // Equivalent to level 1 compression and decompression at the following commit:
    // https://github.com/ariya/FastLZ/commit/344eb4025f9ae866ebf7a2ec48850f7113a97a42
    // Decompression is backwards compatible.

    /// @dev Returns the compressed `data`.
    function flzCompress(bytes memory data) internal pure returns (bytes memory result) {
        /// @solidity memory-safe-assembly
        assembly {
            function ms8(d_, v_) -> _d {
                mstore8(d_, v_)
                _d := add(d_, 1)
            }
            function u24(p_) -> _u {
                let w := mload(p_)
                _u := or(shl(16, byte(2, w)), or(shl(8, byte(1, w)), byte(0, w)))
            }
            function cmp(p_, q_, e_) -> _l {
                for { e_ := sub(e_, q_) } lt(_l, e_) { _l := add(_l, 1) } {
                    e_ := mul(iszero(byte(0, xor(mload(add(p_, _l)), mload(add(q_, _l))))), e_)
                }
            }
            function literals(runs_, src_, dest_) -> _o {
                for { _o := dest_ } iszero(lt(runs_, 0x20)) { runs_ := sub(runs_, 0x20) } {
                    mstore(ms8(_o, 31), mload(src_))
                    _o := add(_o, 0x21)
                    src_ := add(src_, 0x20)
                }
                if iszero(runs_) { leave }
                mstore(ms8(_o, sub(runs_, 1)), mload(src_))
                _o := add(1, add(_o, runs_))
            }
            function match(l_, d_, o_) -> _o {
                for { d_ := sub(d_, 1) } iszero(lt(l_, 263)) { l_ := sub(l_, 262) } {
                    o_ := ms8(ms8(ms8(o_, add(224, shr(8, d_))), 253), and(0xff, d_))
                }
                if iszero(lt(l_, 7)) {
                    _o := ms8(ms8(ms8(o_, add(224, shr(8, d_))), sub(l_, 7)), and(0xff, d_))
                    leave
                }
                _o := ms8(ms8(o_, add(shl(5, l_), shr(8, d_))), and(0xff, d_))
            }
            function setHash(i_, v_) {
                let p := add(mload(0x40), shl(2, i_))
                mstore(p, xor(mload(p), shl(224, xor(shr(224, mload(p)), v_))))
            }
            function getHash(i_) -> _h {
                _h := shr(224, mload(add(mload(0x40), shl(2, i_))))
            }
            function hash(v_) -> _r {
                _r := and(shr(19, mul(2654435769, v_)), 0x1fff)
            }
            function setNextHash(ip_, ipStart_) -> _ip {
                setHash(hash(u24(ip_)), sub(ip_, ipStart_))
                _ip := add(ip_, 1)
            }
            codecopy(mload(0x40), codesize(), 0x8000) // Zeroize the hashmap.
            let op := add(mload(0x40), 0x8000)
            let a := add(data, 0x20)
            let ipStart := a
            let ipLimit := sub(add(ipStart, mload(data)), 13)
            for { let ip := add(2, a) } lt(ip, ipLimit) {} {
                let r := 0
                let d := 0
                for {} 1 {} {
                    let s := u24(ip)
                    let h := hash(s)
                    r := add(ipStart, getHash(h))
                    setHash(h, sub(ip, ipStart))
                    d := sub(ip, r)
                    if iszero(lt(ip, ipLimit)) { break }
                    ip := add(ip, 1)
                    if iszero(gt(d, 0x1fff)) { if eq(s, u24(r)) { break } }
                }
                if iszero(lt(ip, ipLimit)) { break }
                ip := sub(ip, 1)
                if gt(ip, a) { op := literals(sub(ip, a), a, op) }
                let l := cmp(add(r, 3), add(ip, 3), add(ipLimit, 9))
                op := match(l, d, op)
                ip := setNextHash(setNextHash(add(ip, l), ipStart), ipStart)
                a := ip
            }
            op := literals(sub(add(ipStart, mload(data)), a), a, op)
            result := mload(0x40)
            let t := add(result, 0x8000)
            let n := sub(op, t)
            mstore(result, n) // Store the length.
            // Copy the result to compact the memory, overwriting the hashmap.
            let o := add(result, 0x20)
            for { let i } lt(i, n) { i := add(i, 0x20) } { mstore(add(o, i), mload(add(t, i))) }
            mstore(add(o, n), 0) // Zeroize the slot after the string.
            mstore(0x40, add(add(o, n), 0x20)) // Allocate the memory.
        }
    }

    /// @dev Returns the decompressed `data`.
    function flzDecompress(bytes memory data) internal pure returns (bytes memory result) {
        /// @solidity memory-safe-assembly
        assembly {
            let n := 0
            let end := add(add(data, 0x20), mload(data))
            result := mload(0x40)
            let op := add(result, 0x20)
            for { data := add(data, 0x20) } lt(data, end) {} {
                let w := mload(data)
                let c := byte(0, w)
                let t := shr(5, c)
                if iszero(t) {
                    mstore(add(op, n), mload(add(data, 1)))
                    data := add(data, add(2, c))
                    n := add(n, add(1, c))
                    continue
                }
                let g := eq(t, 7)
                let l := add(2, xor(t, mul(g, xor(t, add(7, byte(1, w))))))
                for {
                    let s := add(add(shl(8, and(0x1f, c)), byte(add(1, g), w)), 1)
                    let r := add(op, sub(n, s))
                    let o := add(op, n)
                    let f := xor(s, mul(gt(s, 0x20), xor(s, 0x20)))
                    let j := 0
                } 1 {} {
                    mstore(add(o, j), mload(add(r, j)))
                    j := add(j, f)
                    if iszero(lt(j, l)) { break }
                }
                data := add(data, add(2, g))
                n := add(n, l)
            }
            mstore(result, n) // Store the length.
            let o := add(add(result, 0x20), n)
            mstore(o, 0) // Zeroize the slot after the string.
            mstore(0x40, add(o, 0x20)) // Allocate the memory.
        }
    }

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

    // Calldata compression and decompression using selective run length encoding:
    // - Sequences of 0x00 (up to 128 consecutive).
    // - Sequences of 0xff (up to 32 consecutive).
    //
    // A run length encoded block consists of two bytes:
    // (0) 0x00
    // (1) A control byte with the following bit layout:
    //     - [7]     `0: 0x00, 1: 0xff`.
    //     - [0..6]  `runLength - 1`.
    //
    // The first 4 bytes are bitwise negated so that the compressed calldata
    // can be dispatched into the `fallback` and `receive` functions.

    /// @dev Returns the compressed `data`.
    function cdCompress(bytes memory data) internal pure returns (bytes memory result) {
        /// @solidity memory-safe-assembly
        assembly {
            function rle(v_, o_, d_) -> _o, _d {
                mstore(o_, shl(240, or(and(0xff, add(d_, 0xff)), and(0x80, v_))))
                _o := add(o_, 2)
            }
            result := mload(0x40)
            let o := add(result, 0x20)
            let z := 0 // Number of consecutive 0x00.
            let y := 0 // Number of consecutive 0xff.
            for { let end := add(data, mload(data)) } iszero(eq(data, end)) {} {
                data := add(data, 1)
                let c := byte(31, mload(data))
                if iszero(c) {
                    if y { o, y := rle(0xff, o, y) }
                    z := add(z, 1)
                    if eq(z, 0x80) { o, z := rle(0x00, o, 0x80) }
                    continue
                }
                if eq(c, 0xff) {
                    if z { o, z := rle(0x00, o, z) }
                    y := add(y, 1)
                    if eq(y, 0x20) { o, y := rle(0xff, o, 0x20) }
                    continue
                }
                if y { o, y := rle(0xff, o, y) }
                if z { o, z := rle(0x00, o, z) }
                mstore8(o, c)
                o := add(o, 1)
            }
            if y { o, y := rle(0xff, o, y) }
            if z { o, z := rle(0x00, o, z) }
            // Bitwise negate the first 4 bytes.
            mstore(add(result, 4), not(mload(add(result, 4))))
            mstore(result, sub(o, add(result, 0x20))) // Store the length.
            mstore(o, 0) // Zeroize the slot after the string.
            mstore(0x40, add(o, 0x20)) // Allocate the memory.
        }
    }

    /// @dev Returns the decompressed `data`.
    function cdDecompress(bytes memory data) internal pure returns (bytes memory result) {
        /// @solidity memory-safe-assembly
        assembly {
            if mload(data) {
                result := mload(0x40)
                let o := add(result, 0x20)
                let s := add(data, 4)
                let v := mload(s)
                let end := add(data, mload(data))
                mstore(s, not(v)) // Bitwise negate the first 4 bytes.
                for {} lt(data, end) {} {
                    data := add(data, 1)
                    let c := byte(31, mload(data))
                    if iszero(c) {
                        data := add(data, 1)
                        let d := byte(31, mload(data))
                        // Fill with either 0xff or 0x00.
                        mstore(o, not(0))
                        if iszero(gt(d, 0x7f)) { codecopy(o, codesize(), add(d, 1)) }
                        o := add(o, add(and(d, 0x7f), 1))
                        continue
                    }
                    mstore8(o, c)
                    o := add(o, 1)
                }
                mstore(s, v) // Restore the first 4 bytes.
                mstore(result, sub(o, add(result, 0x20))) // Store the length.
                mstore(o, 0) // Zeroize the slot after the string.
                mstore(0x40, add(o, 0x20)) // Allocate the memory.
            }
        }
    }

    /// @dev To be called in the `receive` and `fallback` functions.
    /// ```
    ///     receive() external payable { LibZip.cdFallback(); }
    ///     fallback() external payable { LibZip.cdFallback(); }
    /// ```
    /// For efficiency, this function will directly return the results, terminating the context.
    /// If called internally, it must be called at the end of the function.
    function cdFallback() internal {
        assembly {
            if iszero(calldatasize()) { return(calldatasize(), calldatasize()) }
            let o := 0
            let f := not(3) // For negating the first 4 bytes.
            for { let i := 0 } lt(i, calldatasize()) {} {
                let c := byte(0, xor(add(i, f), calldataload(i)))
                i := add(i, 1)
                if iszero(c) {
                    let d := byte(0, xor(add(i, f), calldataload(i)))
                    i := add(i, 1)
                    // Fill with either 0xff or 0x00.
                    mstore(o, not(0))
                    if iszero(gt(d, 0x7f)) { codecopy(o, codesize(), add(d, 1)) }
                    o := add(o, add(and(d, 0x7f), 1))
                    continue
                }
                mstore8(o, c)
                o := add(o, 1)
            }
            let success := delegatecall(gas(), address(), 0x00, o, 0x00, 0x00)
            returndatacopy(0x00, 0x00, returndatasize())
            if iszero(success) { revert(0x00, returndatasize()) }
            return(0x00, returndatasize())
        }
    }
}

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

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

/// @notice Library for storage of packed unsigned booleans.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/LibBitmap.sol)
/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/LibBitmap.sol)
/// @author Modified from Solidity-Bits (https://github.com/estarriolvetch/solidity-bits/blob/main/contracts/BitMaps.sol)
library LibBitmap {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                         CONSTANTS                          */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The constant returned when a bitmap scan does not find a result.
    uint256 internal constant NOT_FOUND = type(uint256).max;

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

    /// @dev A bitmap in storage.
    struct Bitmap {
        mapping(uint256 => uint256) map;
    }

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

    /// @dev Returns the boolean value of the bit at `index` in `bitmap`.
    function get(Bitmap storage bitmap, uint256 index) internal view returns (bool isSet) {
        // It is better to set `isSet` to either 0 or 1, than zero vs non-zero.
        // Both cost the same amount of gas, but the former allows the returned value
        // to be reused without cleaning the upper bits.
        uint256 b = (bitmap.map[index >> 8] >> (index & 0xff)) & 1;
        /// @solidity memory-safe-assembly
        assembly {
            isSet := b
        }
    }

    /// @dev Updates the bit at `index` in `bitmap` to true.
    function set(Bitmap storage bitmap, uint256 index) internal {
        bitmap.map[index >> 8] |= (1 << (index & 0xff));
    }

    /// @dev Updates the bit at `index` in `bitmap` to false.
    function unset(Bitmap storage bitmap, uint256 index) internal {
        bitmap.map[index >> 8] &= ~(1 << (index & 0xff));
    }

    /// @dev Flips the bit at `index` in `bitmap`.
    /// Returns the boolean result of the flipped bit.
    function toggle(Bitmap storage bitmap, uint256 index) internal returns (bool newIsSet) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, shr(8, index))
            mstore(0x20, bitmap.slot)
            let storageSlot := keccak256(0x00, 0x40)
            let shift := and(index, 0xff)
            let storageValue := sload(storageSlot)

            let mask := shl(shift, 1)
            storageValue := xor(storageValue, mask)
            // It makes sense to return the `newIsSet`,
            // as it allow us to skip an additional warm `sload`,
            // and it costs minimal gas (about 15),
            // which may be optimized away if the returned value is unused.
            newIsSet := iszero(iszero(and(storageValue, mask)))
            sstore(storageSlot, storageValue)
        }
    }

    /// @dev Updates the bit at `index` in `bitmap` to `shouldSet`.
    function setTo(Bitmap storage bitmap, uint256 index, bool shouldSet) internal {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x20, bitmap.slot)
            mstore(0x00, shr(8, index))
            let storageSlot := keccak256(0x00, 0x40)
            let storageValue := sload(storageSlot)
            let shift := and(index, 0xff)

            sstore(
                storageSlot,
                // Unsets the bit at `shift` via `and`, then sets its new value via `or`.
                or(and(storageValue, not(shl(shift, 1))), shl(shift, iszero(iszero(shouldSet))))
            )
        }
    }

    /// @dev Consecutively sets `amount` of bits starting from the bit at `start`.
    function setBatch(Bitmap storage bitmap, uint256 start, uint256 amount) internal {
        /// @solidity memory-safe-assembly
        assembly {
            let max := not(0)
            let shift := and(start, 0xff)
            mstore(0x20, bitmap.slot)
            mstore(0x00, shr(8, start))
            if iszero(lt(add(shift, amount), 257)) {
                let storageSlot := keccak256(0x00, 0x40)
                sstore(storageSlot, or(sload(storageSlot), shl(shift, max)))
                let bucket := add(mload(0x00), 1)
                let bucketEnd := add(mload(0x00), shr(8, add(amount, shift)))
                amount := and(add(amount, shift), 0xff)
                shift := 0
                for {} iszero(eq(bucket, bucketEnd)) { bucket := add(bucket, 1) } {
                    mstore(0x00, bucket)
                    sstore(keccak256(0x00, 0x40), max)
                }
                mstore(0x00, bucket)
            }
            let storageSlot := keccak256(0x00, 0x40)
            sstore(storageSlot, or(sload(storageSlot), shl(shift, shr(sub(256, amount), max))))
        }
    }

    /// @dev Consecutively unsets `amount` of bits starting from the bit at `start`.
    function unsetBatch(Bitmap storage bitmap, uint256 start, uint256 amount) internal {
        /// @solidity memory-safe-assembly
        assembly {
            let shift := and(start, 0xff)
            mstore(0x20, bitmap.slot)
            mstore(0x00, shr(8, start))
            if iszero(lt(add(shift, amount), 257)) {
                let storageSlot := keccak256(0x00, 0x40)
                sstore(storageSlot, and(sload(storageSlot), not(shl(shift, not(0)))))
                let bucket := add(mload(0x00), 1)
                let bucketEnd := add(mload(0x00), shr(8, add(amount, shift)))
                amount := and(add(amount, shift), 0xff)
                shift := 0
                for {} iszero(eq(bucket, bucketEnd)) { bucket := add(bucket, 1) } {
                    mstore(0x00, bucket)
                    sstore(keccak256(0x00, 0x40), 0)
                }
                mstore(0x00, bucket)
            }
            let storageSlot := keccak256(0x00, 0x40)
            sstore(
                storageSlot, and(sload(storageSlot), not(shl(shift, shr(sub(256, amount), not(0)))))
            )
        }
    }

    /// @dev Returns number of set bits within a range by
    /// scanning `amount` of bits starting from the bit at `start`.
    function popCount(Bitmap storage bitmap, uint256 start, uint256 amount)
        internal
        view
        returns (uint256 count)
    {
        unchecked {
            uint256 bucket = start >> 8;
            uint256 shift = start & 0xff;
            if (!(amount + shift < 257)) {
                count = LibBit.popCount(bitmap.map[bucket] >> shift);
                uint256 bucketEnd = bucket + ((amount + shift) >> 8);
                amount = (amount + shift) & 0xff;
                shift = 0;
                for (++bucket; bucket != bucketEnd; ++bucket) {
                    count += LibBit.popCount(bitmap.map[bucket]);
                }
            }
            count += LibBit.popCount((bitmap.map[bucket] >> shift) << (256 - amount));
        }
    }

    /// @dev Returns the index of the most significant set bit before the bit at `before`.
    /// If no set bit is found, returns `NOT_FOUND`.
    function findLastSet(Bitmap storage bitmap, uint256 before)
        internal
        view
        returns (uint256 setBitIndex)
    {
        uint256 bucket;
        uint256 bucketBits;
        /// @solidity memory-safe-assembly
        assembly {
            setBitIndex := not(0)
            bucket := shr(8, before)
            mstore(0x00, bucket)
            mstore(0x20, bitmap.slot)
            let offset := and(0xff, not(before)) // `256 - (255 & before) - 1`.
            bucketBits := shr(offset, shl(offset, sload(keccak256(0x00, 0x40))))
            if iszero(bucketBits) {
                for {} bucket {} {
                    bucket := add(bucket, setBitIndex) // `sub(bucket, 1)`.
                    mstore(0x00, bucket)
                    bucketBits := sload(keccak256(0x00, 0x40))
                    if bucketBits { break }
                }
            }
        }
        if (bucketBits != 0) {
            setBitIndex = (bucket << 8) | LibBit.fls(bucketBits);
            /// @solidity memory-safe-assembly
            assembly {
                setBitIndex := or(setBitIndex, sub(0, gt(setBitIndex, before)))
            }
        }
    }
}

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

/// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/SafeTransferLib.sol)
/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol)
///
/// @dev Note:
/// - For ETH transfers, please use `forceSafeTransferETH` for DoS protection.
/// - For ERC20s, this implementation won't check that a token has code,
///   responsibility is delegated to the caller.
library SafeTransferLib {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                       CUSTOM ERRORS                        */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

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

    /// @dev The ERC20 `transferFrom` has failed.
    error TransferFromFailed();

    /// @dev The ERC20 `transfer` has failed.
    error TransferFailed();

    /// @dev The ERC20 `approve` has failed.
    error ApproveFailed();

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

    /// @dev Suggested gas stipend for contract receiving ETH that disallows any storage writes.
    uint256 internal constant GAS_STIPEND_NO_STORAGE_WRITES = 2300;

    /// @dev Suggested gas stipend for contract receiving ETH to perform a few
    /// storage reads and writes, but low enough to prevent griefing.
    uint256 internal constant GAS_STIPEND_NO_GRIEF = 100000;

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

    // If the ETH transfer MUST succeed with a reasonable gas budget, use the force variants.
    //
    // The regular variants:
    // - Forwards all remaining gas to the target.
    // - Reverts if the target reverts.
    // - Reverts if the current contract has insufficient balance.
    //
    // The force variants:
    // - Forwards with an optional gas stipend
    //   (defaults to `GAS_STIPEND_NO_GRIEF`, which is sufficient for most cases).
    // - If the target reverts, or if the gas stipend is exhausted,
    //   creates a temporary contract to force send the ETH via `SELFDESTRUCT`.
    //   Future compatible with `SENDALL`: https://eips.ethereum.org/EIPS/eip-4758.
    // - Reverts if the current contract has insufficient balance.
    //
    // The try variants:
    // - Forwards with a mandatory gas stipend.
    // - Instead of reverting, returns whether the transfer succeeded.

    /// @dev Sends `amount` (in wei) ETH to `to`.
    function safeTransferETH(address to, uint256 amount) internal {
        /// @solidity memory-safe-assembly
        assembly {
            if iszero(call(gas(), to, amount, gas(), 0x00, gas(), 0x00)) {
                mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.
                revert(0x1c, 0x04)
            }
        }
    }

    /// @dev Sends all the ETH in the current contract to `to`.
    function safeTransferAllETH(address to) internal {
        /// @solidity memory-safe-assembly
        assembly {
            // Transfer all the ETH and check if it succeeded or not.
            if iszero(call(gas(), to, selfbalance(), gas(), 0x00, gas(), 0x00)) {
                mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.
                revert(0x1c, 0x04)
            }
        }
    }

    /// @dev Force sends `amount` (in wei) ETH to `to`, with a `gasStipend`.
    function forceSafeTransferETH(address to, uint256 amount, uint256 gasStipend) internal {
        /// @solidity memory-safe-assembly
        assembly {
            if lt(selfbalance(), amount) {
                mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.
                revert(0x1c, 0x04)
            }
            if iszero(call(gasStipend, to, amount, gas(), 0x00, gas(), 0x00)) {
                mstore(0x00, to) // Store the address in scratch space.
                mstore8(0x0b, 0x73) // Opcode `PUSH20`.
                mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`.
                if iszero(create(amount, 0x0b, 0x16)) {
                    returndatacopy(gas(), returndatasize(), shr(20, gas())) // For gas estimation.
                }
            }
        }
    }

    /// @dev Force sends all the ETH in the current contract to `to`, with a `gasStipend`.
    function forceSafeTransferAllETH(address to, uint256 gasStipend) internal {
        /// @solidity memory-safe-assembly
        assembly {
            if iszero(call(gasStipend, to, selfbalance(), gas(), 0x00, gas(), 0x00)) {
                mstore(0x00, to) // Store the address in scratch space.
                mstore8(0x0b, 0x73) // Opcode `PUSH20`.
                mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`.
                if iszero(create(selfbalance(), 0x0b, 0x16)) {
                    returndatacopy(gas(), returndatasize(), shr(20, gas())) // For gas estimation.
                }
            }
        }
    }

    /// @dev Force sends `amount` (in wei) ETH to `to`, with `GAS_STIPEND_NO_GRIEF`.
    function forceSafeTransferETH(address to, uint256 amount) internal {
        /// @solidity memory-safe-assembly
        assembly {
            if lt(selfbalance(), amount) {
                mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.
                revert(0x1c, 0x04)
            }
            if iszero(call(GAS_STIPEND_NO_GRIEF, to, amount, gas(), 0x00, gas(), 0x00)) {
                mstore(0x00, to) // Store the address in scratch space.
                mstore8(0x0b, 0x73) // Opcode `PUSH20`.
                mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`.
                if iszero(create(amount, 0x0b, 0x16)) {
                    returndatacopy(gas(), returndatasize(), shr(20, gas())) // For gas estimation.
                }
            }
        }
    }

    /// @dev Force sends all the ETH in the current contract to `to`, with `GAS_STIPEND_NO_GRIEF`.
    function forceSafeTransferAllETH(address to) internal {
        /// @solidity memory-safe-assembly
        assembly {
            if iszero(call(GAS_STIPEND_NO_GRIEF, to, selfbalance(), gas(), 0x00, gas(), 0x00)) {
                mstore(0x00, to) // Store the address in scratch space.
                mstore8(0x0b, 0x73) // Opcode `PUSH20`.
                mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`.
                if iszero(create(selfbalance(), 0x0b, 0x16)) {
                    returndatacopy(gas(), returndatasize(), shr(20, gas())) // For gas estimation.
                }
            }
        }
    }

    /// @dev Sends `amount` (in wei) ETH to `to`, with a `gasStipend`.
    function trySafeTransferETH(address to, uint256 amount, uint256 gasStipend)
        internal
        returns (bool success)
    {
        /// @solidity memory-safe-assembly
        assembly {
            success := call(gasStipend, to, amount, gas(), 0x00, gas(), 0x00)
        }
    }

    /// @dev Sends all the ETH in the current contract to `to`, with a `gasStipend`.
    function trySafeTransferAllETH(address to, uint256 gasStipend)
        internal
        returns (bool success)
    {
        /// @solidity memory-safe-assembly
        assembly {
            success := call(gasStipend, to, selfbalance(), gas(), 0x00, gas(), 0x00)
        }
    }

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

    /// @dev Sends `amount` of ERC20 `token` from `from` to `to`.
    /// Reverts upon failure.
    ///
    /// The `from` account must have at least `amount` approved for
    /// the current contract to manage.
    function safeTransferFrom(address token, address from, address to, uint256 amount) internal {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40) // Cache the free memory pointer.
            mstore(0x60, amount) // Store the `amount` argument.
            mstore(0x40, to) // Store the `to` argument.
            mstore(0x2c, shl(96, from)) // Store the `from` argument.
            mstore(0x0c, 0x23b872dd000000000000000000000000) // `transferFrom(address,address,uint256)`.
            // Perform the transfer, reverting upon failure.
            if iszero(
                and( // The arguments of `and` are evaluated from right to left.
                    or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.
                    call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20)
                )
            ) {
                mstore(0x00, 0x7939f424) // `TransferFromFailed()`.
                revert(0x1c, 0x04)
            }
            mstore(0x60, 0) // Restore the zero slot to zero.
            mstore(0x40, m) // Restore the free memory pointer.
        }
    }

    /// @dev Sends all of ERC20 `token` from `from` to `to`.
    /// Reverts upon failure.
    ///
    /// The `from` account must have their entire balance approved for
    /// the current contract to manage.
    function safeTransferAllFrom(address token, address from, address to)
        internal
        returns (uint256 amount)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40) // Cache the free memory pointer.
            mstore(0x40, to) // Store the `to` argument.
            mstore(0x2c, shl(96, from)) // Store the `from` argument.
            mstore(0x0c, 0x70a08231000000000000000000000000) // `balanceOf(address)`.
            // Read the balance, reverting upon failure.
            if iszero(
                and( // The arguments of `and` are evaluated from right to left.
                    gt(returndatasize(), 0x1f), // At least 32 bytes returned.
                    staticcall(gas(), token, 0x1c, 0x24, 0x60, 0x20)
                )
            ) {
                mstore(0x00, 0x7939f424) // `TransferFromFailed()`.
                revert(0x1c, 0x04)
            }
            mstore(0x00, 0x23b872dd) // `transferFrom(address,address,uint256)`.
            amount := mload(0x60) // The `amount` is already at 0x60. We'll need to return it.
            // Perform the transfer, reverting upon failure.
            if iszero(
                and( // The arguments of `and` are evaluated from right to left.
                    or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.
                    call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20)
                )
            ) {
                mstore(0x00, 0x7939f424) // `TransferFromFailed()`.
                revert(0x1c, 0x04)
            }
            mstore(0x60, 0) // Restore the zero slot to zero.
            mstore(0x40, m) // Restore the free memory pointer.
        }
    }

    /// @dev Sends `amount` of ERC20 `token` from the current contract to `to`.
    /// Reverts upon failure.
    function safeTransfer(address token, address to, uint256 amount) internal {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x14, to) // Store the `to` argument.
            mstore(0x34, amount) // Store the `amount` argument.
            mstore(0x00, 0xa9059cbb000000000000000000000000) // `transfer(address,uint256)`.
            // Perform the transfer, reverting upon failure.
            if iszero(
                and( // The arguments of `and` are evaluated from right to left.
                    or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.
                    call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)
                )
            ) {
                mstore(0x00, 0x90b8ec18) // `TransferFailed()`.
                revert(0x1c, 0x04)
            }
            mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten.
        }
    }

    /// @dev Sends all of ERC20 `token` from the current contract to `to`.
    /// Reverts upon failure.
    function safeTransferAll(address token, address to) internal returns (uint256 amount) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, 0x70a08231) // Store the function selector of `balanceOf(address)`.
            mstore(0x20, address()) // Store the address of the current contract.
            // Read the balance, reverting upon failure.
            if iszero(
                and( // The arguments of `and` are evaluated from right to left.
                    gt(returndatasize(), 0x1f), // At least 32 bytes returned.
                    staticcall(gas(), token, 0x1c, 0x24, 0x34, 0x20)
                )
            ) {
                mstore(0x00, 0x90b8ec18) // `TransferFailed()`.
                revert(0x1c, 0x04)
            }
            mstore(0x14, to) // Store the `to` argument.
            amount := mload(0x34) // The `amount` is already at 0x34. We'll need to return it.
            mstore(0x00, 0xa9059cbb000000000000000000000000) // `transfer(address,uint256)`.
            // Perform the transfer, reverting upon failure.
            if iszero(
                and( // The arguments of `and` are evaluated from right to left.
                    or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.
                    call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)
                )
            ) {
                mstore(0x00, 0x90b8ec18) // `TransferFailed()`.
                revert(0x1c, 0x04)
            }
            mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten.
        }
    }

    /// @dev Sets `amount` of ERC20 `token` for `to` to manage on behalf of the current contract.
    /// Reverts upon failure.
    function safeApprove(address token, address to, uint256 amount) internal {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x14, to) // Store the `to` argument.
            mstore(0x34, amount) // Store the `amount` argument.
            mstore(0x00, 0x095ea7b3000000000000000000000000) // `approve(address,uint256)`.
            // Perform the approval, reverting upon failure.
            if iszero(
                and( // The arguments of `and` are evaluated from right to left.
                    or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.
                    call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)
                )
            ) {
                mstore(0x00, 0x3e3f8f73) // `ApproveFailed()`.
                revert(0x1c, 0x04)
            }
            mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten.
        }
    }

    /// @dev Sets `amount` of ERC20 `token` for `to` to manage on behalf of the current contract.
    /// If the initial attempt to approve fails, attempts to reset the approved amount to zero,
    /// then retries the approval again (some tokens, e.g. USDT, requires this).
    /// Reverts upon failure.
    function safeApproveWithRetry(address token, address to, uint256 amount) internal {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x14, to) // Store the `to` argument.
            mstore(0x34, amount) // Store the `amount` argument.
            mstore(0x00, 0x095ea7b3000000000000000000000000) // `approve(address,uint256)`.
            // Perform the approval, retrying upon failure.
            if iszero(
                and( // The arguments of `and` are evaluated from right to left.
                    or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.
                    call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)
                )
            ) {
                mstore(0x34, 0) // Store 0 for the `amount`.
                mstore(0x00, 0x095ea7b3000000000000000000000000) // `approve(address,uint256)`.
                pop(call(gas(), token, 0, 0x10, 0x44, 0x00, 0x00)) // Reset the approval.
                mstore(0x34, amount) // Store back the original `amount`.
                // Retry the approval, reverting upon failure.
                if iszero(
                    and(
                        or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.
                        call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)
                    )
                ) {
                    mstore(0x00, 0x3e3f8f73) // `ApproveFailed()`.
                    revert(0x1c, 0x04)
                }
            }
            mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten.
        }
    }

    /// @dev Returns the amount of ERC20 `token` owned by `account`.
    /// Returns zero if the `token` does not exist.
    function balanceOf(address token, address account) internal view returns (uint256 amount) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x14, account) // Store the `account` argument.
            mstore(0x00, 0x70a08231000000000000000000000000) // `balanceOf(address)`.
            amount :=
                mul(
                    mload(0x20),
                    and( // The arguments of `and` are evaluated from right to left.
                        gt(returndatasize(), 0x1f), // At least 32 bytes returned.
                        staticcall(gas(), token, 0x10, 0x24, 0x20, 0x20)
                    )
                )
        }
    }
}

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

/// @notice Signature verification helper that supports both ECDSA signatures from EOAs
/// and ERC1271 signatures from smart contract wallets like Argent and Gnosis safe.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/SignatureCheckerLib.sol)
/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/SignatureChecker.sol)
///
/// @dev Note:
/// - The signature checking functions use the ecrecover precompile (0x1).
/// - The `bytes memory signature` variants use the identity precompile (0x4)
///   to copy memory internally.
/// - Unlike ECDSA signatures, contract signatures are revocable.
///
/// WARNING! Do NOT use signatures as unique identifiers.
/// Please use EIP712 with a nonce included in the digest to prevent replay attacks.
/// This implementation does NOT check if a signature is non-malleable.
library SignatureCheckerLib {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*               SIGNATURE CHECKING OPERATIONS                */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns whether `signature` is valid for `signer` and `hash`.
    /// If `signer` is a smart contract, the signature is validated with ERC1271.
    /// Otherwise, the signature is validated with `ECDSA.recover`.
    function isValidSignatureNow(address signer, bytes32 hash, bytes memory signature)
        internal
        view
        returns (bool isValid)
    {
        /// @solidity memory-safe-assembly
        assembly {
            // Clean the upper 96 bits of `signer` in case they are dirty.
            for { signer := shr(96, shl(96, signer)) } signer {} {
                let m := mload(0x40)
                if eq(mload(signature), 65) {
                    mstore(0x00, hash)
                    mstore(0x20, byte(0, mload(add(signature, 0x60)))) // `v`.
                    mstore(0x40, mload(add(signature, 0x20))) // `r`.
                    mstore(0x60, mload(add(signature, 0x40))) // `s`.
                    let t :=
                        staticcall(
                            gas(), // Amount of gas left for the transaction.
                            1, // Address of `ecrecover`.
                            0x00, // Start of input.
                            0x80, // Size of input.
                            0x01, // Start of output.
                            0x20 // Size of output.
                        )
                    // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
                    if iszero(or(iszero(returndatasize()), xor(signer, mload(t)))) {
                        isValid := 1
                        mstore(0x60, 0) // Restore the zero slot.
                        mstore(0x40, m) // Restore the free memory pointer.
                        break
                    }
                }
                mstore(0x60, 0) // Restore the zero slot.
                mstore(0x40, m) // Restore the free memory pointer.

                let f := shl(224, 0x1626ba7e)
                mstore(m, f) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`.
                mstore(add(m, 0x04), hash)
                let d := add(m, 0x24)
                mstore(d, 0x40) // The offset of the `signature` in the calldata.
                // Copy the `signature` over.
                let n := add(0x20, mload(signature))
                pop(staticcall(gas(), 4, signature, n, add(m, 0x44), n))
                // forgefmt: disable-next-item
                isValid := and(
                    // Whether the returndata is the magic value `0x1626ba7e` (left-aligned).
                    eq(mload(d), f),
                    // Whether the staticcall does not revert.
                    // This must be placed at the end of the `and` clause,
                    // as the arguments are evaluated from right to left.
                    staticcall(
                        gas(), // Remaining gas.
                        signer, // The `signer` address.
                        m, // Offset of calldata in memory.
                        add(returndatasize(), 0x44), // Length of calldata in memory.
                        d, // Offset of returndata.
                        0x20 // Length of returndata to write.
                    )
                )
                break
            }
        }
    }

    /// @dev Returns whether `signature` is valid for `signer` and `hash`.
    /// If `signer` is a smart contract, the signature is validated with ERC1271.
    /// Otherwise, the signature is validated with `ECDSA.recover`.
    function isValidSignatureNowCalldata(address signer, bytes32 hash, bytes calldata signature)
        internal
        view
        returns (bool isValid)
    {
        /// @solidity memory-safe-assembly
        assembly {
            // Clean the upper 96 bits of `signer` in case they are dirty.
            for { signer := shr(96, shl(96, signer)) } signer {} {
                let m := mload(0x40)
                if eq(signature.length, 65) {
                    mstore(0x00, hash)
                    mstore(0x20, byte(0, calldataload(add(signature.offset, 0x40)))) // `v`.
                    calldatacopy(0x40, signature.offset, 0x40) // `r`, `s`.
                    let t :=
                        staticcall(
                            gas(), // Amount of gas left for the transaction.
                            1, // Address of `ecrecover`.
                            0x00, // Start of input.
                            0x80, // Size of input.
                            0x01, // Start of output.
                            0x20 // Size of output.
                        )
                    // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
                    if iszero(or(iszero(returndatasize()), xor(signer, mload(t)))) {
                        isValid := 1
                        mstore(0x60, 0) // Restore the zero slot.
                        mstore(0x40, m) // Restore the free memory pointer.
                        break
                    }
                }
                mstore(0x60, 0) // Restore the zero slot.
                mstore(0x40, m) // Restore the free memory pointer.

                let f := shl(224, 0x1626ba7e)
                mstore(m, f) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`.
                mstore(add(m, 0x04), hash)
                let d := add(m, 0x24)
                mstore(d, 0x40) // The offset of the `signature` in the calldata.
                mstore(add(m, 0x44), signature.length)
                // Copy the `signature` over.
                calldatacopy(add(m, 0x64), signature.offset, signature.length)
                // forgefmt: disable-next-item
                isValid := and(
                    // Whether the returndata is the magic value `0x1626ba7e` (left-aligned).
                    eq(mload(d), f),
                    // Whether the staticcall does not revert.
                    // This must be placed at the end of the `and` clause,
                    // as the arguments are evaluated from right to left.
                    staticcall(
                        gas(), // Remaining gas.
                        signer, // The `signer` address.
                        m, // Offset of calldata in memory.
                        add(signature.length, 0x64), // Length of calldata in memory.
                        d, // Offset of returndata.
                        0x20 // Length of returndata to write.
                    )
                )
                break
            }
        }
    }

    /// @dev Returns whether the signature (`r`, `vs`) is valid for `signer` and `hash`.
    /// If `signer` is a smart contract, the signature is validated with ERC1271.
    /// Otherwise, the signature is validated with `ECDSA.recover`.
    function isValidSignatureNow(address signer, bytes32 hash, bytes32 r, bytes32 vs)
        internal
        view
        returns (bool isValid)
    {
        /// @solidity memory-safe-assembly
        assembly {
            // Clean the upper 96 bits of `signer` in case they are dirty.
            for { signer := shr(96, shl(96, signer)) } signer {} {
                let m := mload(0x40)
                mstore(0x00, hash)
                mstore(0x20, add(shr(255, vs), 27)) // `v`.
                mstore(0x40, r) // `r`.
                mstore(0x60, shr(1, shl(1, vs))) // `s`.
                let t :=
                    staticcall(
                        gas(), // Amount of gas left for the transaction.
                        1, // Address of `ecrecover`.
                        0x00, // Start of input.
                        0x80, // Size of input.
                        0x01, // Start of output.
                        0x20 // Size of output.
                    )
                // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
                if iszero(or(iszero(returndatasize()), xor(signer, mload(t)))) {
                    isValid := 1
                    mstore(0x60, 0) // Restore the zero slot.
                    mstore(0x40, m) // Restore the free memory pointer.
                    break
                }

                let f := shl(224, 0x1626ba7e)
                mstore(m, f) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`.
                mstore(add(m, 0x04), hash)
                let d := add(m, 0x24)
                mstore(d, 0x40) // The offset of the `signature` in the calldata.
                mstore(add(m, 0x44), 65) // Length of the signature.
                mstore(add(m, 0x64), r) // `r`.
                mstore(add(m, 0x84), mload(0x60)) // `s`.
                mstore8(add(m, 0xa4), mload(0x20)) // `v`.
                // forgefmt: disable-next-item
                isValid := and(
                    // Whether the returndata is the magic value `0x1626ba7e` (left-aligned).
                    eq(mload(d), f),
                    // Whether the staticcall does not revert.
                    // This must be placed at the end of the `and` clause,
                    // as the arguments are evaluated from right to left.
                    staticcall(
                        gas(), // Remaining gas.
                        signer, // The `signer` address.
                        m, // Offset of calldata in memory.
                        0xa5, // Length of calldata in memory.
                        d, // Offset of returndata.
                        0x20 // Length of returndata to write.
                    )
                )
                mstore(0x60, 0) // Restore the zero slot.
                mstore(0x40, m) // Restore the free memory pointer.
                break
            }
        }
    }

    /// @dev Returns whether the signature (`v`, `r`, `s`) is valid for `signer` and `hash`.
    /// If `signer` is a smart contract, the signature is validated with ERC1271.
    /// Otherwise, the signature is validated with `ECDSA.recover`.
    function isValidSignatureNow(address signer, bytes32 hash, uint8 v, bytes32 r, bytes32 s)
        internal
        view
        returns (bool isValid)
    {
        /// @solidity memory-safe-assembly
        assembly {
            // Clean the upper 96 bits of `signer` in case they are dirty.
            for { signer := shr(96, shl(96, signer)) } signer {} {
                let m := mload(0x40)
                mstore(0x00, hash)
                mstore(0x20, and(v, 0xff)) // `v`.
                mstore(0x40, r) // `r`.
                mstore(0x60, s) // `s`.
                let t :=
                    staticcall(
                        gas(), // Amount of gas left for the transaction.
                        1, // Address of `ecrecover`.
                        0x00, // Start of input.
                        0x80, // Size of input.
                        0x01, // Start of output.
                        0x20 // Size of output.
                    )
                // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
                if iszero(or(iszero(returndatasize()), xor(signer, mload(t)))) {
                    isValid := 1
                    mstore(0x60, 0) // Restore the zero slot.
                    mstore(0x40, m) // Restore the free memory pointer.
                    break
                }

                let f := shl(224, 0x1626ba7e)
                mstore(m, f) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`.
                mstore(add(m, 0x04), hash)
                let d := add(m, 0x24)
                mstore(d, 0x40) // The offset of the `signature` in the calldata.
                mstore(add(m, 0x44), 65) // Length of the signature.
                mstore(add(m, 0x64), r) // `r`.
                mstore(add(m, 0x84), s) // `s`.
                mstore8(add(m, 0xa4), v) // `v`.
                // forgefmt: disable-next-item
                isValid := and(
                    // Whether the returndata is the magic value `0x1626ba7e` (left-aligned).
                    eq(mload(d), f),
                    // Whether the staticcall does not revert.
                    // This must be placed at the end of the `and` clause,
                    // as the arguments are evaluated from right to left.
                    staticcall(
                        gas(), // Remaining gas.
                        signer, // The `signer` address.
                        m, // Offset of calldata in memory.
                        0xa5, // Length of calldata in memory.
                        d, // Offset of returndata.
                        0x20 // Length of returndata to write.
                    )
                )
                mstore(0x60, 0) // Restore the zero slot.
                mstore(0x40, m) // Restore the free memory pointer.
                break
            }
        }
    }

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

    /// @dev Returns whether `signature` is valid for `hash`
    /// for an ERC1271 `signer` contract.
    function isValidERC1271SignatureNow(address signer, bytes32 hash, bytes memory signature)
        internal
        view
        returns (bool isValid)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            let f := shl(224, 0x1626ba7e)
            mstore(m, f) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`.
            mstore(add(m, 0x04), hash)
            let d := add(m, 0x24)
            mstore(d, 0x40) // The offset of the `signature` in the calldata.
            // Copy the `signature` over.
            let n := add(0x20, mload(signature))
            pop(staticcall(gas(), 4, signature, n, add(m, 0x44), n))
            // forgefmt: disable-next-item
            isValid := and(
                // Whether the returndata is the magic value `0x1626ba7e` (left-aligned).
                eq(mload(d), f),
                // Whether the staticcall does not revert.
                // This must be placed at the end of the `and` clause,
                // as the arguments are evaluated from right to left.
                staticcall(
                    gas(), // Remaining gas.
                    signer, // The `signer` address.
                    m, // Offset of calldata in memory.
                    add(returndatasize(), 0x44), // Length of calldata in memory.
                    d, // Offset of returndata.
                    0x20 // Length of returndata to write.
                )
            )
        }
    }

    /// @dev Returns whether `signature` is valid for `hash`
    /// for an ERC1271 `signer` contract.
    function isValidERC1271SignatureNowCalldata(
        address signer,
        bytes32 hash,
        bytes calldata signature
    ) internal view returns (bool isValid) {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            let f := shl(224, 0x1626ba7e)
            mstore(m, f) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`.
            mstore(add(m, 0x04), hash)
            let d := add(m, 0x24)
            mstore(d, 0x40) // The offset of the `signature` in the calldata.
            mstore(add(m, 0x44), signature.length)
            // Copy the `signature` over.
            calldatacopy(add(m, 0x64), signature.offset, signature.length)
            // forgefmt: disable-next-item
            isValid := and(
                // Whether the returndata is the magic value `0x1626ba7e` (left-aligned).
                eq(mload(d), f),
                // Whether the staticcall does not revert.
                // This must be placed at the end of the `and` clause,
                // as the arguments are evaluated from right to left.
                staticcall(
                    gas(), // Remaining gas.
                    signer, // The `signer` address.
                    m, // Offset of calldata in memory.
                    add(signature.length, 0x64), // Length of calldata in memory.
                    d, // Offset of returndata.
                    0x20 // Length of returndata to write.
                )
            )
        }
    }

    /// @dev Returns whether the signature (`r`, `vs`) is valid for `hash`
    /// for an ERC1271 `signer` contract.
    function isValidERC1271SignatureNow(address signer, bytes32 hash, bytes32 r, bytes32 vs)
        internal
        view
        returns (bool isValid)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            let f := shl(224, 0x1626ba7e)
            mstore(m, f) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`.
            mstore(add(m, 0x04), hash)
            let d := add(m, 0x24)
            mstore(d, 0x40) // The offset of the `signature` in the calldata.
            mstore(add(m, 0x44), 65) // Length of the signature.
            mstore(add(m, 0x64), r) // `r`.
            mstore(add(m, 0x84), shr(1, shl(1, vs))) // `s`.
            mstore8(add(m, 0xa4), add(shr(255, vs), 27)) // `v`.
            // forgefmt: disable-next-item
            isValid := and(
                // Whether the returndata is the magic value `0x1626ba7e` (left-aligned).
                eq(mload(d), f),
                // Whether the staticcall does not revert.
                // This must be placed at the end of the `and` clause,
                // as the arguments are evaluated from right to left.
                staticcall(
                    gas(), // Remaining gas.
                    signer, // The `signer` address.
                    m, // Offset of calldata in memory.
                    0xa5, // Length of calldata in memory.
                    d, // Offset of returndata.
                    0x20 // Length of returndata to write.
                )
            )
        }
    }

    /// @dev Returns whether the signature (`v`, `r`, `s`) is valid for `hash`
    /// for an ERC1271 `signer` contract.
    function isValidERC1271SignatureNow(address signer, bytes32 hash, uint8 v, bytes32 r, bytes32 s)
        internal
        view
        returns (bool isValid)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            let f := shl(224, 0x1626ba7e)
            mstore(m, f) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`.
            mstore(add(m, 0x04), hash)
            let d := add(m, 0x24)
            mstore(d, 0x40) // The offset of the `signature` in the calldata.
            mstore(add(m, 0x44), 65) // Length of the signature.
            mstore(add(m, 0x64), r) // `r`.
            mstore(add(m, 0x84), s) // `s`.
            mstore8(add(m, 0xa4), v) // `v`.
            // forgefmt: disable-next-item
            isValid := and(
                // Whether the returndata is the magic value `0x1626ba7e` (left-aligned).
                eq(mload(d), f),
                // Whether the staticcall does not revert.
                // This must be placed at the end of the `and` clause,
                // as the arguments are evaluated from right to left.
                staticcall(
                    gas(), // Remaining gas.
                    signer, // The `signer` address.
                    m, // Offset of calldata in memory.
                    0xa5, // Length of calldata in memory.
                    d, // Offset of returndata.
                    0x20 // Length of returndata to write.
                )
            )
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                   EMPTY CALLDATA HELPERS                   */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns an empty calldata bytes.
    function emptySignature() internal pure returns (bytes calldata signature) {
        /// @solidity memory-safe-assembly
        assembly {
            signature.length := 0
        }
    }
}

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

/// @notice Library for bit twiddling and boolean operations.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/LibBit.sol)
/// @author Inspired by (https://graphics.stanford.edu/~seander/bithacks.html)
library LibBit {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                  BIT TWIDDLING OPERATIONS                  */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Find last set.
    /// Returns the index of the most significant bit of `x`,
    /// counting from the least significant bit position.
    /// If `x` is zero, returns 256.
    function fls(uint256 x) internal pure returns (uint256 r) {
        /// @solidity memory-safe-assembly
        assembly {
            r := or(shl(8, iszero(x)), shl(7, lt(0xffffffffffffffffffffffffffffffff, x)))
            r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, x))))
            r := or(r, shl(5, lt(0xffffffff, shr(r, x))))
            r := or(r, shl(4, lt(0xffff, shr(r, x))))
            r := or(r, shl(3, lt(0xff, shr(r, x))))
            r := or(r, shl(2, lt(0xf, shr(r, x))))
            r := or(r, byte(shr(r, x), hex"00000101020202020303030303030303"))
        }
    }

    /// @dev Count leading zeros.
    /// Returns the number of zeros preceding the most significant one bit.
    /// If `x` is zero, returns 256.
    function clz(uint256 x) internal pure returns (uint256 r) {
        /// @solidity memory-safe-assembly
        assembly {
            r := shl(7, lt(0xffffffffffffffffffffffffffffffff, x))
            r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, x))))
            r := or(r, shl(5, lt(0xffffffff, shr(r, x))))
            r := or(r, shl(4, lt(0xffff, shr(r, x))))
            r := or(r, shl(3, lt(0xff, shr(r, x))))
            r := or(r, shl(2, lt(0xf, shr(r, x))))
            // forgefmt: disable-next-item
            r := add(iszero(x), xor(255,
                or(r, byte(shr(r, x), hex"00000101020202020303030303030303"))))
        }
    }

    /// @dev Find first set.
    /// Returns the index of the least significant bit of `x`,
    /// counting from the least significant bit position.
    /// If `x` is zero, returns 256.
    /// Equivalent to `ctz` (count trailing zeros), which gives
    /// the number of zeros following the least significant one bit.
    function ffs(uint256 x) internal pure returns (uint256 r) {
        /// @solidity memory-safe-assembly
        assembly {
            // Isolate the least significant bit.
            let b := and(x, add(not(x), 1))

            r := or(shl(8, iszero(x)), shl(7, lt(0xffffffffffffffffffffffffffffffff, b)))
            r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, b))))
            r := or(r, shl(5, lt(0xffffffff, shr(r, b))))

            // For the remaining 32 bits, use a De Bruijn lookup.
            // forgefmt: disable-next-item
            r := or(r, byte(and(div(0xd76453e0, shr(r, b)), 0x1f),
                0x001f0d1e100c1d070f090b19131c1706010e11080a1a141802121b1503160405))
        }
    }

    /// @dev Returns the number of set bits in `x`.
    function popCount(uint256 x) internal pure returns (uint256 c) {
        /// @solidity memory-safe-assembly
        assembly {
            let max := not(0)
            let isMax := eq(x, max)
            x := sub(x, and(shr(1, x), div(max, 3)))
            x := add(and(x, div(max, 5)), and(shr(2, x), div(max, 5)))
            x := and(add(x, shr(4, x)), div(max, 17))
            c := or(shl(8, isMax), shr(248, mul(x, div(max, 255))))
        }
    }

    /// @dev Returns whether `x` is a power of 2.
    function isPo2(uint256 x) internal pure returns (bool result) {
        /// @solidity memory-safe-assembly
        assembly {
            // Equivalent to `x && !(x & (x - 1))`.
            result := iszero(add(and(x, sub(x, 1)), iszero(x)))
        }
    }

    /// @dev Returns `x` reversed at the bit level.
    function reverseBits(uint256 x) internal pure returns (uint256 r) {
        /// @solidity memory-safe-assembly
        assembly {
            // Computing masks on-the-fly reduces bytecode size by about 500 bytes.
            let m := not(0)
            r := x
            for { let s := 128 } 1 {} {
                m := xor(m, shl(s, m))
                r := or(and(shr(s, r), m), and(shl(s, r), not(m)))
                s := shr(1, s)
                if iszero(s) { break }
            }
        }
    }

    /// @dev Returns `x` reversed at the byte level.
    function reverseBytes(uint256 x) internal pure returns (uint256 r) {
        /// @solidity memory-safe-assembly
        assembly {
            // Computing masks on-the-fly reduces bytecode size by about 200 bytes.
            let m := not(0)
            r := x
            for { let s := 128 } 1 {} {
                m := xor(m, shl(s, m))
                r := or(and(shr(s, r), m), and(shl(s, r), not(m)))
                s := shr(1, s)
                if eq(s, 4) { break }
            }
        }
    }

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

    // A Solidity bool on the stack or memory is represented as a 256-bit word.
    // Non-zero values are true, zero is false.
    // A clean bool is either 0 (false) or 1 (true) under the hood.
    // Usually, if not always, the bool result of a regular Solidity expression,
    // or the argument of a public/external function will be a clean bool.
    // You can usually use the raw variants for more performance.
    // If uncertain, test (best with exact compiler settings).
    // Or use the non-raw variants (compiler can sometimes optimize out the double `iszero`s).

    /// @dev Returns `x & y`. Inputs must be clean.
    function rawAnd(bool x, bool y) internal pure returns (bool z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := and(x, y)
        }
    }

    /// @dev Returns `x & y`.
    function and(bool x, bool y) internal pure returns (bool z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := and(iszero(iszero(x)), iszero(iszero(y)))
        }
    }

    /// @dev Returns `x | y`. Inputs must be clean.
    function rawOr(bool x, bool y) internal pure returns (bool z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := or(x, y)
        }
    }

    /// @dev Returns `x | y`.
    function or(bool x, bool y) internal pure returns (bool z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := or(iszero(iszero(x)), iszero(iszero(y)))
        }
    }

    /// @dev Returns 1 if `b` is true, else 0. Input must be clean.
    function rawToUint(bool b) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := b
        }
    }

    /// @dev Returns 1 if `b` is true, else 0.
    function toUint(bool b) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := iszero(iszero(b))
        }
    }
}

Settings
{
  "remappings": [
    "openzeppelin/=lib/openzeppelin-contracts/contracts/",
    "openzeppelin-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/",
    "chiru-labs/ERC721A-Upgradeable/=lib/ERC721A-Upgradeable/contracts/",
    "solady/=lib/solady/src/",
    "closedsea/=lib/closedsea/src/",
    "preapprove/=lib/preapprove/src/",
    "multicaller/=lib/multicaller/src/",
    "@core/=contracts/core/",
    "@modules/=contracts/modules/",
    "forge-std/=lib/forge-std/src/",
    "ERC721A-Upgradeable/=lib/ERC721A-Upgradeable/contracts/",
    "ds-test/=lib/solady/lib/ds-test/src/",
    "erc4626-tests/=lib/closedsea/lib/openzeppelin-contracts/lib/erc4626-tests/",
    "erc721a-upgradeable/=lib/multicaller/lib/erc721a-upgradeable/contracts/",
    "erc721a/=lib/multicaller/lib/erc721a/contracts/",
    "murky/=lib/murky/src/",
    "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/",
    "openzeppelin-contracts/=lib/openzeppelin-contracts/",
    "operator-filter-registry/=lib/closedsea/lib/operator-filter-registry/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "ipfs",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "abi"
      ]
    }
  },
  "evmVersion": "paris",
  "libraries": {}
}

Contract Security Audit

Contract ABI

API
[{"inputs":[],"name":"ArrayLengthsMismatch","type":"error"},{"inputs":[],"name":"ImplementationAddressCantBeZero","type":"error"},{"inputs":[],"name":"InvalidSignature","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"},{"indexed":true,"internalType":"address","name":"edition","type":"address"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"bytes","name":"initData","type":"bytes"},{"indexed":false,"internalType":"address[]","name":"contracts","type":"address[]"},{"indexed":false,"internalType":"bytes[]","name":"data","type":"bytes[]"},{"indexed":false,"internalType":"bytes[]","name":"results","type":"bytes[]"}],"name":"Created","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"signer","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"nonces","type":"uint256[]"}],"name":"NoncesInvalidated","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"DOMAIN_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SOUND_CREATION_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"implementation","type":"address"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"bytes","name":"initData","type":"bytes"},{"internalType":"address[]","name":"contracts","type":"address[]"},{"internalType":"bytes[]","name":"data","type":"bytes[]"},{"internalType":"uint256","name":"nonce","type":"uint256"}],"internalType":"struct ISoundCreatorV2.SoundCreation","name":"c","type":"tuple"}],"name":"computeDigest","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"implementation","type":"address"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"bytes","name":"initData","type":"bytes"},{"internalType":"address[]","name":"contracts","type":"address[]"},{"internalType":"bytes[]","name":"data","type":"bytes[]"},{"internalType":"uint256","name":"nonce","type":"uint256"}],"internalType":"struct ISoundCreatorV2.SoundCreation","name":"c","type":"tuple"}],"name":"create","outputs":[{"internalType":"address","name":"edition","type":"address"},{"internalType":"bytes[]","name":"results","type":"bytes[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"implementation","type":"address"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"bytes","name":"initData","type":"bytes"},{"internalType":"address[]","name":"contracts","type":"address[]"},{"internalType":"bytes[]","name":"data","type":"bytes[]"},{"internalType":"uint256","name":"nonce","type":"uint256"}],"internalType":"struct ISoundCreatorV2.SoundCreation","name":"creation","type":"tuple"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"createWithSignature","outputs":[{"internalType":"address","name":"soundEdition","type":"address"},{"internalType":"bytes[]","name":"results","type":"bytes[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"implementation","type":"address"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"bytes","name":"initData","type":"bytes"},{"internalType":"address[]","name":"contracts","type":"address[]"},{"internalType":"bytes[]","name":"data","type":"bytes[]"},{"internalType":"uint256","name":"nonce","type":"uint256"}],"internalType":"struct ISoundCreatorV2.SoundCreation","name":"c","type":"tuple"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"address","name":"minter","type":"address"},{"internalType":"bytes","name":"mintData","type":"bytes"},{"internalType":"address","name":"refundTo","type":"address"}],"name":"createWithSignatureAndMint","outputs":[{"internalType":"address","name":"edition","type":"address"},{"internalType":"bytes[]","name":"results","type":"bytes[]"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"domainSeparator","outputs":[{"internalType":"bytes32","name":"separator","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"eip712Domain","outputs":[{"internalType":"bytes1","name":"fields","type":"bytes1"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"version","type":"string"},{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"address","name":"verifyingContract","type":"address"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"uint256[]","name":"extensions","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"nonces","type":"uint256[]"}],"name":"invalidateNonces","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"implementation","type":"address"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"bytes","name":"initData","type":"bytes"},{"internalType":"address[]","name":"contracts","type":"address[]"},{"internalType":"bytes[]","name":"data","type":"bytes[]"},{"internalType":"uint256","name":"nonce","type":"uint256"}],"internalType":"struct ISoundCreatorV2.SoundCreation","name":"c","type":"tuple"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"isValidSignature","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"minter","type":"address"},{"internalType":"bytes","name":"mintData","type":"bytes"},{"internalType":"address","name":"refundTo","type":"address"}],"name":"mint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"name_","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"signer","type":"address"},{"internalType":"uint256[]","name":"nonces","type":"uint256[]"}],"name":"noncesInvalidated","outputs":[{"internalType":"bool[]","name":"result","type":"bool[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"implementation","type":"address"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"bytes32","name":"salt","type":"bytes32"}],"name":"soundEditionAddress","outputs":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"bool","name":"exists","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"version_","type":"string"}],"stateMutability":"pure","type":"function"},{"stateMutability":"payable","type":"receive"}]

61012060405234801561001157600080fd5b50306080524660a05260608061005e604080518082018252600c81526b29b7bab73221b932b0ba37b960a11b602080830191909152825180840190935260018352601960f91b9083015291565b815160209283012081519183019190912060c082905260e0819052604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f8152938401929092529082015246606082015230608082015260a09020610100525050600160005560805160a05160c05160e05161010051611a3661011160003960008181610f420152610fa1015260006111a901526000611183015260006111e5015260006112080152611a366000f3fe6080604052600436106100ec5760003560e01c806354fd4d501161008a578063b9a257b211610059578063b9a257b2146102c1578063d38dfaf5146102e1578063e361d18f14610311578063f698da2514610331576100fb565b806354fd4d50146102115780637cf5b76314610226578063807c93101461025a57806384b0196e14610299576100fb565b806317447cf1116100c657806317447cf11461016f57806320606b701461019c5780632eb48a80146101de57806340a5468f146101fe576100fb565b806306fdde031461010357806308d1207f1461012e5780630ffc20c91461014f576100fb565b366100fb576100f9610346565b005b6100f9610346565b34801561010f57600080fd5b506101186103de565b6040516101259190611273565b60405180910390f35b61014161013c3660046112fc565b6103ee565b60405161012592919061140c565b34801561015b57600080fd5b5061014161016a366004611430565b610462565b34801561017b57600080fd5b5061018f61018a3660046114dc565b610490565b6040516101259190611521565b3480156101a857600080fd5b506101d07f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81565b604051908152602001610125565b3480156101ea57600080fd5b506100f96101f9366004611567565b610555565b6100f961020c3660046115a8565b6105ff565b34801561021d57600080fd5b50610118610623565b34801561023257600080fd5b506101d07f02851fd84c0125420e90b7716c63914a48e2932366cce89b4a7a0bcdf538d75981565b34801561026657600080fd5b5061027a61027536600461160c565b610633565b604080516001600160a01b039093168352901515602083015201610125565b3480156102a557600080fd5b506102ae6106c3565b6040516101259796959493929190611683565b3480156102cd57600080fd5b506101416102dc3660046116f3565b6106ea565b3480156102ed57600080fd5b506103016102fc366004611430565b61075a565b6040519015158152602001610125565b34801561031d57600080fd5b506101d061032c3660046116f3565b6107e3565b34801561033d57600080fd5b506101d06109e7565b3661034f573636f35b6000805b8036821061036157506103bd565b600180830192600319810190351860001a90816103ad57600019855260028301933560021984011860001a607f80821161039c578282013888395b169490940190930192506103539050565b8185538085019450505050610353565b50600080826000305af490503d6000803e806103d8573d6000fd5b503d6000f35b60606103e86109f6565b50919050565b600060606103fa610a34565b600061042661040c60208c018c611727565b61041c60408d0160208e01611727565b8c60400135610633565b9150508061043f576104398a8a8a610a92565b90935091505b61044b87878787610bc8565b506104566001600055565b97509795505050505050565b6000606061046e610a34565b610479858585610a92565b90925090506104886001600055565b935093915050565b6060816001600160401b038111156104aa576104aa611742565b6040519080825280602002602001820160405280156104d3578160200160208202803683370190505b506001600160a01b03851660009081526001602052604081209192505b80841461054c5761052285858381811061050c5761050c611758565b9050602002013583610c2990919063ffffffff16565b83828151811061053457610534611758565b911515602092830291909101909101526001016104f0565b50509392505050565b600061055f610c4b565b6001600160a01b03811660009081526001602052604081209192505b8084146105b5576105ad85858381811061059757610597611758565b9050602002013583610c8390919063ffffffff16565b60010161057b565b50816001600160a01b03167fc45e3a0dd412bcad8d62398d74d66b1c8449f38beb10da275e4da0c6d3a811a485856040516105f192919061176e565b60405180910390a250505050565b610607610a34565b61061384848484610bc8565b61061d6001600055565b50505050565b606061062d6109f6565b92915050565b602082905246600c5260008181526040812081906106ac90869030604051733d602d80600a3d3981f3363d3d373d3d3d363d7360601b8152606093841b60148201526f5af43d82803e903d91602b57fd5bf3ff60801b6028820152921b6038830152604c8201526037808220606c830152605591012090565b956001600160a01b0387163b151595509350505050565b600f60f81b60608060008080836106d86109f6565b97989097965046955030945091925090565b600060606106f6610a34565b6106fe610c4b565b6001600160a01b03166107176040850160208601611727565b6001600160a01b03161461073d576040516282b42960e81b815260040160405180910390fd5b61074683610cac565b90925090506107556001600055565b915091565b600061077f61076f6040860160208701611727565b610778866107e3565b8585610e95565b80156107db57506107d960c0850135600160006107a26040890160208a01611727565b6001600160a01b0316815260208082019290925260409081016000908120600885901c825290925290205460ff9091161c60011690565b155b949350505050565b60008036816107f560a08601866117a7565b9092509050806000816001600160401b0381111561081557610815611742565b60405190808252806020026020018201604052801561083e578160200160208202803683370190505b50905060005b8281146108aa5784848281811061085d5761085d611758565b905060200281019061086f91906117f0565b60405161087d929190611836565b604051809103902082828151811061089757610897611758565b6020908102919091010152600101610844565b50806040516020016108bc9190611846565b604051602081830303815290604052805190602001209450505050506109e07f02851fd84c0125420e90b7716c63914a48e2932366cce89b4a7a0bcdf538d75984600001602081019061090f9190611727565b61091f6040870160208801611727565b604087013561093160608901896117f0565b60405161093f929190611836565b60405190819003902061095560808a018a6117a7565b60405160200161096692919061187c565b60408051601f198184030181528282528051602091820120908301979097526001600160a01b0395861690820152939092166060840152608083015260a082015260c08082019290925260e08101849052908501356101008201526101200160405160208183030381529060405280519060200120610f3e565b9392505050565b60006109f1610f9f565b905090565b604080518082018252600c81526b29b7bab73221b932b0ba37b960a11b602080830191909152825180840190935260018352601960f91b9083015291565b600260005403610a8b5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064015b60405180910390fd5b6002600055565b60006060610aa185858561075a565b610abe57604051638baa579f60e01b815260040160405180910390fd5b610ac785610cac565b9092509050610b2660c086013560016000610ae860408a0160208b01611727565b6001600160a01b0316815260208082019290925260409081016000908120600885901c825290925290208054600160ff9093169290921b9091179055565b604080516001808252818301909252600091602080830190803683370190505090508560c0013581600081518110610b6057610b60611758565b602002602001018181525050856020016020810190610b7f9190611727565b6001600160a01b03167fc45e3a0dd412bcad8d62398d74d66b1c8449f38beb10da275e4da0c6d3a811a482604051610bb791906118bc565b60405180910390a250935093915050565b6001600160a01b0384161561061d5760405182848237600080848334895af1610bf5573d6000803e3d6000fd5b506001600160a01b0381161561061d57471561061d576000196001600160a01b03821601610c205750335b61061d81610fd8565b600881901c6000908152602092909252604090912054600160ff9092161c1690565b6000336000526e2fd5aeb385d324b580fca7c83823a0803303610c7b5760206000806000845afa610c7b57600080fd5b505060005190565b600881901c600090815260209290925260409091208054600160ff9093169290921b9091179055565b6000606081610cbe6020850185611727565b6001600160a01b031603610ce557604051639841ec5160e01b815260040160405180910390fd5b610d23610cf56020850185611727565b610d1e610d086040870160208801611727565b60205246600c5260408087013560009081522090565b61100c565b9150366000610d3560608601866117f0565b915091506040518183823760008083836000895af1610d58573d6000803e3d6000fd5b50610d7b610d6960808701876117a7565b610d7660a08901896117a7565b6110ac565b92506001600160a01b03841663f2fde38b610d9c6040880160208901611727565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401600060405180830381600087803b158015610ddd57600080fd5b505af1158015610df1573d6000803e3d6000fd5b50610e06925050506040860160208701611727565b6001600160a01b03908116908516610e216020880188611727565b6001600160a01b03167fe94db3a31c09b7894f023c1f9114859672be916ffa8282215d7d43595bdcb3e7610e5860608a018a6117f0565b610e6560808c018c6117a7565b610e7260a08e018e6117a7565b8c604051610e8697969594939291906118f8565b60405180910390a45050915091565b6001600160a01b0390931692600084156107db5760405160418303610ef35784600052604084013560001a602052604084604037602060016080600060015afa805187183d1517610ef1575060006060526040525060016107db565b505b600060605280604052631626ba7e60e01b80825285600483015260248201604081528460448401528486606485013760208160648701858b5afa905190911416915050949350505050565b60007f0000000000000000000000000000000000000000000000000000000000000000610f696111e2565b15610f7957610f7661115a565b90505b67190100000000000060005280601a5282603a52604260182091506000603a5250919050565b7f0000000000000000000000000000000000000000000000000000000000000000610fc86111e2565b15610fd5576109f161115a565b90565b60005a60005a4785620186a0f161100957806000526073600b5360ff6020536016600b47f0611009575a60141c3d5a3e5b50565b6000604051733d602d80600a3d3981f3363d3d373d3d3d363d7360601b81528360601b60148201526e5af43d82803e903d91602b57fd5bf360881b6028820152826037826000f59150506001600160a01b03811661062d5760405162461bcd60e51b815260206004820152601760248201527f455243313136373a2063726561746532206661696c65640000000000000000006044820152606401610a82565b60608382146110ce57604051631dc0052360e11b815260040160405180910390fd5b6040519050818152602081018260051b84018360051b8201855b82811461114b578035870180356020820184378782038a01356000808335866000855af161111a573d6000803e3d6000fd5b50508184526020840193503d82523d6000602084013e3d91909101603f0167ffffffffffffffe016906020016110e8565b50604052509095945050505050565b604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81527f000000000000000000000000000000000000000000000000000000000000000060208201527f00000000000000000000000000000000000000000000000000000000000000009181019190915246606082015230608082015260a0902090565b467f000000000000000000000000000000000000000000000000000000000000000014307f000000000000000000000000000000000000000000000000000000000000000014161590565b6000815180845260005b8181101561125357602081850181015186830182015201611237565b506000602082860101526020601f19601f83011685010191505092915050565b6020815260006109e0602083018461122d565b600060e082840312156103e857600080fd5b60008083601f8401126112aa57600080fd5b5081356001600160401b038111156112c157600080fd5b6020830191508360208285010111156112d957600080fd5b9250929050565b80356001600160a01b03811681146112f757600080fd5b919050565b600080600080600080600060a0888a03121561131757600080fd5b87356001600160401b038082111561132e57600080fd5b61133a8b838c01611286565b985060208a013591508082111561135057600080fd5b61135c8b838c01611298565b909850965086915061137060408b016112e0565b955060608a013591508082111561138657600080fd5b506113938a828b01611298565b90945092506113a69050608089016112e0565b905092959891949750929550565b600082825180855260208086019550808260051b84010181860160005b848110156113ff57601f198684030189526113ed83835161122d565b988401989250908301906001016113d1565b5090979650505050505050565b6001600160a01b03831681526040602082018190526000906107db908301846113b4565b60008060006040848603121561144557600080fd5b83356001600160401b038082111561145c57600080fd5b61146887838801611286565b9450602086013591508082111561147e57600080fd5b5061148b86828701611298565b9497909650939450505050565b60008083601f8401126114aa57600080fd5b5081356001600160401b038111156114c157600080fd5b6020830191508360208260051b85010111156112d957600080fd5b6000806000604084860312156114f157600080fd5b6114fa846112e0565b925060208401356001600160401b0381111561151557600080fd5b61148b86828701611498565b6020808252825182820181905260009190848201906040850190845b8181101561155b57835115158352928401929184019160010161153d565b50909695505050505050565b6000806020838503121561157a57600080fd5b82356001600160401b0381111561159057600080fd5b61159c85828601611498565b90969095509350505050565b600080600080606085870312156115be57600080fd5b6115c7856112e0565b935060208501356001600160401b038111156115e257600080fd5b6115ee87828801611298565b90945092506116019050604086016112e0565b905092959194509250565b60008060006060848603121561162157600080fd5b61162a846112e0565b9250611638602085016112e0565b9150604084013590509250925092565b600081518084526020808501945080840160005b838110156116785781518752958201959082019060010161165c565b509495945050505050565b60ff60f81b8816815260e0602082015260006116a260e083018961122d565b82810360408401526116b4818961122d565b606084018890526001600160a01b038716608085015260a0840186905283810360c085015290506116e58185611648565b9a9950505050505050505050565b60006020828403121561170557600080fd5b81356001600160401b0381111561171b57600080fd5b6107db84828501611286565b60006020828403121561173957600080fd5b6109e0826112e0565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b6020808252810182905260006001600160fb1b0383111561178e57600080fd5b8260051b80856040850137919091016040019392505050565b6000808335601e198436030181126117be57600080fd5b8301803591506001600160401b038211156117d857600080fd5b6020019150600581901b36038213156112d957600080fd5b6000808335601e1984360301811261180757600080fd5b8301803591506001600160401b0382111561182157600080fd5b6020019150368190038213156112d957600080fd5b8183823760009101908152919050565b815160009082906020808601845b8381101561187057815185529382019390820190600101611854565b50929695505050505050565b60008184825b858110156118b1576001600160a01b0361189b836112e0565b1683526020928301929190910190600101611882565b509095945050505050565b6020815260006109e06020830184611648565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60808152600061190c60808301898b6118cf565b8281036020848101919091528782528891810160005b8981101561194e576001600160a01b0361193b856112e0565b1682529282019290820190600101611922565b5084810360408601528681528181019250600587901b810182018860005b898110156119db57838303601f190186528135368c9003601e1901811261199257600080fd5b8b0185810190356001600160401b038111156119ad57600080fd5b8036038213156119bc57600080fd5b6119c78582846118cf565b97870197945050509084019060010161196c565b505085810360608701526119ef81886113b4565b9d9c5050505050505050505050505056fea2646970667358221220d594684cddf3261cd3a8d49bc981d492299a30b7d35d1bd5669ccd0bcc4c29dd64736f6c63430008130033

Deployed Bytecode

0x6080604052600436106100ec5760003560e01c806354fd4d501161008a578063b9a257b211610059578063b9a257b2146102c1578063d38dfaf5146102e1578063e361d18f14610311578063f698da2514610331576100fb565b806354fd4d50146102115780637cf5b76314610226578063807c93101461025a57806384b0196e14610299576100fb565b806317447cf1116100c657806317447cf11461016f57806320606b701461019c5780632eb48a80146101de57806340a5468f146101fe576100fb565b806306fdde031461010357806308d1207f1461012e5780630ffc20c91461014f576100fb565b366100fb576100f9610346565b005b6100f9610346565b34801561010f57600080fd5b506101186103de565b6040516101259190611273565b60405180910390f35b61014161013c3660046112fc565b6103ee565b60405161012592919061140c565b34801561015b57600080fd5b5061014161016a366004611430565b610462565b34801561017b57600080fd5b5061018f61018a3660046114dc565b610490565b6040516101259190611521565b3480156101a857600080fd5b506101d07f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81565b604051908152602001610125565b3480156101ea57600080fd5b506100f96101f9366004611567565b610555565b6100f961020c3660046115a8565b6105ff565b34801561021d57600080fd5b50610118610623565b34801561023257600080fd5b506101d07f02851fd84c0125420e90b7716c63914a48e2932366cce89b4a7a0bcdf538d75981565b34801561026657600080fd5b5061027a61027536600461160c565b610633565b604080516001600160a01b039093168352901515602083015201610125565b3480156102a557600080fd5b506102ae6106c3565b6040516101259796959493929190611683565b3480156102cd57600080fd5b506101416102dc3660046116f3565b6106ea565b3480156102ed57600080fd5b506103016102fc366004611430565b61075a565b6040519015158152602001610125565b34801561031d57600080fd5b506101d061032c3660046116f3565b6107e3565b34801561033d57600080fd5b506101d06109e7565b3661034f573636f35b6000805b8036821061036157506103bd565b600180830192600319810190351860001a90816103ad57600019855260028301933560021984011860001a607f80821161039c578282013888395b169490940190930192506103539050565b8185538085019450505050610353565b50600080826000305af490503d6000803e806103d8573d6000fd5b503d6000f35b60606103e86109f6565b50919050565b600060606103fa610a34565b600061042661040c60208c018c611727565b61041c60408d0160208e01611727565b8c60400135610633565b9150508061043f576104398a8a8a610a92565b90935091505b61044b87878787610bc8565b506104566001600055565b97509795505050505050565b6000606061046e610a34565b610479858585610a92565b90925090506104886001600055565b935093915050565b6060816001600160401b038111156104aa576104aa611742565b6040519080825280602002602001820160405280156104d3578160200160208202803683370190505b506001600160a01b03851660009081526001602052604081209192505b80841461054c5761052285858381811061050c5761050c611758565b9050602002013583610c2990919063ffffffff16565b83828151811061053457610534611758565b911515602092830291909101909101526001016104f0565b50509392505050565b600061055f610c4b565b6001600160a01b03811660009081526001602052604081209192505b8084146105b5576105ad85858381811061059757610597611758565b9050602002013583610c8390919063ffffffff16565b60010161057b565b50816001600160a01b03167fc45e3a0dd412bcad8d62398d74d66b1c8449f38beb10da275e4da0c6d3a811a485856040516105f192919061176e565b60405180910390a250505050565b610607610a34565b61061384848484610bc8565b61061d6001600055565b50505050565b606061062d6109f6565b92915050565b602082905246600c5260008181526040812081906106ac90869030604051733d602d80600a3d3981f3363d3d373d3d3d363d7360601b8152606093841b60148201526f5af43d82803e903d91602b57fd5bf3ff60801b6028820152921b6038830152604c8201526037808220606c830152605591012090565b956001600160a01b0387163b151595509350505050565b600f60f81b60608060008080836106d86109f6565b97989097965046955030945091925090565b600060606106f6610a34565b6106fe610c4b565b6001600160a01b03166107176040850160208601611727565b6001600160a01b03161461073d576040516282b42960e81b815260040160405180910390fd5b61074683610cac565b90925090506107556001600055565b915091565b600061077f61076f6040860160208701611727565b610778866107e3565b8585610e95565b80156107db57506107d960c0850135600160006107a26040890160208a01611727565b6001600160a01b0316815260208082019290925260409081016000908120600885901c825290925290205460ff9091161c60011690565b155b949350505050565b60008036816107f560a08601866117a7565b9092509050806000816001600160401b0381111561081557610815611742565b60405190808252806020026020018201604052801561083e578160200160208202803683370190505b50905060005b8281146108aa5784848281811061085d5761085d611758565b905060200281019061086f91906117f0565b60405161087d929190611836565b604051809103902082828151811061089757610897611758565b6020908102919091010152600101610844565b50806040516020016108bc9190611846565b604051602081830303815290604052805190602001209450505050506109e07f02851fd84c0125420e90b7716c63914a48e2932366cce89b4a7a0bcdf538d75984600001602081019061090f9190611727565b61091f6040870160208801611727565b604087013561093160608901896117f0565b60405161093f929190611836565b60405190819003902061095560808a018a6117a7565b60405160200161096692919061187c565b60408051601f198184030181528282528051602091820120908301979097526001600160a01b0395861690820152939092166060840152608083015260a082015260c08082019290925260e08101849052908501356101008201526101200160405160208183030381529060405280519060200120610f3e565b9392505050565b60006109f1610f9f565b905090565b604080518082018252600c81526b29b7bab73221b932b0ba37b960a11b602080830191909152825180840190935260018352601960f91b9083015291565b600260005403610a8b5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064015b60405180910390fd5b6002600055565b60006060610aa185858561075a565b610abe57604051638baa579f60e01b815260040160405180910390fd5b610ac785610cac565b9092509050610b2660c086013560016000610ae860408a0160208b01611727565b6001600160a01b0316815260208082019290925260409081016000908120600885901c825290925290208054600160ff9093169290921b9091179055565b604080516001808252818301909252600091602080830190803683370190505090508560c0013581600081518110610b6057610b60611758565b602002602001018181525050856020016020810190610b7f9190611727565b6001600160a01b03167fc45e3a0dd412bcad8d62398d74d66b1c8449f38beb10da275e4da0c6d3a811a482604051610bb791906118bc565b60405180910390a250935093915050565b6001600160a01b0384161561061d5760405182848237600080848334895af1610bf5573d6000803e3d6000fd5b506001600160a01b0381161561061d57471561061d576000196001600160a01b03821601610c205750335b61061d81610fd8565b600881901c6000908152602092909252604090912054600160ff9092161c1690565b6000336000526e2fd5aeb385d324b580fca7c83823a0803303610c7b5760206000806000845afa610c7b57600080fd5b505060005190565b600881901c600090815260209290925260409091208054600160ff9093169290921b9091179055565b6000606081610cbe6020850185611727565b6001600160a01b031603610ce557604051639841ec5160e01b815260040160405180910390fd5b610d23610cf56020850185611727565b610d1e610d086040870160208801611727565b60205246600c5260408087013560009081522090565b61100c565b9150366000610d3560608601866117f0565b915091506040518183823760008083836000895af1610d58573d6000803e3d6000fd5b50610d7b610d6960808701876117a7565b610d7660a08901896117a7565b6110ac565b92506001600160a01b03841663f2fde38b610d9c6040880160208901611727565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401600060405180830381600087803b158015610ddd57600080fd5b505af1158015610df1573d6000803e3d6000fd5b50610e06925050506040860160208701611727565b6001600160a01b03908116908516610e216020880188611727565b6001600160a01b03167fe94db3a31c09b7894f023c1f9114859672be916ffa8282215d7d43595bdcb3e7610e5860608a018a6117f0565b610e6560808c018c6117a7565b610e7260a08e018e6117a7565b8c604051610e8697969594939291906118f8565b60405180910390a45050915091565b6001600160a01b0390931692600084156107db5760405160418303610ef35784600052604084013560001a602052604084604037602060016080600060015afa805187183d1517610ef1575060006060526040525060016107db565b505b600060605280604052631626ba7e60e01b80825285600483015260248201604081528460448401528486606485013760208160648701858b5afa905190911416915050949350505050565b60007ff925c052d7deab5d3e4719e7b25c61cc3fd165a61b045233d6fc4cbce22d85cc610f696111e2565b15610f7957610f7661115a565b90505b67190100000000000060005280601a5282603a52604260182091506000603a5250919050565b7ff925c052d7deab5d3e4719e7b25c61cc3fd165a61b045233d6fc4cbce22d85cc610fc86111e2565b15610fd5576109f161115a565b90565b60005a60005a4785620186a0f161100957806000526073600b5360ff6020536016600b47f0611009575a60141c3d5a3e5b50565b6000604051733d602d80600a3d3981f3363d3d373d3d3d363d7360601b81528360601b60148201526e5af43d82803e903d91602b57fd5bf360881b6028820152826037826000f59150506001600160a01b03811661062d5760405162461bcd60e51b815260206004820152601760248201527f455243313136373a2063726561746532206661696c65640000000000000000006044820152606401610a82565b60608382146110ce57604051631dc0052360e11b815260040160405180910390fd5b6040519050818152602081018260051b84018360051b8201855b82811461114b578035870180356020820184378782038a01356000808335866000855af161111a573d6000803e3d6000fd5b50508184526020840193503d82523d6000602084013e3d91909101603f0167ffffffffffffffe016906020016110e8565b50604052509095945050505050565b604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81527f055447914107b5dcd4afdd0a0ec9b0df7575160486e48acf346f43310273a5fa60208201527fad7c5bef027816a800da1736444fb58a807ef4c9603b7848673f7e3a68eb14a59181019190915246606082015230608082015260a0902090565b467f000000000000000000000000000000000000000000000000000000000000000114307f0000000000000000000000000000000000aec84f5bfc2af15eafb943bf4e352214161590565b6000815180845260005b8181101561125357602081850181015186830182015201611237565b506000602082860101526020601f19601f83011685010191505092915050565b6020815260006109e0602083018461122d565b600060e082840312156103e857600080fd5b60008083601f8401126112aa57600080fd5b5081356001600160401b038111156112c157600080fd5b6020830191508360208285010111156112d957600080fd5b9250929050565b80356001600160a01b03811681146112f757600080fd5b919050565b600080600080600080600060a0888a03121561131757600080fd5b87356001600160401b038082111561132e57600080fd5b61133a8b838c01611286565b985060208a013591508082111561135057600080fd5b61135c8b838c01611298565b909850965086915061137060408b016112e0565b955060608a013591508082111561138657600080fd5b506113938a828b01611298565b90945092506113a69050608089016112e0565b905092959891949750929550565b600082825180855260208086019550808260051b84010181860160005b848110156113ff57601f198684030189526113ed83835161122d565b988401989250908301906001016113d1565b5090979650505050505050565b6001600160a01b03831681526040602082018190526000906107db908301846113b4565b60008060006040848603121561144557600080fd5b83356001600160401b038082111561145c57600080fd5b61146887838801611286565b9450602086013591508082111561147e57600080fd5b5061148b86828701611298565b9497909650939450505050565b60008083601f8401126114aa57600080fd5b5081356001600160401b038111156114c157600080fd5b6020830191508360208260051b85010111156112d957600080fd5b6000806000604084860312156114f157600080fd5b6114fa846112e0565b925060208401356001600160401b0381111561151557600080fd5b61148b86828701611498565b6020808252825182820181905260009190848201906040850190845b8181101561155b57835115158352928401929184019160010161153d565b50909695505050505050565b6000806020838503121561157a57600080fd5b82356001600160401b0381111561159057600080fd5b61159c85828601611498565b90969095509350505050565b600080600080606085870312156115be57600080fd5b6115c7856112e0565b935060208501356001600160401b038111156115e257600080fd5b6115ee87828801611298565b90945092506116019050604086016112e0565b905092959194509250565b60008060006060848603121561162157600080fd5b61162a846112e0565b9250611638602085016112e0565b9150604084013590509250925092565b600081518084526020808501945080840160005b838110156116785781518752958201959082019060010161165c565b509495945050505050565b60ff60f81b8816815260e0602082015260006116a260e083018961122d565b82810360408401526116b4818961122d565b606084018890526001600160a01b038716608085015260a0840186905283810360c085015290506116e58185611648565b9a9950505050505050505050565b60006020828403121561170557600080fd5b81356001600160401b0381111561171b57600080fd5b6107db84828501611286565b60006020828403121561173957600080fd5b6109e0826112e0565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b6020808252810182905260006001600160fb1b0383111561178e57600080fd5b8260051b80856040850137919091016040019392505050565b6000808335601e198436030181126117be57600080fd5b8301803591506001600160401b038211156117d857600080fd5b6020019150600581901b36038213156112d957600080fd5b6000808335601e1984360301811261180757600080fd5b8301803591506001600160401b0382111561182157600080fd5b6020019150368190038213156112d957600080fd5b8183823760009101908152919050565b815160009082906020808601845b8381101561187057815185529382019390820190600101611854565b50929695505050505050565b60008184825b858110156118b1576001600160a01b0361189b836112e0565b1683526020928301929190910190600101611882565b509095945050505050565b6020815260006109e06020830184611648565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60808152600061190c60808301898b6118cf565b8281036020848101919091528782528891810160005b8981101561194e576001600160a01b0361193b856112e0565b1682529282019290820190600101611922565b5084810360408601528681528181019250600587901b810182018860005b898110156119db57838303601f190186528135368c9003601e1901811261199257600080fd5b8b0185810190356001600160401b038111156119ad57600080fd5b8036038213156119bc57600080fd5b6119c78582846118cf565b97870197945050509084019060010161196c565b505085810360608701526119ef81886113b4565b9d9c5050505050505050505050505056fea2646970667358221220d594684cddf3261cd3a8d49bc981d492299a30b7d35d1bd5669ccd0bcc4c29dd64736f6c63430008130033

Deployed Bytecode Sourcemap

881:17100:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4448:19;:17;:19::i;:::-;881:17100;;4318:19;:17;:19::i;7174:112::-;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;3211:568;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;2637:277::-;;;;;;;;;;-1:-1:-1;2637:277:0;;;;;:::i;:::-;;:::i;6706:384::-;;;;;;;;;;-1:-1:-1;6706:384:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;1721:58::-;;;;;;;;;;-1:-1:-1;1721:58:0;1250:66:6;1721:58:0;;;;;5817:25:12;;;5805:2;5790:18;1721:58:0;5671:177:12;3836:377:0;;;;;;;;;;-1:-1:-1;3836:377:0;;;;;:::i;:::-;;:::i;2971:183::-;;;;;;:::i;:::-;;:::i;7343:121::-;;;;;;;;;;;;;:::i;1250:394::-;;;;;;;;;;;;1335:309;1250:394;;4724:315;;;;;;;;;;-1:-1:-1;4724:315:0;;;;;:::i;:::-;;:::i;:::-;;;;-1:-1:-1;;;;;7376:32:12;;;7358:51;;7452:14;;7445:22;7440:2;7425:18;;7418:50;7331:18;4724:315:0;7190:284:12;6926:596:6;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;:::i;2347:233:0:-;;;;;;;;;;-1:-1:-1;2347:233:0;;;;;:::i;:::-;;:::i;5096:440::-;;;;;;;;;;-1:-1:-1;5096:440:0;;;;;:::i;:::-;;:::i;:::-;;;9381:14:12;;9374:22;9356:41;;9344:2;9329:18;5096:440:0;9216:187:12;5593:1056:0;;;;;;;;;;-1:-1:-1;5593:1056:0;;;;;:::i;:::-;;:::i;7521:116::-;;;;;;;;;;;;;:::i;11272:1120:9:-;11346:14;11336:68;;11346:14;;11364:38;11336:68;11426:1;;11503:628;11522:21;11346:14;11525:1;11522:21;;;-1:-1:-1;;;11522:21:9;11643:1;11636:9;;;;-1:-1:-1;;11586:9:9;;11597:15;;11582:31;11426:1;11574:40;;;11662:394;;-1:-1:-1;;11856:17:9;;11718:9;11772;;;11729:15;-1:-1:-1;;11718:9:9;;11714:31;11426:1;11706:40;11910:4;11904:11;;;11894:61;;11643:1;11947;11943:9;11931:10;11928:1;11919:34;11894:61;11992:12;11981:28;;;;;;;;-1:-1:-1;11503:628:9;;-1:-1:-1;11503:628:9;11662:394;12084:1;12081;12073:13;11643:1;12112;12108:9;12103:14;;;;;11503:628;;;11507:14;11426:1;;12196;11426;12179:9;12172:5;12159:51;12144:66;;12250:16;11426:1;;12223:44;12290:7;12280:53;;12314:16;11426:1;12301:30;12280:53;;12359:16;11426:1;12346:30;7174:112:0;7213:19;7256:23;:21;:23::i;:::-;-1:-1:-1;7244:35:0;7174:112;-1:-1:-1;7174:112:0:o;3211:568::-;3443:15;3460:22;2246:21:4;:19;:21::i;:::-;3582:11:0::1;3597:54;3617:16;;::::0;::::1;:1:::0;:16:::1;:::i;:::-;3635:7;::::0;;;::::1;::::0;::::1;;:::i;:::-;3644:1;:6;;;3597:19;:54::i;:::-;3579:72;;;3666:6;3661:68;;3695:34;3716:1;3719:9;;3695:20;:34::i;:::-;3674:55:::0;;-1:-1:-1;3674:55:0;-1:-1:-1;3661:68:0::1;3739:33;3745:6;3753:8;;3763;3739:5;:33::i;:::-;3484:295;2288:20:4::0;1701:1;2790:7;:22;2610:209;2288:20;3211:568:0;;;;;;;;;;:::o;2637:277::-;2780:20;2802:22;2246:21:4;:19;:21::i;:::-;2866:41:0::1;2887:8;2897:9;;2866:20;:41::i;:::-;2840:67:::0;;-1:-1:-1;2840:67:0;-1:-1:-1;2288:20:4;1701:1;2790:7;:22;2610:209;2288:20;2637:277:0;;;;;;:::o;6706:384::-;6799:20;6875:6;-1:-1:-1;;;;;6864:25:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;6864:25:0;-1:-1:-1;;;;;;6932:26:0;;6903;6932;;;:18;:26;;;;;6855:34;;-1:-1:-1;6972:102:0;6988:18;;;6972:102;;7043:16;7049:6;;7056:1;7049:9;;;;;;;:::i;:::-;;;;;;;7043:1;:5;;:16;;;;:::i;:::-;7031:6;7038:1;7031:9;;;;;;;;:::i;:::-;:28;;;:9;;;;;;;;;;;:28;7008:3;;6972:102;;;;6831:253;6706:384;;;;;:::o;3836:377::-;3932:14;3949:23;:21;:23::i;:::-;-1:-1:-1;;;;;4015:26:0;;3986;4015;;;:18;:26;;;;;3932:40;;-1:-1:-1;4055:90:0;4071:18;;;4055:90;;4114:16;4120:6;;4127:1;4120:9;;;;;;;:::i;:::-;;;;;;;4114:1;:5;;:16;;;;:::i;:::-;4091:3;;4055:90;;;;4181:6;-1:-1:-1;;;;;4163:33:0;;4189:6;;4163:33;;;;;;;:::i;:::-;;;;;;;;3908:299;;3836:377;;:::o;2971:183::-;2246:21:4;:19;:21::i;:::-;3114:33:0::1;3120:6;3128:8;;3138;3114:5;:33::i;:::-;2288:20:4::0;1701:1;2790:7;:22;2610:209;2288:20;2971:183:0;;;;:::o;7343:121::-;7385:22;7434:23;:21;:23::i;:::-;7419:38;7343:121;-1:-1:-1;;7343:121:0:o;4724:315::-;12746:4;12739:19;;;12784:9;12778:4;12771:23;4857:12;12807:18;;;12864:4;12848:21;;4857:12;;4901:91;;4936:14;;4986:4;2867::3;2861:11;-1:-1:-1;;;2885:79:3;;3004:4;3000:25;;;2993:4;2984:14;;2977:49;-1:-1:-1;;;3055:4:3;3046:14;;3039:90;3165:19;;3158:4;3149:14;;3142:43;3214:4;3205:14;;3198:28;3277:4;3262:20;;;3255:4;3246:14;;3239:44;3335:4;3319:14;;3309:31;;2609:747;4901:91:0;4894:98;-1:-1:-1;;;;;5011:16:0;;;:21;;;-1:-1:-1;4724:315:0;-1:-1:-1;;;;4724:315:0:o;6926:596:6:-;-1:-1:-1;;;7051:18:6;;7024:13;;;7051:18;7322:23;:21;:23::i;:::-;6926:596;;7304:41;;;-1:-1:-1;7365:13:6;;-1:-1:-1;7416:4:6;;-1:-1:-1;6926:596:6;;-1:-1:-1;6926:596:6;:::o;2347:233:0:-;2420:15;2437:22;2246:21:4;:19;:21::i;:::-;2486:23:0::1;:21;:23::i;:::-;-1:-1:-1::0;;;;;2475:34:0::1;:7;::::0;;;::::1;::::0;::::1;;:::i;:::-;-1:-1:-1::0;;;;;2475:34:0::1;;2471:61;;2518:14;;-1:-1:-1::0;;;2518:14:0::1;;;;;;;;;;;2471:61;2563:10;2571:1;2563:7;:10::i;:::-;2542:31:::0;;-1:-1:-1;2542:31:0;-1:-1:-1;2288:20:4;1701:1;2790:7;:22;2610:209;2288:20;2347:233:0;;;:::o;5096:440::-;5195:4;5319:85;5367:7;;;;;;;;:::i;:::-;5376:16;5390:1;5376:13;:16::i;:::-;5394:9;;5319:47;:85::i;:::-;:210;;;;-1:-1:-1;5489:40:0;5521:7;;;;5489:18;:27;5508:7;;;;;;;;:::i;:::-;-1:-1:-1;;;;;5489:27:0;;;;;;;;;;;;;;;-1:-1:-1;5489:27:0;;;2024:1:8;2015:10;;;2004:22;;;;;;;;2039:4;2031:12;;;2004:40;2048:1;2003:46;;1672:479;5489:40:0;5488:41;5319:210;5211:318;5096:440;-1:-1:-1;;;;5096:440:0:o;5593:1056::-;5663:7;;5739:22;5663:7;5764:6;;;;:1;:6;:::i;:::-;5739:31;;-1:-1:-1;5739:31:0;-1:-1:-1;5739:31:0;5784:9;5739:31;-1:-1:-1;;;;;5853:16:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;5853:16:0;;5822:47;;5888:9;5883:102;5908:1;5903;:6;5883:102;;5961:5;;5967:1;5961:8;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;5951:19;;;;;;;:::i;:::-;;;;;;;;5934:11;5946:1;5934:14;;;;;;;;:::i;:::-;;;;;;;;;;:36;5911:3;;5883:102;;;;6043:11;6026:29;;;;;;;;:::i;:::-;;;;;;;;;;;;;6016:40;;;;;;5998:58;;5715:352;;;;6095:547;1335:309;6243:1;:16;;;;;;;;;;:::i;:::-;6296:7;;;;;;;;:::i;:::-;6340:6;;;;6393:10;;;;6340:1;6393:10;:::i;:::-;6383:21;;;;;;;:::i;:::-;;;;;;;;;6466:11;;;;:1;:11;:::i;:::-;6449:29;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;6449:29:0;;;;;;;;;6439:40;;6449:29;6439:40;;;;6158:452;;;13671:25:12;;;;-1:-1:-1;;;;;13770:15:12;;;13750:18;;;13743:43;13822:15;;;;13802:18;;;13795:43;13854:18;;;13847:34;13897:19;;;13890:35;6570:7:0;13941:19:12;;;13934:35;;;;13985:19;;;13978:35;;;6570:7:0;;;;14029:19:12;;;14022:35;13643:19;;6158:452:0;;;;;;;;;;;;6127:501;;;;;;6095:14;:547::i;:::-;6076:566;5593:1056;-1:-1:-1;;;5593:1056:0:o;7521:116::-;7571:17;7612:18;:16;:18::i;:::-;7600:30;;7521:116;:::o;7970:225::-;8142:22;;;;;;;;;;;-1:-1:-1;;;8142:22:0;;;;;;;;8174:14;;;;;;;;;;;-1:-1:-1;;;8174:14:0;;;;8142:22;7970:225::o;2321:283:4:-;1744:1;2449:7;;:19;2441:63;;;;-1:-1:-1;;;2441:63:4;;14270:2:12;2441:63:4;;;14252:21:12;14309:2;14289:18;;;14282:30;14348:33;14328:18;;;14321:61;14399:18;;2441:63:4;;;;;;;;;1744:1;2579:7;:18;2321:283::o;15196:514:0:-;15312:15;15329:22;15372:30;15389:1;15392:9;;15372:16;:30::i;:::-;15367:62;;15411:18;;-1:-1:-1;;;15411:18:0;;;;;;;;;;;15367:62;15460:10;15468:1;15460:7;:10::i;:::-;15439:31;;-1:-1:-1;15439:31:0;-1:-1:-1;15533:40:0;15565:7;;;;15533:18;:27;15552:7;;;;;;;;:::i;:::-;-1:-1:-1;;;;;15533:27:0;;;;;;;;;;;;;;;-1:-1:-1;15533:27:0;;;2308:1:8;2299:10;;;2288:22;;;;;;;:47;;2315:1;2329:4;2321:12;;;2315:19;;;;2288:47;;;;;2218:124;15533:40:0;15609:16;;;15623:1;15609:16;;;;;;;;;15583:23;;15609:16;;;;;;;;;;;-1:-1:-1;15609:16:0;15583:42;;15647:1;:7;;;15635:6;15642:1;15635:9;;;;;;;;:::i;:::-;;;;;;:19;;;;;15687:1;:7;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;15669:34:0;;15696:6;15669:34;;;;;;:::i;:::-;;;;;;;;15357:353;15196:514;;;;;;:::o;16417:1562::-;-1:-1:-1;;;;;16544:20:0;;16540:33;16566:7;16540:33;16665:4;16659:11;16773:15;16756;16753:1;16740:49;17296:4;17233;17171:15;17110:1;17039:11;16985:6;16940:5;16914:441;16887:666;;17475:16;17469:4;17463;17448:44;17522:16;17516:4;17509:30;16887:666;-1:-1:-1;;;;;;17576:22:0;;;17572:401;;17786:21;:26;17782:181;;-1:-1:-1;;;;;;;17836:22:0;;;17832:49;;-1:-1:-1;17871:10:0;17832:49;17899;17939:8;17899:39;:49::i;1672:479:8:-;2024:1;2015:10;;;1746;2004:22;;;;;;;;;;;;;2048:1;2039:4;2031:12;;;2004:40;2003:46;;1672:479::o;1961:485:2:-;2002:14;2107:8;2101:4;2094:22;2147:23;2199:10;2189:8;2186:24;2183:213;;2287:4;2281;2275;2269;2257:10;2250:5;2239:53;2229:153;;2329:4;2323;2316:18;2229:153;-1:-1:-1;;2425:4:2;2419:11;;1961:485::o;2218:124:8:-;2308:1;2299:10;;;2288;:22;;;;;;;;;;;;:47;;2315:1;2329:4;2321:12;;;2315:19;;;;2288:47;;;;;2218:124::o;13245:1545:0:-;13306:15;13323:22;13306:15;13361:16;;;;:1;:16;:::i;:::-;-1:-1:-1;;;;;13361:30:0;;13357:76;;13400:33;;-1:-1:-1;;;13400:33:0;;;;;;;;;;;13357:76;13501:73;13527:16;;;;:1;:16;:::i;:::-;13545:28;13557:7;;;;;;;;:::i;:::-;12746:4;12739:19;12784:9;12778:4;12771:23;13566:6;;;;;12690:14;12807:18;;;12848:21;;12617:268;13545:28;13501:25;:73::i;:::-;13483:92;-1:-1:-1;13586:23:0;;13612:10;;;;:1;:10;:::i;:::-;13586:36;;;;13744:4;13738:11;13850:15;13833;13830:1;13817:49;14313:4;14257;14200:15;14158:1;14100;14044:7;13999:5;13973:391;13946:617;;14485:16;14479:4;14473;14458:44;14532:16;14526:4;14519:30;13946:617;-1:-1:-1;14593:35:0;14608:11;;;;:1;:11;:::i;:::-;14621:6;;;;:1;:6;:::i;:::-;14593:14;:35::i;:::-;14583:45;-1:-1:-1;;;;;;14639:34:0;;;14674:7;;;;;;;;:::i;:::-;14639:43;;-1:-1:-1;;;;;;14639:43:0;;;;;;;-1:-1:-1;;;;;14858:32:12;;;14639:43:0;;;14840:51:12;14813:18;;14639:43:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;14733:7:0;;-1:-1:-1;;;14733:7:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;14698:85:0;;;;;;14706:16;;;;:1;:16;:::i;:::-;-1:-1:-1;;;;;14698:85:0;;14742:10;;;;:1;:10;:::i;:::-;14754:11;;;;:1;:11;:::i;:::-;14767:6;;;;:1;:6;:::i;:::-;14775:7;14698:85;;;;;;;;;;;;:::i;:::-;;;;;;;;13347:1443;;13245:1545;;;:::o;4820:3036:11:-;-1:-1:-1;;;;;5145:24:11;;;;4960:12;5172:6;5129:2711;;;5215:4;5209:11;5261:2;5243:16;5240:24;5237:1102;;5300:4;5294;5287:18;5382:4;5364:16;5360:27;5347:41;5344:1;5339:50;5333:4;5326:64;5456:4;5438:16;5432:4;5419:42;5863:4;5809;5757;5704;5646:1;5568:5;5528:384;6083:1;6077:8;6069:6;6065:21;6046:16;6039:24;6036:51;6026:295;;-1:-1:-1;6165:1:11;6159:4;6152:15;6225:4;6218:15;-1:-1:-1;6126:1:11;6294:5;;6026:295;;5237:1102;6369:1;6363:4;6356:15;6427:1;6421:4;6414:15;6501:10;6496:3;6492:20;6539:1;6536;6529:12;6638:4;6631;6628:1;6624:12;6617:26;6676:4;6673:1;6669:12;6708:4;6705:1;6698:15;6801:16;6794:4;6791:1;6787:12;6780:38;6926:16;6908;6901:4;6898:1;6894:12;6881:62;7726:4;7674:1;7610:4;7592:16;7588:27;7528:1;7471:6;7422:5;7386:400;7140:8;;7137:15;;;7018:786;;-1:-1:-1;;4820:3036:11;;;;;;:::o;5739:840:6:-;5814:14;5997:22;6037:35;:33;:35::i;:::-;6033:76;;;6086:23;:21;:23::i;:::-;6074:35;;6033:76;6243:18;6237:4;6230:32;6309:9;6303:4;6296:23;6376:10;6370:4;6363:24;6452:4;6446;6436:21;6426:31;;6561:1;6555:4;6548:15;6181:392;5739:840;;;:::o;4781:347::-;4999:22;5039:35;:33;:35::i;:::-;5035:76;;;5088:23;:21;:23::i;5035:76::-;4781:347;:::o;6455:614:10:-;6661:4;6654:5;6648:4;6641:5;6626:13;6622:2;6600:20;6595:71;6585:468;;6699:2;6693:4;6686:16;6772:4;6766;6758:19;6828:4;6822;6814:19;6914:4;6908;6893:13;6886:33;6876:163;;6991:5;6987:2;6983:14;6965:16;6958:5;6943:55;6876:163;6455:614;:::o;1906:593:3:-;1990:16;2101:4;2095:11;-1:-1:-1;;;2126:3:3;2119:79;2244:14;2238:4;2234:25;2227:4;2222:3;2218:14;2211:49;-1:-1:-1;;;2289:4:3;2284:3;2280:14;2273:90;2410:4;2404;2399:3;2396:1;2388:27;2376:39;-1:-1:-1;;;;;;;2442:22:3;;2434:58;;;;-1:-1:-1;;;2434:58:3;;17456:2:12;2434:58:3;;;17438:21:12;17495:2;17475:18;;;17468:30;17534:25;17514:18;;;17507:53;17577:18;;2434:58:3;17254:347:12;8478:3795:0;8589:22;8631:31;;;8627:66;;8671:22;;-1:-1:-1;;;8671:22:0;;;;;;;;;;;8627:66;8929:4;8923:11;8912:22;;9029:11;9020:7;9013:28;9159:4;9150:7;9146:18;9371:11;9368:1;9364:19;9351:11;9347:37;9575:11;9572:1;9568:19;9552:14;9548:40;9708:11;9693:2450;9735:14;9732:1;9729:21;9693:2450;;9886:1;9873:15;9860:11;9856:33;10170:1;10157:15;10075:4;10072:1;10068:12;10009:1;9975:248;10569:11;10566:1;10562:19;10544:16;10540:42;10527:56;11093:4;11033;10972:1;10959:15;10886:1;10824;10778;10729:5;10699:449;10668:699;;11281:16;11275:4;11269;11254:44;11332:16;11326:4;11319:30;10668:699;;;11472:1;11456:14;11449:25;11529:4;11513:14;11509:25;11491:43;;11625:16;11622:1;11615:27;11750:16;11744:4;11737;11734:1;11730:12;11715:52;12084:16;12077:24;;;;12103:4;12073:35;12110:18;12069:60;;9766:4;9759:12;9693:2450;;;-1:-1:-1;12249:4:0;12242:15;-1:-1:-1;8478:3795:0;;;-1:-1:-1;;;;;8478:3795:0:o;7862:879:6:-;8426:4;8420:11;;8487:16;8477:27;;8264:15;8531:4;8524:12;;8517:30;8307:18;8567:12;;;8560:33;;;;8627:9;8620:4;8613:12;;8606:31;8671:9;8664:4;8657:12;;8650:31;8720:4;8707:18;;;7862:879::o;8821:340::-;9091:9;8935:14;9088:28;9121:9;8980:11;9118:25;9084:60;9077:68;;8821:340::o;14:423:12:-;56:3;94:5;88:12;121:6;116:3;109:19;146:1;156:162;170:6;167:1;164:13;156:162;;;232:4;288:13;;;284:22;;278:29;260:11;;;256:20;;249:59;185:12;156:162;;;160:3;363:1;356:4;347:6;342:3;338:16;334:27;327:38;426:4;419:2;415:7;410:2;402:6;398:15;394:29;389:3;385:39;381:50;374:57;;;14:423;;;;:::o;442:220::-;591:2;580:9;573:21;554:4;611:45;652:2;641:9;637:18;629:6;611:45;:::i;667:162::-;733:5;778:3;769:6;764:3;760:16;756:26;753:46;;;795:1;792;785:12;834:347;885:8;895:6;949:3;942:4;934:6;930:17;926:27;916:55;;967:1;964;957:12;916:55;-1:-1:-1;990:20:12;;-1:-1:-1;;;;;1022:30:12;;1019:50;;;1065:1;1062;1055:12;1019:50;1102:4;1094:6;1090:17;1078:29;;1154:3;1147:4;1138:6;1130;1126:19;1122:30;1119:39;1116:59;;;1171:1;1168;1161:12;1116:59;834:347;;;;;:::o;1186:173::-;1254:20;;-1:-1:-1;;;;;1303:31:12;;1293:42;;1283:70;;1349:1;1346;1339:12;1283:70;1186:173;;;:::o;1364:1112::-;1513:6;1521;1529;1537;1545;1553;1561;1614:3;1602:9;1593:7;1589:23;1585:33;1582:53;;;1631:1;1628;1621:12;1582:53;1671:9;1658:23;-1:-1:-1;;;;;1741:2:12;1733:6;1730:14;1727:34;;;1757:1;1754;1747:12;1727:34;1780:73;1845:7;1836:6;1825:9;1821:22;1780:73;:::i;:::-;1770:83;;1906:2;1895:9;1891:18;1878:32;1862:48;;1935:2;1925:8;1922:16;1919:36;;;1951:1;1948;1941:12;1919:36;1990:60;2042:7;2031:8;2020:9;2016:24;1990:60;:::i;:::-;2069:8;;-1:-1:-1;1964:86:12;-1:-1:-1;1964:86:12;;-1:-1:-1;2123:38:12;2157:2;2142:18;;2123:38;:::i;:::-;2113:48;;2214:2;2203:9;2199:18;2186:32;2170:48;;2243:2;2233:8;2230:16;2227:36;;;2259:1;2256;2249:12;2227:36;;2298:60;2350:7;2339:8;2328:9;2324:24;2298:60;:::i;:::-;2377:8;;-1:-1:-1;2272:86:12;-1:-1:-1;2431:39:12;;-1:-1:-1;2465:3:12;2450:19;;2431:39;:::i;:::-;2421:49;;1364:1112;;;;;;;;;;:::o;2481:591::-;2532:3;2563;2595:5;2589:12;2622:6;2617:3;2610:19;2648:4;2677:2;2672:3;2668:12;2661:19;;2733:2;2723:6;2720:1;2716:14;2709:5;2705:26;2701:35;2770:2;2763:5;2759:14;2791:1;2801:245;2815:6;2812:1;2809:13;2801:245;;;2902:2;2898:7;2890:5;2884:4;2880:16;2876:30;2871:3;2864:43;2928:38;2961:4;2952:6;2946:13;2928:38;:::i;:::-;3024:12;;;;2920:46;-1:-1:-1;2989:15:12;;;;2837:1;2830:9;2801:245;;;-1:-1:-1;3062:4:12;;2481:591;-1:-1:-1;;;;;;;2481:591:12:o;3077:374::-;-1:-1:-1;;;;;3302:32:12;;3284:51;;3371:2;3366;3351:18;;3344:30;;;-1:-1:-1;;3391:54:12;;3426:18;;3418:6;3391:54;:::i;3456:675::-;3567:6;3575;3583;3636:2;3624:9;3615:7;3611:23;3607:32;3604:52;;;3652:1;3649;3642:12;3604:52;3692:9;3679:23;-1:-1:-1;;;;;3762:2:12;3754:6;3751:14;3748:34;;;3778:1;3775;3768:12;3748:34;3801:73;3866:7;3857:6;3846:9;3842:22;3801:73;:::i;:::-;3791:83;;3927:2;3916:9;3912:18;3899:32;3883:48;;3956:2;3946:8;3943:16;3940:36;;;3972:1;3969;3962:12;3940:36;;4011:60;4063:7;4052:8;4041:9;4037:24;4011:60;:::i;:::-;3456:675;;4090:8;;-1:-1:-1;3985:86:12;;-1:-1:-1;;;;3456:675:12:o;4136:367::-;4199:8;4209:6;4263:3;4256:4;4248:6;4244:17;4240:27;4230:55;;4281:1;4278;4271:12;4230:55;-1:-1:-1;4304:20:12;;-1:-1:-1;;;;;4336:30:12;;4333:50;;;4379:1;4376;4369:12;4333:50;4416:4;4408:6;4404:17;4392:29;;4476:3;4469:4;4459:6;4456:1;4452:14;4444:6;4440:27;4436:38;4433:47;4430:67;;;4493:1;4490;4483:12;4508:511;4603:6;4611;4619;4672:2;4660:9;4651:7;4647:23;4643:32;4640:52;;;4688:1;4685;4678:12;4640:52;4711:29;4730:9;4711:29;:::i;:::-;4701:39;;4791:2;4780:9;4776:18;4763:32;-1:-1:-1;;;;;4810:6:12;4807:30;4804:50;;;4850:1;4847;4840:12;4804:50;4889:70;4951:7;4942:6;4931:9;4927:22;4889:70;:::i;5024:642::-;5189:2;5241:21;;;5311:13;;5214:18;;;5333:22;;;5160:4;;5189:2;5412:15;;;;5386:2;5371:18;;;5160:4;5455:185;5469:6;5466:1;5463:13;5455:185;;;5544:13;;5537:21;5530:29;5518:42;;5615:15;;;;5580:12;;;;5491:1;5484:9;5455:185;;;-1:-1:-1;5657:3:12;;5024:642;-1:-1:-1;;;;;;5024:642:12:o;5853:437::-;5939:6;5947;6000:2;5988:9;5979:7;5975:23;5971:32;5968:52;;;6016:1;6013;6006:12;5968:52;6056:9;6043:23;-1:-1:-1;;;;;6081:6:12;6078:30;6075:50;;;6121:1;6118;6111:12;6075:50;6160:70;6222:7;6213:6;6202:9;6198:22;6160:70;:::i;:::-;6249:8;;6134:96;;-1:-1:-1;5853:437:12;-1:-1:-1;;;;5853:437:12:o;6295:557::-;6383:6;6391;6399;6407;6460:2;6448:9;6439:7;6435:23;6431:32;6428:52;;;6476:1;6473;6466:12;6428:52;6499:29;6518:9;6499:29;:::i;:::-;6489:39;;6579:2;6568:9;6564:18;6551:32;-1:-1:-1;;;;;6598:6:12;6595:30;6592:50;;;6638:1;6635;6628:12;6592:50;6677:58;6727:7;6718:6;6707:9;6703:22;6677:58;:::i;:::-;6754:8;;-1:-1:-1;6651:84:12;-1:-1:-1;6808:38:12;;-1:-1:-1;6842:2:12;6827:18;;6808:38;:::i;:::-;6798:48;;6295:557;;;;;;;:::o;6857:328::-;6934:6;6942;6950;7003:2;6991:9;6982:7;6978:23;6974:32;6971:52;;;7019:1;7016;7009:12;6971:52;7042:29;7061:9;7042:29;:::i;:::-;7032:39;;7090:38;7124:2;7113:9;7109:18;7090:38;:::i;:::-;7080:48;;7175:2;7164:9;7160:18;7147:32;7137:42;;6857:328;;;;;:::o;7479:435::-;7532:3;7570:5;7564:12;7597:6;7592:3;7585:19;7623:4;7652:2;7647:3;7643:12;7636:19;;7689:2;7682:5;7678:14;7710:1;7720:169;7734:6;7731:1;7728:13;7720:169;;;7795:13;;7783:26;;7829:12;;;;7864:15;;;;7756:1;7749:9;7720:169;;;-1:-1:-1;7905:3:12;;7479:435;-1:-1:-1;;;;;7479:435:12:o;7919:920::-;8325:3;8320;8316:13;8308:6;8304:26;8293:9;8286:45;8367:3;8362:2;8351:9;8347:18;8340:31;8267:4;8394:46;8435:3;8424:9;8420:19;8412:6;8394:46;:::i;:::-;8488:9;8480:6;8476:22;8471:2;8460:9;8456:18;8449:50;8522:33;8548:6;8540;8522:33;:::i;:::-;8586:2;8571:18;;8564:34;;;-1:-1:-1;;;;;8635:32:12;;8629:3;8614:19;;8607:61;8655:3;8684:19;;8677:35;;;8749:22;;;8743:3;8728:19;;8721:51;8508:47;-1:-1:-1;8789:44:12;8508:47;8818:6;8789:44;:::i;:::-;8781:52;7919:920;-1:-1:-1;;;;;;;;;;7919:920:12:o;8844:367::-;8935:6;8988:2;8976:9;8967:7;8963:23;8959:32;8956:52;;;9004:1;9001;8994:12;8956:52;9044:9;9031:23;-1:-1:-1;;;;;9069:6:12;9066:30;9063:50;;;9109:1;9106;9099:12;9063:50;9132:73;9197:7;9188:6;9177:9;9173:22;9132:73;:::i;9408:186::-;9467:6;9520:2;9508:9;9499:7;9495:23;9491:32;9488:52;;;9536:1;9533;9526:12;9488:52;9559:29;9578:9;9559:29;:::i;9599:127::-;9660:10;9655:3;9651:20;9648:1;9641:31;9691:4;9688:1;9681:15;9715:4;9712:1;9705:15;9731:127;9792:10;9787:3;9783:20;9780:1;9773:31;9823:4;9820:1;9813:15;9847:4;9844:1;9837:15;9863:443;10052:2;10034:21;;;10071:18;;10064:34;;;-1:-1:-1;;;;;;10110:31:12;;10107:51;;;10154:1;10151;10144:12;10107:51;10188:6;10185:1;10181:14;10245:6;10237;10232:2;10221:9;10217:18;10204:48;10273:22;;;;10297:2;10269:31;;9863:443;-1:-1:-1;;;9863:443:12:o;10311:556::-;10415:4;10421:6;10481:11;10468:25;10575:2;10571:7;10560:8;10544:14;10540:29;10536:43;10516:18;10512:68;10502:96;;10594:1;10591;10584:12;10502:96;10621:33;;10673:20;;;-1:-1:-1;;;;;;10705:30:12;;10702:50;;;10748:1;10745;10738:12;10702:50;10781:4;10769:17;;-1:-1:-1;10832:1:12;10828:14;;;10812;10808:35;10798:46;;10795:66;;;10857:1;10854;10847:12;10872:521;10949:4;10955:6;11015:11;11002:25;11109:2;11105:7;11094:8;11078:14;11074:29;11070:43;11050:18;11046:68;11036:96;;11128:1;11125;11118:12;11036:96;11155:33;;11207:20;;;-1:-1:-1;;;;;;11239:30:12;;11236:50;;;11282:1;11279;11272:12;11236:50;11315:4;11303:17;;-1:-1:-1;11346:14:12;11342:27;;;11332:38;;11329:58;;;11383:1;11380;11373:12;11398:271;11581:6;11573;11568:3;11555:33;11537:3;11607:16;;11632:13;;;11607:16;11398:271;-1:-1:-1;11398:271:12:o;11674:543::-;11892:13;;11835:3;;11866;;11945:4;11972:15;;;11835:3;12015:175;12029:6;12026:1;12023:13;12015:175;;;12092:13;;12078:28;;12128:14;;;;12165:15;;;;12051:1;12044:9;12015:175;;;-1:-1:-1;12206:5:12;;11674:543;-1:-1:-1;;;;;;11674:543:12:o;12772:551::-;12943:3;12974;13021:6;12943:3;13055:241;13069:6;13066:1;13063:13;13055:241;;;-1:-1:-1;;;;;13136:26:12;13155:6;13136:26;:::i;:::-;13132:52;13118:67;;13208:4;13234:14;;;;13271:15;;;;;13091:1;13084:9;13055:241;;;-1:-1:-1;13312:5:12;;12772:551;-1:-1:-1;;;;;12772:551:12:o;14428:261::-;14607:2;14596:9;14589:21;14570:4;14627:56;14679:2;14668:9;14664:18;14656:6;14627:56;:::i;14902:266::-;14990:6;14985:3;14978:19;15042:6;15035:5;15028:4;15023:3;15019:14;15006:43;-1:-1:-1;15094:1:12;15069:16;;;15087:4;15065:27;;;15058:38;;;;15150:2;15129:15;;;-1:-1:-1;;15125:29:12;15116:39;;;15112:50;;14902:266::o;15173:2076::-;15622:3;15611:9;15604:22;15585:4;15649:62;15706:3;15695:9;15691:19;15683:6;15675;15649:62;:::i;:::-;15768:22;;;15730:2;15748:18;;;15741:50;;;;15826:22;;;15902:6;;15864:15;;15926:1;15936:208;15950:6;15947:1;15944:13;15936:208;;;-1:-1:-1;;;;;16015:26:12;16034:6;16015:26;:::i;:::-;16011:52;15999:65;;16119:15;;;;16084:12;;;;15972:1;15965:9;15936:208;;;-1:-1:-1;16180:19:12;;;16175:2;16160:18;;16153:47;16234:19;;;16271:12;;;;-1:-1:-1;16323:1:12;16319:14;;;16310:24;;16306:33;;16364:6;16390:1;16400:725;16416:6;16411:3;16408:15;16400:725;;;16487:16;;;-1:-1:-1;;16483:30:12;16469:45;;16553:22;;16630:14;16626:27;;;-1:-1:-1;;16622:41:12;16598:66;;16588:94;;16678:1;16675;16668:12;16588:94;16708:31;;16813:14;;;;16766:19;-1:-1:-1;;;;;16843:30:12;;16840:50;;;16886:1;16883;16876:12;16840:50;16939:6;16923:14;16919:27;16910:7;16906:41;16903:61;;;16960:1;16957;16950:12;16903:61;16987:50;17030:6;17022;17013:7;16987:50;:::i;:::-;17101:14;;;;16977:60;-1:-1:-1;;;17062:17:12;;;;16442:1;16433:11;16400:725;;;16404:3;;17173:9;17165:6;17161:22;17156:2;17145:9;17141:18;17134:50;17201:42;17236:6;17228;17201:42;:::i;:::-;17193:50;15173:2076;-1:-1:-1;;;;;;;;;;;;;15173:2076:12:o

Swarm Source

ipfs://d594684cddf3261cd3a8d49bc981d492299a30b7d35d1bd5669ccd0bcc4c29dd
Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]

A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.