ETH Price: $1,961.08 (-2.56%)
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

More Info

Private Name Tags

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Withdraw245005442026-02-20 20:46:119 days ago1771620371IN
0xc5132725...5D7fb2808
0 ETH0.000002130.05939842
Batch Mint244861672026-02-18 20:39:2311 days ago1771447163IN
0xc5132725...5D7fb2808
0.05 ETH0.000144431.17484699
Batch Mint244860912026-02-18 20:23:5911 days ago1771446239IN
0xc5132725...5D7fb2808
0.01 ETH0.000005720.12195487
Batch Mint244860262026-02-18 20:10:5911 days ago1771445459IN
0xc5132725...5D7fb2808
0.015 ETH0.000014470.25651542
Batch Mint244860262026-02-18 20:10:5911 days ago1771445459IN
0xc5132725...5D7fb2808
0.015 ETH0.000014490.25661542
Batch Mint244860242026-02-18 20:10:3511 days ago1771445435IN
0xc5132725...5D7fb2808
0.05 ETH0.000033370.27124453
Mint244860242026-02-18 20:10:3511 days ago1771445435IN
0xc5132725...5D7fb2808
0.005 ETH0.000021850.27124453
Mint244860172026-02-18 20:09:1111 days ago1771445351IN
0xc5132725...5D7fb2808
0.005 ETH0.000018460.2909318
Batch Mint244860172026-02-18 20:09:1111 days ago1771445351IN
0xc5132725...5D7fb2808
0.01 ETH0.000025250.2909318
Batch Mint244860172026-02-18 20:09:1111 days ago1771445351IN
0xc5132725...5D7fb2808
0.01 ETH0.000025250.2909318
Batch Mint244860172026-02-18 20:09:1111 days ago1771445351IN
0xc5132725...5D7fb2808
0.01 ETH0.000025250.2909318
Batch Mint244860172026-02-18 20:09:1111 days ago1771445351IN
0xc5132725...5D7fb2808
0.02 ETH0.000027810.2909318
Batch Mint244860172026-02-18 20:09:1111 days ago1771445351IN
0xc5132725...5D7fb2808
0.05 ETH0.000035810.2909318
Batch Mint244860102026-02-18 20:07:4711 days ago1771445267IN
0xc5132725...5D7fb2808
0.01 ETH0.000027380.31547624
Batch Mint244860102026-02-18 20:07:4711 days ago1771445267IN
0xc5132725...5D7fb2808
0.01 ETH0.000027390.31547624
Batch Mint244860102026-02-18 20:07:4711 days ago1771445267IN
0xc5132725...5D7fb2808
0.01 ETH0.000027390.31547624
Batch Mint244860102026-02-18 20:07:4711 days ago1771445267IN
0xc5132725...5D7fb2808
0.02 ETH0.000030180.31547624
Batch Mint244860102026-02-18 20:07:4711 days ago1771445267IN
0xc5132725...5D7fb2808
0.01 ETH0.000028330.32637756
Mint244860072026-02-18 20:07:1111 days ago1771445231IN
0xc5132725...5D7fb2808
0.005 ETH0.000027320.3392
Mint244860072026-02-18 20:07:1111 days ago1771445231IN
0xc5132725...5D7fb2808
0.005 ETH0.000188422.33778431
Mint244860072026-02-18 20:07:1111 days ago1771445231IN
0xc5132725...5D7fb2808
0.005 ETH0.000027320.3392
Mint244860072026-02-18 20:07:1111 days ago1771445231IN
0xc5132725...5D7fb2808
0.005 ETH0.000057650.71538431
Mint244860072026-02-18 20:07:1111 days ago1771445231IN
0xc5132725...5D7fb2808
0.005 ETH0.000027320.3392
Mint244860072026-02-18 20:07:1111 days ago1771445231IN
0xc5132725...5D7fb2808
0.005 ETH0.000027330.3392
Mint244860072026-02-18 20:07:1111 days ago1771445231IN
0xc5132725...5D7fb2808
0.005 ETH0.000027330.3392
View all transactions

Latest 3 internal transactions

Advanced mode:
Parent Transaction Hash Method Block
From
To
Transfer245005442026-02-20 20:46:119 days ago1771620371
0xc5132725...5D7fb2808
49.995 ETH
Batch Mint244859832026-02-18 20:02:2311 days ago1771444943
0xc5132725...5D7fb2808
0.05 ETH
Transfer244843532026-02-18 14:35:2311 days ago1771425323
0xc5132725...5D7fb2808
0.005 ETH
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Validator Index Block Amount
View All Withdrawals

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

Contract Source Code Verified (Exact Match)

Contract Name:
NormiesMinterV2

Compiler Version
v0.8.33+commit.64118f21

Optimization Enabled:
Yes with 10000 runs

Other Settings:
prague EvmVersion
// SPDX-License-Identifier: MIT
pragma solidity 0.8.33;

import { INormies } from "./interfaces/INormies.sol";
import { INormiesStorage } from "./interfaces/INormiesStorage.sol";
import { IDelegateRegistry } from "./interfaces/IDelegateRegistry.sol";
import { IDelegateRegistryV1 } from "./interfaces/IDelegateRegistryV1.sol";
import { SignatureCheckerLib } from "solady/utils/SignatureCheckerLib.sol";
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import { Lifebuoy } from "solady/utils/Lifebuoy.sol";

/**
 * @title NormiesMinterV2
 * @author Normies by Serc (https://x.com/serc1n)
 * @author Smart Contract by Yigit Duman (https://x.com/yigitduman)
 * @dev Added Delegate.xyz v1 support
 */
contract NormiesMinterV2 is Ownable, Lifebuoy {
    IDelegateRegistry public constant DELEGATE_REGISTRY_V2 =
        IDelegateRegistry(0x00000000000000447e69651d841bD8D104Bed493);
    IDelegateRegistryV1 public constant DELEGATE_REGISTRY_V1 =
        IDelegateRegistryV1(0x00000000000076A84feF008CDAbe6409d2FE638B);

    INormies public normies;
    INormiesStorage public normiesStorage;
    address public signer;
    address public withdrawAddress;
    uint256 public mintPrice;
    uint256 public nextTokenId;
    bool public paused;

    /// @notice Number of tokens minted per wallet address
    mapping(address => uint256) public mintCount;

    error InvalidSignature();
    error InsufficientPayment();
    error MintLimitReached();
    error NotMinterOrDelegate();
    error WithdrawFailed();
    error ArrayLengthMismatch();
    error SignatureExpired();
    error MintingPaused();

    event Mint(address indexed minter, uint256 indexed tokenId, bytes imageData, bytes8 traits);

    constructor(
        INormies _normies,
        INormiesStorage _normiesStorage,
        address _signer,
        uint256 _mintPrice,
        address _withdrawAddress
    ) Ownable() Lifebuoy() {
        normies = _normies;
        normiesStorage = _normiesStorage;
        signer = _signer;
        mintPrice = _mintPrice;
        withdrawAddress = _withdrawAddress;
    }

    /**
     * @notice Mints a token with server-signed data. Supports delegate.xyz v2 and v1 for cold wallet delegation.
     * @param minter The allowlisted wallet that receives the NFT (cold wallet if delegated)
     * @param imageData The encrypted raw image data of the token (200 bytes)
     * @param traits Encrypted packed bytes8 trait indices
     * @param maxMints Maximum number of mints allowed for this wallet (phase-specific, signed by server)
     * @param deadline Unix timestamp after which the signature is no longer valid
     * @param signature Server signature over (imageData, traits, minter, maxMints, deadline)
     */
    function mint(
        address minter,
        bytes calldata imageData,
        bytes8 traits,
        uint8 maxMints,
        uint256 deadline,
        bytes calldata signature
    ) external payable {
        require(!paused, MintingPaused());
        require(block.timestamp <= deadline, SignatureExpired());
        require(msg.value >= mintPrice, InsufficientPayment());
        require(mintCount[minter] < maxMints, MintLimitReached());

        // Verify caller is minter or a delegate.xyz v2/v1 delegate
        if (msg.sender != minter) {
            require(
                DELEGATE_REGISTRY_V2.checkDelegateForAll(msg.sender, minter, "")
                    || DELEGATE_REGISTRY_V2.checkDelegateForContract(msg.sender, minter, address(normies), "")
                    || DELEGATE_REGISTRY_V1.checkDelegateForAll(msg.sender, minter)
                    || DELEGATE_REGISTRY_V1.checkDelegateForContract(msg.sender, minter, address(normies)),
                NotMinterOrDelegate()
            );
        }

        // Verify server signature over (imageData ++ traits ++ minter ++ maxMints ++ deadline)
        // Uses EIP-191 prefix so backend can sign with standard signMessage
        bytes32 messageHash = keccak256(abi.encodePacked(imageData, traits, minter, maxMints, deadline));
        bytes32 ethSignedHash = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", messageHash));
        require(SignatureCheckerLib.isValidSignatureNow(signer, ethSignedHash, signature), InvalidSignature());

        // Track mints
        mintCount[minter]++;

        // Mint the token
        uint256 tokenId = nextTokenId++;
        normies.mint(minter, tokenId);

        // Set the token data
        normiesStorage.setTokenRawImageData(tokenId, imageData);
        normiesStorage.setTokenTraits(tokenId, traits);

        emit Mint(minter, tokenId, imageData, traits);
    }

    /**
     * @notice Mints multiple tokens in a single transaction with a single server-signed message.
     * @param minter The whitelisted wallet that receives the NFTs (cold wallet if delegated)
     * @param imageDataArray Array of encrypted raw image data (200 bytes each)
     * @param traitsArray Array of encrypted packed bytes8 trait indices
     * @param maxMints Maximum number of mints allowed for this wallet (phase-specific, signed by server)
     * @param deadline Unix timestamp after which the signature is no longer valid
     * @param signature Server signature over abi.encode(imageDataArray, traitsArray, minter, maxMints, deadline)
     */
    function batchMint(
        address minter,
        bytes[] calldata imageDataArray,
        bytes8[] calldata traitsArray,
        uint8 maxMints,
        uint256 deadline,
        bytes calldata signature
    ) external payable {
        require(!paused, MintingPaused());
        require(block.timestamp <= deadline, SignatureExpired());
        uint256 count = imageDataArray.length;
        require(count == traitsArray.length, ArrayLengthMismatch());
        require(msg.value >= mintPrice * count, InsufficientPayment());
        require(mintCount[minter] + count <= maxMints, MintLimitReached());

        // Verify caller is minter or a delegate.xyz v2/v1 delegate (once for the batch)
        if (msg.sender != minter) {
            require(
                DELEGATE_REGISTRY_V2.checkDelegateForAll(msg.sender, minter, "")
                    || DELEGATE_REGISTRY_V2.checkDelegateForContract(msg.sender, minter, address(normies), "")
                    || DELEGATE_REGISTRY_V1.checkDelegateForAll(msg.sender, minter)
                    || DELEGATE_REGISTRY_V1.checkDelegateForContract(msg.sender, minter, address(normies)),
                NotMinterOrDelegate()
            );
        }

        // Verify single server signature over all batch data
        bytes32 messageHash = keccak256(abi.encode(imageDataArray, traitsArray, minter, maxMints, deadline));
        bytes32 ethSignedHash = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", messageHash));
        require(SignatureCheckerLib.isValidSignatureNow(signer, ethSignedHash, signature), InvalidSignature());

        for (uint256 i; i < count; ++i) {
            mintCount[minter]++;

            uint256 tokenId = nextTokenId++;
            normies.mint(minter, tokenId);

            normiesStorage.setTokenRawImageData(tokenId, imageDataArray[i]);
            normiesStorage.setTokenTraits(tokenId, traitsArray[i]);

            emit Mint(minter, tokenId, imageDataArray[i], traitsArray[i]);
        }
    }

    function withdraw() external onlyOwner {
        (bool success,) = withdrawAddress.call{ value: address(this).balance }("");
        require(success, WithdrawFailed());
    }

    function setWithdrawAddress(address _withdrawAddress) external onlyOwner {
        withdrawAddress = _withdrawAddress;
    }

    function setPaused(bool _paused) external onlyOwner {
        paused = _paused;
    }

    function setMintPrice(uint256 _mintPrice) external onlyOwner {
        mintPrice = _mintPrice;
    }

    function setSigner(address _signer) external onlyOwner {
        signer = _signer;
    }

    function setNormies(address _normies) external onlyOwner {
        normies = INormies(_normies);
    }

    function setNormiesStorage(address _normiesStorage) external onlyOwner {
        normiesStorage = INormiesStorage(_normiesStorage);
    }
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.33;

interface INormies {
    function mint(address to, uint256 tokenId) external;
    function totalSupply() external view returns (uint256);
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.33;

interface INormiesStorage {
    function getTokenRawImageData(uint256 tokenId) external view returns (bytes memory);
    function getTokenTraits(uint256 tokenId) external view returns (bytes8);
    function setTokenRawImageData(uint256 tokenId, bytes calldata imageData) external;
    function setTokenTraits(uint256 tokenId, bytes8 traits) external;
    function isTokenDataSet(uint256 tokenId) external view returns (bool);
    function isRevealed() external view returns (bool);
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.33;

/// @notice Minimal interface for delegate.xyz v2 registry
/// @dev Full registry at 0x00000000000000447e69651d841bD8D104Bed493
interface IDelegateRegistry {
    function checkDelegateForAll(address to, address from, bytes32 rights) external view returns (bool);
    function checkDelegateForContract(
        address to,
        address from,
        address contract_,
        bytes32 rights
    ) external view returns (bool);
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.33;

/// @notice Minimal interface for delegate.xyz v1 registry
/// @dev Full registry at 0x00000000000076A84feF008CDAbe6409d2FE638B
interface IDelegateRegistryV1 {
    function checkDelegateForAll(address delegate, address vault) external view returns (bool);
    function checkDelegateForContract(
        address delegate,
        address vault,
        address contract_
    ) external view returns (bool);
}

// 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.
/// - As of Solady version 0.0.134, all `bytes signature` variants accept both
///   regular 65-byte `(r, s, v)` and EIP-2098 `(r, vs)` short form signatures.
///   See: https://eips.ethereum.org/EIPS/eip-2098
///   This is for calldata efficiency on smart accounts prevalent on L2s.
///
/// WARNING! Do NOT use signatures as unique identifiers:
/// - Use a nonce in the digest to prevent replay attacks on the same contract.
/// - Use EIP-712 for the digest to prevent replay attacks across different chains and contracts.
///   EIP-712 also enables readable signing of typed data for better user safety.
/// 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.code.length == 0`, then validate with `ecrecover`, else
    /// it will validate with ERC1271 on `signer`.
    function isValidSignatureNow(address signer, bytes32 hash, bytes memory signature)
        internal
        view
        returns (bool isValid)
    {
        if (signer == address(0)) return isValid;
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            for {} 1 {} {
                if iszero(extcodesize(signer)) {
                    switch mload(signature)
                    case 64 {
                        let vs := mload(add(signature, 0x40))
                        mstore(0x20, add(shr(255, vs), 27)) // `v`.
                        mstore(0x60, shr(1, shl(1, vs))) // `s`.
                    }
                    case 65 {
                        mstore(0x20, byte(0, mload(add(signature, 0x60)))) // `v`.
                        mstore(0x60, mload(add(signature, 0x40))) // `s`.
                    }
                    default { break }
                    mstore(0x00, hash)
                    mstore(0x40, mload(add(signature, 0x20))) // `r`.
                    let recovered := mload(staticcall(gas(), 1, 0x00, 0x80, 0x01, 0x20))
                    isValid := gt(returndatasize(), shl(96, xor(signer, recovered)))
                    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.
                // Copy the `signature` over.
                let n := add(0x20, mload(signature))
                let copied := staticcall(gas(), 4, signature, n, add(m, 0x44), n)
                isValid := staticcall(gas(), signer, m, add(returndatasize(), 0x44), d, 0x20)
                isValid := and(eq(mload(d), f), and(isValid, copied))
                break
            }
        }
    }

    /// @dev Returns whether `signature` is valid for `signer` and `hash`.
    /// If `signer.code.length == 0`, then validate with `ecrecover`, else
    /// it will validate with ERC1271 on `signer`.
    function isValidSignatureNowCalldata(address signer, bytes32 hash, bytes calldata signature)
        internal
        view
        returns (bool isValid)
    {
        if (signer == address(0)) return isValid;
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            for {} 1 {} {
                if iszero(extcodesize(signer)) {
                    switch signature.length
                    case 64 {
                        let vs := calldataload(add(signature.offset, 0x20))
                        mstore(0x20, add(shr(255, vs), 27)) // `v`.
                        mstore(0x40, calldataload(signature.offset)) // `r`.
                        mstore(0x60, shr(1, shl(1, vs))) // `s`.
                    }
                    case 65 {
                        mstore(0x20, byte(0, calldataload(add(signature.offset, 0x40)))) // `v`.
                        calldatacopy(0x40, signature.offset, 0x40) // `r`, `s`.
                    }
                    default { break }
                    mstore(0x00, hash)
                    let recovered := mload(staticcall(gas(), 1, 0x00, 0x80, 0x01, 0x20))
                    isValid := gt(returndatasize(), shl(96, xor(signer, recovered)))
                    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), signature.length)
                // Copy the `signature` over.
                calldatacopy(add(m, 0x64), signature.offset, signature.length)
                isValid := staticcall(gas(), signer, m, add(signature.length, 0x64), d, 0x20)
                isValid := and(eq(mload(d), f), isValid)
                break
            }
        }
    }

    /// @dev Returns whether the signature (`r`, `vs`) is valid for `signer` and `hash`.
    /// If `signer.code.length == 0`, then validate with `ecrecover`, else
    /// it will validate with ERC1271 on `signer`.
    function isValidSignatureNow(address signer, bytes32 hash, bytes32 r, bytes32 vs)
        internal
        view
        returns (bool isValid)
    {
        if (signer == address(0)) return isValid;
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            for {} 1 {} {
                if iszero(extcodesize(signer)) {
                    mstore(0x00, hash)
                    mstore(0x20, add(shr(255, vs), 27)) // `v`.
                    mstore(0x40, r) // `r`.
                    mstore(0x60, shr(1, shl(1, vs))) // `s`.
                    let recovered := mload(staticcall(gas(), 1, 0x00, 0x80, 0x01, 0x20))
                    isValid := gt(returndatasize(), shl(96, xor(signer, recovered)))
                    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), shr(1, shl(1, vs))) // `s`.
                mstore8(add(m, 0xa4), add(shr(255, vs), 27)) // `v`.
                isValid := staticcall(gas(), signer, m, 0xa5, d, 0x20)
                isValid := and(eq(mload(d), f), isValid)
                break
            }
        }
    }

    /// @dev Returns whether the signature (`v`, `r`, `s`) is valid for `signer` and `hash`.
    /// If `signer.code.length == 0`, then validate with `ecrecover`, else
    /// it will validate with ERC1271 on `signer`.
    function isValidSignatureNow(address signer, bytes32 hash, uint8 v, bytes32 r, bytes32 s)
        internal
        view
        returns (bool isValid)
    {
        if (signer == address(0)) return isValid;
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            for {} 1 {} {
                if iszero(extcodesize(signer)) {
                    mstore(0x00, hash)
                    mstore(0x20, and(v, 0xff)) // `v`.
                    mstore(0x40, r) // `r`.
                    mstore(0x60, s) // `s`.
                    let recovered := mload(staticcall(gas(), 1, 0x00, 0x80, 0x01, 0x20))
                    isValid := gt(returndatasize(), shl(96, xor(signer, recovered)))
                    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`.
                isValid := staticcall(gas(), signer, m, 0xa5, d, 0x20)
                isValid := and(eq(mload(d), f), isValid)
                break
            }
        }
    }

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

    // Note: These ERC1271 operations do NOT have an ECDSA fallback.

    /// @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))
            let copied := staticcall(gas(), 4, signature, n, add(m, 0x44), n)
            isValid := staticcall(gas(), signer, m, add(returndatasize(), 0x44), d, 0x20)
            isValid := and(eq(mload(d), f), and(isValid, copied))
        }
    }

    /// @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)
            isValid := staticcall(gas(), signer, m, add(signature.length, 0x64), d, 0x20)
            isValid := and(eq(mload(d), f), isValid)
        }
    }

    /// @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`.
            isValid := staticcall(gas(), signer, m, 0xa5, d, 0x20)
            isValid := and(eq(mload(d), f), isValid)
        }
    }

    /// @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`.
            isValid := staticcall(gas(), signer, m, 0xa5, d, 0x20)
            isValid := and(eq(mload(d), f), isValid)
        }
    }

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

    // Note: These ERC6492 operations now include an ECDSA fallback at the very end.
    // The calldata variants are excluded for brevity.

    /// @dev Returns whether `signature` is valid for `hash`.
    /// If the signature is postfixed with the ERC6492 magic number, it will attempt to
    /// deploy / prepare the `signer` smart account before doing a regular ERC1271 check.
    /// Note: This function is NOT reentrancy safe.
    /// The verifier must be deployed.
    /// Otherwise, the function will return false if `signer` is not yet deployed / prepared.
    /// See: https://gist.github.com/Vectorized/011d6becff6e0a73e42fe100f8d7ef04
    /// With a dedicated verifier, this function is safe to use in contracts
    /// that have been granted special permissions.
    function isValidERC6492SignatureNowAllowSideEffects(
        address signer,
        bytes32 hash,
        bytes memory signature
    ) internal returns (bool isValid) {
        /// @solidity memory-safe-assembly
        assembly {
            function callIsValidSignature(signer_, hash_, signature_) -> _isValid {
                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.
                let n_ := add(0x20, mload(signature_))
                let copied_ := staticcall(gas(), 4, signature_, n_, add(m_, 0x44), n_)
                _isValid := staticcall(gas(), signer_, m_, add(returndatasize(), 0x44), d_, 0x20)
                _isValid := and(eq(mload(d_), f_), and(_isValid, copied_))
            }
            let noCode := iszero(extcodesize(signer))
            let n := mload(signature)
            for {} 1 {} {
                if iszero(eq(mload(add(signature, n)), mul(0x6492, div(not(isValid), 0xffff)))) {
                    if iszero(noCode) { isValid := callIsValidSignature(signer, hash, signature) }
                    break
                }
                if iszero(noCode) {
                    let o := add(signature, 0x20) // Signature bytes.
                    isValid := callIsValidSignature(signer, hash, add(o, mload(add(o, 0x40))))
                    if isValid { break }
                }
                let m := mload(0x40)
                mstore(m, signer)
                mstore(add(m, 0x20), hash)
                pop(
                    call(
                        gas(), // Remaining gas.
                        0x0000bc370E4DC924F427d84e2f4B9Ec81626ba7E, // Non-reverting verifier.
                        0, // Send zero ETH.
                        m, // Start of memory.
                        add(returndatasize(), 0x40), // Length of calldata in memory.
                        staticcall(gas(), 4, add(signature, 0x20), n, add(m, 0x40), n), // 1.
                        0x00 // Length of returndata to write.
                    )
                )
                isValid := returndatasize()
                break
            }
            // Do `ecrecover` fallback if `noCode && !isValid`.
            for {} gt(noCode, isValid) {} {
                switch n
                case 64 {
                    let vs := mload(add(signature, 0x40))
                    mstore(0x20, add(shr(255, vs), 27)) // `v`.
                    mstore(0x60, shr(1, shl(1, vs))) // `s`.
                }
                case 65 {
                    mstore(0x20, byte(0, mload(add(signature, 0x60)))) // `v`.
                    mstore(0x60, mload(add(signature, 0x40))) // `s`.
                }
                default { break }
                let m := mload(0x40)
                mstore(0x00, hash)
                mstore(0x40, mload(add(signature, 0x20))) // `r`.
                let recovered := mload(staticcall(gas(), 1, 0x00, 0x80, 0x01, 0x20))
                isValid := gt(returndatasize(), shl(96, xor(signer, recovered)))
                mstore(0x60, 0) // Restore the zero slot.
                mstore(0x40, m) // Restore the free memory pointer.
                break
            }
        }
    }

    /// @dev Returns whether `signature` is valid for `hash`.
    /// If the signature is postfixed with the ERC6492 magic number, it will attempt
    /// to use a reverting verifier to deploy / prepare the `signer` smart account
    /// and do a `isValidSignature` check via the reverting verifier.
    /// Note: This function is reentrancy safe.
    /// The reverting verifier must be deployed.
    /// Otherwise, the function will return false if `signer` is not yet deployed / prepared.
    /// See: https://gist.github.com/Vectorized/846a474c855eee9e441506676800a9ad
    function isValidERC6492SignatureNow(address signer, bytes32 hash, bytes memory signature)
        internal
        returns (bool isValid)
    {
        /// @solidity memory-safe-assembly
        assembly {
            function callIsValidSignature(signer_, hash_, signature_) -> _isValid {
                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.
                let n_ := add(0x20, mload(signature_))
                let copied_ := staticcall(gas(), 4, signature_, n_, add(m_, 0x44), n_)
                _isValid := staticcall(gas(), signer_, m_, add(returndatasize(), 0x44), d_, 0x20)
                _isValid := and(eq(mload(d_), f_), and(_isValid, copied_))
            }
            let noCode := iszero(extcodesize(signer))
            let n := mload(signature)
            for {} 1 {} {
                if iszero(eq(mload(add(signature, n)), mul(0x6492, div(not(isValid), 0xffff)))) {
                    if iszero(noCode) { isValid := callIsValidSignature(signer, hash, signature) }
                    break
                }
                if iszero(noCode) {
                    let o := add(signature, 0x20) // Signature bytes.
                    isValid := callIsValidSignature(signer, hash, add(o, mload(add(o, 0x40))))
                    if isValid { break }
                }
                let m := mload(0x40)
                mstore(m, signer)
                mstore(add(m, 0x20), hash)
                let willBeZeroIfRevertingVerifierExists :=
                    call(
                        gas(), // Remaining gas.
                        0x00007bd799e4A591FeA53f8A8a3E9f931626Ba7e, // Reverting verifier.
                        0, // Send zero ETH.
                        m, // Start of memory.
                        add(returndatasize(), 0x40), // Length of calldata in memory.
                        staticcall(gas(), 4, add(signature, 0x20), n, add(m, 0x40), n), // 1.
                        0x00 // Length of returndata to write.
                    )
                isValid := gt(returndatasize(), willBeZeroIfRevertingVerifierExists)
                break
            }
            // Do `ecrecover` fallback if `noCode && !isValid`.
            for {} gt(noCode, isValid) {} {
                switch n
                case 64 {
                    let vs := mload(add(signature, 0x40))
                    mstore(0x20, add(shr(255, vs), 27)) // `v`.
                    mstore(0x60, shr(1, shl(1, vs))) // `s`.
                }
                case 65 {
                    mstore(0x20, byte(0, mload(add(signature, 0x60)))) // `v`.
                    mstore(0x60, mload(add(signature, 0x40))) // `s`.
                }
                default { break }
                let m := mload(0x40)
                mstore(0x00, hash)
                mstore(0x40, mload(add(signature, 0x20))) // `r`.
                let recovered := mload(staticcall(gas(), 1, 0x00, 0x80, 0x01, 0x20))
                isValid := gt(returndatasize(), shl(96, xor(signer, recovered)))
                mstore(0x60, 0) // Restore the zero slot.
                mstore(0x40, m) // Restore the free memory pointer.
                break
            }
        }
    }

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

    /// @dev Returns an Ethereum Signed Message, created from a `hash`.
    /// This produces a hash corresponding to the one signed with the
    /// [`eth_sign`](https://eth.wiki/json-rpc/API#eth_sign)
    /// JSON-RPC method as part of EIP-191.
    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x20, hash) // Store into scratch space for keccak256.
            mstore(0x00, "\x00\x00\x00\x00\x19Ethereum Signed Message:\n32") // 28 bytes.
            result := keccak256(0x04, 0x3c) // `32 * 2 - (32 - 28) = 60 = 0x3c`.
        }
    }

    /// @dev Returns an Ethereum Signed Message, created from `s`.
    /// This produces a hash corresponding to the one signed with the
    /// [`eth_sign`](https://eth.wiki/json-rpc/API#eth_sign)
    /// JSON-RPC method as part of EIP-191.
    /// Note: Supports lengths of `s` up to 999999 bytes.
    function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            let sLength := mload(s)
            let o := 0x20
            mstore(o, "\x19Ethereum Signed Message:\n") // 26 bytes, zero-right-padded.
            mstore(0x00, 0x00)
            // Convert the `s.length` to ASCII decimal representation: `base10(s.length)`.
            for { let temp := sLength } 1 {} {
                o := sub(o, 1)
                mstore8(o, add(48, mod(temp, 10)))
                temp := div(temp, 10)
                if iszero(temp) { break }
            }
            let n := sub(0x3a, o) // Header length: `26 + 32 - o`.
            // Throw an out-of-offset error (consumes all gas) if the header exceeds 32 bytes.
            returndatacopy(returndatasize(), returndatasize(), gt(n, 0x20))
            mstore(s, or(mload(0x00), mload(n))) // Temporarily store the header.
            result := keccak256(add(s, sub(0x20, n)), add(n, sLength))
            mstore(s, sLength) // Restore the length.
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                   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
// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)

pragma solidity ^0.8.0;

import "../utils/Context.sol";

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is Context {
    address private _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

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

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

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

    /**
     * @dev Throws if the sender is not the owner.
     */
    function _checkOwner() internal view virtual {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby disabling any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

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

/// @notice Class that allows for rescue of ETH, ERC20, ERC721 tokens.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/Lifebuoy.sol)
///
/// @dev This contract is created to mitigate the following disasters:
/// - Careless user sends tokens to the wrong chain or wrong contract.
/// - Careless dev deploys a contract without a withdraw function in attempt to rescue
///   careless user's tokens, due to deployment nonce mismatch caused by
///   script misfire / misconfiguration.
/// - Careless dev forgets to add a withdraw function to a NFT sale contract.
///
/// Note: if you are deploying via a untrusted `tx.origin`,
/// you MUST override `_lifebuoyDefaultDeployer` to return a trusted address.
///
/// For best safety:
/// - For non-escrow contracts, inherit Lifebuoy as much as possible,
///   and leave it unlocked.
/// - For escrow contracts, lock access as tight as possible,
///   as soon as possible. Or simply don't inherit Lifebuoy.
/// Escrow: Your contract is designed to hold ETH, ERC20s, ERC721s
/// (e.g. liquidity pools).
///
/// All rescue and rescue authorization functions require either:
/// - Caller is the deployer
///   AND the contract is not a proxy
///   AND `rescueLocked() & _LIFEBUOY_DEPLOYER_ACCESS_LOCK == 0`.
/// - Caller is `owner()`
///   AND `rescueLocked() & _LIFEBUOY_OWNER_ACCESS_LOCK == 0`.
///
/// The choice of using bit flags to represent locked statuses is for
/// efficiency, flexibility, convenience.
///
/// This contract is optimized with a priority on minimal bytecode size,
/// as the methods are not intended to be called often.
contract Lifebuoy {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                       CUSTOM ERRORS                        */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The caller is not authorized to rescue or lock the rescue function.
    error RescueUnauthorizedOrLocked();

    /// @dev The rescue operation has failed due to a failed transfer.
    error RescueTransferFailed();

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

    // These flags are kept internal to avoid bloating up the function dispatch.
    // You can just copy paste this into your own code.

    /// @dev Flag to denote that the deployer's access is locked. (1)
    uint256 internal constant _LIFEBUOY_DEPLOYER_ACCESS_LOCK = 1 << 0;

    /// @dev Flag to denote that the `owner()`'s access is locked. (2)
    uint256 internal constant _LIFEBUOY_OWNER_ACCESS_LOCK = 1 << 1;

    /// @dev Flag to denote that the `lockRescue` function is locked. (4)
    uint256 internal constant _LIFEBUOY_LOCK_RESCUE_LOCK = 1 << 2;

    /// @dev Flag to denote that the `rescueETH` function is locked. (8)
    uint256 internal constant _LIFEBUOY_RESCUE_ETH_LOCK = 1 << 3;

    /// @dev Flag to denote that the `rescueERC20` function is locked. (16)
    uint256 internal constant _LIFEBUOY_RESCUE_ERC20_LOCK = 1 << 4;

    /// @dev Flag to denote that the `rescueERC721` function is locked. (32)
    uint256 internal constant _LIFEBUOY_RESCUE_ERC721_LOCK = 1 << 5;

    /// @dev Flag to denote that the `rescueERC1155` function is locked. (64)
    uint256 internal constant _LIFEBUOY_RESCUE_ERC1155_LOCK = 1 << 6;

    /// @dev Flag to denote that the `rescueERC6909` function is locked. (128)
    uint256 internal constant _LIFEBUOY_RESCUE_ERC6909_LOCK = 1 << 7;

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

    /// @dev For checking that the caller is the deployer and
    /// that the context is not a delegatecall
    /// (so that the implementation deployer cannot drain proxies).
    bytes32 internal immutable _lifebuoyDeployerHash;

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

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

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

    constructor() payable {
        bytes32 hash;
        uint256 deployer = uint160(_lifebuoyDefaultDeployer());
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, address())
            mstore(0x20, deployer)
            hash := keccak256(0x00, 0x40)
        }
        _lifebuoyDeployerHash = hash;
    }

    /// @dev Returns `tx.origin` by default. Override to return another address if needed.
    ///
    /// Note: If you are deploying via a untrusted `tx.origin` (e.g. ERC4337 bundler)
    /// you MUST override this function to return a trusted address.
    function _lifebuoyDefaultDeployer() internal view virtual returns (address) {
        // I know about EIP7645, and I will stop it if it gets traction.
        // Worse case, I will add an `ecrecover` method. But not today.
        return tx.origin;
    }

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

    /// @dev Sends `amount` (in wei) ETH from the current contract to `to`.
    /// Reverts upon failure.
    function rescueETH(address to, uint256 amount)
        public
        payable
        virtual
        onlyRescuer(_LIFEBUOY_RESCUE_ETH_LOCK)
    {
        /// @solidity memory-safe-assembly
        assembly {
            if iszero(call(gas(), to, amount, codesize(), 0x00, codesize(), 0x00)) {
                mstore(0x00, 0x7ec62e76) // `RescueTransferFailed()`.
                revert(0x1c, 0x04)
            }
        }
    }

    /// @dev Sends `amount` of ERC20 `token` from the current contract to `to`.
    /// Does not check for existence of token or return data. Reverts upon failure.
    function rescueERC20(address token, address to, uint256 amount)
        public
        payable
        virtual
        onlyRescuer(_LIFEBUOY_RESCUE_ERC20_LOCK)
    {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x14, to) // Store the `to` argument.
            mstore(0x34, amount) // Store the `amount` argument.
            // `RescueTransferFailed()` and `transfer(address,uint256)`.
            mstore(0x00, shl(96, 0x7ec62e76a9059cbb))
            if iszero(call(gas(), token, callvalue(), 0x10, 0x44, codesize(), 0x00)) {
                revert(0x0c, 0x04)
            }
            mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten.
        }
    }

    /// @dev Sends `id` of ERC721 `token` from the current contract to `to`.
    /// Does not check for existence of token or return data. Reverts upon failure.
    function rescueERC721(address token, address to, uint256 id)
        public
        payable
        virtual
        onlyRescuer(_LIFEBUOY_RESCUE_ERC721_LOCK)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40) // Cache the free memory pointer.
            mstore(0x60, id) // Store the `id` argument.
            mstore(0x40, shr(96, shl(96, to))) // Store the `to` argument.
            mstore(0x20, address()) // Store the `from` argument.
            // `RescueTransferFailed()` and `transferFrom(address,address,uint256)`.
            mstore(0x00, 0x7ec62e7623b872dd)
            if iszero(call(gas(), token, callvalue(), 0x1c, 0x64, codesize(), 0x00)) {
                revert(0x18, 0x04)
            }
            mstore(0x60, 0) // Restore the zero slot to zero.
            mstore(0x40, m) // Restore the free memory pointer.
        }
    }

    /// @dev Sends `amount` of `id` of ERC1155 `token` from the current contract to `to`.
    /// Does not check for existence of token or return data. Reverts upon failure.
    function rescueERC1155(
        address token,
        address to,
        uint256 id,
        uint256 amount,
        bytes calldata data
    ) public payable virtual onlyRescuer(_LIFEBUOY_RESCUE_ERC1155_LOCK) {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40) // Cache the free memory pointer.
            // `RescueTransferFailed()` and `safeTransferFrom(address,address,uint256,uint256,bytes)`.
            mstore(m, 0x7ec62e76f242432a)
            mstore(add(0x20, m), address()) // Store the `from` argument.
            mstore(add(0x40, m), shr(96, shl(96, to))) // Store the `to` argument.
            mstore(add(0x60, m), id) // Store the `id` argument.
            mstore(add(0x80, m), amount) // Store the `amount` argument.
            mstore(add(0xa0, m), 0xa0) // Store the offset to `data`.
            mstore(add(0xc0, m), data.length)
            calldatacopy(add(m, 0xe0), data.offset, data.length)
            // forgefmt: disable-next-item
            if iszero(
                call(gas(), token, callvalue(), add(m, 0x1c), add(0xc4, data.length), codesize(), 0x00)
            ) { revert(add(m, 0x18), 0x04) }
        }
    }

    /// @dev Sends `amount` of `id` of ERC6909 `token` from the current contract to `to`.
    /// Does not check for existence of token or return data. Reverts upon failure.
    function rescueERC6909(address token, address to, uint256 id, uint256 amount)
        public
        payable
        virtual
        onlyRescuer(_LIFEBUOY_RESCUE_ERC6909_LOCK)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40) // Cache the free memory pointer.
            mstore(0x14, to) // Store the `to` argument.
            mstore(0x34, id) // Store the `id` argument.
            mstore(0x54, amount) // Store the `amount` argument.
            // `RescueTransferFailed()` and `transfer(address,uint256,uint256)`.
            mstore(0x00, shl(96, 0x7ec62e76095bcdb6))
            if iszero(call(gas(), token, callvalue(), 0x10, 0x64, codesize(), 0x00)) {
                revert(0x0c, 0x04)
            }
            mstore(0x60, 0) // Restore the zero slot to zero.
            mstore(0x40, m) // Restore the free memory pointer.
        }
    }

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

    /// @dev Returns the flags denoting whether access to rescue functions
    /// (including `lockRescue`) is locked.
    function rescueLocked() public view virtual returns (uint256 locks) {
        /// @solidity memory-safe-assembly
        assembly {
            locks := sload(_RESCUE_LOCKED_FLAGS_SLOT)
        }
    }

    /// @dev Locks (i.e. permanently removes) access to rescue functions (including `lockRescue`).
    function lockRescue(uint256 locksToSet)
        public
        payable
        virtual
        onlyRescuer(_LIFEBUOY_LOCK_RESCUE_LOCK)
    {
        _lockRescue(locksToSet);
    }

    /// @dev Internal function to set the lock flags without going through access control.
    function _lockRescue(uint256 locksToSet) internal virtual {
        /// @solidity memory-safe-assembly
        assembly {
            let s := _RESCUE_LOCKED_FLAGS_SLOT
            sstore(s, or(sload(s), locksToSet))
        }
    }

    /// @dev Requires that the rescue function being guarded is:
    /// 1. Not locked, AND
    /// 2. Called by either:
    ///   (a) The `owner()`, OR
    ///   (b) The deployer (if not via a delegate call and deployer is an EOA).
    function _checkRescuer(uint256 modeLock) internal view virtual {
        uint256 locks = rescueLocked();
        bytes32 h = _lifebuoyDeployerHash;
        /// @solidity memory-safe-assembly
        assembly {
            for {} 1 {} {
                // If the `modeLock` flag is true, set all bits in `locks` to true.
                locks := or(sub(0, iszero(iszero(and(modeLock, locks)))), locks)
                // Caller is the deployer
                // AND the contract is not a proxy
                // AND `locks & _LIFEBUOY_DEPLOYER_ACCESS_LOCK` is false.
                mstore(0x20, caller())
                mstore(and(locks, _LIFEBUOY_DEPLOYER_ACCESS_LOCK), address())
                if eq(keccak256(0x00, 0x40), h) { break }
                // If the caller is `owner()`
                // AND `locks & _LIFEBUOY_OWNER_ACCESS_LOCK` is false.
                mstore(0x08, 0x8da5cb5b0a0362e0) // `owner()` and `RescueUnauthorizedOrLocked()`.
                if and( // The arguments of `and` are evaluated from right to left.
                    lt(
                        and(locks, _LIFEBUOY_OWNER_ACCESS_LOCK),
                        and(gt(returndatasize(), 0x1f), eq(mload(0x00), caller()))
                    ),
                    staticcall(gas(), address(), 0x20, 0x04, 0x00, 0x20)
                ) { break }
                revert(0x24, 0x04)
            }
        }
    }

    /// @dev Modifier that calls `_checkRescuer()` at the start of the function.
    modifier onlyRescuer(uint256 modeLock) virtual {
        _checkRescuer(modeLock);
        _;
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)

pragma solidity ^0.8.0;

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
}

Settings
{
  "remappings": [
    "@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/",
    "@openzeppelin/contracts-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/",
    "forge-std/=node_modules/forge-std/",
    "@manifoldxyz/creator-core-solidity/=node_modules/@manifoldxyz/creator-core-solidity/",
    "solady/=node_modules/solady/src/",
    "@ensdomains/=node_modules/@ensdomains/",
    "@limitbreak/=node_modules/@limitbreak/",
    "erc721a/=node_modules/erc721a/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 10000
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "none",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "prague",
  "viaIR": false
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"contract INormies","name":"_normies","type":"address"},{"internalType":"contract INormiesStorage","name":"_normiesStorage","type":"address"},{"internalType":"address","name":"_signer","type":"address"},{"internalType":"uint256","name":"_mintPrice","type":"uint256"},{"internalType":"address","name":"_withdrawAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ArrayLengthMismatch","type":"error"},{"inputs":[],"name":"InsufficientPayment","type":"error"},{"inputs":[],"name":"InvalidSignature","type":"error"},{"inputs":[],"name":"MintLimitReached","type":"error"},{"inputs":[],"name":"MintingPaused","type":"error"},{"inputs":[],"name":"NotMinterOrDelegate","type":"error"},{"inputs":[],"name":"RescueTransferFailed","type":"error"},{"inputs":[],"name":"RescueUnauthorizedOrLocked","type":"error"},{"inputs":[],"name":"SignatureExpired","type":"error"},{"inputs":[],"name":"WithdrawFailed","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"minter","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"imageData","type":"bytes"},{"indexed":false,"internalType":"bytes8","name":"traits","type":"bytes8"}],"name":"Mint","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[],"name":"DELEGATE_REGISTRY_V1","outputs":[{"internalType":"contract IDelegateRegistryV1","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DELEGATE_REGISTRY_V2","outputs":[{"internalType":"contract IDelegateRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"minter","type":"address"},{"internalType":"bytes[]","name":"imageDataArray","type":"bytes[]"},{"internalType":"bytes8[]","name":"traitsArray","type":"bytes8[]"},{"internalType":"uint8","name":"maxMints","type":"uint8"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"batchMint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"locksToSet","type":"uint256"}],"name":"lockRescue","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"minter","type":"address"},{"internalType":"bytes","name":"imageData","type":"bytes"},{"internalType":"bytes8","name":"traits","type":"bytes8"},{"internalType":"uint8","name":"maxMints","type":"uint8"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"mint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"mintCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mintPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nextTokenId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"normies","outputs":[{"internalType":"contract INormies","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"normiesStorage","outputs":[{"internalType":"contract INormiesStorage","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"rescueERC1155","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"rescueERC20","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"rescueERC6909","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"rescueERC721","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"rescueETH","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"rescueLocked","outputs":[{"internalType":"uint256","name":"locks","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_mintPrice","type":"uint256"}],"name":"setMintPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_normies","type":"address"}],"name":"setNormies","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_normiesStorage","type":"address"}],"name":"setNormiesStorage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_paused","type":"bool"}],"name":"setPaused","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_signer","type":"address"}],"name":"setSigner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_withdrawAddress","type":"address"}],"name":"setWithdrawAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"signer","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]

60a060405234801561000f575f5ffd5b5060405161265c38038061265c83398101604081905261002e91610103565b6100373361009d565b305f9081523260205260409020608052600180546001600160a01b039687166001600160a01b031991821617909155600280549587169582169590951790945560038054938616938516939093179092556005556004805491909316911617905561016a565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b0381168114610100575f5ffd5b50565b5f5f5f5f5f60a08688031215610117575f5ffd5b8551610122816100ec565b6020870151909550610133816100ec565b6040870151909450610144816100ec565b60608701516080880151919450925061015c816100ec565b809150509295509295909350565b6080516124da6101825f395f611a7d01526124da5ff3fe6080604052600436106101ba575f3560e01c8063715018a6116100f25780639573e1c611610092578063dffc5ed311610062578063dffc5ed3146104d0578063ed9ec888146104ef578063f2fde38b1461051a578063f4a0a52814610539575f5ffd5b80639573e1c61461046a5780639865eb941461048b578063b2118a8d1461049e578063c5ff9155146104b1575f5ffd5b80637f1f0c67116100cd5780637f1f0c67146104085780638191ad911461041b5780638da5cb5b1461042e5780639311ca8914610457575f5ffd5b8063715018a6146103cc57806375794a3c146103e05780637df325e1146103f5575f5ffd5b806335facc851161015d5780634839053c116101385780634839053c146103435780635c975abb1461036f5780636817c76c146103985780636c19e783146103ad575f5ffd5b806335facc85146102e45780633ab1a494146103105780633ccfd60b1461032f575f5ffd5b806316c38b3c1161019857806316c38b3c1461023c5780631ede96201461025b578063238ac9331461027b5780633571ae8f146102a7575f5ffd5b8063099a04e5146101be5780631135c5d2146101d35780631581b600146101e6575b5f5ffd5b6101d16101cc366004611d0b565b610558565b005b6101d16101e1366004611d78565b610581565b3480156101f1575f5ffd5b506004546102129073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b348015610247575f5ffd5b506101d1610256366004611df8565b6105f0565b348015610266575f5ffd5b506102126c447e69651d841bd8d104bed49381565b348015610286575f5ffd5b506003546102129073ffffffffffffffffffffffffffffffffffffffff1681565b3480156102b2575f5ffd5b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffb8e2915b545b604051908152602001610233565b3480156102ef575f5ffd5b506001546102129073ffffffffffffffffffffffffffffffffffffffff1681565b34801561031b575f5ffd5b506101d161032a366004611e13565b610629565b34801561033a575f5ffd5b506101d1610678565b34801561034e575f5ffd5b506002546102129073ffffffffffffffffffffffffffffffffffffffff1681565b34801561037a575f5ffd5b506007546103889060ff1681565b6040519015158152602001610233565b3480156103a3575f5ffd5b506102d660055481565b3480156103b8575f5ffd5b506101d16103c7366004611e13565b61071a565b3480156103d7575f5ffd5b506101d1610769565b3480156103eb575f5ffd5b506102d660065481565b6101d1610403366004611e2c565b61077c565b6101d1610416366004611e66565b6107c8565b6101d1610429366004611ebc565b6107fe565b348015610439575f5ffd5b505f5473ffffffffffffffffffffffffffffffffffffffff16610212565b6101d1610465366004611f66565b610fac565b348015610475575f5ffd5b506102126d76a84fef008cdabe6409d2fe638b81565b6101d1610499366004611fe6565b610ff6565b6101d16104ac366004611e2c565b6118ad565b3480156104bc575f5ffd5b506101d16104cb366004611e13565b6118ec565b3480156104db575f5ffd5b506101d16104ea366004611e13565b61193b565b3480156104fa575f5ffd5b506102d6610509366004611e13565b60086020525f908152604090205481565b348015610525575f5ffd5b506101d1610534366004611e13565b61198a565b348015610544575f5ffd5b506101d1610553366004611e66565b611a43565b600861056381611a50565b5f385f3885875af161057c57637ec62e765f526004601cfd5b505050565b604061058c81611a50565b604051677ec62e76f242432a81523081602001528660601b60601c816040015285816060015284816080015260a08160a00152828160c00152828460e08301375f388460c401601c8401348c5af16105e657600460188201fd5b5050505050505050565b6105f8611aeb565b600780547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610631611aeb565b600480547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b610680611aeb565b6004546040515f9173ffffffffffffffffffffffffffffffffffffffff169047908381818185875af1925050503d805f81146106d7576040519150601f19603f3d011682016040523d82523d5f602084013e6106dc565b606091505b5050905080610717576040517f750b219c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50565b610722611aeb565b600380547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b610771611aeb565b61077a5f611b6b565b565b602061078781611a50565b604051826060528360601b60601c60405230602052677ec62e7623b872dd5f525f386064601c34895af16107bb5760046018fd5b5f60605260405250505050565b60046107d381611a50565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffb8e2915b8054831790555050565b60075460ff161561083b576040517feb56075600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82421115610875576040517f0819bdcd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6005543410156108b1576040517fcd1c886700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff88165f9081526008602052604090205460ff851611610911576040517f303b682f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff891614610c18576040517fe839bd5300000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff891660248201525f60448201526c447e69651d841bd8d104bed4939063e839bd5390606401602060405180830381865afa1580156109af573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109d391906120b1565b80610a8a57506001546040517f8988eea900000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff808b16602483015290911660448201525f60648201526c447e69651d841bd8d104bed49390638988eea990608401602060405180830381865afa158015610a66573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a8a91906120b1565b80610b3057506040517f9c395bc200000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff891660248201526d76a84fef008cdabe6409d2fe638b90639c395bc290604401602060405180830381865afa158015610b0c573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b3091906120b1565b80610be257506001546040517f90c9a2d000000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff808b16602483015290911660448201526d76a84fef008cdabe6409d2fe638b906390c9a2d090606401602060405180830381865afa158015610bbe573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610be291906120b1565b610c18576040517f0e1db23000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8787878b8888604051602001610c34969594939291906120cc565b6040516020818303038152906040528051906020012090505f81604051602001610c8a91907f19457468657265756d205369676e6564204d6573736167653a0a3332000000008152601c810191909152603c0190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120600354601f88018390048302850183019093528684529350610d169273ffffffffffffffffffffffffffffffffffffffff90921691849188908890819084018382808284375f92019190915250611bdf92505050565b610d4c576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8a165f908152600860205260408120805491610d7c83612190565b9091555050600680545f9182610d9183612190565b909155506001546040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8e81166004830152602482018490529293509116906340c10f19906044015f604051808303815f87803b158015610e08575f5ffd5b505af1158015610e1a573d5f5f3e3d5ffd5b50506002546040517fdb1d29ab00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909116925063db1d29ab9150610e789084908e908e9060040161220e565b5f604051808303815f87803b158015610e8f575f5ffd5b505af1158015610ea1573d5f5f3e3d5ffd5b50506002546040517fe2fc13e0000000000000000000000000000000000000000000000000000000008152600481018590527fffffffffffffffff0000000000000000000000000000000000000000000000008c16602482015273ffffffffffffffffffffffffffffffffffffffff909116925063e2fc13e091506044015f604051808303815f87803b158015610f36575f5ffd5b505af1158015610f48573d5f5f3e3d5ffd5b50505050808b73ffffffffffffffffffffffffffffffffffffffff167f45982c0325b1855b2321d28e3e38f9c4caaa2cdc247e038e3213fb7144f0a3808c8c8c604051610f9793929190612230565b60405180910390a35050505050505050505050565b6080610fb781611a50565b604051846014528360345282605452677ec62e76095bcdb660601b5f525f3860646010348a5af1610fe8576004600cfd5b5f6060526040525050505050565b60075460ff1615611033576040517feb56075600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8242111561106d576040517f0819bdcd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b868581146110a7576040517fa24a13a600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806005546110b59190612275565b3410156110ee576040517fcd1c886700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8a165f9081526008602052604090205460ff861690611123908390612292565b111561115b576040517f303b682f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff8b1614611462576040517fe839bd5300000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff8b1660248201525f60448201526c447e69651d841bd8d104bed4939063e839bd5390606401602060405180830381865afa1580156111f9573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061121d91906120b1565b806112d457506001546040517f8988eea900000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff808d16602483015290911660448201525f60648201526c447e69651d841bd8d104bed49390638988eea990608401602060405180830381865afa1580156112b0573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112d491906120b1565b8061137a57506040517f9c395bc200000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff8b1660248201526d76a84fef008cdabe6409d2fe638b90639c395bc290604401602060405180830381865afa158015611356573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061137a91906120b1565b8061142c57506001546040517f90c9a2d000000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff808d16602483015290911660448201526d76a84fef008cdabe6409d2fe638b906390c9a2d090606401602060405180830381865afa158015611408573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061142c91906120b1565b611462576040517f0e1db23000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f898989898e8a8a6040516020016114809796959493929190612304565b6040516020818303038152906040528051906020012090505f816040516020016114d691907f19457468657265756d205369676e6564204d6573736167653a0a3332000000008152601c810191909152603c0190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120600354601f890183900483028501830190935287845293506115629273ffffffffffffffffffffffffffffffffffffffff90921691849189908990819084018382808284375f92019190915250611bdf92505050565b611598576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f5b8381101561189e5773ffffffffffffffffffffffffffffffffffffffff8d165f9081526008602052604081208054916115d283612190565b9091555050600680545f91826115e783612190565b91905055905060015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166340c10f198f836040518363ffffffff1660e01b815260040161166a92919073ffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b5f604051808303815f87803b158015611681575f5ffd5b505af1158015611693573d5f5f3e3d5ffd5b505060025473ffffffffffffffffffffffffffffffffffffffff16915063db1d29ab9050828f8f868181106116ca576116ca612426565b90506020028101906116dc9190612453565b6040518463ffffffff1660e01b81526004016116fa9392919061220e565b5f604051808303815f87803b158015611711575f5ffd5b505af1158015611723573d5f5f3e3d5ffd5b505060025473ffffffffffffffffffffffffffffffffffffffff16915063e2fc13e09050828d8d8681811061175a5761175a612426565b905060200201602081019061176f91906124b4565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815260048101929092527fffffffffffffffff0000000000000000000000000000000000000000000000001660248201526044015f604051808303815f87803b1580156117e4575f5ffd5b505af11580156117f6573d5f5f3e3d5ffd5b50505050808e73ffffffffffffffffffffffffffffffffffffffff167f45982c0325b1855b2321d28e3e38f9c4caaa2cdc247e038e3213fb7144f0a3808f8f8681811061184557611845612426565b90506020028101906118579190612453565b8f8f8881811061186957611869612426565b905060200201602081019061187e91906124b4565b60405161188d93929190612230565b60405180910390a35060010161159a565b50505050505050505050505050565b60106118b881611a50565b8260145281603452677ec62e76a9059cbb60601b5f525f386044601034885af16118e2576004600cfd5b5f60345250505050565b6118f4611aeb565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b611943611aeb565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b611992611aeb565b73ffffffffffffffffffffffffffffffffffffffff8116611a3a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b61071781611b6b565b611a4b611aeb565b600555565b5f611a797fffffffffffffffffffffffffffffffffffffffffffffffffffffffffb8e2915b5490565b90507f00000000000000000000000000000000000000000000000000000000000000008182841615155f03179150336020523060018316528060405f20031561057c57678da5cb5b0a0362e060085260205f60046020305afa335f5114601f3d111660028416101661057c5760046024fd5b5f5473ffffffffffffffffffffffffffffffffffffffff16331461077a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401611a31565b5f805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b5f73ffffffffffffffffffffffffffffffffffffffff841615611cdc57604051843b611c9a57825160408114611c1d5760418114611c575750611cda565b604084015160ff81901c601b016020527f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff16606052611c6a565b60608401515f1a60205260408401516060525b50835f5260208301516040526020600160805f60015afa5180861860601b3d119250505f60605280604052611cda565b631626ba7e60e01b808252846004830152602482016040815284516020018060448501828860045afa905060208260443d01868b5afa9151911691141691505b505b9392505050565b803573ffffffffffffffffffffffffffffffffffffffff81168114611d06575f5ffd5b919050565b5f5f60408385031215611d1c575f5ffd5b611d2583611ce3565b946020939093013593505050565b5f5f83601f840112611d43575f5ffd5b50813567ffffffffffffffff811115611d5a575f5ffd5b602083019150836020828501011115611d71575f5ffd5b9250929050565b5f5f5f5f5f5f60a08789031215611d8d575f5ffd5b611d9687611ce3565b9550611da460208801611ce3565b94506040870135935060608701359250608087013567ffffffffffffffff811115611dcd575f5ffd5b611dd989828a01611d33565b979a9699509497509295939492505050565b8015158114610717575f5ffd5b5f60208284031215611e08575f5ffd5b8135611cdc81611deb565b5f60208284031215611e23575f5ffd5b611cdc82611ce3565b5f5f5f60608486031215611e3e575f5ffd5b611e4784611ce3565b9250611e5560208501611ce3565b929592945050506040919091013590565b5f60208284031215611e76575f5ffd5b5035919050565b80357fffffffffffffffff00000000000000000000000000000000000000000000000081168114611d06575f5ffd5b803560ff81168114611d06575f5ffd5b5f5f5f5f5f5f5f5f60c0898b031215611ed3575f5ffd5b611edc89611ce3565b9750602089013567ffffffffffffffff811115611ef7575f5ffd5b611f038b828c01611d33565b9098509650611f16905060408a01611e7d565b9450611f2460608a01611eac565b93506080890135925060a089013567ffffffffffffffff811115611f46575f5ffd5b611f528b828c01611d33565b999c989b5096995094979396929594505050565b5f5f5f5f60808587031215611f79575f5ffd5b611f8285611ce3565b9350611f9060208601611ce3565b93969395505050506040820135916060013590565b5f5f83601f840112611fb5575f5ffd5b50813567ffffffffffffffff811115611fcc575f5ffd5b6020830191508360208260051b8501011115611d71575f5ffd5b5f5f5f5f5f5f5f5f5f60c08a8c031215611ffe575f5ffd5b6120078a611ce3565b985060208a013567ffffffffffffffff811115612022575f5ffd5b61202e8c828d01611fa5565b90995097505060408a013567ffffffffffffffff81111561204d575f5ffd5b6120598c828d01611fa5565b909750955061206c905060608b01611eac565b935060808a0135925060a08a013567ffffffffffffffff81111561208e575f5ffd5b61209a8c828d01611d33565b915080935050809150509295985092959850929598565b5f602082840312156120c1575f5ffd5b8151611cdc81611deb565b858782377fffffffffffffffff000000000000000000000000000000000000000000000000949094169390940192835260609190911b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016600883015260f81b7fff0000000000000000000000000000000000000000000000000000000000000016601c820152601d810191909152603d01919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036121c0576121c0612163565b5060010190565b81835281816020850137505f602082840101525f60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b838152604060208201525f6122276040830184866121c7565b95945050505050565b604081525f6122436040830185876121c7565b90507fffffffffffffffff00000000000000000000000000000000000000000000000083166020830152949350505050565b808202811582820484141761228c5761228c612163565b92915050565b8082018082111561228c5761228c612163565b8183526020830192505f815f5b848110156122fa577fffffffffffffffff0000000000000000000000000000000000000000000000006122e483611e7d565b16865260209586019591909101906001016122b2565b5093949350505050565b60a080825281018790525f60c0600589901b830181019083018a837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe136839003015b8c8210156123d2577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff408786030184528235818112612382575f5ffd5b8e0160208101903567ffffffffffffffff81111561239e575f5ffd5b8036038213156123ac575f5ffd5b6123b78782846121c7565b96505050602083019250602084019350600182019150612346565b5050505082810360208401526123e981888a6122a5565b91505061240e604083018673ffffffffffffffffffffffffffffffffffffffff169052565b60ff9390931660608201526080015295945050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f5f83357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112612486575f5ffd5b83018035915067ffffffffffffffff8211156124a0575f5ffd5b602001915036819003821315611d71575f5ffd5b5f602082840312156124c4575f5ffd5b611cdc82611e7d56fea164736f6c6343000821000a0000000000000000000000009eb6e2025b64f340691e424b7fe7022ffde124380000000000000000000000001b976baf51cf51f0e369c070d47fbc47a706e602000000000000000000000000d7ed3c08666c429f9a442f8ed15549c63847c5a50000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000007a85ac4db0042241451f6184d91d6736070a5fce

Deployed Bytecode

0x6080604052600436106101ba575f3560e01c8063715018a6116100f25780639573e1c611610092578063dffc5ed311610062578063dffc5ed3146104d0578063ed9ec888146104ef578063f2fde38b1461051a578063f4a0a52814610539575f5ffd5b80639573e1c61461046a5780639865eb941461048b578063b2118a8d1461049e578063c5ff9155146104b1575f5ffd5b80637f1f0c67116100cd5780637f1f0c67146104085780638191ad911461041b5780638da5cb5b1461042e5780639311ca8914610457575f5ffd5b8063715018a6146103cc57806375794a3c146103e05780637df325e1146103f5575f5ffd5b806335facc851161015d5780634839053c116101385780634839053c146103435780635c975abb1461036f5780636817c76c146103985780636c19e783146103ad575f5ffd5b806335facc85146102e45780633ab1a494146103105780633ccfd60b1461032f575f5ffd5b806316c38b3c1161019857806316c38b3c1461023c5780631ede96201461025b578063238ac9331461027b5780633571ae8f146102a7575f5ffd5b8063099a04e5146101be5780631135c5d2146101d35780631581b600146101e6575b5f5ffd5b6101d16101cc366004611d0b565b610558565b005b6101d16101e1366004611d78565b610581565b3480156101f1575f5ffd5b506004546102129073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b348015610247575f5ffd5b506101d1610256366004611df8565b6105f0565b348015610266575f5ffd5b506102126c447e69651d841bd8d104bed49381565b348015610286575f5ffd5b506003546102129073ffffffffffffffffffffffffffffffffffffffff1681565b3480156102b2575f5ffd5b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffb8e2915b545b604051908152602001610233565b3480156102ef575f5ffd5b506001546102129073ffffffffffffffffffffffffffffffffffffffff1681565b34801561031b575f5ffd5b506101d161032a366004611e13565b610629565b34801561033a575f5ffd5b506101d1610678565b34801561034e575f5ffd5b506002546102129073ffffffffffffffffffffffffffffffffffffffff1681565b34801561037a575f5ffd5b506007546103889060ff1681565b6040519015158152602001610233565b3480156103a3575f5ffd5b506102d660055481565b3480156103b8575f5ffd5b506101d16103c7366004611e13565b61071a565b3480156103d7575f5ffd5b506101d1610769565b3480156103eb575f5ffd5b506102d660065481565b6101d1610403366004611e2c565b61077c565b6101d1610416366004611e66565b6107c8565b6101d1610429366004611ebc565b6107fe565b348015610439575f5ffd5b505f5473ffffffffffffffffffffffffffffffffffffffff16610212565b6101d1610465366004611f66565b610fac565b348015610475575f5ffd5b506102126d76a84fef008cdabe6409d2fe638b81565b6101d1610499366004611fe6565b610ff6565b6101d16104ac366004611e2c565b6118ad565b3480156104bc575f5ffd5b506101d16104cb366004611e13565b6118ec565b3480156104db575f5ffd5b506101d16104ea366004611e13565b61193b565b3480156104fa575f5ffd5b506102d6610509366004611e13565b60086020525f908152604090205481565b348015610525575f5ffd5b506101d1610534366004611e13565b61198a565b348015610544575f5ffd5b506101d1610553366004611e66565b611a43565b600861056381611a50565b5f385f3885875af161057c57637ec62e765f526004601cfd5b505050565b604061058c81611a50565b604051677ec62e76f242432a81523081602001528660601b60601c816040015285816060015284816080015260a08160a00152828160c00152828460e08301375f388460c401601c8401348c5af16105e657600460188201fd5b5050505050505050565b6105f8611aeb565b600780547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610631611aeb565b600480547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b610680611aeb565b6004546040515f9173ffffffffffffffffffffffffffffffffffffffff169047908381818185875af1925050503d805f81146106d7576040519150601f19603f3d011682016040523d82523d5f602084013e6106dc565b606091505b5050905080610717576040517f750b219c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50565b610722611aeb565b600380547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b610771611aeb565b61077a5f611b6b565b565b602061078781611a50565b604051826060528360601b60601c60405230602052677ec62e7623b872dd5f525f386064601c34895af16107bb5760046018fd5b5f60605260405250505050565b60046107d381611a50565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffb8e2915b8054831790555050565b60075460ff161561083b576040517feb56075600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82421115610875576040517f0819bdcd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6005543410156108b1576040517fcd1c886700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff88165f9081526008602052604090205460ff851611610911576040517f303b682f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff891614610c18576040517fe839bd5300000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff891660248201525f60448201526c447e69651d841bd8d104bed4939063e839bd5390606401602060405180830381865afa1580156109af573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109d391906120b1565b80610a8a57506001546040517f8988eea900000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff808b16602483015290911660448201525f60648201526c447e69651d841bd8d104bed49390638988eea990608401602060405180830381865afa158015610a66573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a8a91906120b1565b80610b3057506040517f9c395bc200000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff891660248201526d76a84fef008cdabe6409d2fe638b90639c395bc290604401602060405180830381865afa158015610b0c573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b3091906120b1565b80610be257506001546040517f90c9a2d000000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff808b16602483015290911660448201526d76a84fef008cdabe6409d2fe638b906390c9a2d090606401602060405180830381865afa158015610bbe573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610be291906120b1565b610c18576040517f0e1db23000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8787878b8888604051602001610c34969594939291906120cc565b6040516020818303038152906040528051906020012090505f81604051602001610c8a91907f19457468657265756d205369676e6564204d6573736167653a0a3332000000008152601c810191909152603c0190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120600354601f88018390048302850183019093528684529350610d169273ffffffffffffffffffffffffffffffffffffffff90921691849188908890819084018382808284375f92019190915250611bdf92505050565b610d4c576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8a165f908152600860205260408120805491610d7c83612190565b9091555050600680545f9182610d9183612190565b909155506001546040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8e81166004830152602482018490529293509116906340c10f19906044015f604051808303815f87803b158015610e08575f5ffd5b505af1158015610e1a573d5f5f3e3d5ffd5b50506002546040517fdb1d29ab00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909116925063db1d29ab9150610e789084908e908e9060040161220e565b5f604051808303815f87803b158015610e8f575f5ffd5b505af1158015610ea1573d5f5f3e3d5ffd5b50506002546040517fe2fc13e0000000000000000000000000000000000000000000000000000000008152600481018590527fffffffffffffffff0000000000000000000000000000000000000000000000008c16602482015273ffffffffffffffffffffffffffffffffffffffff909116925063e2fc13e091506044015f604051808303815f87803b158015610f36575f5ffd5b505af1158015610f48573d5f5f3e3d5ffd5b50505050808b73ffffffffffffffffffffffffffffffffffffffff167f45982c0325b1855b2321d28e3e38f9c4caaa2cdc247e038e3213fb7144f0a3808c8c8c604051610f9793929190612230565b60405180910390a35050505050505050505050565b6080610fb781611a50565b604051846014528360345282605452677ec62e76095bcdb660601b5f525f3860646010348a5af1610fe8576004600cfd5b5f6060526040525050505050565b60075460ff1615611033576040517feb56075600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8242111561106d576040517f0819bdcd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b868581146110a7576040517fa24a13a600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806005546110b59190612275565b3410156110ee576040517fcd1c886700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8a165f9081526008602052604090205460ff861690611123908390612292565b111561115b576040517f303b682f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff8b1614611462576040517fe839bd5300000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff8b1660248201525f60448201526c447e69651d841bd8d104bed4939063e839bd5390606401602060405180830381865afa1580156111f9573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061121d91906120b1565b806112d457506001546040517f8988eea900000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff808d16602483015290911660448201525f60648201526c447e69651d841bd8d104bed49390638988eea990608401602060405180830381865afa1580156112b0573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112d491906120b1565b8061137a57506040517f9c395bc200000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff8b1660248201526d76a84fef008cdabe6409d2fe638b90639c395bc290604401602060405180830381865afa158015611356573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061137a91906120b1565b8061142c57506001546040517f90c9a2d000000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff808d16602483015290911660448201526d76a84fef008cdabe6409d2fe638b906390c9a2d090606401602060405180830381865afa158015611408573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061142c91906120b1565b611462576040517f0e1db23000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f898989898e8a8a6040516020016114809796959493929190612304565b6040516020818303038152906040528051906020012090505f816040516020016114d691907f19457468657265756d205369676e6564204d6573736167653a0a3332000000008152601c810191909152603c0190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120600354601f890183900483028501830190935287845293506115629273ffffffffffffffffffffffffffffffffffffffff90921691849189908990819084018382808284375f92019190915250611bdf92505050565b611598576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f5b8381101561189e5773ffffffffffffffffffffffffffffffffffffffff8d165f9081526008602052604081208054916115d283612190565b9091555050600680545f91826115e783612190565b91905055905060015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166340c10f198f836040518363ffffffff1660e01b815260040161166a92919073ffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b5f604051808303815f87803b158015611681575f5ffd5b505af1158015611693573d5f5f3e3d5ffd5b505060025473ffffffffffffffffffffffffffffffffffffffff16915063db1d29ab9050828f8f868181106116ca576116ca612426565b90506020028101906116dc9190612453565b6040518463ffffffff1660e01b81526004016116fa9392919061220e565b5f604051808303815f87803b158015611711575f5ffd5b505af1158015611723573d5f5f3e3d5ffd5b505060025473ffffffffffffffffffffffffffffffffffffffff16915063e2fc13e09050828d8d8681811061175a5761175a612426565b905060200201602081019061176f91906124b4565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815260048101929092527fffffffffffffffff0000000000000000000000000000000000000000000000001660248201526044015f604051808303815f87803b1580156117e4575f5ffd5b505af11580156117f6573d5f5f3e3d5ffd5b50505050808e73ffffffffffffffffffffffffffffffffffffffff167f45982c0325b1855b2321d28e3e38f9c4caaa2cdc247e038e3213fb7144f0a3808f8f8681811061184557611845612426565b90506020028101906118579190612453565b8f8f8881811061186957611869612426565b905060200201602081019061187e91906124b4565b60405161188d93929190612230565b60405180910390a35060010161159a565b50505050505050505050505050565b60106118b881611a50565b8260145281603452677ec62e76a9059cbb60601b5f525f386044601034885af16118e2576004600cfd5b5f60345250505050565b6118f4611aeb565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b611943611aeb565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b611992611aeb565b73ffffffffffffffffffffffffffffffffffffffff8116611a3a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b61071781611b6b565b611a4b611aeb565b600555565b5f611a797fffffffffffffffffffffffffffffffffffffffffffffffffffffffffb8e2915b5490565b90507fd067ddabe98d0cdeb5eb001459828040105577dd0d99fd2bf668e130d894818f8182841615155f03179150336020523060018316528060405f20031561057c57678da5cb5b0a0362e060085260205f60046020305afa335f5114601f3d111660028416101661057c5760046024fd5b5f5473ffffffffffffffffffffffffffffffffffffffff16331461077a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401611a31565b5f805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b5f73ffffffffffffffffffffffffffffffffffffffff841615611cdc57604051843b611c9a57825160408114611c1d5760418114611c575750611cda565b604084015160ff81901c601b016020527f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff16606052611c6a565b60608401515f1a60205260408401516060525b50835f5260208301516040526020600160805f60015afa5180861860601b3d119250505f60605280604052611cda565b631626ba7e60e01b808252846004830152602482016040815284516020018060448501828860045afa905060208260443d01868b5afa9151911691141691505b505b9392505050565b803573ffffffffffffffffffffffffffffffffffffffff81168114611d06575f5ffd5b919050565b5f5f60408385031215611d1c575f5ffd5b611d2583611ce3565b946020939093013593505050565b5f5f83601f840112611d43575f5ffd5b50813567ffffffffffffffff811115611d5a575f5ffd5b602083019150836020828501011115611d71575f5ffd5b9250929050565b5f5f5f5f5f5f60a08789031215611d8d575f5ffd5b611d9687611ce3565b9550611da460208801611ce3565b94506040870135935060608701359250608087013567ffffffffffffffff811115611dcd575f5ffd5b611dd989828a01611d33565b979a9699509497509295939492505050565b8015158114610717575f5ffd5b5f60208284031215611e08575f5ffd5b8135611cdc81611deb565b5f60208284031215611e23575f5ffd5b611cdc82611ce3565b5f5f5f60608486031215611e3e575f5ffd5b611e4784611ce3565b9250611e5560208501611ce3565b929592945050506040919091013590565b5f60208284031215611e76575f5ffd5b5035919050565b80357fffffffffffffffff00000000000000000000000000000000000000000000000081168114611d06575f5ffd5b803560ff81168114611d06575f5ffd5b5f5f5f5f5f5f5f5f60c0898b031215611ed3575f5ffd5b611edc89611ce3565b9750602089013567ffffffffffffffff811115611ef7575f5ffd5b611f038b828c01611d33565b9098509650611f16905060408a01611e7d565b9450611f2460608a01611eac565b93506080890135925060a089013567ffffffffffffffff811115611f46575f5ffd5b611f528b828c01611d33565b999c989b5096995094979396929594505050565b5f5f5f5f60808587031215611f79575f5ffd5b611f8285611ce3565b9350611f9060208601611ce3565b93969395505050506040820135916060013590565b5f5f83601f840112611fb5575f5ffd5b50813567ffffffffffffffff811115611fcc575f5ffd5b6020830191508360208260051b8501011115611d71575f5ffd5b5f5f5f5f5f5f5f5f5f60c08a8c031215611ffe575f5ffd5b6120078a611ce3565b985060208a013567ffffffffffffffff811115612022575f5ffd5b61202e8c828d01611fa5565b90995097505060408a013567ffffffffffffffff81111561204d575f5ffd5b6120598c828d01611fa5565b909750955061206c905060608b01611eac565b935060808a0135925060a08a013567ffffffffffffffff81111561208e575f5ffd5b61209a8c828d01611d33565b915080935050809150509295985092959850929598565b5f602082840312156120c1575f5ffd5b8151611cdc81611deb565b858782377fffffffffffffffff000000000000000000000000000000000000000000000000949094169390940192835260609190911b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016600883015260f81b7fff0000000000000000000000000000000000000000000000000000000000000016601c820152601d810191909152603d01919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036121c0576121c0612163565b5060010190565b81835281816020850137505f602082840101525f60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b838152604060208201525f6122276040830184866121c7565b95945050505050565b604081525f6122436040830185876121c7565b90507fffffffffffffffff00000000000000000000000000000000000000000000000083166020830152949350505050565b808202811582820484141761228c5761228c612163565b92915050565b8082018082111561228c5761228c612163565b8183526020830192505f815f5b848110156122fa577fffffffffffffffff0000000000000000000000000000000000000000000000006122e483611e7d565b16865260209586019591909101906001016122b2565b5093949350505050565b60a080825281018790525f60c0600589901b830181019083018a837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe136839003015b8c8210156123d2577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff408786030184528235818112612382575f5ffd5b8e0160208101903567ffffffffffffffff81111561239e575f5ffd5b8036038213156123ac575f5ffd5b6123b78782846121c7565b96505050602083019250602084019350600182019150612346565b5050505082810360208401526123e981888a6122a5565b91505061240e604083018673ffffffffffffffffffffffffffffffffffffffff169052565b60ff9390931660608201526080015295945050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f5f83357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112612486575f5ffd5b83018035915067ffffffffffffffff8211156124a0575f5ffd5b602001915036819003821315611d71575f5ffd5b5f602082840312156124c4575f5ffd5b611cdc82611e7d56fea164736f6c6343000821000a

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

0000000000000000000000009eb6e2025b64f340691e424b7fe7022ffde124380000000000000000000000001b976baf51cf51f0e369c070d47fbc47a706e602000000000000000000000000d7ed3c08666c429f9a442f8ed15549c63847c5a50000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000007a85ac4db0042241451f6184d91d6736070a5fce

-----Decoded View---------------
Arg [0] : _normies (address): 0x9Eb6E2025B64f340691e424b7fe7022fFDE12438
Arg [1] : _normiesStorage (address): 0x1B976bAf51cF51F0e369C070d47FBc47A706e602
Arg [2] : _signer (address): 0xD7eD3c08666C429F9a442F8eD15549C63847C5a5
Arg [3] : _mintPrice (uint256): 5000000000000000
Arg [4] : _withdrawAddress (address): 0x7a85AC4dB0042241451f6184d91D6736070a5FCE

-----Encoded View---------------
5 Constructor Arguments found :
Arg [0] : 0000000000000000000000009eb6e2025b64f340691e424b7fe7022ffde12438
Arg [1] : 0000000000000000000000001b976baf51cf51f0e369c070d47fbc47a706e602
Arg [2] : 000000000000000000000000d7ed3c08666c429f9a442f8ed15549c63847c5a5
Arg [3] : 0000000000000000000000000000000000000000000000000011c37937e08000
Arg [4] : 0000000000000000000000007a85ac4db0042241451f6184d91d6736070a5fce


Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

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