ETH Price: $1,972.61 (-1.99%)
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

More Info

Private Name Tags

TokenTracker

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
0xc0b8fa825d3012513ca8f85b6b9cc41f1a83a4282459ec19992f61662ef862fb Mint(pending)2026-03-01 16:23:289 hrs ago1772382208IN
mint.fun: Fundrop Stickers
0 ETH(Pending)(Pending)
0x3ba1b677325411472393a0301adf10dd89884c85b9c43537ff3dc3df3491ac9c Mint(pending)2026-03-01 16:23:289 hrs ago1772382208IN
mint.fun: Fundrop Stickers
0 ETH(Pending)(Pending)
0x77b3dbe54469c6c1c41a5eefc42cf1b2083306b64f19bcd5ecfdcbf5fbbe16d9 Mint(pending)2026-03-01 16:23:289 hrs ago1772382208IN
mint.fun: Fundrop Stickers
0 ETH(Pending)(Pending)
0x215ef31371fc81a30f91da89b11ab7b50327f8f88e691b04827639a04a017cb5 Mint(pending)2026-03-01 16:23:289 hrs ago1772382208IN
mint.fun: Fundrop Stickers
0 ETH(Pending)(Pending)
0xdb2ec377e44c32d831a85244428cbccbbfcc97aaa1c6542dd7736f683fb47b5c Mint(pending)2026-03-01 16:23:289 hrs ago1772382208IN
mint.fun: Fundrop Stickers
0 ETH(Pending)(Pending)
0x9052abb90f7c8b047e4f5b8a3f4a1b6df5f536a41ec95b259949bc2358f07800 Mint(pending)2026-03-01 6:18:3719 hrs ago1772345917IN
mint.fun: Fundrop Stickers
0 ETH(Pending)(Pending)
0xb5890ba0dd2df4bad0af1d6bb2a8fa0556a6c7fec144b13925e3c9f1b5a621c4 Mint(pending)2026-03-01 6:18:3719 hrs ago1772345917IN
mint.fun: Fundrop Stickers
0 ETH(Pending)(Pending)
0x8066b0ba387874313b1d26fe5ec80248223f04f6c3e86e54479660791bc40af7 Mint(pending)2026-03-01 4:30:0720 hrs ago1772339407IN
mint.fun: Fundrop Stickers
0 ETH(Pending)(Pending)
0x2ccd07823f38965f52bc1b12c94ea82e40f83bc14a6f538fe8ada8b02ee4a919 Mint(pending)2026-03-01 2:51:2622 hrs ago1772333486IN
mint.fun: Fundrop Stickers
0 ETH(Pending)(Pending)
0x372c902dedaddc3290abc3537848a60c8a5ab7609fdfeff7d3c7d090661900ee Mint(pending)2026-03-01 2:33:2822 hrs ago1772332408IN
mint.fun: Fundrop Stickers
0 ETH(Pending)(Pending)
0xf999fd7de2dc96306340507bbe200256f856a678de5f2e1fd03845284d0fa1f2 Mint(pending)2026-03-01 2:10:3923 hrs ago1772331039IN
mint.fun: Fundrop Stickers
0 ETH(Pending)(Pending)
0xf45f14d2eea3f4201c81d705c3e09432a3d834c2804a15074f5ef3b3c67092ae Mint(pending)2026-03-01 2:05:2123 hrs ago1772330721IN
mint.fun: Fundrop Stickers
0 ETH(Pending)(Pending)
0x39eeb7a2b1c40c87b15cd7ab07e69bfae2c337338deb5f4a1865bf5e67b4c65e Mint(pending)2026-03-01 2:04:5923 hrs ago1772330699IN
mint.fun: Fundrop Stickers
0 ETH(Pending)(Pending)
0x980286da7ec1ad31fb33a45ae5589e131327e6eaa6430ec097c89f829ed4851e Mint(pending)2026-03-01 2:04:4123 hrs ago1772330681IN
mint.fun: Fundrop Stickers
0 ETH(Pending)(Pending)
0x5ccfc888365a34d6c9b0c9854fbe03295258d4043fa8e82ccfe9be87ac64c9a2 Mint(pending)2026-03-01 2:03:5923 hrs ago1772330639IN
mint.fun: Fundrop Stickers
0 ETH(Pending)(Pending)
0xd849b5fb6b30cce4cd770058f448a73e875a209cde8f75175da614f250f91876 Mint(pending)2026-03-01 2:02:0623 hrs ago1772330526IN
mint.fun: Fundrop Stickers
0 ETH(Pending)(Pending)
0x8769f7238c737005fdb38050aece8f9a940368b1a170c613a05a38598191c9b7 Mint(pending)2026-03-01 2:02:0623 hrs ago1772330526IN
mint.fun: Fundrop Stickers
0 ETH(Pending)(Pending)
0x54b18d08011dc60f6c5f4ff00787bd6eaf455bc395064f42c3964463a3454792 Mint(pending)2026-03-01 2:02:0623 hrs ago1772330526IN
mint.fun: Fundrop Stickers
0 ETH(Pending)(Pending)
0x441bfbe2d6d93ac6df52387294a3f7a8fe273bb927cdbde910a9741388844d94 Mint(pending)2026-03-01 1:55:1323 hrs ago1772330113IN
mint.fun: Fundrop Stickers
0 ETH(Pending)(Pending)
0x49fd68e815c38bdcbdca0f9b09fe61a8a294c187230dbf92293a60e3fcf377c5 Mint(pending)2026-03-01 1:44:4623 hrs ago1772329486IN
mint.fun: Fundrop Stickers
0 ETH(Pending)(Pending)
0x1172b14ecb27d04b03929f63b3dd8035b2c6249b45690fb04698087e54215e90 Mint(pending)2026-03-01 1:44:4323 hrs ago1772329483IN
mint.fun: Fundrop Stickers
0 ETH(Pending)(Pending)
0x06fe350385f70010245545cd3073d15085b53a59bdebdcd28c6c7f7c3f07a189 Mint(pending)2026-03-01 1:43:3923 hrs ago1772329419IN
mint.fun: Fundrop Stickers
0 ETH(Pending)(Pending)
0x51b0a7be88561460610c154de708b273c715680c3a5071642d19f4bf9bfea1ec Mint(pending)2026-03-01 1:39:0523 hrs ago1772329145IN
mint.fun: Fundrop Stickers
0 ETH(Pending)(Pending)
0xe01fd330739ab2d28d8144e3d66e92bab9e3d14a46bf896c42ae99190c5704c4 Mint(pending)2026-03-01 1:38:5123 hrs ago1772329131IN
mint.fun: Fundrop Stickers
0 ETH(Pending)(Pending)
0x2c8c70955f8818f815db3560fabd8f2164321d6264b9226f7795573fb4f95b69 Mint(pending)2026-03-01 1:38:4223 hrs ago1772329122IN
mint.fun: Fundrop Stickers
0 ETH(Pending)(Pending)
View all transactions

Latest 1 internal transaction

Advanced mode:
Parent Transaction Hash Method Block
From
To
0x60806040179329472023-08-17 7:08:11927 days ago1692256091  Contract Creation0 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:
Stickers

Compiler Version
v0.8.20+commit.a1b79de6

Optimization Enabled:
Yes with 250000 runs

Other Settings:
paris EvmVersion
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.19;

import {ECDSA} from "solady/utils/ECDSA.sol";
import {Ownable} from "solady/auth/Ownable.sol";
import {ERC1155} from "solmate/tokens/ERC1155.sol";

import {IERC165} from "openzeppelin/utils/introspection/IERC165.sol";
import {IERC1155} from "openzeppelin/token/ERC1155/IERC1155.sol";
import "fundrop/IMetadataRenderer.sol";
import "fundrop/IERC4906.sol";

contract Stickers is ERC1155, Ownable {
    address public signer;
    address public metadataRenderer;
    uint256 public mintEnd;
    mapping(bytes32 => bool) _hasMinted;

    error InvalidSignature();
    error MintClosed();
    error MintedAlready();

    constructor() {
        _initializeOwner(tx.origin);
    }

    function name() public view virtual returns (string memory) {
        return "!fundrop Stickers";
    }

    function _packRecipientAndRound(address _address, uint16 _round) internal pure returns (bytes32) {
        return (bytes32(uint256(uint160(_address))) << 96) | bytes32(uint256(_round));
    }

    function mint(uint256[] calldata tokens, uint256[] calldata amounts, uint16 round, bytes calldata signature)
        public
        payable
    {
        bytes32 packedRecipientAndRound = _packRecipientAndRound(msg.sender, round);
        if (block.timestamp > mintEnd) revert MintClosed();
        if (_hasMinted[packedRecipientAndRound]) revert MintedAlready();
        address recovered =
            ECDSA.tryRecoverCalldata(keccak256(abi.encodePacked(msg.sender, round, tokens, amounts)), signature);
        if (recovered != signer) revert InvalidSignature();
        _hasMinted[packedRecipientAndRound] = true;
        _batchMint(msg.sender, tokens, amounts, "");
    }

    function adminMint(address to, uint256[] calldata tokens, uint256[] calldata amounts) public onlyOwner {
        _batchMint(to, tokens, amounts, "");
    }

    function uri(uint256 id) public view override returns (string memory) {
        return IMetadataRenderer(metadataRenderer).tokenURI(id);
    }

    // Admin functions

    function setMetadataRenderer(address _metadataRenderer) public onlyOwner {
        metadataRenderer = _metadataRenderer;
    }

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

    function setMintEnd(uint256 _mintEnd) public onlyOwner {
        mintEnd = _mintEnd;
    }

    function supportsInterface(bytes4 interfaceId) public pure virtual override returns (bool) {
        return interfaceId == type(IERC165).interfaceId || interfaceId == type(IERC1155).interfaceId
            || interfaceId == type(IERC4906).interfaceId;
    }
}

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

/// @notice Gas optimized ECDSA wrapper.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/ECDSA.sol)
/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/ECDSA.sol)
/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/ECDSA.sol)
library ECDSA {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                        CUSTOM ERRORS                       */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The signature is invalid.
    error InvalidSignature();

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

    /// @dev The number which `s` must not exceed in order for
    /// the signature to be non-malleable.
    bytes32 private constant _MALLEABILITY_THRESHOLD =
        0x7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0;

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

    // Note: as of Solady version 0.0.68, these functions will
    // revert upon recovery failure for more safety by default.

    /// @dev Recovers the signer's address from a message digest `hash`,
    /// and the `signature`.
    ///
    /// This function does NOT accept EIP-2098 short form signatures.
    /// Use `recover(bytes32 hash, bytes32 r, bytes32 vs)` for EIP-2098
    /// short form signatures instead.
    function recover(bytes32 hash, bytes memory signature) internal view returns (address result) {
        /// @solidity memory-safe-assembly
        assembly {
            // Copy the free memory pointer so that we can restore it later.
            let m := mload(0x40)
            // Copy `r` and `s`.
            mstore(0x40, mload(add(signature, 0x20))) // `r`.
            let s := mload(add(signature, 0x40))
            mstore(0x60, s)
            // Store the `hash` in the scratch space.
            mstore(0x00, hash)
            // Compute `v` and store it in the scratch space.
            mstore(0x20, byte(0, mload(add(signature, 0x60))))
            pop(
                staticcall(
                    gas(), // Amount of gas left for the transaction.
                    and(
                        // If the signature is exactly 65 bytes in length.
                        eq(mload(signature), 65),
                        // If `s` in lower half order, such that the signature is not malleable.
                        lt(s, add(_MALLEABILITY_THRESHOLD, 1))
                    ), // Address of `ecrecover`.
                    0x00, // Start of input.
                    0x80, // Size of input.
                    0x00, // Start of output.
                    0x20 // Size of output.
                )
            )
            result := mload(0x00)
            // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
            if iszero(returndatasize()) {
                // Store the function selector of `InvalidSignature()`.
                mstore(0x00, 0x8baa579f)
                // Revert with (offset, size).
                revert(0x1c, 0x04)
            }
            // Restore the zero slot.
            mstore(0x60, 0)
            // Restore the free memory pointer.
            mstore(0x40, m)
        }
    }

    /// @dev Recovers the signer's address from a message digest `hash`,
    /// and the `signature`.
    ///
    /// This function does NOT accept EIP-2098 short form signatures.
    /// Use `recover(bytes32 hash, bytes32 r, bytes32 vs)` for EIP-2098
    /// short form signatures instead.
    function recoverCalldata(bytes32 hash, bytes calldata signature)
        internal
        view
        returns (address result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            // Copy the free memory pointer so that we can restore it later.
            let m := mload(0x40)
            // Directly copy `r` and `s` from the calldata.
            calldatacopy(0x40, signature.offset, 0x40)
            // Store the `hash` in the scratch space.
            mstore(0x00, hash)
            // Compute `v` and store it in the scratch space.
            mstore(0x20, byte(0, calldataload(add(signature.offset, 0x40))))
            pop(
                staticcall(
                    gas(), // Amount of gas left for the transaction.
                    and(
                        // If the signature is exactly 65 bytes in length.
                        eq(signature.length, 65),
                        // If `s` in lower half order, such that the signature is not malleable.
                        lt(mload(0x60), add(_MALLEABILITY_THRESHOLD, 1))
                    ), // Address of `ecrecover`.
                    0x00, // Start of input.
                    0x80, // Size of input.
                    0x00, // Start of output.
                    0x20 // Size of output.
                )
            )
            result := mload(0x00)
            // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
            if iszero(returndatasize()) {
                // Store the function selector of `InvalidSignature()`.
                mstore(0x00, 0x8baa579f)
                // Revert with (offset, size).
                revert(0x1c, 0x04)
            }
            // Restore the zero slot.
            mstore(0x60, 0)
            // Restore the free memory pointer.
            mstore(0x40, m)
        }
    }

    /// @dev Recovers the signer's address from a message digest `hash`,
    /// and the EIP-2098 short form signature defined by `r` and `vs`.
    ///
    /// This function only accepts EIP-2098 short form signatures.
    /// See: https://eips.ethereum.org/EIPS/eip-2098
    ///
    /// To be honest, I do not recommend using EIP-2098 signatures
    /// for simplicity, performance, and security reasons. Most if not
    /// all clients support traditional non EIP-2098 signatures by default.
    /// As such, this method is intentionally not fully inlined.
    /// It is merely included for completeness.
    function recover(bytes32 hash, bytes32 r, bytes32 vs) internal view returns (address result) {
        uint8 v;
        bytes32 s;
        /// @solidity memory-safe-assembly
        assembly {
            s := shr(1, shl(1, vs))
            v := add(shr(255, vs), 27)
        }
        result = recover(hash, v, r, s);
    }

    /// @dev Recovers the signer's address from a message digest `hash`,
    /// and the signature defined by `v`, `r`, `s`.
    function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s)
        internal
        view
        returns (address result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            // Copy the free memory pointer so that we can restore it later.
            let m := mload(0x40)
            mstore(0x00, hash)
            mstore(0x20, and(v, 0xff))
            mstore(0x40, r)
            mstore(0x60, s)
            pop(
                staticcall(
                    gas(), // Amount of gas left for the transaction.
                    // If `s` in lower half order, such that the signature is not malleable.
                    lt(s, add(_MALLEABILITY_THRESHOLD, 1)), // Address of `ecrecover`.
                    0x00, // Start of input.
                    0x80, // Size of input.
                    0x00, // Start of output.
                    0x20 // Size of output.
                )
            )
            result := mload(0x00)
            // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
            if iszero(returndatasize()) {
                // Store the function selector of `InvalidSignature()`.
                mstore(0x00, 0x8baa579f)
                // Revert with (offset, size).
                revert(0x1c, 0x04)
            }
            // Restore the zero slot.
            mstore(0x60, 0)
            // Restore the free memory pointer.
            mstore(0x40, m)
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                   TRY-RECOVER OPERATIONS                   */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    // WARNING!
    // These functions will NOT revert upon recovery failure.
    // Instead, they will return the zero address upon recovery failure.
    // It is critical that the returned address is NEVER compared against
    // a zero address (e.g. an uninitialized address variable).

    /// @dev Recovers the signer's address from a message digest `hash`,
    /// and the `signature`.
    ///
    /// This function does NOT accept EIP-2098 short form signatures.
    /// Use `recover(bytes32 hash, bytes32 r, bytes32 vs)` for EIP-2098
    /// short form signatures instead.
    function tryRecover(bytes32 hash, bytes memory signature)
        internal
        view
        returns (address result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            if iszero(xor(mload(signature), 65)) {
                // Copy the free memory pointer so that we can restore it later.
                let m := mload(0x40)
                // Copy `r` and `s`.
                mstore(0x40, mload(add(signature, 0x20))) // `r`.
                let s := mload(add(signature, 0x40))
                mstore(0x60, s)
                // If `s` in lower half order, such that the signature is not malleable.
                if iszero(gt(s, _MALLEABILITY_THRESHOLD)) {
                    // Store the `hash` in the scratch space.
                    mstore(0x00, hash)
                    // Compute `v` and store it in the scratch space.
                    mstore(0x20, byte(0, mload(add(signature, 0x60))))
                    pop(
                        staticcall(
                            gas(), // Amount of gas left for the transaction.
                            0x01, // Address of `ecrecover`.
                            0x00, // Start of input.
                            0x80, // Size of input.
                            0x40, // Start of output.
                            0x20 // Size of output.
                        )
                    )
                    // Restore the zero slot.
                    mstore(0x60, 0)
                    // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
                    result := mload(xor(0x60, returndatasize()))
                }
                // Restore the free memory pointer.
                mstore(0x40, m)
            }
        }
    }

    /// @dev Recovers the signer's address from a message digest `hash`,
    /// and the `signature`.
    ///
    /// This function does NOT accept EIP-2098 short form signatures.
    /// Use `recover(bytes32 hash, bytes32 r, bytes32 vs)` for EIP-2098
    /// short form signatures instead.
    function tryRecoverCalldata(bytes32 hash, bytes calldata signature)
        internal
        view
        returns (address result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            if iszero(xor(signature.length, 65)) {
                // Copy the free memory pointer so that we can restore it later.
                let m := mload(0x40)
                // Directly copy `r` and `s` from the calldata.
                calldatacopy(0x40, signature.offset, 0x40)
                // If `s` in lower half order, such that the signature is not malleable.
                if iszero(gt(mload(0x60), _MALLEABILITY_THRESHOLD)) {
                    // Store the `hash` in the scratch space.
                    mstore(0x00, hash)
                    // Compute `v` and store it in the scratch space.
                    mstore(0x20, byte(0, calldataload(add(signature.offset, 0x40))))
                    pop(
                        staticcall(
                            gas(), // Amount of gas left for the transaction.
                            0x01, // Address of `ecrecover`.
                            0x00, // Start of input.
                            0x80, // Size of input.
                            0x40, // Start of output.
                            0x20 // Size of output.
                        )
                    )
                    // Restore the zero slot.
                    mstore(0x60, 0)
                    // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
                    result := mload(xor(0x60, returndatasize()))
                }
                // Restore the free memory pointer.
                mstore(0x40, m)
            }
        }
    }

    /// @dev Recovers the signer's address from a message digest `hash`,
    /// and the EIP-2098 short form signature defined by `r` and `vs`.
    ///
    /// This function only accepts EIP-2098 short form signatures.
    /// See: https://eips.ethereum.org/EIPS/eip-2098
    ///
    /// To be honest, I do not recommend using EIP-2098 signatures
    /// for simplicity, performance, and security reasons. Most if not
    /// all clients support traditional non EIP-2098 signatures by default.
    /// As such, this method is intentionally not fully inlined.
    /// It is merely included for completeness.
    function tryRecover(bytes32 hash, bytes32 r, bytes32 vs)
        internal
        view
        returns (address result)
    {
        uint8 v;
        bytes32 s;
        /// @solidity memory-safe-assembly
        assembly {
            s := shr(1, shl(1, vs))
            v := add(shr(255, vs), 27)
        }
        result = tryRecover(hash, v, r, s);
    }

    /// @dev Recovers the signer's address from a message digest `hash`,
    /// and the signature defined by `v`, `r`, `s`.
    function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s)
        internal
        view
        returns (address result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            // Copy the free memory pointer so that we can restore it later.
            let m := mload(0x40)
            // If `s` in lower half order, such that the signature is not malleable.
            if iszero(gt(s, _MALLEABILITY_THRESHOLD)) {
                // Store the `hash`, `v`, `r`, `s` in the scratch space.
                mstore(0x00, hash)
                mstore(0x20, and(v, 0xff))
                mstore(0x40, r)
                mstore(0x60, s)
                pop(
                    staticcall(
                        gas(), // Amount of gas left for the transaction.
                        0x01, // Address of `ecrecover`.
                        0x00, // Start of input.
                        0x80, // Size of input.
                        0x40, // Start of output.
                        0x20 // Size of output.
                    )
                )
                // Restore the zero slot.
                mstore(0x60, 0)
                // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
                result := mload(xor(0x60, returndatasize()))
            }
            // Restore the free memory pointer.
            mstore(0x40, m)
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                     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 {
            // Store into scratch space for keccak256.
            mstore(0x20, hash)
            mstore(0x00, "\x00\x00\x00\x00\x19Ethereum Signed Message:\n32")
            // 0x40 - 0x04 = 0x3c
            result := keccak256(0x04, 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.
    function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32 result) {
        assembly {
            // The length of "\x19Ethereum Signed Message:\n" is 26 bytes (i.e. 0x1a).
            // If we reserve 2 words, we'll have 64 - 26 = 38 bytes to store the
            // ASCII decimal representation of the length of `s` up to about 2 ** 126.

            // Instead of allocating, we temporarily copy the 64 bytes before the
            // start of `s` data to some variables.
            let m := mload(sub(s, 0x20))
            // The length of `s` is in bytes.
            let sLength := mload(s)
            let ptr := add(s, 0x20)
            let w := not(0)
            // `end` marks the end of the memory which we will compute the keccak256 of.
            let end := add(ptr, sLength)
            // Convert the length of the bytes to ASCII decimal representation
            // and store it into the memory.
            for { let temp := sLength } 1 {} {
                ptr := add(ptr, w) // `sub(ptr, 1)`.
                mstore8(ptr, add(48, mod(temp, 10)))
                temp := div(temp, 10)
                if iszero(temp) { break }
            }
            // Copy the header over to the memory.
            mstore(sub(ptr, 0x20), "\x00\x00\x00\x00\x00\x00\x19Ethereum Signed Message:\n")
            // Compute the keccak256 of the memory.
            result := keccak256(sub(ptr, 0x1a), sub(end, sub(ptr, 0x1a)))
            // Restore the previous memory.
            mstore(s, sLength)
            mstore(sub(s, 0x20), m)
        }
    }

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

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

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

/// @notice Simple single owner authorization mixin.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/auth/Ownable.sol)
/// @dev While the ownable portion follows [EIP-173](https://eips.ethereum.org/EIPS/eip-173)
/// for compatibility, the nomenclature for the 2-step ownership handover
/// may be unique to this codebase.
abstract contract Ownable {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                       CUSTOM ERRORS                        */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

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

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

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

    /// @dev `bytes4(keccak256(bytes("Unauthorized()")))`.
    uint256 private constant _UNAUTHORIZED_ERROR_SELECTOR = 0x82b42900;

    /// @dev `bytes4(keccak256(bytes("NewOwnerIsZeroAddress()")))`.
    uint256 private constant _NEW_OWNER_IS_ZERO_ADDRESS_ERROR_SELECTOR = 0x7448fbae;

    /// @dev `bytes4(keccak256(bytes("NoHandoverRequest()")))`.
    uint256 private constant _NO_HANDOVER_REQUEST_ERROR_SELECTOR = 0x6f5e8818;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    /// @dev Returns how long a two-step ownership handover is valid for in seconds.
    function ownershipHandoverValidFor() public view virtual returns (uint64) {
        return 48 * 3600;
    }

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

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

// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

/// @notice Minimalist and gas efficient standard ERC1155 implementation.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC1155.sol)
abstract contract ERC1155 {
    /*//////////////////////////////////////////////////////////////
                                 EVENTS
    //////////////////////////////////////////////////////////////*/

    event TransferSingle(
        address indexed operator,
        address indexed from,
        address indexed to,
        uint256 id,
        uint256 amount
    );

    event TransferBatch(
        address indexed operator,
        address indexed from,
        address indexed to,
        uint256[] ids,
        uint256[] amounts
    );

    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    event URI(string value, uint256 indexed id);

    /*//////////////////////////////////////////////////////////////
                             ERC1155 STORAGE
    //////////////////////////////////////////////////////////////*/

    mapping(address => mapping(uint256 => uint256)) public balanceOf;

    mapping(address => mapping(address => bool)) public isApprovedForAll;

    /*//////////////////////////////////////////////////////////////
                             METADATA LOGIC
    //////////////////////////////////////////////////////////////*/

    function uri(uint256 id) public view virtual returns (string memory);

    /*//////////////////////////////////////////////////////////////
                              ERC1155 LOGIC
    //////////////////////////////////////////////////////////////*/

    function setApprovalForAll(address operator, bool approved) public virtual {
        isApprovedForAll[msg.sender][operator] = approved;

        emit ApprovalForAll(msg.sender, operator, approved);
    }

    function safeTransferFrom(
        address from,
        address to,
        uint256 id,
        uint256 amount,
        bytes calldata data
    ) public virtual {
        require(msg.sender == from || isApprovedForAll[from][msg.sender], "NOT_AUTHORIZED");

        balanceOf[from][id] -= amount;
        balanceOf[to][id] += amount;

        emit TransferSingle(msg.sender, from, to, id, amount);

        require(
            to.code.length == 0
                ? to != address(0)
                : ERC1155TokenReceiver(to).onERC1155Received(msg.sender, from, id, amount, data) ==
                    ERC1155TokenReceiver.onERC1155Received.selector,
            "UNSAFE_RECIPIENT"
        );
    }

    function safeBatchTransferFrom(
        address from,
        address to,
        uint256[] calldata ids,
        uint256[] calldata amounts,
        bytes calldata data
    ) public virtual {
        require(ids.length == amounts.length, "LENGTH_MISMATCH");

        require(msg.sender == from || isApprovedForAll[from][msg.sender], "NOT_AUTHORIZED");

        // Storing these outside the loop saves ~15 gas per iteration.
        uint256 id;
        uint256 amount;

        for (uint256 i = 0; i < ids.length; ) {
            id = ids[i];
            amount = amounts[i];

            balanceOf[from][id] -= amount;
            balanceOf[to][id] += amount;

            // An array can't have a total length
            // larger than the max uint256 value.
            unchecked {
                ++i;
            }
        }

        emit TransferBatch(msg.sender, from, to, ids, amounts);

        require(
            to.code.length == 0
                ? to != address(0)
                : ERC1155TokenReceiver(to).onERC1155BatchReceived(msg.sender, from, ids, amounts, data) ==
                    ERC1155TokenReceiver.onERC1155BatchReceived.selector,
            "UNSAFE_RECIPIENT"
        );
    }

    function balanceOfBatch(address[] calldata owners, uint256[] calldata ids)
        public
        view
        virtual
        returns (uint256[] memory balances)
    {
        require(owners.length == ids.length, "LENGTH_MISMATCH");

        balances = new uint256[](owners.length);

        // Unchecked because the only math done is incrementing
        // the array index counter which cannot possibly overflow.
        unchecked {
            for (uint256 i = 0; i < owners.length; ++i) {
                balances[i] = balanceOf[owners[i]][ids[i]];
            }
        }
    }

    /*//////////////////////////////////////////////////////////////
                              ERC165 LOGIC
    //////////////////////////////////////////////////////////////*/

    function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
        return
            interfaceId == 0x01ffc9a7 || // ERC165 Interface ID for ERC165
            interfaceId == 0xd9b67a26 || // ERC165 Interface ID for ERC1155
            interfaceId == 0x0e89341c; // ERC165 Interface ID for ERC1155MetadataURI
    }

    /*//////////////////////////////////////////////////////////////
                        INTERNAL MINT/BURN LOGIC
    //////////////////////////////////////////////////////////////*/

    function _mint(
        address to,
        uint256 id,
        uint256 amount,
        bytes memory data
    ) internal virtual {
        balanceOf[to][id] += amount;

        emit TransferSingle(msg.sender, address(0), to, id, amount);

        require(
            to.code.length == 0
                ? to != address(0)
                : ERC1155TokenReceiver(to).onERC1155Received(msg.sender, address(0), id, amount, data) ==
                    ERC1155TokenReceiver.onERC1155Received.selector,
            "UNSAFE_RECIPIENT"
        );
    }

    function _batchMint(
        address to,
        uint256[] memory ids,
        uint256[] memory amounts,
        bytes memory data
    ) internal virtual {
        uint256 idsLength = ids.length; // Saves MLOADs.

        require(idsLength == amounts.length, "LENGTH_MISMATCH");

        for (uint256 i = 0; i < idsLength; ) {
            balanceOf[to][ids[i]] += amounts[i];

            // An array can't have a total length
            // larger than the max uint256 value.
            unchecked {
                ++i;
            }
        }

        emit TransferBatch(msg.sender, address(0), to, ids, amounts);

        require(
            to.code.length == 0
                ? to != address(0)
                : ERC1155TokenReceiver(to).onERC1155BatchReceived(msg.sender, address(0), ids, amounts, data) ==
                    ERC1155TokenReceiver.onERC1155BatchReceived.selector,
            "UNSAFE_RECIPIENT"
        );
    }

    function _batchBurn(
        address from,
        uint256[] memory ids,
        uint256[] memory amounts
    ) internal virtual {
        uint256 idsLength = ids.length; // Saves MLOADs.

        require(idsLength == amounts.length, "LENGTH_MISMATCH");

        for (uint256 i = 0; i < idsLength; ) {
            balanceOf[from][ids[i]] -= amounts[i];

            // An array can't have a total length
            // larger than the max uint256 value.
            unchecked {
                ++i;
            }
        }

        emit TransferBatch(msg.sender, from, address(0), ids, amounts);
    }

    function _burn(
        address from,
        uint256 id,
        uint256 amount
    ) internal virtual {
        balanceOf[from][id] -= amount;

        emit TransferSingle(msg.sender, from, address(0), id, amount);
    }
}

/// @notice A generic interface for a contract which properly accepts ERC1155 tokens.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC1155.sol)
abstract contract ERC1155TokenReceiver {
    function onERC1155Received(
        address,
        address,
        uint256,
        uint256,
        bytes calldata
    ) external virtual returns (bytes4) {
        return ERC1155TokenReceiver.onERC1155Received.selector;
    }

    function onERC1155BatchReceived(
        address,
        address,
        uint256[] calldata,
        uint256[] calldata,
        bytes calldata
    ) external virtual returns (bytes4) {
        return ERC1155TokenReceiver.onERC1155BatchReceived.selector;
    }
}

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

pragma solidity ^0.8.0;

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

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC1155/IERC1155.sol)

pragma solidity ^0.8.0;

import "../../utils/introspection/IERC165.sol";

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

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

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

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

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

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

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

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

    /**
     * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.
     *
     * Emits a {TransferSingle} event.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.
     * - `from` must have a balance of tokens of type `id` of at least `amount`.
     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the
     * acceptance magic value.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 id,
        uint256 amount,
        bytes calldata data
    ) external;

    /**
     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.
     *
     * Emits a {TransferBatch} event.
     *
     * Requirements:
     *
     * - `ids` and `amounts` must have the same length.
     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the
     * acceptance magic value.
     */
    function safeBatchTransferFrom(
        address from,
        address to,
        uint256[] calldata ids,
        uint256[] calldata amounts,
        bytes calldata data
    ) external;
}

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.17;

interface IMetadataRenderer {
    function tokenURI(uint256 id) external view returns (string memory);
}

File 8 of 8 : IERC4906.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

interface IERC4906 {
    /// @dev This event emits when the metadata of a token is changed.
    /// So that the third-party platforms such as NFT market could
    /// timely update the images and related attributes of the NFT.
    event MetadataUpdate(uint256 _tokenId);

    /// @dev This event emits when the metadata of a range of tokens is changed.
    /// So that the third-party platforms such as NFT market could
    /// timely update the images and related attributes of the NFTs.
    event BatchMetadataUpdate(uint256 _fromTokenId, uint256 _toTokenId);
}

Settings
{
  "remappings": [
    "ERC721A/=lib/ERC721A/contracts/",
    "ds-test/=lib/forge-std/lib/ds-test/src/",
    "forge-std/=lib/forge-std/src/",
    "openzeppelin/=lib/openzeppelin-contracts/contracts/",
    "solmate/=lib/solmate/src/",
    "solady/=lib/solady/src/",
    "fundrop/=src/Fundrop/",
    "operator-filter-registry/=lib/operator-filter-registry/src/",
    "erc4626-tests/=lib/operator-filter-registry/lib/openzeppelin-contracts/lib/erc4626-tests/",
    "openzeppelin-contracts-upgradeable/=lib/operator-filter-registry/lib/openzeppelin-contracts-upgradeable/",
    "openzeppelin-contracts/=lib/openzeppelin-contracts/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 250000
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "ipfs",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "paris",
  "libraries": {}
}

Contract Security Audit

Contract ABI

API
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"InvalidSignature","type":"error"},{"inputs":[],"name":"MintClosed","type":"error"},{"inputs":[],"name":"MintedAlready","type":"error"},{"inputs":[],"name":"NewOwnerIsZeroAddress","type":"error"},{"inputs":[],"name":"NoHandoverRequest","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pendingOwner","type":"address"}],"name":"OwnershipHandoverCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pendingOwner","type":"address"}],"name":"OwnershipHandoverRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"name":"TransferBatch","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"TransferSingle","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"value","type":"string"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"URI","type":"event"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256[]","name":"tokens","type":"uint256[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"name":"adminMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"owners","type":"address[]"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"}],"name":"balanceOfBatch","outputs":[{"internalType":"uint256[]","name":"balances","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cancelOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"pendingOwner","type":"address"}],"name":"completeOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"metadataRenderer","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokens","type":"uint256[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"uint16","name":"round","type":"uint16"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"mint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"mintEnd","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"result","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pendingOwner","type":"address"}],"name":"ownershipHandoverExpiresAt","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ownershipHandoverValidFor","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"requestOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeBatchTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","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":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_metadataRenderer","type":"address"}],"name":"setMetadataRenderer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_mintEnd","type":"uint256"}],"name":"setMintEnd","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_signer","type":"address"}],"name":"setSigner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"signer","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"uri","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"}]

608060405234801561001057600080fd5b5061001a3261001f565b61005b565b6001600160a01b0316638b78c6d8198190558060007f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08180a350565b6121ff8061006a6000396000f3fe6080604052600436106101955760003560e01c8063715018a6116100e1578063ea2b4ab21161008a578063f242432a11610064578063f242432a146104b0578063f2fde38b146104d0578063fd4fe8a8146104e3578063fee81cf41461050357600080fd5b8063ea2b4ab214610467578063eb20614e1461047d578063f04e283e1461049d57600080fd5b8063a22cb465116100bb578063a22cb465146103ee578063d7533f021461040e578063e985e9c51461042c57600080fd5b8063715018a614610392578063812015b91461039a5780638da5cb5b146103ba57600080fd5b80632eb2c2d61161014357806354d1f13d1161011d57806354d1f13d1461033d5780636c19e78314610345578063703199701461036557600080fd5b80632eb2c2d6146102dd5780634e1273f4146102fd578063525b6ba01461032a57600080fd5b80630e89341c116101745780630e89341c14610261578063238ac9331461028157806325692962146102d357600080fd5b8062fdd58e1461019a57806301ffc9a7146101e257806306fdde0314610212575b600080fd5b3480156101a657600080fd5b506101cf6101b5366004611829565b600060208181529281526040808220909352908152205481565b6040519081526020015b60405180910390f35b3480156101ee57600080fd5b506102026101fd366004611881565b610536565b60405190151581526020016101d9565b34801561021e57600080fd5b5060408051808201909152601181527f2166756e64726f7020537469636b65727300000000000000000000000000000060208201525b6040516101d9919061190c565b34801561026d57600080fd5b5061025461027c36600461191f565b6105fa565b34801561028d57600080fd5b506002546102ae9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101d9565b6102db6106b0565b005b3480156102e957600080fd5b506102db6102f83660046119c6565b610700565b34801561030957600080fd5b5061031d610318366004611a81565b610af6565b6040516101d99190611b28565b6102db610338366004611b3b565b610c6d565b6102db610e70565b34801561035157600080fd5b506102db610360366004611bf1565b610eac565b34801561037157600080fd5b506003546102ae9073ffffffffffffffffffffffffffffffffffffffff1681565b6102db610efb565b3480156103a657600080fd5b506102db6103b5366004611c0c565b610f0f565b3480156103c657600080fd5b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffff74873927546102ae565b3480156103fa57600080fd5b506102db610409366004611c8d565b610f9a565b34801561041a57600080fd5b506040516202a30081526020016101d9565b34801561043857600080fd5b50610202610447366004611cc9565b600160209081526000928352604080842090915290825290205460ff1681565b34801561047357600080fd5b506101cf60045481565b34801561048957600080fd5b506102db61049836600461191f565b611031565b6102db6104ab366004611bf1565b61103e565b3480156104bc57600080fd5b506102db6104cb366004611cfc565b61107e565b6102db6104de366004611bf1565b611384565b3480156104ef57600080fd5b506102db6104fe366004611bf1565b6113ab565b34801561050f57600080fd5b506101cf61051e366004611bf1565b63389a75e1600c908152600091909152602090205490565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a70000000000000000000000000000000000000000000000000000000014806105c957507fffffffff0000000000000000000000000000000000000000000000000000000082167fd9b67a2600000000000000000000000000000000000000000000000000000000145b806105f457507fffffffff000000000000000000000000000000000000000000000000000000008216155b92915050565b6003546040517fc87b56dd0000000000000000000000000000000000000000000000000000000081526004810183905260609173ffffffffffffffffffffffffffffffffffffffff169063c87b56dd90602401600060405180830381865afa15801561066a573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526105f49190810190611da3565b60006202a30067ffffffffffffffff164201905063389a75e1600c5233600052806020600c2055337fdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d600080a250565b84831461076e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f4c454e4754485f4d49534d41544348000000000000000000000000000000000060448201526064015b60405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff891614806107c2575073ffffffffffffffffffffffffffffffffffffffff8816600090815260016020908152604080832033845290915290205460ff165b610828576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f4e4f545f415554484f52495a45440000000000000000000000000000000000006044820152606401610765565b60008060005b878110156108fd5788888281811061084857610848611e6e565b90506020020135925086868281811061086357610863611e6e565b73ffffffffffffffffffffffffffffffffffffffff8e16600090815260208181526040808320898452825282208054939091029490940135955085939250906108ad908490611ecc565b909155505073ffffffffffffffffffffffffffffffffffffffff8a16600090815260208181526040808320868452909152812080548492906108f0908490611edf565b909155505060010161082e565b508873ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8b8b8b8b6040516109789493929190611f3d565b60405180910390a473ffffffffffffffffffffffffffffffffffffffff89163b15610a6a576040517fbc197c81000000000000000000000000000000000000000000000000000000008082529073ffffffffffffffffffffffffffffffffffffffff8b169063bc197c81906109ff9033908f908e908e908e908e908e908e90600401611fad565b6020604051808303816000875af1158015610a1e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a42919061201e565b7fffffffff000000000000000000000000000000000000000000000000000000001614610a84565b73ffffffffffffffffffffffffffffffffffffffff891615155b610aea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f554e534146455f524543495049454e54000000000000000000000000000000006044820152606401610765565b50505050505050505050565b6060838214610b61576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f4c454e4754485f4d49534d4154434800000000000000000000000000000000006044820152606401610765565b8367ffffffffffffffff811115610b7a57610b7a611d74565b604051908082528060200260200182016040528015610ba3578160200160208202803683370190505b50905060005b84811015610c6457600080878784818110610bc657610bc6611e6e565b9050602002016020810190610bdb9190611bf1565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000858584818110610c2957610c29611e6e565b90506020020135815260200190815260200160002054828281518110610c5157610c51611e6e565b6020908102919091010152600101610ba9565b50949350505050565b60045461ffff84163360601b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000161790421115610cd6576040517f589ed34b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008181526005602052604090205460ff1615610d1f576040517f96dd8aac00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610d5c33868b8b8b8b604051602001610d3f9695949392919061207d565b6040516020818303038152906040528051906020012085856113fa565b60025490915073ffffffffffffffffffffffffffffffffffffffff808316911614610db3576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008281526005602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905581518a820281810183019093528a8152610e659233928d918d9182919085019084908082843760009201919091525050604080516020808e0282810182019093528d82529093508d92508c91829185019084908082843760009201829052506040805160208101909152908152925061146a915050565b505050505050505050565b63389a75e1600c523360005260006020600c2055337ffa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c92600080a2565b610eb4611764565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b610f03611764565b610f0d600061179a565b565b610f17611764565b610f93858585808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152505060408051602080890282810182019093528882529093508892508791829185019084908082843760009201829052506040805160208101909152908152925061146a915050565b5050505050565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff87168085529083529281902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b611039611764565b600455565b611046611764565b63389a75e1600c52806000526020600c20805442111561106e57636f5e88186000526004601cfd5b6000905561107b8161179a565b50565b3373ffffffffffffffffffffffffffffffffffffffff871614806110d2575073ffffffffffffffffffffffffffffffffffffffff8616600090815260016020908152604080832033845290915290205460ff165b611138576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f4e4f545f415554484f52495a45440000000000000000000000000000000000006044820152606401610765565b73ffffffffffffffffffffffffffffffffffffffff861660009081526020818152604080832087845290915281208054859290611176908490611ecc565b909155505073ffffffffffffffffffffffffffffffffffffffff8516600090815260208181526040808320878452909152812080548592906111b9908490611edf565b9091555050604080518581526020810185905273ffffffffffffffffffffffffffffffffffffffff808816929089169133917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a473ffffffffffffffffffffffffffffffffffffffff85163b156112fc576040517ff23a6e61000000000000000000000000000000000000000000000000000000008082529073ffffffffffffffffffffffffffffffffffffffff87169063f23a6e61906112919033908b908a908a908a908a906004016120f6565b6020604051808303816000875af11580156112b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112d4919061201e565b7fffffffff000000000000000000000000000000000000000000000000000000001614611316565b73ffffffffffffffffffffffffffffffffffffffff851615155b61137c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f554e534146455f524543495049454e54000000000000000000000000000000006044820152606401610765565b505050505050565b61138c611764565b8060601b6113a257637448fbae6000526004601cfd5b61107b8161179a565b6113b3611764565b600380547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b600060418218611463576040516040846040377f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a06060511161145f5784600052604084013560001a602052602060406080600060015afa5060006060523d6060185191505b6040525b9392505050565b8251825181146114d6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f4c454e4754485f4d49534d4154434800000000000000000000000000000000006044820152606401610765565b60005b8181101561157f578381815181106114f3576114f3611e6e565b60200260200101516000808873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600087848151811061154d5761154d611e6e565b6020026020010151815260200190815260200160002060008282546115729190611edf565b90915550506001016114d9565b508473ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb87876040516115f792919061213c565b60405180910390a473ffffffffffffffffffffffffffffffffffffffff85163b156116e4576040517fbc197c81000000000000000000000000000000000000000000000000000000008082529073ffffffffffffffffffffffffffffffffffffffff87169063bc197c81906116799033906000908a908a908a9060040161216a565b6020604051808303816000875af1158015611698573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116bc919061201e565b7fffffffff0000000000000000000000000000000000000000000000000000000016146116fe565b73ffffffffffffffffffffffffffffffffffffffff851615155b610f93576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f554e534146455f524543495049454e54000000000000000000000000000000006044820152606401610765565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffff74873927543314610f0d576382b429006000526004601cfd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffff74873927805473ffffffffffffffffffffffffffffffffffffffff9092169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a355565b803573ffffffffffffffffffffffffffffffffffffffff8116811461182457600080fd5b919050565b6000806040838503121561183c57600080fd5b61184583611800565b946020939093013593505050565b7fffffffff000000000000000000000000000000000000000000000000000000008116811461107b57600080fd5b60006020828403121561189357600080fd5b813561146381611853565b60005b838110156118b95781810151838201526020016118a1565b50506000910152565b600081518084526118da81602086016020860161189e565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061146360208301846118c2565b60006020828403121561193157600080fd5b5035919050565b60008083601f84011261194a57600080fd5b50813567ffffffffffffffff81111561196257600080fd5b6020830191508360208260051b850101111561197d57600080fd5b9250929050565b60008083601f84011261199657600080fd5b50813567ffffffffffffffff8111156119ae57600080fd5b60208301915083602082850101111561197d57600080fd5b60008060008060008060008060a0898b0312156119e257600080fd5b6119eb89611800565b97506119f960208a01611800565b9650604089013567ffffffffffffffff80821115611a1657600080fd5b611a228c838d01611938565b909850965060608b0135915080821115611a3b57600080fd5b611a478c838d01611938565b909650945060808b0135915080821115611a6057600080fd5b50611a6d8b828c01611984565b999c989b5096995094979396929594505050565b60008060008060408587031215611a9757600080fd5b843567ffffffffffffffff80821115611aaf57600080fd5b611abb88838901611938565b90965094506020870135915080821115611ad457600080fd5b50611ae187828801611938565b95989497509550505050565b600081518084526020808501945080840160005b83811015611b1d57815187529582019590820190600101611b01565b509495945050505050565b6020815260006114636020830184611aed565b60008060008060008060006080888a031215611b5657600080fd5b873567ffffffffffffffff80821115611b6e57600080fd5b611b7a8b838c01611938565b909950975060208a0135915080821115611b9357600080fd5b611b9f8b838c01611938565b909750955060408a0135915061ffff82168214611bbb57600080fd5b90935060608901359080821115611bd157600080fd5b50611bde8a828b01611984565b989b979a50959850939692959293505050565b600060208284031215611c0357600080fd5b61146382611800565b600080600080600060608688031215611c2457600080fd5b611c2d86611800565b9450602086013567ffffffffffffffff80821115611c4a57600080fd5b611c5689838a01611938565b90965094506040880135915080821115611c6f57600080fd5b50611c7c88828901611938565b969995985093965092949392505050565b60008060408385031215611ca057600080fd5b611ca983611800565b915060208301358015158114611cbe57600080fd5b809150509250929050565b60008060408385031215611cdc57600080fd5b611ce583611800565b9150611cf360208401611800565b90509250929050565b60008060008060008060a08789031215611d1557600080fd5b611d1e87611800565b9550611d2c60208801611800565b94506040870135935060608701359250608087013567ffffffffffffffff811115611d5657600080fd5b611d6289828a01611984565b979a9699509497509295939492505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600060208284031215611db557600080fd5b815167ffffffffffffffff80821115611dcd57600080fd5b818401915084601f830112611de157600080fd5b815181811115611df357611df3611d74565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715611e3957611e39611d74565b81604052828152876020848701011115611e5257600080fd5b611e6383602083016020880161189e565b979650505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b818103818111156105f4576105f4611e9d565b808201808211156105f4576105f4611e9d565b81835260007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831115611f2457600080fd5b8260051b80836020870137939093016020019392505050565b604081526000611f51604083018688611ef2565b8281036020840152611e63818587611ef2565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b600073ffffffffffffffffffffffffffffffffffffffff808b168352808a1660208401525060a06040830152611fe760a08301888a611ef2565b8281036060840152611ffa818789611ef2565b9050828103608084015261200f818587611f64565b9b9a5050505050505050505050565b60006020828403121561203057600080fd5b815161146381611853565b60007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83111561206a57600080fd5b8260051b80838637939093019392505050565b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008760601b1681527fffff0000000000000000000000000000000000000000000000000000000000008660f01b16601482015260006120ea6120e360168401878961203b565b848661203b565b98975050505050505050565b600073ffffffffffffffffffffffffffffffffffffffff808916835280881660208401525085604083015284606083015260a060808301526120ea60a083018486611f64565b60408152600061214f6040830185611aed565b82810360208401526121618185611aed565b95945050505050565b600073ffffffffffffffffffffffffffffffffffffffff808816835280871660208401525060a060408301526121a360a0830186611aed565b82810360608401526121b58186611aed565b905082810360808401526120ea81856118c256fea26469706673582212204f435c2221be3df7ed00f719688c96d8efeb99481b1d32738bd68358ff82ec9764736f6c63430008140033

Deployed Bytecode

0x6080604052600436106101955760003560e01c8063715018a6116100e1578063ea2b4ab21161008a578063f242432a11610064578063f242432a146104b0578063f2fde38b146104d0578063fd4fe8a8146104e3578063fee81cf41461050357600080fd5b8063ea2b4ab214610467578063eb20614e1461047d578063f04e283e1461049d57600080fd5b8063a22cb465116100bb578063a22cb465146103ee578063d7533f021461040e578063e985e9c51461042c57600080fd5b8063715018a614610392578063812015b91461039a5780638da5cb5b146103ba57600080fd5b80632eb2c2d61161014357806354d1f13d1161011d57806354d1f13d1461033d5780636c19e78314610345578063703199701461036557600080fd5b80632eb2c2d6146102dd5780634e1273f4146102fd578063525b6ba01461032a57600080fd5b80630e89341c116101745780630e89341c14610261578063238ac9331461028157806325692962146102d357600080fd5b8062fdd58e1461019a57806301ffc9a7146101e257806306fdde0314610212575b600080fd5b3480156101a657600080fd5b506101cf6101b5366004611829565b600060208181529281526040808220909352908152205481565b6040519081526020015b60405180910390f35b3480156101ee57600080fd5b506102026101fd366004611881565b610536565b60405190151581526020016101d9565b34801561021e57600080fd5b5060408051808201909152601181527f2166756e64726f7020537469636b65727300000000000000000000000000000060208201525b6040516101d9919061190c565b34801561026d57600080fd5b5061025461027c36600461191f565b6105fa565b34801561028d57600080fd5b506002546102ae9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101d9565b6102db6106b0565b005b3480156102e957600080fd5b506102db6102f83660046119c6565b610700565b34801561030957600080fd5b5061031d610318366004611a81565b610af6565b6040516101d99190611b28565b6102db610338366004611b3b565b610c6d565b6102db610e70565b34801561035157600080fd5b506102db610360366004611bf1565b610eac565b34801561037157600080fd5b506003546102ae9073ffffffffffffffffffffffffffffffffffffffff1681565b6102db610efb565b3480156103a657600080fd5b506102db6103b5366004611c0c565b610f0f565b3480156103c657600080fd5b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffff74873927546102ae565b3480156103fa57600080fd5b506102db610409366004611c8d565b610f9a565b34801561041a57600080fd5b506040516202a30081526020016101d9565b34801561043857600080fd5b50610202610447366004611cc9565b600160209081526000928352604080842090915290825290205460ff1681565b34801561047357600080fd5b506101cf60045481565b34801561048957600080fd5b506102db61049836600461191f565b611031565b6102db6104ab366004611bf1565b61103e565b3480156104bc57600080fd5b506102db6104cb366004611cfc565b61107e565b6102db6104de366004611bf1565b611384565b3480156104ef57600080fd5b506102db6104fe366004611bf1565b6113ab565b34801561050f57600080fd5b506101cf61051e366004611bf1565b63389a75e1600c908152600091909152602090205490565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a70000000000000000000000000000000000000000000000000000000014806105c957507fffffffff0000000000000000000000000000000000000000000000000000000082167fd9b67a2600000000000000000000000000000000000000000000000000000000145b806105f457507fffffffff000000000000000000000000000000000000000000000000000000008216155b92915050565b6003546040517fc87b56dd0000000000000000000000000000000000000000000000000000000081526004810183905260609173ffffffffffffffffffffffffffffffffffffffff169063c87b56dd90602401600060405180830381865afa15801561066a573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526105f49190810190611da3565b60006202a30067ffffffffffffffff164201905063389a75e1600c5233600052806020600c2055337fdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d600080a250565b84831461076e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f4c454e4754485f4d49534d41544348000000000000000000000000000000000060448201526064015b60405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff891614806107c2575073ffffffffffffffffffffffffffffffffffffffff8816600090815260016020908152604080832033845290915290205460ff165b610828576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f4e4f545f415554484f52495a45440000000000000000000000000000000000006044820152606401610765565b60008060005b878110156108fd5788888281811061084857610848611e6e565b90506020020135925086868281811061086357610863611e6e565b73ffffffffffffffffffffffffffffffffffffffff8e16600090815260208181526040808320898452825282208054939091029490940135955085939250906108ad908490611ecc565b909155505073ffffffffffffffffffffffffffffffffffffffff8a16600090815260208181526040808320868452909152812080548492906108f0908490611edf565b909155505060010161082e565b508873ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8b8b8b8b6040516109789493929190611f3d565b60405180910390a473ffffffffffffffffffffffffffffffffffffffff89163b15610a6a576040517fbc197c81000000000000000000000000000000000000000000000000000000008082529073ffffffffffffffffffffffffffffffffffffffff8b169063bc197c81906109ff9033908f908e908e908e908e908e908e90600401611fad565b6020604051808303816000875af1158015610a1e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a42919061201e565b7fffffffff000000000000000000000000000000000000000000000000000000001614610a84565b73ffffffffffffffffffffffffffffffffffffffff891615155b610aea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f554e534146455f524543495049454e54000000000000000000000000000000006044820152606401610765565b50505050505050505050565b6060838214610b61576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f4c454e4754485f4d49534d4154434800000000000000000000000000000000006044820152606401610765565b8367ffffffffffffffff811115610b7a57610b7a611d74565b604051908082528060200260200182016040528015610ba3578160200160208202803683370190505b50905060005b84811015610c6457600080878784818110610bc657610bc6611e6e565b9050602002016020810190610bdb9190611bf1565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000858584818110610c2957610c29611e6e565b90506020020135815260200190815260200160002054828281518110610c5157610c51611e6e565b6020908102919091010152600101610ba9565b50949350505050565b60045461ffff84163360601b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000161790421115610cd6576040517f589ed34b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008181526005602052604090205460ff1615610d1f576040517f96dd8aac00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610d5c33868b8b8b8b604051602001610d3f9695949392919061207d565b6040516020818303038152906040528051906020012085856113fa565b60025490915073ffffffffffffffffffffffffffffffffffffffff808316911614610db3576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008281526005602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905581518a820281810183019093528a8152610e659233928d918d9182919085019084908082843760009201919091525050604080516020808e0282810182019093528d82529093508d92508c91829185019084908082843760009201829052506040805160208101909152908152925061146a915050565b505050505050505050565b63389a75e1600c523360005260006020600c2055337ffa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c92600080a2565b610eb4611764565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b610f03611764565b610f0d600061179a565b565b610f17611764565b610f93858585808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152505060408051602080890282810182019093528882529093508892508791829185019084908082843760009201829052506040805160208101909152908152925061146a915050565b5050505050565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff87168085529083529281902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b611039611764565b600455565b611046611764565b63389a75e1600c52806000526020600c20805442111561106e57636f5e88186000526004601cfd5b6000905561107b8161179a565b50565b3373ffffffffffffffffffffffffffffffffffffffff871614806110d2575073ffffffffffffffffffffffffffffffffffffffff8616600090815260016020908152604080832033845290915290205460ff165b611138576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f4e4f545f415554484f52495a45440000000000000000000000000000000000006044820152606401610765565b73ffffffffffffffffffffffffffffffffffffffff861660009081526020818152604080832087845290915281208054859290611176908490611ecc565b909155505073ffffffffffffffffffffffffffffffffffffffff8516600090815260208181526040808320878452909152812080548592906111b9908490611edf565b9091555050604080518581526020810185905273ffffffffffffffffffffffffffffffffffffffff808816929089169133917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a473ffffffffffffffffffffffffffffffffffffffff85163b156112fc576040517ff23a6e61000000000000000000000000000000000000000000000000000000008082529073ffffffffffffffffffffffffffffffffffffffff87169063f23a6e61906112919033908b908a908a908a908a906004016120f6565b6020604051808303816000875af11580156112b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112d4919061201e565b7fffffffff000000000000000000000000000000000000000000000000000000001614611316565b73ffffffffffffffffffffffffffffffffffffffff851615155b61137c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f554e534146455f524543495049454e54000000000000000000000000000000006044820152606401610765565b505050505050565b61138c611764565b8060601b6113a257637448fbae6000526004601cfd5b61107b8161179a565b6113b3611764565b600380547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b600060418218611463576040516040846040377f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a06060511161145f5784600052604084013560001a602052602060406080600060015afa5060006060523d6060185191505b6040525b9392505050565b8251825181146114d6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f4c454e4754485f4d49534d4154434800000000000000000000000000000000006044820152606401610765565b60005b8181101561157f578381815181106114f3576114f3611e6e565b60200260200101516000808873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600087848151811061154d5761154d611e6e565b6020026020010151815260200190815260200160002060008282546115729190611edf565b90915550506001016114d9565b508473ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb87876040516115f792919061213c565b60405180910390a473ffffffffffffffffffffffffffffffffffffffff85163b156116e4576040517fbc197c81000000000000000000000000000000000000000000000000000000008082529073ffffffffffffffffffffffffffffffffffffffff87169063bc197c81906116799033906000908a908a908a9060040161216a565b6020604051808303816000875af1158015611698573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116bc919061201e565b7fffffffff0000000000000000000000000000000000000000000000000000000016146116fe565b73ffffffffffffffffffffffffffffffffffffffff851615155b610f93576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f554e534146455f524543495049454e54000000000000000000000000000000006044820152606401610765565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffff74873927543314610f0d576382b429006000526004601cfd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffff74873927805473ffffffffffffffffffffffffffffffffffffffff9092169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a355565b803573ffffffffffffffffffffffffffffffffffffffff8116811461182457600080fd5b919050565b6000806040838503121561183c57600080fd5b61184583611800565b946020939093013593505050565b7fffffffff000000000000000000000000000000000000000000000000000000008116811461107b57600080fd5b60006020828403121561189357600080fd5b813561146381611853565b60005b838110156118b95781810151838201526020016118a1565b50506000910152565b600081518084526118da81602086016020860161189e565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061146360208301846118c2565b60006020828403121561193157600080fd5b5035919050565b60008083601f84011261194a57600080fd5b50813567ffffffffffffffff81111561196257600080fd5b6020830191508360208260051b850101111561197d57600080fd5b9250929050565b60008083601f84011261199657600080fd5b50813567ffffffffffffffff8111156119ae57600080fd5b60208301915083602082850101111561197d57600080fd5b60008060008060008060008060a0898b0312156119e257600080fd5b6119eb89611800565b97506119f960208a01611800565b9650604089013567ffffffffffffffff80821115611a1657600080fd5b611a228c838d01611938565b909850965060608b0135915080821115611a3b57600080fd5b611a478c838d01611938565b909650945060808b0135915080821115611a6057600080fd5b50611a6d8b828c01611984565b999c989b5096995094979396929594505050565b60008060008060408587031215611a9757600080fd5b843567ffffffffffffffff80821115611aaf57600080fd5b611abb88838901611938565b90965094506020870135915080821115611ad457600080fd5b50611ae187828801611938565b95989497509550505050565b600081518084526020808501945080840160005b83811015611b1d57815187529582019590820190600101611b01565b509495945050505050565b6020815260006114636020830184611aed565b60008060008060008060006080888a031215611b5657600080fd5b873567ffffffffffffffff80821115611b6e57600080fd5b611b7a8b838c01611938565b909950975060208a0135915080821115611b9357600080fd5b611b9f8b838c01611938565b909750955060408a0135915061ffff82168214611bbb57600080fd5b90935060608901359080821115611bd157600080fd5b50611bde8a828b01611984565b989b979a50959850939692959293505050565b600060208284031215611c0357600080fd5b61146382611800565b600080600080600060608688031215611c2457600080fd5b611c2d86611800565b9450602086013567ffffffffffffffff80821115611c4a57600080fd5b611c5689838a01611938565b90965094506040880135915080821115611c6f57600080fd5b50611c7c88828901611938565b969995985093965092949392505050565b60008060408385031215611ca057600080fd5b611ca983611800565b915060208301358015158114611cbe57600080fd5b809150509250929050565b60008060408385031215611cdc57600080fd5b611ce583611800565b9150611cf360208401611800565b90509250929050565b60008060008060008060a08789031215611d1557600080fd5b611d1e87611800565b9550611d2c60208801611800565b94506040870135935060608701359250608087013567ffffffffffffffff811115611d5657600080fd5b611d6289828a01611984565b979a9699509497509295939492505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600060208284031215611db557600080fd5b815167ffffffffffffffff80821115611dcd57600080fd5b818401915084601f830112611de157600080fd5b815181811115611df357611df3611d74565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715611e3957611e39611d74565b81604052828152876020848701011115611e5257600080fd5b611e6383602083016020880161189e565b979650505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b818103818111156105f4576105f4611e9d565b808201808211156105f4576105f4611e9d565b81835260007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831115611f2457600080fd5b8260051b80836020870137939093016020019392505050565b604081526000611f51604083018688611ef2565b8281036020840152611e63818587611ef2565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b600073ffffffffffffffffffffffffffffffffffffffff808b168352808a1660208401525060a06040830152611fe760a08301888a611ef2565b8281036060840152611ffa818789611ef2565b9050828103608084015261200f818587611f64565b9b9a5050505050505050505050565b60006020828403121561203057600080fd5b815161146381611853565b60007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83111561206a57600080fd5b8260051b80838637939093019392505050565b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008760601b1681527fffff0000000000000000000000000000000000000000000000000000000000008660f01b16601482015260006120ea6120e360168401878961203b565b848661203b565b98975050505050505050565b600073ffffffffffffffffffffffffffffffffffffffff808916835280881660208401525085604083015284606083015260a060808301526120ea60a083018486611f64565b60408152600061214f6040830185611aed565b82810360208401526121618185611aed565b95945050505050565b600073ffffffffffffffffffffffffffffffffffffffff808816835280871660208401525060a060408301526121a360a0830186611aed565b82810360608401526121b58186611aed565b905082810360808401526120ea81856118c256fea26469706673582212204f435c2221be3df7ed00f719688c96d8efeb99481b1d32738bd68358ff82ec9764736f6c63430008140033

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.