ETH Price: $3,346.38 (-1.26%)

Contract

0x1CDBc6a0DE7f74084156c6D02FF32E7E7D442465
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Claim Prize152115022022-07-25 11:53:14888 days ago1658749994IN
0x1CDBc6a0...E7D442465
0 ETH0.0018408319.97884336
Claim Prize152080942022-07-24 22:49:07888 days ago1658702947IN
0x1CDBc6a0...E7D442465
0 ETH0.0009558213.01310656
Trigger Claw152057322022-07-24 14:05:36889 days ago1658671536IN
0x1CDBc6a0...E7D442465
0 ETH0.0005066615.44836779
Trigger Claw152057322022-07-24 14:05:36889 days ago1658671536IN
0x1CDBc6a0...E7D442465
0 ETH0.0005066615.44836779
Buy Ticket152055802022-07-24 13:31:34889 days ago1658669494IN
0x1CDBc6a0...E7D442465
0 ETH0.0013054213.0627326
Buy Ticket152051222022-07-24 11:46:48889 days ago1658663208IN
0x1CDBc6a0...E7D442465
0 ETH0.000840228.40767192
Buy Ticket152050942022-07-24 11:39:32889 days ago1658662772IN
0x1CDBc6a0...E7D442465
0 ETH0.000860848.61405086
Buy Ticket152039832022-07-24 7:27:49889 days ago1658647669IN
0x1CDBc6a0...E7D442465
0 ETH0.000586465.86841844
Buy Ticket152035682022-07-24 5:56:00889 days ago1658642160IN
0x1CDBc6a0...E7D442465
0 ETH0.000601186.01575134
Buy Ticket152016782022-07-23 22:39:52889 days ago1658615992IN
0x1CDBc6a0...E7D442465
0 ETH0.0015387515.39754727
Buy Ticket152003692022-07-23 18:00:54889 days ago1658599254IN
0x1CDBc6a0...E7D442465
0 ETH0.0017147417.15862157
Buy Ticket152003682022-07-23 18:00:50889 days ago1658599250IN
0x1CDBc6a0...E7D442465
0 ETH0.0018249318.26125135
Buy Ticket151999392022-07-23 16:16:11890 days ago1658592971IN
0x1CDBc6a0...E7D442465
0 ETH0.00231823.19513324
Buy Ticket151999392022-07-23 16:16:11890 days ago1658592971IN
0x1CDBc6a0...E7D442465
0 ETH0.00231823.19513324
Buy Ticket151998692022-07-23 15:58:30890 days ago1658591910IN
0x1CDBc6a0...E7D442465
0 ETH0.000854138.54687207
Buy Ticket151997252022-07-23 15:25:23890 days ago1658589923IN
0x1CDBc6a0...E7D442465
0 ETH0.0010777110.78412832
Buy Ticket151997202022-07-23 15:24:03890 days ago1658589843IN
0x1CDBc6a0...E7D442465
0 ETH0.0010045210.0517711
Buy Ticket151993142022-07-23 13:54:25890 days ago1658584465IN
0x1CDBc6a0...E7D442465
0 ETH0.000803368.03885987
Buy Ticket151993142022-07-23 13:54:25890 days ago1658584465IN
0x1CDBc6a0...E7D442465
0 ETH0.000803368.03885987
Buy Ticket151992772022-07-23 13:47:13890 days ago1658584033IN
0x1CDBc6a0...E7D442465
0 ETH0.0010055610.06223239
Buy Ticket151989392022-07-23 12:37:57890 days ago1658579877IN
0x1CDBc6a0...E7D442465
0 ETH0.0010396310.40307772
Buy Ticket151988862022-07-23 12:24:07890 days ago1658579047IN
0x1CDBc6a0...E7D442465
0 ETH0.0011521311.52880388
Buy Ticket151988812022-07-23 12:23:44890 days ago1658579024IN
0x1CDBc6a0...E7D442465
0 ETH0.0015882115.8924843
Buy Ticket151988782022-07-23 12:22:57890 days ago1658578977IN
0x1CDBc6a0...E7D442465
0 ETH0.0015699415.7096981
Buy Ticket151988762022-07-23 12:22:37890 days ago1658578957IN
0x1CDBc6a0...E7D442465
0 ETH0.0017545117.5565462
View all transactions

Latest 25 internal transactions (View All)

Advanced mode:
Parent Transaction Hash Block
From
To
151075292022-07-09 9:20:33904 days ago1657358433
0x1CDBc6a0...E7D442465
 Contract Creation0 ETH
151075232022-07-09 9:19:15904 days ago1657358355
0x1CDBc6a0...E7D442465
 Contract Creation0 ETH
151075212022-07-09 9:18:48904 days ago1657358328
0x1CDBc6a0...E7D442465
 Contract Creation0 ETH
148419422022-05-25 12:47:25949 days ago1653482845
0x1CDBc6a0...E7D442465
 Contract Creation0 ETH
148417672022-05-25 12:01:13949 days ago1653480073
0x1CDBc6a0...E7D442465
 Contract Creation0 ETH
148417622022-05-25 12:00:25949 days ago1653480025
0x1CDBc6a0...E7D442465
 Contract Creation0 ETH
148417502022-05-25 11:57:20949 days ago1653479840
0x1CDBc6a0...E7D442465
 Contract Creation0 ETH
147185652022-05-05 17:35:35968 days ago1651772135
0x1CDBc6a0...E7D442465
 Contract Creation0 ETH
147185642022-05-05 17:35:28968 days ago1651772128
0x1CDBc6a0...E7D442465
 Contract Creation0 ETH
147185572022-05-05 17:33:34968 days ago1651772014
0x1CDBc6a0...E7D442465
 Contract Creation0 ETH
147185312022-05-05 17:28:58968 days ago1651771738
0x1CDBc6a0...E7D442465
 Contract Creation0 ETH
147185202022-05-05 17:27:03968 days ago1651771623
0x1CDBc6a0...E7D442465
 Contract Creation0 ETH
147185172022-05-05 17:25:57968 days ago1651771557
0x1CDBc6a0...E7D442465
 Contract Creation0 ETH
147184982022-05-05 17:20:54968 days ago1651771254
0x1CDBc6a0...E7D442465
 Contract Creation0 ETH
147184242022-05-05 17:04:25969 days ago1651770265
0x1CDBc6a0...E7D442465
 Contract Creation0 ETH
147167332022-05-05 10:26:32969 days ago1651746392
0x1CDBc6a0...E7D442465
 Contract Creation0 ETH
147167302022-05-05 10:25:55969 days ago1651746355
0x1CDBc6a0...E7D442465
 Contract Creation0 ETH
147167292022-05-05 10:25:26969 days ago1651746326
0x1CDBc6a0...E7D442465
 Contract Creation0 ETH
147112012022-05-04 13:25:54970 days ago1651670754
0x1CDBc6a0...E7D442465
 Contract Creation0 ETH
147112012022-05-04 13:25:54970 days ago1651670754
0x1CDBc6a0...E7D442465
 Contract Creation0 ETH
147112012022-05-04 13:25:54970 days ago1651670754
0x1CDBc6a0...E7D442465
 Contract Creation0 ETH
147112012022-05-04 13:25:54970 days ago1651670754
0x1CDBc6a0...E7D442465
 Contract Creation0 ETH
147112012022-05-04 13:25:54970 days ago1651670754
0x1CDBc6a0...E7D442465
 Contract Creation0 ETH
147111142022-05-04 13:07:54970 days ago1651669674
0x1CDBc6a0...E7D442465
 Contract Creation0 ETH
147111142022-05-04 13:07:54970 days ago1651669674
0x1CDBc6a0...E7D442465
 Contract Creation0 ETH
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
Gachapon

Compiler Version
v0.8.12+commit.f00d7308

Optimization Enabled:
Yes with 10000 runs

Other Settings:
default evmVersion
File 1 of 13 : Gachapon.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.12;

// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM`MMM NMM MMM MMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMM  MMMMhMMMMMMM  MMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
// MMMMMMMMMMMMMMMMMMMMMMMMMM  MM-MMMMM   MMMM    MMMM   lMMMDMMMMMMMMMMMMMMMMMMMMMMMMMM
// MMMMMMMMMMMMMMMMMMMMMMM jMMMMl   MM    MMM  M  MMM   M   MMMM MMMMMMMMMMMMMMMMMMMMMMM
// MMMMMMMMMMMMMMMMMMMM MMMMMMMMM  , `     M   Y   MM  MMM  BMMMMMM MMMMMMMMMMMMMMMMMMMM
// MMMMMMMMMMMMMMMMM MMMMMMMMMMMM  IM  MM  l  MMM  X   MM.  MMMMMMMMMM MMMMMMMMMMMMMMMMM
// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMM.nlMMMMMMMMMMMMMMMMM]._  MMMMMMMMMMMMMMMNMMMMMMMMMMMMMM
// MMMMMMMMMMMMMM TMMMMMMMMMMMMMMMMMM          +MMMMMMMMMMMM:  rMMMMMMMMN MMMMMMMMMMMMMM
// MMMMMMMMMMMM MMMMMMMMMMMMMMMM                  MMMMMM           MMMMMMMM qMMMMMMMMMMM
// MMMMMMMMMMMMMMMMMMMMMMMMMMM^                   MMMb              .MMMMMMMMMMMMMMMMMMM
// MMMMMMMMMM MMMMMMMMMMMMMMM                     MM                  MMMMMMM MMMMMMMMMM
// MMMMMMMMMMMMMMMMMMMMMMMMMM                     M                   gMMMMMMMMMMMMMMMMM
// MMMMMMMMu MMMMMMMMMMMMMMM                                           MMMMMMM .MMMMMMMM
// MMMMMMMMMMMMMMMMMMMMMMMMM                                           :MMMMMMMMMMMMMMMM
// MMMMMMM^ MMMMMMMMMMMMMMMl                                            MMMMMMMM MMMMMMM
// MMMMMMMMMMMMMMMMMMMMMMMM                                             MMMMMMMMMMMMMMMM
// MMMMMMM MMMMMMMMMMMMMMMM                                             MMMMMMMM MMMMMMM
// MMMMMMMMMMMMMMMMMMMMMMMM                                             MMMMMMMMMMMMMMMM
// MMMMMMr MMMMMMMMMMMMMMMM                                             MMMMMMMM .MMMMMM
// MMMMMMMMMMMMMMMMMMMMMMMMM                                           MMMMMMMMMMMMMMMMM
// MMMMMMM MMMMMMMMMMMMMMMMM                                         DMMMMMMMMMM MMMMMMM
// MMMMMMMMMMMMMMMMMMMMMMMMMM                              MMMMMMMMMMMMMMMMMMMMMMMMMMMMM
// MMMMMMM|`MMMMMMMMMMMMMMMM         q                      MMMMMMMMMMMMMMMMMMM  MMMMMMM
// MMMMMMMMMTMMMMMMMMMMMMMMM                               qMMMMMMMMMMMMMMMMMMgMMMMMMMMM
// MMMMMMMMq MMMMMMMMMMMMMMMh                             jMMMMMMMMMMMMMMMMMMM nMMMMMMMM
// MMMMMMMMMM MMMMMMMMMMMMMMMQ      nc    -MMMMMn        MMMMMMMMMMMMMMMMMMMM MMMMMMMMMM
// MMMMMMMMMM.MMMMMMMMMMMMMMMMMMl            M1       `MMMMMMMMMMMMMMMMMMMMMMrMMMMMMMMMM
// MMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMM               :MMMMMMMMMM MMMMMMMMMMMM qMMMMMMMMMMM
// MMMMMMMMMMMMMMMMMMMMMMMMMM  MMMMMMX       MMMMMMMMMMMMMMM  uMMMMMMMMMMMMMMMMMMMMMMMMM
// MMMMMMMMMMMMMM DMMMMMMMMM   IMMMMMMMMMMMMMMMMMMMMMMM   M   Y  MMMMMMMN MMMMMMMMMMMMMM
// MMMMMMMMMMMMMMMMM MMMMMM    ``    M      MM  MMM   , MMMM    Mv  MMM MMMMMMMMMMMMMMMM
// MMMMMMMMMMMMMMMMMMM MMh  Ml  .   M  MMMM  I  MMMT  M     :M   ,MMMMMMMMMMMMMMMMMMMMMM
// MMMMMMMMMMMMMMMMMMMM MMMMMMMMt  MM  MMMMB m  ]MMM  MMMM   MMMMMM MMMMMMMMMMMMMMMMMMMM
// MMMMMMMMMMMMMMMMMMMMMMM MMMMM  MMM   TM   MM  9U  .MM  _MMMMM MMMMMMMMMMMMMMMMMMMMMMM
// MMMMMMMMMMMMMMMMMMMMMMMMMM YMMMMMMMn     MMMM    +MMMMMMM1`MMMMMMMMMMMMMMMMMMMMMMMMMM
// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM.`MMM MMM MMMMM`.MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM author: phaze MMM

import {Strings} from "../lib/openzeppelin-contracts/contracts/utils/Strings.sol";
import {IERC20} from "../lib/openzeppelin-contracts/contracts/interfaces/IERC20.sol";
import {IERC721} from "../lib/openzeppelin-contracts/contracts/interfaces/IERC721.sol";
import {IERC721Metadata} from "../lib/openzeppelin-contracts/contracts/interfaces/IERC721Metadata.sol";

import {IGouda, IMadMouse} from "./lib/interfaces.sol";
import {Ownable} from "./lib/Ownable.sol";
import {Choice} from "./lib/Choice.sol";

import {SoulboundTickets as Tickets} from "./SoulboundTickets.sol";

error RaffleNotActive();
error RaffleOngoing();
error RaffleRandomSeedSet();
error RaffleAlreadyCancelled();
error TicketsMaxSupplyReached();

error RaffleUnrevealed();
error PrizeAlreadyClaimed();

error BetterLuckNextTime();
error MachineBeDoinWork();
error NeedsMoarTickets();
error TicketsImplementationUnset();
error InvalidTimestamps();
error InvalidTicketPrice();
error RequirementNotFulfilled();

error ContractCallNotAllowed();

contract Gachapon is Ownable {
    using Strings for uint256;

    event Chachingg();
    event GrappleGrapple();
    event BZZzzt();

    struct Raffle {
        address prizeNFT;
        uint40 start;
        uint40 end;
        uint16 ticketPrice; // in multiples of 1e18
        // first slot
        uint16 ticketSupply;
        uint16 maxTicketSupply;
        uint8 refundRate; // set in range [0, 2^8 - 1] (0, 100%)
        uint8 requirement;
        bool cancelled;
        uint40 randomSeed;
        address tickets;
        // second slot
        uint32[] prizeTokenIds;
    }

    string ticketURI = "ipfs://QmSwrzsySKnkQmRQoZYmZ2XuJx3NMn2awdHwf1fezAJbq3/silver-ticket.json";
    string losingTicketURI = "ipfs://QmSwrzsySKnkQmRQoZYmZ2XuJx3NMn2awdHwf1fezAJbq3/red-ticket.json";
    string winningTicketURI = "ipfs://QmSwrzsySKnkQmRQoZYmZ2XuJx3NMn2awdHwf1fezAJbq3/gold-ticket.json";

    address ticketsImplementation;

    uint256 public numRaffles;
    mapping(uint256 => Raffle) private raffles;
    mapping(address => uint256) public ticketsToRaffleId;
    mapping(uint256 => uint256) requestIdToLot;

    mapping(uint256 => mapping(uint256 => bool)) public claimedPrize;

    uint256 constant ONE_MONTH = 3600 * 24 * 28;

    IGouda constant gouda = IGouda(0x3aD30C5E3496BE07968579169a96f00D56De4C1A);
    IMadMouse constant genesis = IMadMouse(0x3aD30c5e2985e960E89F4a28eFc91BA73e104b77);
    IMadMouse constant troupe = IMadMouse(0x74d9d90a7fc261FBe92eD47B606b6E0E00d75E70);

    /* ------------- External ------------- */

    function buyTicket(uint256 raffleId, uint256 requirementData) external noContract {
        unchecked {
            Raffle storage raffle = raffles[raffleId];
            uint256 ticketSupply = raffle.ticketSupply;

            if (ticketSupply == raffle.maxTicketSupply) revert TicketsMaxSupplyReached();
            if (block.timestamp < raffle.start || raffle.end < block.timestamp || raffle.cancelled)
                revert RaffleNotActive();

            uint256 requirement = raffle.requirement;
            if (requirement != 0 && !fulfillsRequirement(msg.sender, requirement, requirementData))
                revert RequirementNotFulfilled();

            // verifies ownership
            gouda.burnFrom(msg.sender, uint256(raffle.ticketPrice) * 1e18);

            uint256 ticketId = ++ticketSupply;
            raffle.ticketSupply = uint16(ticketSupply);

            Tickets(raffle.tickets).mint(msg.sender, ticketId);
        }
    }

    function claimPrize(uint256 raffleId, uint256 ticketId) external noContract {
        Raffle storage raffle = raffles[raffleId];
        Tickets tickets = Tickets(raffle.tickets);

        uint256 randomSeed = raffle.randomSeed;

        if (raffle.cancelled) revert RaffleNotActive();
        if (randomSeed == 0) revert RaffleUnrevealed();

        uint256 numPrizes = raffle.prizeTokenIds.length;
        uint256 numEntries = raffle.ticketSupply;
        bool win;
        uint256 prizeId;

        // ticketId starts at 1; ownerOf is checked, so underflow is no issue
        unchecked {
            (win, prizeId) = Choice.indexOfSelectNOfM(ticketId - 1, numPrizes, numEntries, randomSeed);
        }

        if (tickets.ownerOf(ticketId) != msg.sender || !win) revert BetterLuckNextTime();

        uint256 prizeTokenId = raffle.prizeTokenIds[prizeId];

        // encode whether the user has claimed in with the tokenId by setting the first bit; saves a cold sload/sstore
        if (prizeTokenId > 0x7fffffff) revert PrizeAlreadyClaimed();
        raffle.prizeTokenIds[prizeId] = uint32(prizeTokenId) | 0x80000000;

        IERC721 prizeNFT = IERC721(raffle.prizeNFT);
        prizeNFT.transferFrom(owner(), msg.sender, prizeTokenId & 0x0fffffff);
    }

    function burnTickets(uint256[] calldata burnRaffleIds, uint256[] calldata burnTicketIds) external noContract {
        Raffle storage raffle;

        uint256 refund;
        uint256 refundRate;

        uint256 numBurnTickets = burnTicketIds.length;
        if (numBurnTickets == 0) revert NeedsMoarTickets();

        unchecked {
            for (uint256 i; i < numBurnTickets; ++i) {
                raffle = raffles[burnRaffleIds[i]];
                Tickets tickets = Tickets(raffle.tickets);

                tickets.burnFrom(msg.sender, burnTicketIds[i]);

                refundRate = raffle.refundRate;
                // type(uint40).max * 1e18 * type(uint8).max < type(uint256).max
                if (refundRate > 0) refund += (uint256(raffle.ticketPrice) * 1e18 * (refundRate + 1)) >> 8; // slight imprecission is ok
            }
        }

        gouda.mint(msg.sender, refund);
    }

    /* ------------- View ------------- */

    function isWinningTicket(uint256 raffleId, uint256 ticketId) public view returns (bool win) {
        Raffle storage raffle = raffles[raffleId];
        uint256 randomSeed = raffle.randomSeed;

        if (raffle.cancelled || randomSeed == 0) return false;

        uint256 numPrizes = raffle.prizeTokenIds.length;
        uint256 numEntrants = raffle.ticketSupply;

        unchecked {
            (win, ) = Choice.indexOfSelectNOfM(ticketId - 1, numPrizes, numEntrants, randomSeed);
        }
        return win;
    }

    function getWinningTickets(uint256 raffleId) public view returns (uint256[] memory ticketIds) {
        Raffle storage raffle = raffles[raffleId];

        uint256 randomSeed = raffle.randomSeed;

        if (raffle.cancelled || randomSeed == 0) return ticketIds;

        uint256 numPrizes = raffle.prizeTokenIds.length;
        uint256 numEntrants = raffle.ticketSupply;

        return Choice.selectNOfM(numPrizes, numEntrants, randomSeed, 1);
    }

    function getWinners(uint256 raffleId) public view returns (address[] memory winners) {
        Tickets tickets = Tickets(raffles[raffleId].tickets);

        uint256[] memory prizeTokenIds = getWinningTickets(raffleId);
        uint256 numIds = prizeTokenIds.length;

        winners = new address[](numIds);
        for (uint256 i; i < numIds; ++i) winners[i] = tickets.ownerOf(prizeTokenIds[i]);
    }

    function getRaffle(uint256 raffleId) external view returns (Raffle memory) {
        return raffles[raffleId];
    }

    function fulfillsRequirement(
        address user,
        uint256 requirement,
        uint256 data
    ) public view returns (bool) {
        unchecked {
            if (requirement == 1 && genesis.numOwned(user) > 0) return true;
            else if (requirement == 2 && troupe.numOwned(user) > 0) return true;
            else if (
                requirement == 3 &&
                // specify data == 1 to direct that user is holding troupe and potentially save an sload;
                // or leave unspecified and worst-case check both
                ((data != 2 && troupe.numOwned(user) > 0) || (data != 1 && genesis.numOwned(user) > 0))
            ) return true;
            else if (
                requirement == 4 &&
                (
                    data > 5000 // specify owner-held id: data > 5000 refers to genesis collection
                        ? genesis.getLevel(data - 5000) > 1 && genesis.ownerOf(data - 5000) == user
                        : troupe.getLevel(data) > 1 && troupe.ownerOf(data) == user
                )
            ) return true;
            else if (
                requirement == 5 &&
                (
                    data > 5000
                        ? genesis.getLevel(data - 5000) > 2 && genesis.ownerOf(data - 5000) == user
                        : troupe.getLevel(data) > 2 && troupe.ownerOf(data) == user
                )
            ) return true;
            return false;
        }
    }

    /* ------------- Tickets Callbacks ------------- */

    function ticketsSupply() external view returns (uint256) {
        uint256 raffleId = ticketsToRaffleId[msg.sender];
        return raffles[raffleId].ticketSupply;
    }

    function ticketsName() external view returns (string memory) {
        uint256 raffleId = ticketsToRaffleId[msg.sender];
        string memory prizeNFTName = IERC721Metadata(raffles[raffleId].prizeNFT).name();
        return string.concat("Gouda Slot Machine Raffle #", raffleId.toString(), ": ", prizeNFTName);
    }

    function ticketsSymbol() external view returns (string memory) {
        uint256 raffleId = ticketsToRaffleId[msg.sender];
        return string.concat("GRAFF", raffleId.toString());
    }

    function ticketsTokenURI(uint256 id) external view returns (string memory) {
        uint256 raffleId = ticketsToRaffleId[msg.sender];
        return
            raffles[raffleId].randomSeed != 0
                ? isWinningTicket(raffleId, id) ? winningTicketURI : losingTicketURI
                : ticketURI;
    }

    /* ------------- Owner ------------- */

    function feedToys(
        address prizeNFT,
        uint32[] calldata prizeTokenIds,
        uint40 start,
        uint40 end,
        uint16 ticketPrice,
        uint8 refundRate,
        uint16 maxTicketSupply,
        uint8 requirement
    ) external onlyOwner {
        unchecked {
            // don't transfer to contract to save gas
            // need to make sure that contract has allowance to transfer NFTs of owner
            // for (uint256 i; i < prizeTokenIds.length; ++i)
            //     IERC721(prizeNFT).transferFrom(msg.sender, address(this), prizeTokenIds[i]);

            uint256 raffleId = ++numRaffles;
            Raffle storage raffle = raffles[raffleId];

            if (ticketPrice >= 1e18) revert InvalidTicketPrice(); // sanity check, since ticketPrice is kept in multiples of 1e18
            if (ticketsImplementation == address(0)) revert TicketsImplementationUnset();
            if (ONE_MONTH < start - block.timestamp || ONE_MONTH < end - start) revert InvalidTimestamps(); // underflow desired

            address tickets = createTicketsClone(ticketsImplementation);
            ticketsToRaffleId[tickets] = raffleId;

            raffle.tickets = tickets;
            raffle.prizeNFT = prizeNFT;
            raffle.prizeTokenIds = prizeTokenIds;
            raffle.start = start;
            raffle.end = end;
            raffle.ticketPrice = ticketPrice;
            raffle.refundRate = refundRate;
            raffle.maxTicketSupply = maxTicketSupply;
            raffle.requirement = requirement;

            emit Chachingg();
        }
    }

    // should normally be ignored
    function incrementRaffleId(uint256 num) external onlyOwner {
        numRaffles += num;
    }

    function editRaffle(
        uint256 raffleId,
        address prizeNFT,
        uint32[] calldata prizeTokenIds,
        uint40 start,
        uint40 end,
        uint16 ticketPrice,
        uint8 refundRate,
        uint16 maxTicketSupply,
        uint8 requirement,
        bool cancelled
    ) external onlyOwner {
        unchecked {
            if (ticketPrice >= 1e18) revert InvalidTicketPrice();
            if (block.timestamp + ONE_MONTH < start || ONE_MONTH < end - start) revert InvalidTimestamps();

            Raffle storage raffle = raffles[raffleId];

            raffle.prizeNFT = prizeNFT;
            raffle.prizeTokenIds = prizeTokenIds;
            raffle.start = start;
            raffle.end = end;
            raffle.ticketPrice = ticketPrice;
            raffle.refundRate = refundRate;
            raffle.maxTicketSupply = maxTicketSupply;
            raffle.requirement = requirement;
            raffle.cancelled = cancelled;
        }
    }

    function rescueToys(IERC721 toy, uint256[] calldata toyIds) external onlyOwner {
        unchecked {
            for (uint256 i; i < toyIds.length; ++i) toy.transferFrom(address(this), msg.sender, toyIds[i]);
        }
    }

    function rescueERC20(IERC20 token) external onlyOwner {
        token.transfer(msg.sender, token.balanceOf(address(this)));
    }

    function triggerClaw(uint256 raffleId) external onlyOwner {
        Raffle storage raffle = raffles[raffleId];

        if (raffle.cancelled) revert RaffleNotActive();
        if (block.timestamp < raffle.end) revert RaffleOngoing();
        if (raffle.randomSeed != 0) revert MachineBeDoinWork();

        emit GrappleGrapple();
        emit BZZzzt();

        raffle.randomSeed = uint40(uint256(blockhash(block.number - 1)));
    }

    function setTicketsImplementation(address ticketsImplementation_) external onlyOwner {
        ticketsImplementation = ticketsImplementation_;
    }

    function setTicketURIs(
        string calldata ticketURI_,
        string calldata losingTicketURI_,
        string calldata winningTicketURI_
    ) external onlyOwner {
        ticketURI = ticketURI_;
        losingTicketURI = losingTicketURI_;
        winningTicketURI = winningTicketURI_;
    }

    /* ------------- Private ------------- */

    // https://github.com/optionality/clone-factory/blob/master/contracts/CloneFactory.sol
    function createTicketsClone(address target) private returns (address result) {
        bytes20 targetBytes = bytes20(target);
        assembly {
            let clone := mload(0x40)
            mstore(clone, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)
            mstore(add(clone, 0x14), targetBytes)
            mstore(add(clone, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)
            result := create(0, clone, 0x37)
        }
    }

    /* ------------- Modifier ------------- */

    modifier noContract() {
        if (msg.sender != tx.origin) revert ContractCallNotAllowed();
        _;
    }
}

File 2 of 13 : Strings.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)

pragma solidity ^0.8.0;

/**
 * @dev String operations.
 */
library Strings {
    bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";

    /**
     * @dev Converts a `uint256` to its ASCII `string` decimal representation.
     */
    function toString(uint256 value) internal pure returns (string memory) {
        // Inspired by OraclizeAPI's implementation - MIT licence
        // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol

        if (value == 0) {
            return "0";
        }
        uint256 temp = value;
        uint256 digits;
        while (temp != 0) {
            digits++;
            temp /= 10;
        }
        bytes memory buffer = new bytes(digits);
        while (value != 0) {
            digits -= 1;
            buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
            value /= 10;
        }
        return string(buffer);
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
     */
    function toHexString(uint256 value) internal pure returns (string memory) {
        if (value == 0) {
            return "0x00";
        }
        uint256 temp = value;
        uint256 length = 0;
        while (temp != 0) {
            length++;
            temp >>= 8;
        }
        return toHexString(value, length);
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
     */
    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
        bytes memory buffer = new bytes(2 * length + 2);
        buffer[0] = "0";
        buffer[1] = "x";
        for (uint256 i = 2 * length + 1; i > 1; --i) {
            buffer[i] = _HEX_SYMBOLS[value & 0xf];
            value >>= 4;
        }
        require(value == 0, "Strings: hex length insufficient");
        return string(buffer);
    }
}

File 3 of 13 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (interfaces/IERC20.sol)

pragma solidity ^0.8.0;

import "../token/ERC20/IERC20.sol";

File 4 of 13 : IERC721.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (interfaces/IERC721.sol)

pragma solidity ^0.8.0;

import "../token/ERC721/IERC721.sol";

File 5 of 13 : IERC721Metadata.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (interfaces/IERC721Metadata.sol)

pragma solidity ^0.8.0;

import "../token/ERC721/extensions/IERC721Metadata.sol";

File 6 of 13 : interfaces.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.12;

interface IGouda {
    function transferFrom(
        address from,
        address to,
        uint256 amount
    ) external;

    function transfer(address to, uint256 amount) external;

    function balanceOf(address account) external view returns (uint256);

    function mint(address user, uint256 amount) external;

    function burnFrom(address account, uint256 amount) external;
}

interface IMadMouse {
    function numStaked(address user) external view returns (uint256);

    function numOwned(address user) external view returns (uint256);

    function balanceOf(address user) external view returns (uint256);

    function ownerOf(uint256 tokenId) external view returns (address);

    function getLevel(uint256 tokenId) external view returns (uint256);

    function getDNA(uint256 tokenId) external view returns (uint256);
}

File 7 of 13 : Ownable.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

error CallerNotOwner();

abstract contract Ownable {
    address _owner = msg.sender;

    function owner() public view returns (address) {
        return _owner;
    }

    function transferOwnership(address newOwner) external onlyOwner {
        _owner = newOwner;
    }

    modifier onlyOwner() {
        if (msg.sender != _owner) revert CallerNotOwner();
        _;
    }
}

File 8 of 13 : Choice.sol
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.12;

// author: phaze

// assumption: n << m
// caveats: splits random number into 16 parts for efficiency
// this means that 65536 is the highest random number
// (can skew uniform distributions when m is hight)
library Choice {
    function selectNOfM(
        uint256 n,
        uint256 m,
        uint256 r
    ) internal pure returns (uint256[] memory) {
        unchecked {
            if (n > m) n = m;

            uint256[] memory choice = new uint256[](n);

            uint256 s;
            uint256 slot;

            uint256 j;
            uint256 c;

            bool invalidChoice;

            for (uint256 i; i < n; ++i) {
                do {
                    slot = (s & 0xF) << 4;
                    if (slot == 0 && i != 0) r = uint256(keccak256(abi.encode(r, s)));
                    c = ((r >> slot) & 0xFFFF) % m;
                    invalidChoice = false;
                    for (j = 0; j < i && !invalidChoice; ++j) invalidChoice = choice[j] == c;
                    ++s;
                } while (invalidChoice);

                choice[i] = c;
            }
            return choice;
        }
    }

    function selectNOfM(
        uint256 n,
        uint256 m,
        uint256 r,
        uint256 offset
    ) internal pure returns (uint256[] memory) {
        unchecked {
            if (n > m) n = m;

            uint256[] memory choice = new uint256[](n);

            uint256 s;
            uint256 slot;

            uint256 j;
            uint256 c;

            bool invalidChoice;

            for (uint256 i; i < n; ++i) {
                do {
                    slot = (s & 0xF) << 4;
                    if (slot == 0 && i != 0) r = uint256(keccak256(abi.encode(r, s)));
                    c = (((r >> slot) & 0xFFFF) % m) + offset;
                    invalidChoice = false;
                    for (j = 0; j < i && !invalidChoice; ++j) invalidChoice = choice[j] == c;
                    ++s;
                } while (invalidChoice);

                choice[i] = c;
            }
            return choice;
        }
    }

    function indexOfSelectNOfM(
        uint256 x,
        uint256 n,
        uint256 m,
        uint256 r
    ) internal pure returns (bool, uint256) {
        unchecked {
            if (n > m) n = m;

            uint256[] memory choice = new uint256[](n);

            uint256 s;
            uint256 slot;

            uint256 j;
            uint256 c;

            bool invalidChoice;

            for (uint256 i; i < n; ++i) {
                do {
                    slot = (s & 0xF) << 4;
                    if (slot == 0 && i != 0) r = uint256(keccak256(abi.encode(r, s)));
                    c = ((r >> slot) & 0xFFFF) % m;
                    invalidChoice = false;
                    for (j = 0; j < i && !invalidChoice; ++j) invalidChoice = choice[j] == c;
                    ++s;
                } while (invalidChoice);

                if (x == c) return (true, i);

                choice[i] = c;
            }
            return (false, 0);
        }
    }
}

File 9 of 13 : SoulboundTickets.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.12;

// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM`MMM NMM MMM MMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMM  MMMMhMMMMMMM  MMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
// MMMMMMMMMMMMMMMMMMMMMMMMMM  MM-MMMMM   MMMM    MMMM   lMMMDMMMMMMMMMMMMMMMMMMMMMMMMMM
// MMMMMMMMMMMMMMMMMMMMMMM jMMMMl   MM    MMM  M  MMM   M   MMMM MMMMMMMMMMMMMMMMMMMMMMM
// MMMMMMMMMMMMMMMMMMMM MMMMMMMMM  , `     M   Y   MM  MMM  BMMMMMM MMMMMMMMMMMMMMMMMMMM
// MMMMMMMMMMMMMMMMM MMMMMMMMMMMM  IM  MM  l  MMM  X   MM.  MMMMMMMMMM MMMMMMMMMMMMMMMMM
// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMM.nlMMMMMMMMMMMMMMMMM]._  MMMMMMMMMMMMMMMNMMMMMMMMMMMMMM
// MMMMMMMMMMMMMM TMMMMMMMMMMMMMMMMMM          +MMMMMMMMMMMM:  rMMMMMMMMN MMMMMMMMMMMMMM
// MMMMMMMMMMMM MMMMMMMMMMMMMMMM                  MMMMMM           MMMMMMMM qMMMMMMMMMMM
// MMMMMMMMMMMMMMMMMMMMMMMMMMM^                   MMMb              .MMMMMMMMMMMMMMMMMMM
// MMMMMMMMMM MMMMMMMMMMMMMMM                     MM                  MMMMMMM MMMMMMMMMM
// MMMMMMMMMMMMMMMMMMMMMMMMMM                     M                   gMMMMMMMMMMMMMMMMM
// MMMMMMMMu MMMMMMMMMMMMMMM                                           MMMMMMM .MMMMMMMM
// MMMMMMMMMMMMMMMMMMMMMMMMM                                           :MMMMMMMMMMMMMMMM
// MMMMMMM^ MMMMMMMMMMMMMMMl                                            MMMMMMMM MMMMMMM
// MMMMMMMMMMMMMMMMMMMMMMMM                                             MMMMMMMMMMMMMMMM
// MMMMMMM MMMMMMMMMMMMMMMM                                             MMMMMMMM MMMMMMM
// MMMMMMMMMMMMMMMMMMMMMMMM                                             MMMMMMMMMMMMMMMM
// MMMMMMr MMMMMMMMMMMMMMMM                                             MMMMMMMM .MMMMMM
// MMMMMMMMMMMMMMMMMMMMMMMMM                                           MMMMMMMMMMMMMMMMM
// MMMMMMM MMMMMMMMMMMMMMMMM                                         DMMMMMMMMMM MMMMMMM
// MMMMMMMMMMMMMMMMMMMMMMMMMM                              MMMMMMMMMMMMMMMMMMMMMMMMMMMMM
// MMMMMMM|`MMMMMMMMMMMMMMMM         q                      MMMMMMMMMMMMMMMMMMM  MMMMMMM
// MMMMMMMMMTMMMMMMMMMMMMMMM                               qMMMMMMMMMMMMMMMMMMgMMMMMMMMM
// MMMMMMMMq MMMMMMMMMMMMMMMh                             jMMMMMMMMMMMMMMMMMMM nMMMMMMMM
// MMMMMMMMMM MMMMMMMMMMMMMMMQ      nc    -MMMMMn        MMMMMMMMMMMMMMMMMMMM MMMMMMMMMM
// MMMMMMMMMM.MMMMMMMMMMMMMMMMMMl            M1       `MMMMMMMMMMMMMMMMMMMMMMrMMMMMMMMMM
// MMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMM               :MMMMMMMMMM MMMMMMMMMMMM qMMMMMMMMMMM
// MMMMMMMMMMMMMMMMMMMMMMMMMM  MMMMMMX       MMMMMMMMMMMMMMM  uMMMMMMMMMMMMMMMMMMMMMMMMM
// MMMMMMMMMMMMMM DMMMMMMMMM   IMMMMMMMMMMMMMMMMMMMMMMM   M   Y  MMMMMMMN MMMMMMMMMMMMMM
// MMMMMMMMMMMMMMMMM MMMMMM    ``    M      MM  MMM   , MMMM    Mv  MMM MMMMMMMMMMMMMMMM
// MMMMMMMMMMMMMMMMMMM MMh  Ml  .   M  MMMM  I  MMMT  M     :M   ,MMMMMMMMMMMMMMMMMMMMMM
// MMMMMMMMMMMMMMMMMMMM MMMMMMMMt  MM  MMMMB m  ]MMM  MMMM   MMMMMM MMMMMMMMMMMMMMMMMMMM
// MMMMMMMMMMMMMMMMMMMMMMM MMMMM  MMM   TM   MM  9U  .MM  _MMMMM MMMMMMMMMMMMMMMMMMMMMMM
// MMMMMMMMMMMMMMMMMMMMMMMMMM YMMMMMMMn     MMMM    +MMMMMMM1`MMMMMMMMMMMMMMMMMMMMMMMMMM
// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM.`MMM MMM MMMMM`.MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM author: phaze MMM

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

error CallerNotOwner();
error CallerNotApproved();
error CallerNotOwnerNorApproved();

error MintExceedsLimit();

error TransferFromIncorrectOwner();
error TransferToNonERC721Receiver();
error TransferToZeroAddress();

error BurnFromIncorrectOwner();

contract SoulboundTickets {
    event Transfer(address indexed from, address indexed to, uint256 indexed id);

    mapping(uint256 => address) public ownerOf;
    mapping(address => uint256) public balanceOf;
    mapping(uint256 => address) public getApproved;
    mapping(address => mapping(address => bool)) public isApprovedForAll;

    Gachapon immutable gachapon;

    constructor(Gachapon gachapon_) {
        gachapon = gachapon_;
    }

    /* ------------- View ------------- */

    function tokenURI(uint256 id) external view returns (string memory) {
        return gachapon.ticketsTokenURI(id);
    }

    function name() external view returns (string memory) {
        return gachapon.ticketsName();
    }

    function symbol() external view returns (string memory) {
        return gachapon.ticketsSymbol();
    }

    function supportsInterface(bytes4 interfaceId) external view virtual returns (bool) {
        return
            interfaceId == 0x01ffc9a7 || // ERC165 Interface ID for ERC165
            interfaceId == 0x80ac58cd || // ERC165 Interface ID for ERC721
            interfaceId == 0x5b5e139f; // ERC165 Interface ID for ERC721Metadata
    }

    /* ------------- Restricted ------------- */

    // @note assumes correct handling by master contract in order to save gas
    function mint(address to, uint256 id) external onlyGachapon {
        if (balanceOf[to] == 1) revert MintExceedsLimit();

        ownerOf[id] = to;

        unchecked {
            ++balanceOf[to];
        }

        emit Transfer(address(0), to, id);
    }

    function burnFrom(address from, uint256 id) external onlyGachapon {
        if (ownerOf[id] != from) revert BurnFromIncorrectOwner();

        unchecked {
            --balanceOf[from];
        }

        emit Transfer(from, address(0), id);

        delete ownerOf[id];
    }

    modifier onlyGachapon() {
        if (msg.sender != address(gachapon)) revert CallerNotApproved();
        _;
    }

    /* ------------- O(N) Read Only ------------- */

    function ticketIdOf(address user) external view returns (uint256) {
        unchecked {
            uint256 supply = gachapon.ticketsSupply() + 1;
            for (uint256 id; id < supply; ++id) if (ownerOf[id] == user) return id;
            return 0;
        }
    }
}

interface IERC721Receiver {
    function onERC721Received(
        address operator,
        address from,
        uint256 id,
        bytes calldata data
    ) external returns (bytes4);
}

File 10 of 13 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

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

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

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

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

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

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

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

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

File 11 of 13 : IERC721.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721.sol)

pragma solidity ^0.8.0;

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

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

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

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

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

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

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

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

    /**
     * @dev Transfers `tokenId` token from `from` to `to`.
     *
     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external;

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

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

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

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

File 12 of 13 : IERC165.sol
// 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);
}

File 13 of 13 : IERC721Metadata.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)

pragma solidity ^0.8.0;

import "../IERC721.sol";

/**
 * @title ERC-721 Non-Fungible Token Standard, optional metadata extension
 * @dev See https://eips.ethereum.org/EIPS/eip-721
 */
interface IERC721Metadata is IERC721 {
    /**
     * @dev Returns the token collection name.
     */
    function name() external view returns (string memory);

    /**
     * @dev Returns the token collection symbol.
     */
    function symbol() external view returns (string memory);

    /**
     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.
     */
    function tokenURI(uint256 tokenId) external view returns (string memory);
}

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 10000
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[],"name":"BetterLuckNextTime","type":"error"},{"inputs":[],"name":"CallerNotOwner","type":"error"},{"inputs":[],"name":"ContractCallNotAllowed","type":"error"},{"inputs":[],"name":"InvalidTicketPrice","type":"error"},{"inputs":[],"name":"InvalidTimestamps","type":"error"},{"inputs":[],"name":"MachineBeDoinWork","type":"error"},{"inputs":[],"name":"NeedsMoarTickets","type":"error"},{"inputs":[],"name":"PrizeAlreadyClaimed","type":"error"},{"inputs":[],"name":"RaffleNotActive","type":"error"},{"inputs":[],"name":"RaffleOngoing","type":"error"},{"inputs":[],"name":"RaffleUnrevealed","type":"error"},{"inputs":[],"name":"RequirementNotFulfilled","type":"error"},{"inputs":[],"name":"TicketsImplementationUnset","type":"error"},{"inputs":[],"name":"TicketsMaxSupplyReached","type":"error"},{"anonymous":false,"inputs":[],"name":"BZZzzt","type":"event"},{"anonymous":false,"inputs":[],"name":"Chachingg","type":"event"},{"anonymous":false,"inputs":[],"name":"GrappleGrapple","type":"event"},{"inputs":[{"internalType":"uint256[]","name":"burnRaffleIds","type":"uint256[]"},{"internalType":"uint256[]","name":"burnTicketIds","type":"uint256[]"}],"name":"burnTickets","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"raffleId","type":"uint256"},{"internalType":"uint256","name":"requirementData","type":"uint256"}],"name":"buyTicket","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"raffleId","type":"uint256"},{"internalType":"uint256","name":"ticketId","type":"uint256"}],"name":"claimPrize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"claimedPrize","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"raffleId","type":"uint256"},{"internalType":"address","name":"prizeNFT","type":"address"},{"internalType":"uint32[]","name":"prizeTokenIds","type":"uint32[]"},{"internalType":"uint40","name":"start","type":"uint40"},{"internalType":"uint40","name":"end","type":"uint40"},{"internalType":"uint16","name":"ticketPrice","type":"uint16"},{"internalType":"uint8","name":"refundRate","type":"uint8"},{"internalType":"uint16","name":"maxTicketSupply","type":"uint16"},{"internalType":"uint8","name":"requirement","type":"uint8"},{"internalType":"bool","name":"cancelled","type":"bool"}],"name":"editRaffle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"prizeNFT","type":"address"},{"internalType":"uint32[]","name":"prizeTokenIds","type":"uint32[]"},{"internalType":"uint40","name":"start","type":"uint40"},{"internalType":"uint40","name":"end","type":"uint40"},{"internalType":"uint16","name":"ticketPrice","type":"uint16"},{"internalType":"uint8","name":"refundRate","type":"uint8"},{"internalType":"uint16","name":"maxTicketSupply","type":"uint16"},{"internalType":"uint8","name":"requirement","type":"uint8"}],"name":"feedToys","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"requirement","type":"uint256"},{"internalType":"uint256","name":"data","type":"uint256"}],"name":"fulfillsRequirement","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"raffleId","type":"uint256"}],"name":"getRaffle","outputs":[{"components":[{"internalType":"address","name":"prizeNFT","type":"address"},{"internalType":"uint40","name":"start","type":"uint40"},{"internalType":"uint40","name":"end","type":"uint40"},{"internalType":"uint16","name":"ticketPrice","type":"uint16"},{"internalType":"uint16","name":"ticketSupply","type":"uint16"},{"internalType":"uint16","name":"maxTicketSupply","type":"uint16"},{"internalType":"uint8","name":"refundRate","type":"uint8"},{"internalType":"uint8","name":"requirement","type":"uint8"},{"internalType":"bool","name":"cancelled","type":"bool"},{"internalType":"uint40","name":"randomSeed","type":"uint40"},{"internalType":"address","name":"tickets","type":"address"},{"internalType":"uint32[]","name":"prizeTokenIds","type":"uint32[]"}],"internalType":"struct Gachapon.Raffle","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"raffleId","type":"uint256"}],"name":"getWinners","outputs":[{"internalType":"address[]","name":"winners","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"raffleId","type":"uint256"}],"name":"getWinningTickets","outputs":[{"internalType":"uint256[]","name":"ticketIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"num","type":"uint256"}],"name":"incrementRaffleId","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"raffleId","type":"uint256"},{"internalType":"uint256","name":"ticketId","type":"uint256"}],"name":"isWinningTicket","outputs":[{"internalType":"bool","name":"win","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"numRaffles","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"token","type":"address"}],"name":"rescueERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC721","name":"toy","type":"address"},{"internalType":"uint256[]","name":"toyIds","type":"uint256[]"}],"name":"rescueToys","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"ticketURI_","type":"string"},{"internalType":"string","name":"losingTicketURI_","type":"string"},{"internalType":"string","name":"winningTicketURI_","type":"string"}],"name":"setTicketURIs","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"ticketsImplementation_","type":"address"}],"name":"setTicketsImplementation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"ticketsName","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ticketsSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ticketsSymbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"ticketsToRaffleId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"ticketsTokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"raffleId","type":"uint256"}],"name":"triggerClaw","outputs":[],"stateMutability":"nonpayable","type":"function"}]

600080546001600160a01b03191633179055610100604052604860808181529062003b1b60a03980516200003c91600191602090910190620000b3565b5060405180608001604052806045815260200162003ad66045913980516200006d91600291602090910190620000b3565b5060405180608001604052806046815260200162003a906046913980516200009e91600391602090910190620000b3565b50348015620000ac57600080fd5b5062000196565b828054620000c19062000159565b90600052602060002090601f016020900481019282620000e5576000855562000130565b82601f106200010057805160ff191683800117855562000130565b8280016001018555821562000130579182015b828111156200013057825182559160200191906001019062000113565b506200013e92915062000142565b5090565b5b808211156200013e576000815560010162000143565b600181811c908216806200016e57607f821691505b602082108114156200019057634e487b7160e01b600052602260045260246000fd5b50919050565b6138ea80620001a66000396000f3fe608060405234801561001057600080fd5b50600436106101a35760003560e01c806385386405116100ee578063b862ae6c11610097578063ccec371611610071578063ccec3716146103b8578063dbccf418146103cb578063e4dafec9146103d3578063f2fde38b146103f357600080fd5b8063b862ae6c14610372578063bce9f75214610385578063c7120b9d1461039857600080fd5b80639ac7e9ca116100c85780639ac7e9ca146103115780639c1aa9061461033f578063ae3149681461035f57600080fd5b806385386405146102d05780638da5cb5b146102e35780639319e136146102fe57600080fd5b806364f3775811610150578063745684a61161012a578063745684a614610281578063796128a4146102aa5780637b154140146102bd57600080fd5b806364f377581461023b5780636b1426a41461024e5780636cfe348e1461026e57600080fd5b8063298ec20811610181578063298ec208146101fe5780633e8aa3881461021157806345e8ae1a1461022857600080fd5b806307144796146101a857806321b7bf59146101bd578063292406a1146101db575b600080fd5b6101bb6101b6366004612ec9565b610406565b005b6101c561065f565b6040516101d29190612f61565b60405180910390f35b6101ee6101e9366004612fca565b610757565b60405190151581526020016101d2565b6101bb61020c366004612fff565b610fee565b61021a60055481565b6040519081526020016101d2565b6101ee610236366004612fff565b611304565b6101bb610249366004613021565b61139a565b61026161025c366004613021565b611588565b6040516101d2919061303a565b6101c561027c366004613021565b6116e1565b336000908152600760209081526040808320548352600690915290206001015461ffff1661021a565b6101bb6102b83660046130c4565b6117cd565b6101bb6102cb366004612fff565b611b5e565b6101bb6102de3660046131c0565b611ee8565b6000546040516001600160a01b0390911681526020016101d2565b6101bb61030c36600461325a565b611f5b565b6101ee61031f366004612fff565b600960209081526000928352604080842090915290825290205460ff1681565b61035261034d366004613021565b612065565b6040516101d291906132af565b6101bb61036d3660046132e7565b6120da565b6101bb610380366004613312565b612158565b6101bb610393366004613021565b61243a565b61021a6103a63660046132e7565b60076020526000908152604090205481565b6101bb6103c63660046132e7565b612498565b6101c56125f2565b6103e66103e1366004613021565b612633565b6040516101d2919061342e565b6101bb6104013660046132e7565b612839565b33321461043f576040517f9453980400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008080838061047b576040517f55f8217c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b818110156105d057600660008a8a8481811061049c5761049c613530565b6020908102929092013583525081019190915260400160002060018101549095506c0100000000000000000000000090046001600160a01b0316806379cc6790338a8a868181106104ef576104ef613530565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e087901b1681526001600160a01b0390941660048501526020029190910135602483015250604401600060405180830381600087803b15801561055657600080fd5b505af115801561056a573d6000803e3d6000fd5b505050506001860154640100000000900460ff16935083156105c757855461ffff7e01000000000000000000000000000000000000000000000000000000000000909104166001850102670de0b6b3a76400000260081c94909401935b5060010161047e565b506040517f40c10f1900000000000000000000000000000000000000000000000000000000815233600482015260248101849052733ad30c5e3496be07968579169a96f00d56de4c1a906340c10f1990604401600060405180830381600087803b15801561063d57600080fd5b505af1158015610651573d6000803e3d6000fd5b505050505050505050505050565b3360009081526007602090815260408083205480845260069092528083205481517f06fdde030000000000000000000000000000000000000000000000000000000081529151606094926001600160a01b03909216916306fdde0391600480830192869291908290030181865afa1580156106de573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052610724919081019061358e565b905061072f826128b7565b81604051602001610741929190613659565b6040516020818303038152906040529250505090565b60008260011480156107fe57506040517f7168fcea0000000000000000000000000000000000000000000000000000000081526001600160a01b0385166004820152600090733ad30c5e2985e960e89f4a28efc91ba73e104b7790637168fcea90602401602060405180830381865afa1580156107d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107fc91906136da565b115b1561080b57506001610fe7565b8260021480156108b057506040517f7168fcea0000000000000000000000000000000000000000000000000000000081526001600160a01b03851660048201526000907374d9d90a7fc261fbe92ed47b606b6e0e00d75e7090637168fcea90602401602060405180830381865afa15801561088a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108ae91906136da565b115b156108bd57506001610fe7565b826003148015610a1a57508160021415801561096e57506040517f7168fcea0000000000000000000000000000000000000000000000000000000081526001600160a01b03851660048201526000907374d9d90a7fc261fbe92ed47b606b6e0e00d75e7090637168fcea90602401602060405180830381865afa158015610948573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061096c91906136da565b115b80610a1a575081600114158015610a1a57506040517f7168fcea0000000000000000000000000000000000000000000000000000000081526001600160a01b0385166004820152600090733ad30c5e2985e960e89f4a28efc91ba73e104b7790637168fcea90602401602060405180830381865afa1580156109f4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a1891906136da565b115b15610a2757506001610fe7565b826004148015610cf857506113888211610b7b576040517f86481d40000000000000000000000000000000000000000000000000000000008152600481018390526001907374d9d90a7fc261fbe92ed47b606b6e0e00d75e70906386481d4090602401602060405180830381865afa158015610aa7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610acb91906136da565b118015610b7657506040517f6352211e000000000000000000000000000000000000000000000000000000008152600481018390526001600160a01b038516907374d9d90a7fc261fbe92ed47b606b6e0e00d75e7090636352211e90602401602060405180830381865afa158015610b47573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b6b91906136f3565b6001600160a01b0316145b610cf8565b6040517f86481d400000000000000000000000000000000000000000000000000000000081527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec7883016004820152600190733ad30c5e2985e960e89f4a28efc91ba73e104b77906386481d4090602401602060405180830381865afa158015610c08573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c2c91906136da565b118015610cf857506040517f6352211e0000000000000000000000000000000000000000000000000000000081527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec78830160048201526001600160a01b03851690733ad30c5e2985e960e89f4a28efc91ba73e104b7790636352211e90602401602060405180830381865afa158015610cc9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ced91906136f3565b6001600160a01b0316145b15610d0557506001610fe7565b826005148015610fd657506113888211610e59576040517f86481d40000000000000000000000000000000000000000000000000000000008152600481018390526002907374d9d90a7fc261fbe92ed47b606b6e0e00d75e70906386481d4090602401602060405180830381865afa158015610d85573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610da991906136da565b118015610e5457506040517f6352211e000000000000000000000000000000000000000000000000000000008152600481018390526001600160a01b038516907374d9d90a7fc261fbe92ed47b606b6e0e00d75e7090636352211e90602401602060405180830381865afa158015610e25573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e4991906136f3565b6001600160a01b0316145b610fd6565b6040517f86481d400000000000000000000000000000000000000000000000000000000081527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec7883016004820152600290733ad30c5e2985e960e89f4a28efc91ba73e104b77906386481d4090602401602060405180830381865afa158015610ee6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f0a91906136da565b118015610fd657506040517f6352211e0000000000000000000000000000000000000000000000000000000081527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec78830160048201526001600160a01b03851690733ad30c5e2985e960e89f4a28efc91ba73e104b7790636352211e90602401602060405180830381865afa158015610fa7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fcb91906136f3565b6001600160a01b0316145b15610fe357506001610fe7565b5060005b9392505050565b333214611027576040517f9453980400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600660205260409020600181015461ffff8082169162010000900416811415611081576040517f2e4dd41200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b815474010000000000000000000000000000000000000000900464ffffffffff164210806110d4575081544279010000000000000000000000000000000000000000000000000090910464ffffffffff16105b806110ed575060018201546601000000000000900460ff165b15611124576040517f2ae47f7300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600182015465010000000000900460ff16801580159061114c575061114a338286610757565b155b15611183576040517fa33cd09400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82546040517f79cc67900000000000000000000000000000000000000000000000000000000081523360048201527e0100000000000000000000000000000000000000000000000000000000000090910461ffff16670de0b6b3a7640000026024820152733ad30c5e3496be07968579169a96f00d56de4c1a906379cc679090604401600060405180830381600087803b15801561122057600080fd5b505af1158015611234573d6000803e3d6000fd5b50505050600183810180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000169390910161ffff811693909317908190556040517f40c10f190000000000000000000000000000000000000000000000000000000081523360048201526024810184905283916c0100000000000000000000000090046001600160a01b0316906340c10f1990604401600060405180830381600087803b1580156112e457600080fd5b505af11580156112f8573d6000803e3d6000fd5b50505050505050505050565b60008281526006602052604081206001810154670100000000000000810464ffffffffff16906601000000000000900460ff1680611340575080155b1561135057600092505050611394565b6002820154600183015461ffff1661138c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff87018383866129f1565b509450505050505b92915050565b6000546001600160a01b031633146113de576040517f5cd8319200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600081815260066020526040902060018101546601000000000000900460ff1615611435576040517f2ae47f7300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8054790100000000000000000000000000000000000000000000000000900464ffffffffff16421015611494576040517f26429f5c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001810154670100000000000000900464ffffffffff16156114e2576040517f662c34a300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517fd486bfcd577d0f237d20588d84190c149c0b5bbc65395f36bf00ecf2ffb43b3c90600090a16040517f2d4d15d295ba951c9b11fa72018f8275fe07df4412b169e047bd0d574c6c312090600090a161153f60014361373f565b60019190910180547fffffffffffffffffffffffffffffffffffffffff0000000000ffffffffffffff16670100000000000000924064ffffffffff169290920291909117905550565b6000818152600660205260408120600101546060916c010000000000000000000000009091046001600160a01b0316906115c184612065565b80519091508067ffffffffffffffff8111156115df576115df61355f565b604051908082528060200260200182016040528015611608578160200160208202803683370190505b50935060005b818110156116d857836001600160a01b0316636352211e84838151811061163757611637613530565b60200260200101516040518263ffffffff1660e01b815260040161165d91815260200190565b602060405180830381865afa15801561167a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061169e91906136f3565b8582815181106116b0576116b0613530565b6001600160a01b03909216602092830291909101909101526116d181613756565b905061160e565b50505050919050565b3360009081526007602090815260408083205480845260069092529091206001015460609190670100000000000000900464ffffffffff1661172457600161173c565b61172e8184611304565b61173957600261173c565b60035b80546117479061378f565b80601f01602080910402602001604051908101604052809291908181526020018280546117739061378f565b80156117c05780601f10611795576101008083540402835291602001916117c0565b820191906000526020600020905b8154815290600101906020018083116117a357829003601f168201915b5050505050915050919050565b6000546001600160a01b03163314611811576040517f5cd8319200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60058054600101908190556000818152600660205260409020670de0b6b3a764000061ffff87161061186f576040517f06f6808b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004546001600160a01b03166118b1576040517f19d1aa2700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b428864ffffffffff16036224ea0010806118d6575087870364ffffffffff166224ea00105b1561190d576040517fd22806e300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600454600090611925906001600160a01b0316612b65565b6001600160a01b0381811660008181526007602052604090208690556001850180546bffffffffffffffffffffffff166c0100000000000000000000000090920291909117905583547fffffffffffffffffffffffff000000000000000000000000000000000000000016908e1617835590506119a6600283018c8c612d21565b50815461ffff8089167e01000000000000000000000000000000000000000000000000000000000000027dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff64ffffffffff8c8116790100000000000000000000000000000000000000000000000000027fffff0000000000ffffffffffffffffffffffffffffffffffffffffffffffffff918f167401000000000000000000000000000000000000000002919091167fffff00000000000000000000ffffffffffffffffffffffffffffffffffffffff90951694909417939093179290921691909117835560018301805460ff87811665010000000000027fffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffff948a1662010000027fffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000ffff928c1664010000000002929092167fffffffffffffffffffffffffffffffffffffffffffffffffffffff000000ffff9093169290921717929092169190911790556040517f6ffc078903936557084626668e47c8f214201fa460608302fec249b7aeb5f86a90600090a1505050505050505050505050565b333214611b97576040517f9453980400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600082815260066020526040902060018101546c0100000000000000000000000081046001600160a01b031690670100000000000000810464ffffffffff16906601000000000000900460ff1615611c1b576040517f2ae47f7300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80611c52576040517f1580c37f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002830154600184015461ffff16600080611c917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff89018585886129f1565b6040517f6352211e000000000000000000000000000000000000000000000000000000008152600481018b9052919350915033906001600160a01b03881690636352211e90602401602060405180830381865afa158015611cf6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d1a91906136f3565b6001600160a01b0316141580611d2e575081155b15611d65576040517f750fcd9900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000876002018281548110611d7c57611d7c613530565b6000918252602090912060088204015460079091166004026101000a900463ffffffff169050637fffffff811115611de0576040517fc235631200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80638000000017886002018381548110611dfc57611dfc613530565b600091825260209091206008820401805463ffffffff93841660046007909416939093026101000a928302939092021990911691909117905587546001600160a01b0316806323b872dd611e586000546001600160a01b031690565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526001600160a01b039091166004820152336024820152630fffffff85166044820152606401600060405180830381600087803b158015611ec357600080fd5b505af1158015611ed7573d6000803e3d6000fd5b505050505050505050505050505050565b6000546001600160a01b03163314611f2c576040517f5cd8319200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611f3860018787612dd6565b50611f4560028585612dd6565b50611f5260038383612dd6565b50505050505050565b6000546001600160a01b03163314611f9f576040517f5cd8319200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8181101561205f57836001600160a01b03166323b872dd3033868686818110611fcd57611fcd613530565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e088901b1681526001600160a01b03958616600482015294909316602485015250602090910201356044820152606401600060405180830381600087803b15801561203c57600080fd5b505af1158015612050573d6000803e3d6000fd5b50505050806001019050611fa2565b50505050565b6000818152600660205260409020600181015460609190670100000000000000810464ffffffffff16906601000000000000900460ff16806120a5575080155b156120b1575050919050565b600282015460018084015461ffff16906120d090839083908690612bce565b9695505050505050565b6000546001600160a01b0316331461211e576040517f5cd8319200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600480547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6000546001600160a01b0316331461219c576040517f5cd8319200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b670de0b6b3a76400008561ffff16106121e1576040517f06f6808b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8664ffffffffff166224ea0042011080612206575086860364ffffffffff166224ea00105b1561223d576040517fd22806e300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008b815260066020526040902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b038c1617815561228a600282018b8b612d21565b5080547fffff00000000000000000000ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000064ffffffffff998a16027fffff0000000000ffffffffffffffffffffffffffffffffffffffffffffffffff16177901000000000000000000000000000000000000000000000000009790981696909602969096177dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e0100000000000000000000000000000000000000000000000000000000000061ffff95861602178555600190940180547fffffffffffffffffffffffffffffffffffffffffffffffffffffff000000ffff1664010000000060ff948516027fffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000ffff1617620100009290941691909102929092177fffffffffffffffffffffffffffffffffffffffffffffffffff0000ffffffffff166501000000000091909316027fffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffff169190911766010000000000009215159290920291909117905550505050565b6000546001600160a01b0316331461247e576040517f5cd8319200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806005600082825461249091906137e3565b909155505050565b6000546001600160a01b031633146124dc576040517f5cd8319200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0382169063a9059cbb90339083906370a0823190602401602060405180830381865afa158015612543573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061256791906136da565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af11580156125ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125ee91906137fb565b5050565b3360009081526007602052604090205460609061260e816128b7565b60405160200161261e9190613818565b60405160208183030381529060405291505090565b604080516101808101825260008082526020820181905291810182905260608082018390526080820183905260a0820183905260c0820183905260e082018390526101008201839052610120820183905261014082019290925261016081019190915260008281526006602090815260409182902082516101808101845281546001600160a01b03808216835264ffffffffff740100000000000000000000000000000000000000008304811684870152790100000000000000000000000000000000000000000000000000830481168488015261ffff7e01000000000000000000000000000000000000000000000000000000000000909304831660608501526001850154808416608086015262010000810490931660a085015260ff6401000000008404811660c0860152650100000000008404811660e0860152660100000000000084041615156101008501526701000000000000008304166101208401526c010000000000000000000000009091041661014082015260028201805485518186028101860190965280865291949293610160860193929083018282801561282957602002820191906000526020600020906000905b82829054906101000a900463ffffffff1663ffffffff16815260200190600401906020826003010492830192600103820291508084116127ec5790505b5050505050815250509050919050565b6000546001600160a01b0316331461287d576040517f5cd8319200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6060816128f757505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115612921578061290b81613756565b915061291a9050600a8361388c565b91506128fb565b60008167ffffffffffffffff81111561293c5761293c61355f565b6040519080825280601f01601f191660200182016040528015612966576020820181803683370190505b5090505b84156129e95761297b60018361373f565b9150612988600a866138a0565b6129939060306137e3565b60f81b8183815181106129a8576129a8613530565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506129e2600a8661388c565b945061296a565b949350505050565b60008083851115612a00578394505b60008567ffffffffffffffff811115612a1b57612a1b61355f565b604051908082528060200260200182016040528015612a44578160200160208202803683370190505b5090506000806000806000805b8b811015612b4d575b60f0600487901b16945084158015612a7157508015155b15612aa65760408051602081018c90529081018790526060016040516020818303038152906040528051906020012060001c99505b8a61ffff8b871c1681612abb57612abb61385d565b06925060009150600093505b8084108015612ad4575081155b15612b025782878581518110612aec57612aec613530565b6020026020010151149150836001019350612ac7565b85600101955081612a5a57828d1415612b2757600198509650612b5c95505050505050565b82878281518110612b3a57612b3a613530565b6020908102919091010152600101612a51565b50600080975097505050505050505b94509492505050565b6000808260601b90506040517f3d602d80600a3d3981f3363d3d373d3d3d363d7300000000000000000000000081528160148201527f5af43d82803e903d91602b57fd5bf3000000000000000000000000000000000060288201526037816000f0949350505050565b606083851115612bdc578394505b60008567ffffffffffffffff811115612bf757612bf761355f565b604051908082528060200260200182016040528015612c20578160200160208202803683370190505b5090506000806000806000805b8b811015612d11575b60f0600487901b16945084158015612c4d57508015155b15612c825760408051602081018c90529081018790526060016040516020818303038152906040528051906020012060001c99505b888b61ffff8c881c1681612c9857612c9861385d565b0601925060009150600093505b8084108015612cb2575081155b15612ce05782878581518110612cca57612cca613530565b6020026020010151149150836001019350612ca5565b85600101955081612c365782878281518110612cfe57612cfe613530565b6020908102919091010152600101612c2d565b50949a9950505050505050505050565b82805482825590600052602060002090600701600890048101928215612dc65791602002820160005b83821115612d9457833563ffffffff1683826101000a81548163ffffffff021916908363ffffffff1602179055509260200192600401602081600301049283019260010302612d4a565b8015612dc45782816101000a81549063ffffffff0219169055600401602081600301049283019260010302612d94565b505b50612dd2929150612e68565b5090565b828054612de29061378f565b90600052602060002090601f016020900481019282612e045760008555612dc6565b82601f10612e3b578280017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00823516178555612dc6565b82800160010185558215612dc6579182015b82811115612dc6578235825591602001919060010190612e4d565b5b80821115612dd25760008155600101612e69565b60008083601f840112612e8f57600080fd5b50813567ffffffffffffffff811115612ea757600080fd5b6020830191508360208260051b8501011115612ec257600080fd5b9250929050565b60008060008060408587031215612edf57600080fd5b843567ffffffffffffffff80821115612ef757600080fd5b612f0388838901612e7d565b90965094506020870135915080821115612f1c57600080fd5b50612f2987828801612e7d565b95989497509550505050565b60005b83811015612f50578181015183820152602001612f38565b8381111561205f5750506000910152565b6020815260008251806020840152612f80816040850160208701612f35565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b6001600160a01b0381168114612fc757600080fd5b50565b600080600060608486031215612fdf57600080fd5b8335612fea81612fb2565b95602085013595506040909401359392505050565b6000806040838503121561301257600080fd5b50508035926020909101359150565b60006020828403121561303357600080fd5b5035919050565b6020808252825182820181905260009190848201906040850190845b8181101561307b5783516001600160a01b031683529284019291840191600101613056565b50909695505050505050565b803564ffffffffff8116811461309c57600080fd5b919050565b803561ffff8116811461309c57600080fd5b803560ff8116811461309c57600080fd5b60008060008060008060008060006101008a8c0312156130e357600080fd5b89356130ee81612fb2565b985060208a013567ffffffffffffffff81111561310a57600080fd5b6131168c828d01612e7d565b9099509750613129905060408b01613087565b955061313760608b01613087565b945061314560808b016130a1565b935061315360a08b016130b3565b925061316160c08b016130a1565b915061316f60e08b016130b3565b90509295985092959850929598565b60008083601f84011261319057600080fd5b50813567ffffffffffffffff8111156131a857600080fd5b602083019150836020828501011115612ec257600080fd5b600080600080600080606087890312156131d957600080fd5b863567ffffffffffffffff808211156131f157600080fd5b6131fd8a838b0161317e565b9098509650602089013591508082111561321657600080fd5b6132228a838b0161317e565b9096509450604089013591508082111561323b57600080fd5b5061324889828a0161317e565b979a9699509497509295939492505050565b60008060006040848603121561326f57600080fd5b833561327a81612fb2565b9250602084013567ffffffffffffffff81111561329657600080fd5b6132a286828701612e7d565b9497909650939450505050565b6020808252825182820181905260009190848201906040850190845b8181101561307b578351835292840192918401916001016132cb565b6000602082840312156132f957600080fd5b8135610fe781612fb2565b8015158114612fc757600080fd5b60008060008060008060008060008060006101408c8e03121561333457600080fd5b8b359a5060208c013561334681612fb2565b995060408c013567ffffffffffffffff81111561336257600080fd5b61336e8e828f01612e7d565b909a509850613381905060608d01613087565b965061338f60808d01613087565b955061339d60a08d016130a1565b94506133ab60c08d016130b3565b93506133b960e08d016130a1565b92506133c86101008d016130b3565b91506101208c01356133d981613304565b809150509295989b509295989b9093969950565b600081518084526020808501945080840160005b8381101561342357815163ffffffff1687529582019590820190600101613401565b509495945050505050565b602081526134486020820183516001600160a01b03169052565b60006020830151613462604084018264ffffffffff169052565b50604083015164ffffffffff8116606084015250606083015161ffff8116608084015250608083015161ffff811660a08401525060a083015161ffff811660c08401525060c083015160ff811660e08401525060e08301516101006134cb8185018360ff169052565b84015190506101206134e08482018315159052565b84015190506101406134fa8482018364ffffffffff169052565b8401519050610160613516848201836001600160a01b03169052565b8401516101808481015290506129e96101a08401826133ed565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000602082840312156135a057600080fd5b815167ffffffffffffffff808211156135b857600080fd5b818401915084601f8301126135cc57600080fd5b8151818111156135de576135de61355f565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156136245761362461355f565b8160405282815287602084870101111561363d57600080fd5b61364e836020830160208801612f35565b979650505050505050565b7f476f75646120536c6f74204d616368696e6520526166666c652023000000000081526000835161369181601b850160208801612f35565b7f3a20000000000000000000000000000000000000000000000000000000000000601b9184019182015283516136ce81601d840160208801612f35565b01601d01949350505050565b6000602082840312156136ec57600080fd5b5051919050565b60006020828403121561370557600080fd5b8151610fe781612fb2565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008282101561375157613751613710565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561378857613788613710565b5060010190565b600181811c908216806137a357607f821691505b602082108114156137dd577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b600082198211156137f6576137f6613710565b500190565b60006020828403121561380d57600080fd5b8151610fe781613304565b7f4752414646000000000000000000000000000000000000000000000000000000815260008251613850816005850160208701612f35565b9190910160050192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261389b5761389b61385d565b500490565b6000826138af576138af61385d565b50069056fea264697066735822122003beb9771599e48f614a87fd936a75f96fb6bbebd227ccd36a50b02a661ffd3c64736f6c634300080c0033697066733a2f2f516d5377727a7379534b6e6b516d52516f5a596d5a3258754a78334e4d6e326177644877663166657a414a6271332f676f6c642d7469636b65742e6a736f6e697066733a2f2f516d5377727a7379534b6e6b516d52516f5a596d5a3258754a78334e4d6e326177644877663166657a414a6271332f7265642d7469636b65742e6a736f6e697066733a2f2f516d5377727a7379534b6e6b516d52516f5a596d5a3258754a78334e4d6e326177644877663166657a414a6271332f73696c7665722d7469636b65742e6a736f6e

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106101a35760003560e01c806385386405116100ee578063b862ae6c11610097578063ccec371611610071578063ccec3716146103b8578063dbccf418146103cb578063e4dafec9146103d3578063f2fde38b146103f357600080fd5b8063b862ae6c14610372578063bce9f75214610385578063c7120b9d1461039857600080fd5b80639ac7e9ca116100c85780639ac7e9ca146103115780639c1aa9061461033f578063ae3149681461035f57600080fd5b806385386405146102d05780638da5cb5b146102e35780639319e136146102fe57600080fd5b806364f3775811610150578063745684a61161012a578063745684a614610281578063796128a4146102aa5780637b154140146102bd57600080fd5b806364f377581461023b5780636b1426a41461024e5780636cfe348e1461026e57600080fd5b8063298ec20811610181578063298ec208146101fe5780633e8aa3881461021157806345e8ae1a1461022857600080fd5b806307144796146101a857806321b7bf59146101bd578063292406a1146101db575b600080fd5b6101bb6101b6366004612ec9565b610406565b005b6101c561065f565b6040516101d29190612f61565b60405180910390f35b6101ee6101e9366004612fca565b610757565b60405190151581526020016101d2565b6101bb61020c366004612fff565b610fee565b61021a60055481565b6040519081526020016101d2565b6101ee610236366004612fff565b611304565b6101bb610249366004613021565b61139a565b61026161025c366004613021565b611588565b6040516101d2919061303a565b6101c561027c366004613021565b6116e1565b336000908152600760209081526040808320548352600690915290206001015461ffff1661021a565b6101bb6102b83660046130c4565b6117cd565b6101bb6102cb366004612fff565b611b5e565b6101bb6102de3660046131c0565b611ee8565b6000546040516001600160a01b0390911681526020016101d2565b6101bb61030c36600461325a565b611f5b565b6101ee61031f366004612fff565b600960209081526000928352604080842090915290825290205460ff1681565b61035261034d366004613021565b612065565b6040516101d291906132af565b6101bb61036d3660046132e7565b6120da565b6101bb610380366004613312565b612158565b6101bb610393366004613021565b61243a565b61021a6103a63660046132e7565b60076020526000908152604090205481565b6101bb6103c63660046132e7565b612498565b6101c56125f2565b6103e66103e1366004613021565b612633565b6040516101d2919061342e565b6101bb6104013660046132e7565b612839565b33321461043f576040517f9453980400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008080838061047b576040517f55f8217c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b818110156105d057600660008a8a8481811061049c5761049c613530565b6020908102929092013583525081019190915260400160002060018101549095506c0100000000000000000000000090046001600160a01b0316806379cc6790338a8a868181106104ef576104ef613530565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e087901b1681526001600160a01b0390941660048501526020029190910135602483015250604401600060405180830381600087803b15801561055657600080fd5b505af115801561056a573d6000803e3d6000fd5b505050506001860154640100000000900460ff16935083156105c757855461ffff7e01000000000000000000000000000000000000000000000000000000000000909104166001850102670de0b6b3a76400000260081c94909401935b5060010161047e565b506040517f40c10f1900000000000000000000000000000000000000000000000000000000815233600482015260248101849052733ad30c5e3496be07968579169a96f00d56de4c1a906340c10f1990604401600060405180830381600087803b15801561063d57600080fd5b505af1158015610651573d6000803e3d6000fd5b505050505050505050505050565b3360009081526007602090815260408083205480845260069092528083205481517f06fdde030000000000000000000000000000000000000000000000000000000081529151606094926001600160a01b03909216916306fdde0391600480830192869291908290030181865afa1580156106de573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052610724919081019061358e565b905061072f826128b7565b81604051602001610741929190613659565b6040516020818303038152906040529250505090565b60008260011480156107fe57506040517f7168fcea0000000000000000000000000000000000000000000000000000000081526001600160a01b0385166004820152600090733ad30c5e2985e960e89f4a28efc91ba73e104b7790637168fcea90602401602060405180830381865afa1580156107d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107fc91906136da565b115b1561080b57506001610fe7565b8260021480156108b057506040517f7168fcea0000000000000000000000000000000000000000000000000000000081526001600160a01b03851660048201526000907374d9d90a7fc261fbe92ed47b606b6e0e00d75e7090637168fcea90602401602060405180830381865afa15801561088a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108ae91906136da565b115b156108bd57506001610fe7565b826003148015610a1a57508160021415801561096e57506040517f7168fcea0000000000000000000000000000000000000000000000000000000081526001600160a01b03851660048201526000907374d9d90a7fc261fbe92ed47b606b6e0e00d75e7090637168fcea90602401602060405180830381865afa158015610948573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061096c91906136da565b115b80610a1a575081600114158015610a1a57506040517f7168fcea0000000000000000000000000000000000000000000000000000000081526001600160a01b0385166004820152600090733ad30c5e2985e960e89f4a28efc91ba73e104b7790637168fcea90602401602060405180830381865afa1580156109f4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a1891906136da565b115b15610a2757506001610fe7565b826004148015610cf857506113888211610b7b576040517f86481d40000000000000000000000000000000000000000000000000000000008152600481018390526001907374d9d90a7fc261fbe92ed47b606b6e0e00d75e70906386481d4090602401602060405180830381865afa158015610aa7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610acb91906136da565b118015610b7657506040517f6352211e000000000000000000000000000000000000000000000000000000008152600481018390526001600160a01b038516907374d9d90a7fc261fbe92ed47b606b6e0e00d75e7090636352211e90602401602060405180830381865afa158015610b47573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b6b91906136f3565b6001600160a01b0316145b610cf8565b6040517f86481d400000000000000000000000000000000000000000000000000000000081527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec7883016004820152600190733ad30c5e2985e960e89f4a28efc91ba73e104b77906386481d4090602401602060405180830381865afa158015610c08573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c2c91906136da565b118015610cf857506040517f6352211e0000000000000000000000000000000000000000000000000000000081527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec78830160048201526001600160a01b03851690733ad30c5e2985e960e89f4a28efc91ba73e104b7790636352211e90602401602060405180830381865afa158015610cc9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ced91906136f3565b6001600160a01b0316145b15610d0557506001610fe7565b826005148015610fd657506113888211610e59576040517f86481d40000000000000000000000000000000000000000000000000000000008152600481018390526002907374d9d90a7fc261fbe92ed47b606b6e0e00d75e70906386481d4090602401602060405180830381865afa158015610d85573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610da991906136da565b118015610e5457506040517f6352211e000000000000000000000000000000000000000000000000000000008152600481018390526001600160a01b038516907374d9d90a7fc261fbe92ed47b606b6e0e00d75e7090636352211e90602401602060405180830381865afa158015610e25573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e4991906136f3565b6001600160a01b0316145b610fd6565b6040517f86481d400000000000000000000000000000000000000000000000000000000081527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec7883016004820152600290733ad30c5e2985e960e89f4a28efc91ba73e104b77906386481d4090602401602060405180830381865afa158015610ee6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f0a91906136da565b118015610fd657506040517f6352211e0000000000000000000000000000000000000000000000000000000081527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec78830160048201526001600160a01b03851690733ad30c5e2985e960e89f4a28efc91ba73e104b7790636352211e90602401602060405180830381865afa158015610fa7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fcb91906136f3565b6001600160a01b0316145b15610fe357506001610fe7565b5060005b9392505050565b333214611027576040517f9453980400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600660205260409020600181015461ffff8082169162010000900416811415611081576040517f2e4dd41200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b815474010000000000000000000000000000000000000000900464ffffffffff164210806110d4575081544279010000000000000000000000000000000000000000000000000090910464ffffffffff16105b806110ed575060018201546601000000000000900460ff165b15611124576040517f2ae47f7300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600182015465010000000000900460ff16801580159061114c575061114a338286610757565b155b15611183576040517fa33cd09400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82546040517f79cc67900000000000000000000000000000000000000000000000000000000081523360048201527e0100000000000000000000000000000000000000000000000000000000000090910461ffff16670de0b6b3a7640000026024820152733ad30c5e3496be07968579169a96f00d56de4c1a906379cc679090604401600060405180830381600087803b15801561122057600080fd5b505af1158015611234573d6000803e3d6000fd5b50505050600183810180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000169390910161ffff811693909317908190556040517f40c10f190000000000000000000000000000000000000000000000000000000081523360048201526024810184905283916c0100000000000000000000000090046001600160a01b0316906340c10f1990604401600060405180830381600087803b1580156112e457600080fd5b505af11580156112f8573d6000803e3d6000fd5b50505050505050505050565b60008281526006602052604081206001810154670100000000000000810464ffffffffff16906601000000000000900460ff1680611340575080155b1561135057600092505050611394565b6002820154600183015461ffff1661138c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff87018383866129f1565b509450505050505b92915050565b6000546001600160a01b031633146113de576040517f5cd8319200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600081815260066020526040902060018101546601000000000000900460ff1615611435576040517f2ae47f7300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8054790100000000000000000000000000000000000000000000000000900464ffffffffff16421015611494576040517f26429f5c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001810154670100000000000000900464ffffffffff16156114e2576040517f662c34a300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517fd486bfcd577d0f237d20588d84190c149c0b5bbc65395f36bf00ecf2ffb43b3c90600090a16040517f2d4d15d295ba951c9b11fa72018f8275fe07df4412b169e047bd0d574c6c312090600090a161153f60014361373f565b60019190910180547fffffffffffffffffffffffffffffffffffffffff0000000000ffffffffffffff16670100000000000000924064ffffffffff169290920291909117905550565b6000818152600660205260408120600101546060916c010000000000000000000000009091046001600160a01b0316906115c184612065565b80519091508067ffffffffffffffff8111156115df576115df61355f565b604051908082528060200260200182016040528015611608578160200160208202803683370190505b50935060005b818110156116d857836001600160a01b0316636352211e84838151811061163757611637613530565b60200260200101516040518263ffffffff1660e01b815260040161165d91815260200190565b602060405180830381865afa15801561167a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061169e91906136f3565b8582815181106116b0576116b0613530565b6001600160a01b03909216602092830291909101909101526116d181613756565b905061160e565b50505050919050565b3360009081526007602090815260408083205480845260069092529091206001015460609190670100000000000000900464ffffffffff1661172457600161173c565b61172e8184611304565b61173957600261173c565b60035b80546117479061378f565b80601f01602080910402602001604051908101604052809291908181526020018280546117739061378f565b80156117c05780601f10611795576101008083540402835291602001916117c0565b820191906000526020600020905b8154815290600101906020018083116117a357829003601f168201915b5050505050915050919050565b6000546001600160a01b03163314611811576040517f5cd8319200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60058054600101908190556000818152600660205260409020670de0b6b3a764000061ffff87161061186f576040517f06f6808b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004546001600160a01b03166118b1576040517f19d1aa2700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b428864ffffffffff16036224ea0010806118d6575087870364ffffffffff166224ea00105b1561190d576040517fd22806e300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600454600090611925906001600160a01b0316612b65565b6001600160a01b0381811660008181526007602052604090208690556001850180546bffffffffffffffffffffffff166c0100000000000000000000000090920291909117905583547fffffffffffffffffffffffff000000000000000000000000000000000000000016908e1617835590506119a6600283018c8c612d21565b50815461ffff8089167e01000000000000000000000000000000000000000000000000000000000000027dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff64ffffffffff8c8116790100000000000000000000000000000000000000000000000000027fffff0000000000ffffffffffffffffffffffffffffffffffffffffffffffffff918f167401000000000000000000000000000000000000000002919091167fffff00000000000000000000ffffffffffffffffffffffffffffffffffffffff90951694909417939093179290921691909117835560018301805460ff87811665010000000000027fffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffff948a1662010000027fffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000ffff928c1664010000000002929092167fffffffffffffffffffffffffffffffffffffffffffffffffffffff000000ffff9093169290921717929092169190911790556040517f6ffc078903936557084626668e47c8f214201fa460608302fec249b7aeb5f86a90600090a1505050505050505050505050565b333214611b97576040517f9453980400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600082815260066020526040902060018101546c0100000000000000000000000081046001600160a01b031690670100000000000000810464ffffffffff16906601000000000000900460ff1615611c1b576040517f2ae47f7300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80611c52576040517f1580c37f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002830154600184015461ffff16600080611c917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff89018585886129f1565b6040517f6352211e000000000000000000000000000000000000000000000000000000008152600481018b9052919350915033906001600160a01b03881690636352211e90602401602060405180830381865afa158015611cf6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d1a91906136f3565b6001600160a01b0316141580611d2e575081155b15611d65576040517f750fcd9900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000876002018281548110611d7c57611d7c613530565b6000918252602090912060088204015460079091166004026101000a900463ffffffff169050637fffffff811115611de0576040517fc235631200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80638000000017886002018381548110611dfc57611dfc613530565b600091825260209091206008820401805463ffffffff93841660046007909416939093026101000a928302939092021990911691909117905587546001600160a01b0316806323b872dd611e586000546001600160a01b031690565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526001600160a01b039091166004820152336024820152630fffffff85166044820152606401600060405180830381600087803b158015611ec357600080fd5b505af1158015611ed7573d6000803e3d6000fd5b505050505050505050505050505050565b6000546001600160a01b03163314611f2c576040517f5cd8319200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611f3860018787612dd6565b50611f4560028585612dd6565b50611f5260038383612dd6565b50505050505050565b6000546001600160a01b03163314611f9f576040517f5cd8319200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8181101561205f57836001600160a01b03166323b872dd3033868686818110611fcd57611fcd613530565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e088901b1681526001600160a01b03958616600482015294909316602485015250602090910201356044820152606401600060405180830381600087803b15801561203c57600080fd5b505af1158015612050573d6000803e3d6000fd5b50505050806001019050611fa2565b50505050565b6000818152600660205260409020600181015460609190670100000000000000810464ffffffffff16906601000000000000900460ff16806120a5575080155b156120b1575050919050565b600282015460018084015461ffff16906120d090839083908690612bce565b9695505050505050565b6000546001600160a01b0316331461211e576040517f5cd8319200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600480547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6000546001600160a01b0316331461219c576040517f5cd8319200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b670de0b6b3a76400008561ffff16106121e1576040517f06f6808b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8664ffffffffff166224ea0042011080612206575086860364ffffffffff166224ea00105b1561223d576040517fd22806e300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008b815260066020526040902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b038c1617815561228a600282018b8b612d21565b5080547fffff00000000000000000000ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000064ffffffffff998a16027fffff0000000000ffffffffffffffffffffffffffffffffffffffffffffffffff16177901000000000000000000000000000000000000000000000000009790981696909602969096177dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e0100000000000000000000000000000000000000000000000000000000000061ffff95861602178555600190940180547fffffffffffffffffffffffffffffffffffffffffffffffffffffff000000ffff1664010000000060ff948516027fffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000ffff1617620100009290941691909102929092177fffffffffffffffffffffffffffffffffffffffffffffffffff0000ffffffffff166501000000000091909316027fffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffff169190911766010000000000009215159290920291909117905550505050565b6000546001600160a01b0316331461247e576040517f5cd8319200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806005600082825461249091906137e3565b909155505050565b6000546001600160a01b031633146124dc576040517f5cd8319200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0382169063a9059cbb90339083906370a0823190602401602060405180830381865afa158015612543573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061256791906136da565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af11580156125ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125ee91906137fb565b5050565b3360009081526007602052604090205460609061260e816128b7565b60405160200161261e9190613818565b60405160208183030381529060405291505090565b604080516101808101825260008082526020820181905291810182905260608082018390526080820183905260a0820183905260c0820183905260e082018390526101008201839052610120820183905261014082019290925261016081019190915260008281526006602090815260409182902082516101808101845281546001600160a01b03808216835264ffffffffff740100000000000000000000000000000000000000008304811684870152790100000000000000000000000000000000000000000000000000830481168488015261ffff7e01000000000000000000000000000000000000000000000000000000000000909304831660608501526001850154808416608086015262010000810490931660a085015260ff6401000000008404811660c0860152650100000000008404811660e0860152660100000000000084041615156101008501526701000000000000008304166101208401526c010000000000000000000000009091041661014082015260028201805485518186028101860190965280865291949293610160860193929083018282801561282957602002820191906000526020600020906000905b82829054906101000a900463ffffffff1663ffffffff16815260200190600401906020826003010492830192600103820291508084116127ec5790505b5050505050815250509050919050565b6000546001600160a01b0316331461287d576040517f5cd8319200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6060816128f757505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115612921578061290b81613756565b915061291a9050600a8361388c565b91506128fb565b60008167ffffffffffffffff81111561293c5761293c61355f565b6040519080825280601f01601f191660200182016040528015612966576020820181803683370190505b5090505b84156129e95761297b60018361373f565b9150612988600a866138a0565b6129939060306137e3565b60f81b8183815181106129a8576129a8613530565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506129e2600a8661388c565b945061296a565b949350505050565b60008083851115612a00578394505b60008567ffffffffffffffff811115612a1b57612a1b61355f565b604051908082528060200260200182016040528015612a44578160200160208202803683370190505b5090506000806000806000805b8b811015612b4d575b60f0600487901b16945084158015612a7157508015155b15612aa65760408051602081018c90529081018790526060016040516020818303038152906040528051906020012060001c99505b8a61ffff8b871c1681612abb57612abb61385d565b06925060009150600093505b8084108015612ad4575081155b15612b025782878581518110612aec57612aec613530565b6020026020010151149150836001019350612ac7565b85600101955081612a5a57828d1415612b2757600198509650612b5c95505050505050565b82878281518110612b3a57612b3a613530565b6020908102919091010152600101612a51565b50600080975097505050505050505b94509492505050565b6000808260601b90506040517f3d602d80600a3d3981f3363d3d373d3d3d363d7300000000000000000000000081528160148201527f5af43d82803e903d91602b57fd5bf3000000000000000000000000000000000060288201526037816000f0949350505050565b606083851115612bdc578394505b60008567ffffffffffffffff811115612bf757612bf761355f565b604051908082528060200260200182016040528015612c20578160200160208202803683370190505b5090506000806000806000805b8b811015612d11575b60f0600487901b16945084158015612c4d57508015155b15612c825760408051602081018c90529081018790526060016040516020818303038152906040528051906020012060001c99505b888b61ffff8c881c1681612c9857612c9861385d565b0601925060009150600093505b8084108015612cb2575081155b15612ce05782878581518110612cca57612cca613530565b6020026020010151149150836001019350612ca5565b85600101955081612c365782878281518110612cfe57612cfe613530565b6020908102919091010152600101612c2d565b50949a9950505050505050505050565b82805482825590600052602060002090600701600890048101928215612dc65791602002820160005b83821115612d9457833563ffffffff1683826101000a81548163ffffffff021916908363ffffffff1602179055509260200192600401602081600301049283019260010302612d4a565b8015612dc45782816101000a81549063ffffffff0219169055600401602081600301049283019260010302612d94565b505b50612dd2929150612e68565b5090565b828054612de29061378f565b90600052602060002090601f016020900481019282612e045760008555612dc6565b82601f10612e3b578280017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00823516178555612dc6565b82800160010185558215612dc6579182015b82811115612dc6578235825591602001919060010190612e4d565b5b80821115612dd25760008155600101612e69565b60008083601f840112612e8f57600080fd5b50813567ffffffffffffffff811115612ea757600080fd5b6020830191508360208260051b8501011115612ec257600080fd5b9250929050565b60008060008060408587031215612edf57600080fd5b843567ffffffffffffffff80821115612ef757600080fd5b612f0388838901612e7d565b90965094506020870135915080821115612f1c57600080fd5b50612f2987828801612e7d565b95989497509550505050565b60005b83811015612f50578181015183820152602001612f38565b8381111561205f5750506000910152565b6020815260008251806020840152612f80816040850160208701612f35565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b6001600160a01b0381168114612fc757600080fd5b50565b600080600060608486031215612fdf57600080fd5b8335612fea81612fb2565b95602085013595506040909401359392505050565b6000806040838503121561301257600080fd5b50508035926020909101359150565b60006020828403121561303357600080fd5b5035919050565b6020808252825182820181905260009190848201906040850190845b8181101561307b5783516001600160a01b031683529284019291840191600101613056565b50909695505050505050565b803564ffffffffff8116811461309c57600080fd5b919050565b803561ffff8116811461309c57600080fd5b803560ff8116811461309c57600080fd5b60008060008060008060008060006101008a8c0312156130e357600080fd5b89356130ee81612fb2565b985060208a013567ffffffffffffffff81111561310a57600080fd5b6131168c828d01612e7d565b9099509750613129905060408b01613087565b955061313760608b01613087565b945061314560808b016130a1565b935061315360a08b016130b3565b925061316160c08b016130a1565b915061316f60e08b016130b3565b90509295985092959850929598565b60008083601f84011261319057600080fd5b50813567ffffffffffffffff8111156131a857600080fd5b602083019150836020828501011115612ec257600080fd5b600080600080600080606087890312156131d957600080fd5b863567ffffffffffffffff808211156131f157600080fd5b6131fd8a838b0161317e565b9098509650602089013591508082111561321657600080fd5b6132228a838b0161317e565b9096509450604089013591508082111561323b57600080fd5b5061324889828a0161317e565b979a9699509497509295939492505050565b60008060006040848603121561326f57600080fd5b833561327a81612fb2565b9250602084013567ffffffffffffffff81111561329657600080fd5b6132a286828701612e7d565b9497909650939450505050565b6020808252825182820181905260009190848201906040850190845b8181101561307b578351835292840192918401916001016132cb565b6000602082840312156132f957600080fd5b8135610fe781612fb2565b8015158114612fc757600080fd5b60008060008060008060008060008060006101408c8e03121561333457600080fd5b8b359a5060208c013561334681612fb2565b995060408c013567ffffffffffffffff81111561336257600080fd5b61336e8e828f01612e7d565b909a509850613381905060608d01613087565b965061338f60808d01613087565b955061339d60a08d016130a1565b94506133ab60c08d016130b3565b93506133b960e08d016130a1565b92506133c86101008d016130b3565b91506101208c01356133d981613304565b809150509295989b509295989b9093969950565b600081518084526020808501945080840160005b8381101561342357815163ffffffff1687529582019590820190600101613401565b509495945050505050565b602081526134486020820183516001600160a01b03169052565b60006020830151613462604084018264ffffffffff169052565b50604083015164ffffffffff8116606084015250606083015161ffff8116608084015250608083015161ffff811660a08401525060a083015161ffff811660c08401525060c083015160ff811660e08401525060e08301516101006134cb8185018360ff169052565b84015190506101206134e08482018315159052565b84015190506101406134fa8482018364ffffffffff169052565b8401519050610160613516848201836001600160a01b03169052565b8401516101808481015290506129e96101a08401826133ed565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000602082840312156135a057600080fd5b815167ffffffffffffffff808211156135b857600080fd5b818401915084601f8301126135cc57600080fd5b8151818111156135de576135de61355f565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156136245761362461355f565b8160405282815287602084870101111561363d57600080fd5b61364e836020830160208801612f35565b979650505050505050565b7f476f75646120536c6f74204d616368696e6520526166666c652023000000000081526000835161369181601b850160208801612f35565b7f3a20000000000000000000000000000000000000000000000000000000000000601b9184019182015283516136ce81601d840160208801612f35565b01601d01949350505050565b6000602082840312156136ec57600080fd5b5051919050565b60006020828403121561370557600080fd5b8151610fe781612fb2565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008282101561375157613751613710565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561378857613788613710565b5060010190565b600181811c908216806137a357607f821691505b602082108114156137dd577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b600082198211156137f6576137f6613710565b500190565b60006020828403121561380d57600080fd5b8151610fe781613304565b7f4752414646000000000000000000000000000000000000000000000000000000815260008251613850816005850160208701612f35565b9190910160050192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261389b5761389b61385d565b500490565b6000826138af576138af61385d565b50069056fea264697066735822122003beb9771599e48f614a87fd936a75f96fb6bbebd227ccd36a50b02a661ffd3c64736f6c634300080c0033

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
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.