ETH Price: $1,981.30 (-5.11%)

Contract

0xe2A1499ca2caD493b2fA25206Faa150cA5396212
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Token Holdings

More Info

Private Name Tags

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Claim244917792026-02-19 15:26:2315 days ago1771514783IN
0xe2A1499c...cA5396212
0 ETH0.000026580.28669022
Claim243989562026-02-06 16:23:4728 days ago1770395027IN
0xe2A1499c...cA5396212
0 ETH0.000278413.00239344
Claim237658472025-11-10 2:22:11116 days ago1762741331IN
0xe2A1499c...cA5396212
0 ETH0.000156722.07213973
Claim233098412025-09-07 7:51:47180 days ago1757231507IN
0xe2A1499c...cA5396212
0 ETH0.000067061.14574683
Claim230011802025-07-26 5:18:47223 days ago1753507127IN
0xe2A1499c...cA5396212
0 ETH0.00013172.25014553
Claim227748902025-06-24 14:28:47255 days ago1750775327IN
0xe2A1499c...cA5396212
0 ETH0.0009102512.0353261
Claim224802292025-05-14 8:30:11296 days ago1747211411IN
0xe2A1499c...cA5396212
0 ETH0.00015121.9991617
Claim223521522025-04-26 8:56:11314 days ago1745657771IN
0xe2A1499c...cA5396212
0 ETH0.000097351.28722264
Claim223521392025-04-26 8:53:23314 days ago1745657603IN
0xe2A1499c...cA5396212
0 ETH0.000094381.24789043
Claim221462882025-03-28 15:24:23343 days ago1743175463IN
0xe2A1499c...cA5396212
0 ETH0.000163561.7638108
Claim221453852025-03-28 12:23:23343 days ago1743164603IN
0xe2A1499c...cA5396212
0 ETH0.000063291.08138827
Claim221453792025-03-28 12:22:11343 days ago1743164531IN
0xe2A1499c...cA5396212
0 ETH0.000066031.12811234
Claim220711632025-03-18 3:44:47353 days ago1742269487IN
0xe2A1499c...cA5396212
0 ETH0.000069740.92218758
Claim220711602025-03-18 3:44:11353 days ago1742269451IN
0xe2A1499c...cA5396212
0 ETH0.000066760.88269549
Claim220711572025-03-18 3:43:35353 days ago1742269415IN
0xe2A1499c...cA5396212
0 ETH0.000070380.93062999
Claim220711502025-03-18 3:42:11353 days ago1742269331IN
0xe2A1499c...cA5396212
0 ETH0.000046080.91919891
Claim220711492025-03-18 3:41:59353 days ago1742269319IN
0xe2A1499c...cA5396212
0 ETH0.000070870.9371389
Claim220711462025-03-18 3:41:23353 days ago1742269283IN
0xe2A1499c...cA5396212
0 ETH0.000044510.88797789
Claim220711452025-03-18 3:41:11353 days ago1742269271IN
0xe2A1499c...cA5396212
0 ETH0.000070360.93033473
Claim220555702025-03-15 23:29:11356 days ago1742081351IN
0xe2A1499c...cA5396212
0 ETH0.000058531
Claim220516962025-03-15 10:31:11356 days ago1742034671IN
0xe2A1499c...cA5396212
0 ETH0.000070120.92717277
Claim220497912025-03-15 4:08:47356 days ago1742011727IN
0xe2A1499c...cA5396212
0 ETH0.000070990.93873504
Claim220497692025-03-15 4:04:23356 days ago1742011463IN
0xe2A1499c...cA5396212
0 ETH0.000071810.94947608
Claim220478492025-03-14 21:37:59357 days ago1741988279IN
0xe2A1499c...cA5396212
0 ETH0.00007781.02873745
Claim220387452025-03-13 15:08:47358 days ago1741878527IN
0xe2A1499c...cA5396212
0 ETH0.000143061.8915318
View all transactions

Latest 2 internal transactions

Advanced mode:
Parent Transaction Hash Method Block
From
To
Transfer209872032024-10-17 18:53:47505 days ago1729191227
0xe2A1499c...cA5396212
15.75809798 ETH
Transfer209868852024-10-17 17:49:47505 days ago1729187387
0xe2A1499c...cA5396212
127.46385442 ETH
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Validator Index Block Amount
View All Withdrawals

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

Similar Match Source Code
This contract matches the deployed Bytecode of the Source Code for Contract 0xADABa1d9...989C9c68b
The constructor portion of the code might be different and could alter the actual behaviour of the contract

Contract Name:
Presale

Compiler Version
v0.8.26+commit.8a97fa7a

Optimization Enabled:
Yes with 200 runs

Other Settings:
paris EvmVersion

Contract Source Code (Solidity Standard Json-Input format)

// SPDX-License-Identifier: None

pragma solidity ^0.8.24;

import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

import "@chainlink/contracts/src/v0.8/vrf/dev/libraries/VRFV2PlusClient.sol";
import {IVRFCoordinatorV2Plus} from "@chainlink/contracts/src/v0.8/vrf/dev/interfaces/IVRFCoordinatorV2Plus.sol";
import "@chainlink/contracts/src/v0.8/vrf/VRFConsumerBaseV2.sol";

import './interfaces/IDelegateRegistry.sol';
import './interfaces/IDelegationRegistry.sol';

contract Presale is VRFConsumerBaseV2, Ownable {

    // Maintains various token balances for users
    struct userInfo {
        uint256 KOLPurchased;
        uint256 superKOLPurchased;
        uint256 totalPurchased;
        uint256 rafflesWon;
        uint256 rafflesPurchased;
        uint256 amountClaimed;
    }

    // Each user's info 
    mapping(address => userInfo) public usersInfo;

    // Purchased per NFT ID
    mapping(uint256 => uint256) public phaseOnePurchased; 

    // Phase 2 whitelists 
    mapping(address => bool) public KOLWhitelist; 
    mapping(address => bool) public superKOLWhitelist;

    // List of users who have entered the raffle - one entry per ticket purchased
    address[] public raffleEntries;

    // Total tokens that can be purchased in phase 1
    uint256 public phaseOneSupply = 33000000 * 10**18;
    uint256 public phaseOnePurchasedTotal;
    
    // Total tokens that can be purchased in phase 2 - rolls over from phase 1
    uint256 public phaseTwoSupply = 132000000 * 10**18;
    uint256 public KOLPurchasedTotal;
    uint256 public superKOLPurchasedTotal;

    // Total tokens that can be purchased in phase 3 - rolls over from phase 1 and 2
    uint256 public phaseThreeSupply;
    uint256 public phaseThreePurchasedTotal;

    // Tokens purchased across all phases 
    uint256 public totalTokensPurchased;
    // ETH collected in phase 1 and 2 - allows for withdrawing during phase 3
    uint256 public phaseOneTwoETH;

    // Used to maintain the contract's current phase
    uint256 public launchTime;
    bool public claimEnabled;
    uint256 public claimTime;

    // Limit of number of tokens that can be purchased by each user in each phase
    uint256 public phaseOneCap;
    uint256 public KOLCap;
    uint256 public superKOLCap;

    // Cost per entry and winning token amount for raffles
    uint256 public rafflePrice;
    uint256 public raffleAmount;
    uint256 public raffleLimit = 20;

    // Tokens per ETH for each phase
    uint256 public phaseOneRatio;
    uint256 public phaseTwoRatio;

    // Used to calculate each user's vested amount when claiming
    uint256 public vestingPeriod = 14 days;
    uint256 public cliffDuration = 12 hours;
    uint256 public initialUnlockPercent = 75;

    // Used to rollover tokens between phases
    bool public phaseOneEnded;
    bool public phaseTwoEnded;

    // Used to enable users to refund losing tickets
    bool public refundsEnabled;

    // Vars required for Chainlink VRF
    uint256 public subscriptionId;
    IVRFCoordinatorV2Plus public coordinator;
    bytes32 public keyHash = 0x3fd2fec10d06ee8f65e7f2e95f5c56511359ece3f33960ad8a866ae24a8ff10b;
    uint32 public callbackGasLimit = 15000000;
    uint16 public requestConfirmations = 3;

    // NFTs required for phase one purchase
    IERC721 public nftAddress;
    // Tokens being bought in each phase
    IERC20 public tokenAddress;
    // Delegate registries to support delegating NFTs
    IDelegateRegistry public immutable delegateRegistryV2 =
        IDelegateRegistry(0x00000000000000447e69651d841bD8D104Bed493);
    IDelegationRegistry public immutable delegateRegistryV1 =
        IDelegationRegistry(0x00000000000076A84feF008CDAbe6409d2FE638B);

    error OutsideTimeWindow();
    error ExceedsPurchaseCap();
    error NFTOwner();
    error Whitelist();
    error IncorrectPrice();
    error NotEnabled();
    error AlreadyLaunched();

    // Creates the presale and sets the required values
    constructor(address _nftAddress, address _tokenAddress, address _vrfCoordinator, uint256 _subscriptionId) VRFConsumerBaseV2(_vrfCoordinator) Ownable(msg.sender) {
        coordinator = IVRFCoordinatorV2Plus(_vrfCoordinator);
        subscriptionId = _subscriptionId;
        nftAddress = IERC721(_nftAddress);
        tokenAddress = IERC20(_tokenAddress);
    }

    // Begins the presale process and sets prices and caps
    function launch(uint256 _phaseOneRatio, uint256 _phaseTwoRatio, uint256 _phaseOneCap, uint256 _KOLCap, uint256 _superKOLCap, uint256 _rafflePrice, uint256 _raffleAmount) external onlyOwner {
        if(launchTime != 0) { // 2 hours phase one + 2 hours phase 2 + 24 hours phase 3
            revert AlreadyLaunched();
        }
        launchTime = block.timestamp;
        phaseOneRatio = _phaseOneRatio;
        phaseTwoRatio = _phaseTwoRatio;
        phaseOneCap = _phaseOneCap;
        KOLCap = _KOLCap;
        superKOLCap = _superKOLCap;
        rafflePrice = _rafflePrice;
        raffleAmount = _raffleAmount;
    }

    // Allows users to refund their losing tickets - no draws must happen after 
    function enableRefunds() external onlyOwner {
        refundsEnabled = true;
    }

    // Allows users to claim 
    function enableClaims() external onlyOwner {
        // Ensures phase three has ended 
        if(block.timestamp < launchTime + 100800) { // 2 hours phase one + 2 hours phase 2 + 24 hours phase 3
            revert OutsideTimeWindow();
        }
        claimEnabled = true;
        claimTime = block.timestamp;
        // Transfers the total required tokens to the contract 
        tokenAddress.transferFrom(msg.sender, address(this), totalTokensPurchased);
    }

    // Allows an NFT holder to purchase tokens 
    function phaseOnePurchase(uint256[] calldata nftIds, uint256[] calldata amounts) external payable {
        if(block.timestamp > launchTime + 7200) { 
            // Two hours from launch to purchase in phase one 
            revert OutsideTimeWindow();
        }

        uint256 totalAmount;
        for(uint256 i = 0; i < amounts.length; i++) {
            totalAmount += amounts[i];
        }

        if(msg.value != totalAmount) {
            revert IncorrectPrice();
        }

        for(uint256 i = 0; i < nftIds.length; i++) {
            _phaseOnePurchase(nftIds[i], amounts[i]);
        }

        phaseOneTwoETH += msg.value;

    }

    function _phaseOnePurchase(uint256 nftId, uint256 amount) internal {
        // User must own the specified NFT or be a delegate
        if(!_verifyTokenOwner(nftId)) {
            revert NFTOwner();
        }

        // Convert ETH to tokens 
        uint256 purchasedAmount = amount * phaseOneRatio;
        if(phaseOnePurchased[nftId] + purchasedAmount > phaseOneCap) {
            revert ExceedsPurchaseCap();
        }

        // Check we dont exceed the phase one supply
        if(phaseOnePurchasedTotal + purchasedAmount > phaseOneSupply) {
            revert ExceedsPurchaseCap();
        }

        // Increment all associated values
        usersInfo[msg.sender].totalPurchased += purchasedAmount;
        phaseOnePurchased[nftId] += purchasedAmount;
        phaseOnePurchasedTotal += purchasedAmount;
        totalTokensPurchased += purchasedAmount;
    }

    // Allows whitelisted users to purchase tokens after phase one ends
    function phaseTwoKOLPurchase() external payable {
        if(block.timestamp < launchTime + 7200 || block.timestamp > launchTime + 14400) {
            // Phase two starts two hours after launch and lasts another two hours 
            revert OutsideTimeWindow();
        }

        // Carries over any not purchased phase one tokens - should only trigger after phase one due to above time constraints
        if(!phaseOneEnded) {
            phaseTwoSupply += (phaseOneSupply - phaseOnePurchasedTotal);
            phaseOneEnded = true;
        }

        // User must be whitelisted
        if(KOLWhitelist[msg.sender] == false) {
            revert Whitelist();
        }

        // Convert ETH to tokens 
        uint256 purchasedAmount = msg.value * phaseTwoRatio;
        if(usersInfo[msg.sender].KOLPurchased + purchasedAmount > KOLCap) {
            revert ExceedsPurchaseCap();
        }

        // Check total phase two purchased tokens dont exceed phase two supply
        if(KOLPurchasedTotal + superKOLPurchasedTotal + purchasedAmount > phaseTwoSupply) {
            revert ExceedsPurchaseCap();
        }

        // Increment all associated values
        usersInfo[msg.sender].KOLPurchased += purchasedAmount;
        usersInfo[msg.sender].totalPurchased += purchasedAmount;
        KOLPurchasedTotal += purchasedAmount;
        totalTokensPurchased += purchasedAmount;
        phaseOneTwoETH += msg.value;
    }

    // Allows whitelisted users to purchase tokens after phase one ends
    function phaseTwoSuperKOLPurchase() external payable {
        if(block.timestamp < launchTime + 7200 || block.timestamp > launchTime + 14400) {
            // Phase two starts two hours after launch and lasts another two hours
            revert OutsideTimeWindow();
        }

        // Carries over any not purchased phase one tokens - should only trigger after phase one due to above time constraints
        if(!phaseOneEnded) {
            phaseTwoSupply += (phaseOneSupply - phaseOnePurchasedTotal);
            phaseOneEnded = true;
        }

        // User must be whitelisted
        if(superKOLWhitelist[msg.sender] == false) {
            revert Whitelist();
        }

        // Convert ETH to tokens 
        uint256 purchasedAmount = msg.value * phaseTwoRatio;
        if(usersInfo[msg.sender].superKOLPurchased + purchasedAmount > superKOLCap) {
            revert ExceedsPurchaseCap();
        }

        // Check total phase two purchased tokens dont exceed phase two supply
        if(KOLPurchasedTotal + superKOLPurchasedTotal + purchasedAmount > phaseTwoSupply) {
            revert ExceedsPurchaseCap();
        }

        // Increment all associated values
        usersInfo[msg.sender].superKOLPurchased += purchasedAmount;
        usersInfo[msg.sender].totalPurchased += purchasedAmount;
        superKOLPurchasedTotal += purchasedAmount;
        totalTokensPurchased += purchasedAmount;
        phaseOneTwoETH += msg.value;
    }

    // Allows any users to purchase a raffle ticket after phase two ends
    function phaseThreePurchase(uint256 numTickets) external payable {
        if(block.timestamp < launchTime + 14400 || block.timestamp > launchTime + 100800) {
            // Phase three starts four hours after launch and lasts another 24 hours
            revert OutsideTimeWindow();
        }

        // Carries over any not purchased phase two tokens - should only trigger after phase one due to above time constraints
        if(!phaseTwoEnded) {
            phaseThreeSupply += (phaseTwoSupply - (KOLPurchasedTotal + superKOLPurchasedTotal));
            phaseTwoEnded = true;
        }

        // Ensure user provided correct amount of ETH 
        if(msg.value != rafflePrice * numTickets) {
            revert IncorrectPrice();
        }

        if(usersInfo[msg.sender].rafflesPurchased + numTickets > raffleLimit) {
            revert ExceedsPurchaseCap();
        }
        
        // Credit the user with the number of tickets
        usersInfo[msg.sender].rafflesPurchased += numTickets;
        for(uint256 i = 0; i < numTickets; i++) {
            // Add user to the actual entries
            raffleEntries.push(msg.sender);
        }
    }

    // Allows the owner to draw the specified number of winners
    function draw(uint256 numDraws) external onlyOwner() {
        if(block.timestamp < launchTime + 100800) {
            // Raffle can be drawn after phase three ends
            revert OutsideTimeWindow();
        }

        // Check total phase three purchased tokens dont exceed phase three supply
        if((numDraws * raffleAmount) + phaseThreePurchasedTotal > phaseThreeSupply) {
            revert ExceedsPurchaseCap();
        }

        // Request random values from Chainlink VRF provider
        requestRandomWords(callbackGasLimit, requestConfirmations, uint32(numDraws));
    }

    // Sends the request for random values to Chainlink VRF provider
    function requestRandomWords(
        uint32 _callbackGasLimit,
        uint16 _requestConfirmations,
        uint32 _numWords
    ) internal {
        bytes memory args = VRFV2PlusClient._argsToBytes(
            VRFV2PlusClient.ExtraArgsV1({nativePayment: false})
        );

        VRFV2PlusClient.RandomWordsRequest memory request = VRFV2PlusClient
            .RandomWordsRequest({
                keyHash: keyHash,
                subId: subscriptionId,
                requestConfirmations: _requestConfirmations,
                callbackGasLimit: _callbackGasLimit,
                numWords: _numWords,
                extraArgs: args
            });

        coordinator.requestRandomWords(request);
    }

    // Called by Chainklink VRF provider to provide requested random values
    function fulfillRandomWords(
        uint256 _requestId,
        uint256[] memory randomWords
    ) internal override {
        selectWinners(randomWords);
    }

    // Used to select winners based on provided random values
    function selectWinners(uint256[] memory randomness) internal {
        // Selects the correct number of winners
        for (uint256 i; i < randomness.length; i++) {
            // Find the right winner from the entries
            uint256 winnerIndex = randomness[i] % raffleEntries.length;
            address winner = raffleEntries[winnerIndex];
            // Credit the user with the amount and the win
            usersInfo[winner].totalPurchased += raffleAmount;
            totalTokensPurchased += raffleAmount;
            phaseThreePurchasedTotal += raffleAmount;
            usersInfo[winner].rafflesWon += 1;
            // Remove the user from the entries 
            raffleEntries[winnerIndex] = raffleEntries[raffleEntries.length-1];
            raffleEntries.pop();
        }
    }

    // Allows the users to claim tokens once enabled
    function claim() external {
        if(!claimEnabled) {
            revert NotEnabled();
        }
        // Claimable tokens vest over time 
        uint256 vested = vestedAmount(usersInfo[msg.sender].totalPurchased);
        // Calculate claimable, update claimed amount, send user their tokens
        uint256 claimable = vested - usersInfo[msg.sender].amountClaimed;
        usersInfo[msg.sender].amountClaimed = vested;
        tokenAddress.transfer(msg.sender, claimable);
    }

    // Calculates the amount of vested tokens from the time claiming was enabled
    function vestedAmount(uint256 totalPurchased) public view returns (uint256) {
        if(claimTime == 0) {
            return 0;
        }
        uint256 elapsedTime = block.timestamp - claimTime;
        uint256 initalUnlockAmount = (totalPurchased * initialUnlockPercent) / 100;
        if (elapsedTime < cliffDuration) {
            // Before 12 hours, only the initial 75% is available
            return initalUnlockAmount;
        } else if (elapsedTime >= cliffDuration + vestingPeriod) {
            // After the vesting period, 100% is vested
            return totalPurchased;
        } else { // calculate vested amount 
            elapsedTime = block.timestamp - (claimTime + cliffDuration); // vesting starts from cliff duration
            uint256 nonInitialAmount = (totalPurchased * (100 - initialUnlockPercent)) / 100; // amount that vests after initial unlock
            uint256 vestedAmount = (nonInitialAmount * elapsedTime) / vestingPeriod; // amount of non-initial that has vested
            return initalUnlockAmount + vestedAmount; // initial unlock + vested amount 
        }
    }

    // Allows users to refund raffle entries that were not selected
    function refundRaffle() external { 
        if(!refundsEnabled) {
            // Cannot claim until team is done drawing winners
            revert NotEnabled();
        }
        uint256 ticketsRefunded =  usersInfo[msg.sender].rafflesPurchased -  usersInfo[msg.sender].rafflesWon;
        // Users receive a 97.5% refund
        uint256 refundAmount = (ticketsRefunded * rafflePrice * 975) / 1000;
        usersInfo[msg.sender].rafflesPurchased = 0; // will cause revert if they call this again 
        msg.sender.call{value: refundAmount}("");
    }

    // Allows owner to add users to the KOL Whitelist
    function setKOLWhitelist(address[] memory users, bool value) external onlyOwner {
        for(uint256 i = 0; i < users.length; i++) {
            KOLWhitelist[users[i]] = value;
        }
    }

    // Allows owner to add users to the Super KOL Whitelist
    function setSuperKOLWhitelist(address[] memory users, bool value) external onlyOwner {
        for(uint256 i = 0; i < users.length; i++) {
            superKOLWhitelist[users[i]] = value;
        }
    }

    // Allows the owner to set the number of tokens won per raffle
    function setRaffleAmount(uint256 amount) external onlyOwner {
        raffleAmount = amount;
    }

    // Allows the owner to set the price of each raffle entry
    function setRafflePrice(uint256 amount) external onlyOwner {
        if(block.timestamp > launchTime + 14400) {
            // Can only change the price before raffles are purchased
            revert OutsideTimeWindow();
        }

        rafflePrice = amount;
    }

    // Sets the Chainlink VRF gas callback limit
    function setGasLimit(uint256 limit) external onlyOwner {
        callbackGasLimit = uint32(limit);
    }

    // Sets the Chainlink VRF gas callback limit
    function setSubId(uint256 id) external onlyOwner {
        subscriptionId = id;
    }

    // Sets the Chainlink keyhash
    function setKeyHash(bytes32 newHash) external onlyOwner {
        keyHash = newHash;
    }

    // Withdraws all ETH from the contract - should not be used until users are given sufficient time to refund their tickets
    function withdrawETH() external onlyOwner {
        msg.sender.call{value: address(this).balance}(""); // This will withdraw all ETH including potential ETH for refunds
    }

    // Withdraws the ETH collected in phases one and two - should only be called after phase 2 and before calling withdrawETHNoRefunds
    function withdrawETHNoRaffle() external onlyOwner {
        uint256 amount = phaseOneTwoETH;
        phaseOneTwoETH = 0;
        msg.sender.call{value: amount}(""); 
    }

    // Withdraws all ETH not allocated to refunds 
    function withdrawETHNoRefunds() external onlyOwner {
        if(block.timestamp < launchTime + 100800 ) {
            revert OutsideTimeWindow();
        }
        uint256 totalRefunds = raffleEntries.length; // all winners should be popped from the array by now 
        uint256 refundAmount = (totalRefunds * rafflePrice * 975) / 1000;
        msg.sender.call{value: address(this).balance - refundAmount}(""); 
    }

    // Withdraws all of a specified token to a contract - should only be used on the presale token in case of emergency
    function emergencyWithdrawTokens(address token) external onlyOwner {
        IERC20(token).transfer(msg.sender, IERC20(token).balanceOf(address(this)));
    }

    receive() external payable {}

    function _verifyTokenOwner(uint256 NFTId) internal view returns(bool) {
        address NFTOwner = nftAddress.ownerOf(NFTId);

        // check sender is owner
        if (NFTOwner == msg.sender) return true;

        // check with delegate registry v2
        if (
            delegateRegistryV2.checkDelegateForERC721(
                msg.sender,
                NFTOwner,
                address(nftAddress),
                NFTId,
                ''
            )
        ) return true;

        // check with delegate registry v1
        if (
            delegateRegistryV1.checkDelegateForToken(
                msg.sender,
                NFTOwner,
                address(nftAddress),
                NFTId
            )
        ) return true;

        // false if not owner or delegate
        return false;
    }
}

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

import {VRFV2PlusClient} from "../libraries/VRFV2PlusClient.sol";
import {IVRFSubscriptionV2Plus} from "./IVRFSubscriptionV2Plus.sol";

// Interface that enables consumers of VRFCoordinatorV2Plus to be future-proof for upgrades
// This interface is supported by subsequent versions of VRFCoordinatorV2Plus
interface IVRFCoordinatorV2Plus is IVRFSubscriptionV2Plus {
  /**
   * @notice Request a set of random words.
   * @param req - a struct containing following fields for randomness request:
   * keyHash - Corresponds to a particular oracle job which uses
   * that key for generating the VRF proof. Different keyHash's have different gas price
   * ceilings, so you can select a specific one to bound your maximum per request cost.
   * subId  - The ID of the VRF subscription. Must be funded
   * with the minimum subscription balance required for the selected keyHash.
   * requestConfirmations - How many blocks you'd like the
   * oracle to wait before responding to the request. See SECURITY CONSIDERATIONS
   * for why you may want to request more. The acceptable range is
   * [minimumRequestBlockConfirmations, 200].
   * callbackGasLimit - How much gas you'd like to receive in your
   * fulfillRandomWords callback. Note that gasleft() inside fulfillRandomWords
   * may be slightly less than this amount because of gas used calling the function
   * (argument decoding etc.), so you may need to request slightly more than you expect
   * to have inside fulfillRandomWords. The acceptable range is
   * [0, maxGasLimit]
   * numWords - The number of uint256 random values you'd like to receive
   * in your fulfillRandomWords callback. Note these numbers are expanded in a
   * secure way by the VRFCoordinator from a single random value supplied by the oracle.
   * extraArgs - abi-encoded extra args
   * @return requestId - A unique identifier of the request. Can be used to match
   * a request to a response in fulfillRandomWords.
   */
  function requestRandomWords(VRFV2PlusClient.RandomWordsRequest calldata req) external returns (uint256 requestId);
}

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

/// @notice The IVRFSubscriptionV2Plus interface defines the subscription
/// @notice related methods implemented by the V2Plus coordinator.
interface IVRFSubscriptionV2Plus {
  /**
   * @notice Add a consumer to a VRF subscription.
   * @param subId - ID of the subscription
   * @param consumer - New consumer which can use the subscription
   */
  function addConsumer(uint256 subId, address consumer) external;

  /**
   * @notice Remove a consumer from a VRF subscription.
   * @param subId - ID of the subscription
   * @param consumer - Consumer to remove from the subscription
   */
  function removeConsumer(uint256 subId, address consumer) external;

  /**
   * @notice Cancel a subscription
   * @param subId - ID of the subscription
   * @param to - Where to send the remaining LINK to
   */
  function cancelSubscription(uint256 subId, address to) external;

  /**
   * @notice Accept subscription owner transfer.
   * @param subId - ID of the subscription
   * @dev will revert if original owner of subId has
   * not requested that msg.sender become the new owner.
   */
  function acceptSubscriptionOwnerTransfer(uint256 subId) external;

  /**
   * @notice Request subscription owner transfer.
   * @param subId - ID of the subscription
   * @param newOwner - proposed new owner of the subscription
   */
  function requestSubscriptionOwnerTransfer(uint256 subId, address newOwner) external;

  /**
   * @notice Create a VRF subscription.
   * @return subId - A unique subscription id.
   * @dev You can manage the consumer set dynamically with addConsumer/removeConsumer.
   * @dev Note to fund the subscription with LINK, use transferAndCall. For example
   * @dev  LINKTOKEN.transferAndCall(
   * @dev    address(COORDINATOR),
   * @dev    amount,
   * @dev    abi.encode(subId));
   * @dev Note to fund the subscription with Native, use fundSubscriptionWithNative. Be sure
   * @dev  to send Native with the call, for example:
   * @dev COORDINATOR.fundSubscriptionWithNative{value: amount}(subId);
   */
  function createSubscription() external returns (uint256 subId);

  /**
   * @notice Get a VRF subscription.
   * @param subId - ID of the subscription
   * @return balance - LINK balance of the subscription in juels.
   * @return nativeBalance - native balance of the subscription in wei.
   * @return reqCount - Requests count of subscription.
   * @return owner - owner of the subscription.
   * @return consumers - list of consumer address which are able to use this subscription.
   */
  function getSubscription(
    uint256 subId
  )
    external
    view
    returns (uint96 balance, uint96 nativeBalance, uint64 reqCount, address owner, address[] memory consumers);

  /*
   * @notice Check to see if there exists a request commitment consumers
   * for all consumers and keyhashes for a given sub.
   * @param subId - ID of the subscription
   * @return true if there exists at least one unfulfilled request for the subscription, false
   * otherwise.
   */
  function pendingRequestExists(uint256 subId) external view returns (bool);

  /**
   * @notice Paginate through all active VRF subscriptions.
   * @param startIndex index of the subscription to start from
   * @param maxCount maximum number of subscriptions to return, 0 to return all
   * @dev the order of IDs in the list is **not guaranteed**, therefore, if making successive calls, one
   * @dev should consider keeping the blockheight constant to ensure a holistic picture of the contract state
   */
  function getActiveSubscriptionIds(uint256 startIndex, uint256 maxCount) external view returns (uint256[] memory);

  /**
   * @notice Fund a subscription with native.
   * @param subId - ID of the subscription
   * @notice This method expects msg.value to be greater than or equal to 0.
   */
  function fundSubscriptionWithNative(uint256 subId) external payable;
}

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

// End consumer library.
library VRFV2PlusClient {
  // extraArgs will evolve to support new features
  bytes4 public constant EXTRA_ARGS_V1_TAG = bytes4(keccak256("VRF ExtraArgsV1"));
  struct ExtraArgsV1 {
    bool nativePayment;
  }

  struct RandomWordsRequest {
    bytes32 keyHash;
    uint256 subId;
    uint16 requestConfirmations;
    uint32 callbackGasLimit;
    uint32 numWords;
    bytes extraArgs;
  }

  function _argsToBytes(ExtraArgsV1 memory extraArgs) internal pure returns (bytes memory bts) {
    return abi.encodeWithSelector(EXTRA_ARGS_V1_TAG, extraArgs);
  }
}

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

/** ****************************************************************************
 * @notice Interface for contracts using VRF randomness
 * *****************************************************************************
 * @dev PURPOSE
 *
 * @dev Reggie the Random Oracle (not his real job) wants to provide randomness
 * @dev to Vera the verifier in such a way that Vera can be sure he's not
 * @dev making his output up to suit himself. Reggie provides Vera a public key
 * @dev to which he knows the secret key. Each time Vera provides a seed to
 * @dev Reggie, he gives back a value which is computed completely
 * @dev deterministically from the seed and the secret key.
 *
 * @dev Reggie provides a proof by which Vera can verify that the output was
 * @dev correctly computed once Reggie tells it to her, but without that proof,
 * @dev the output is indistinguishable to her from a uniform random sample
 * @dev from the output space.
 *
 * @dev The purpose of this contract is to make it easy for unrelated contracts
 * @dev to talk to Vera the verifier about the work Reggie is doing, to provide
 * @dev simple access to a verifiable source of randomness. It ensures 2 things:
 * @dev 1. The fulfillment came from the VRFCoordinator
 * @dev 2. The consumer contract implements fulfillRandomWords.
 * *****************************************************************************
 * @dev USAGE
 *
 * @dev Calling contracts must inherit from VRFConsumerBase, and can
 * @dev initialize VRFConsumerBase's attributes in their constructor as
 * @dev shown:
 *
 * @dev   contract VRFConsumer {
 * @dev     constructor(<other arguments>, address _vrfCoordinator, address _link)
 * @dev       VRFConsumerBase(_vrfCoordinator) public {
 * @dev         <initialization with other arguments goes here>
 * @dev       }
 * @dev   }
 *
 * @dev The oracle will have given you an ID for the VRF keypair they have
 * @dev committed to (let's call it keyHash). Create subscription, fund it
 * @dev and your consumer contract as a consumer of it (see VRFCoordinatorInterface
 * @dev subscription management functions).
 * @dev Call requestRandomWords(keyHash, subId, minimumRequestConfirmations,
 * @dev callbackGasLimit, numWords),
 * @dev see (VRFCoordinatorInterface for a description of the arguments).
 *
 * @dev Once the VRFCoordinator has received and validated the oracle's response
 * @dev to your request, it will call your contract's fulfillRandomWords method.
 *
 * @dev The randomness argument to fulfillRandomWords is a set of random words
 * @dev generated from your requestId and the blockHash of the request.
 *
 * @dev If your contract could have concurrent requests open, you can use the
 * @dev requestId returned from requestRandomWords to track which response is associated
 * @dev with which randomness request.
 * @dev See "SECURITY CONSIDERATIONS" for principles to keep in mind,
 * @dev if your contract could have multiple requests in flight simultaneously.
 *
 * @dev Colliding `requestId`s are cryptographically impossible as long as seeds
 * @dev differ.
 *
 * *****************************************************************************
 * @dev SECURITY CONSIDERATIONS
 *
 * @dev A method with the ability to call your fulfillRandomness method directly
 * @dev could spoof a VRF response with any random value, so it's critical that
 * @dev it cannot be directly called by anything other than this base contract
 * @dev (specifically, by the VRFConsumerBase.rawFulfillRandomness method).
 *
 * @dev For your users to trust that your contract's random behavior is free
 * @dev from malicious interference, it's best if you can write it so that all
 * @dev behaviors implied by a VRF response are executed *during* your
 * @dev fulfillRandomness method. If your contract must store the response (or
 * @dev anything derived from it) and use it later, you must ensure that any
 * @dev user-significant behavior which depends on that stored value cannot be
 * @dev manipulated by a subsequent VRF request.
 *
 * @dev Similarly, both miners and the VRF oracle itself have some influence
 * @dev over the order in which VRF responses appear on the blockchain, so if
 * @dev your contract could have multiple VRF requests in flight simultaneously,
 * @dev you must ensure that the order in which the VRF responses arrive cannot
 * @dev be used to manipulate your contract's user-significant behavior.
 *
 * @dev Since the block hash of the block which contains the requestRandomness
 * @dev call is mixed into the input to the VRF *last*, a sufficiently powerful
 * @dev miner could, in principle, fork the blockchain to evict the block
 * @dev containing the request, forcing the request to be included in a
 * @dev different block with a different hash, and therefore a different input
 * @dev to the VRF. However, such an attack would incur a substantial economic
 * @dev cost. This cost scales with the number of blocks the VRF oracle waits
 * @dev until it calls responds to a request. It is for this reason that
 * @dev that you can signal to an oracle you'd like them to wait longer before
 * @dev responding to the request (however this is not enforced in the contract
 * @dev and so remains effective only in the case of unmodified oracle software).
 */
abstract contract VRFConsumerBaseV2 {
  error OnlyCoordinatorCanFulfill(address have, address want);
  // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i
  address private immutable vrfCoordinator;

  /**
   * @param _vrfCoordinator address of VRFCoordinator contract
   */
  constructor(address _vrfCoordinator) {
    vrfCoordinator = _vrfCoordinator;
  }

  /**
   * @notice fulfillRandomness handles the VRF response. Your contract must
   * @notice implement it. See "SECURITY CONSIDERATIONS" above for important
   * @notice principles to keep in mind when implementing your fulfillRandomness
   * @notice method.
   *
   * @dev VRFConsumerBaseV2 expects its subcontracts to have a method with this
   * @dev signature, and will call it once it has verified the proof
   * @dev associated with the randomness. (It is triggered via a call to
   * @dev rawFulfillRandomness, below.)
   *
   * @param requestId The Id initially returned by requestRandomness
   * @param randomWords the VRF output expanded to the requested number of words
   */
  // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore
  function fulfillRandomWords(uint256 requestId, uint256[] memory randomWords) internal virtual;

  // rawFulfillRandomness is called by VRFCoordinator when it receives a valid VRF
  // proof. rawFulfillRandomness then calls fulfillRandomness, after validating
  // the origin of the call
  function rawFulfillRandomWords(uint256 requestId, uint256[] memory randomWords) external {
    if (msg.sender != vrfCoordinator) {
      revert OnlyCoordinatorCanFulfill(msg.sender, vrfCoordinator);
    }
    fulfillRandomWords(requestId, randomWords);
  }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)

pragma solidity ^0.8.20;

import {Context} from "../utils/Context.sol";

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

    /**
     * @dev The caller account is not authorized to perform an operation.
     */
    error OwnableUnauthorizedAccount(address account);

    /**
     * @dev The owner is not a valid owner account. (eg. `address(0)`)
     */
    error OwnableInvalidOwner(address owner);

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

    /**
     * @dev Initializes the contract setting the address provided by the deployer as the initial owner.
     */
    constructor(address initialOwner) {
        if (initialOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _transferOwnership(initialOwner);
    }

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

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

    /**
     * @dev Throws if the sender is not the owner.
     */
    function _checkOwner() internal view virtual {
        if (owner() != _msgSender()) {
            revert OwnableUnauthorizedAccount(_msgSender());
        }
    }

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

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        if (newOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _transferOwnership(newOwner);
    }

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

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.20;

/**
 * @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 value of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

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

    /**
     * @dev Moves a `value` amount of 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 value) 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 a `value` amount of tokens 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 value) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to` using the
     * allowance mechanism. `value` 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 value) external returns (bool);
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/IERC721.sol)

pragma solidity ^0.8.20;

import {IERC165} from "../../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 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: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721
     * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must
     * understand this adds an external call which potentially creates a reentrancy vulnerability.
     *
     * 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 address zero.
     *
     * 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);
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)

pragma solidity ^0.8.20;

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

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

    function _contextSuffixLength() internal view virtual returns (uint256) {
        return 0;
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)

pragma solidity ^0.8.20;

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

// SPDX-License-Identifier: CC0-1.0
pragma solidity >=0.8.13;

/**
 * @title IDelegateRegistry
 * @custom:version 2.0
 * @custom:author foobar (0xfoobar)
 * @notice A standalone immutable registry storing delegated permissions from one address to another
 */
interface IDelegateRegistry {
    /// @notice Delegation type, NONE is used when a delegation does not exist or is revoked
    enum DelegationType {
        NONE,
        ALL,
        CONTRACT,
        ERC721,
        ERC20,
        ERC1155
    }

    /// @notice Struct for returning delegations
    struct Delegation {
        DelegationType type_;
        address to;
        address from;
        bytes32 rights;
        address contract_;
        uint256 tokenId;
        uint256 amount;
    }

    /// @notice Emitted when an address delegates or revokes rights for their entire wallet
    event DelegateAll(address indexed from, address indexed to, bytes32 rights, bool enable);

    /// @notice Emitted when an address delegates or revokes rights for a contract address
    event DelegateContract(address indexed from, address indexed to, address indexed contract_, bytes32 rights, bool enable);

    /// @notice Emitted when an address delegates or revokes rights for an ERC721 tokenId
    event DelegateERC721(address indexed from, address indexed to, address indexed contract_, uint256 tokenId, bytes32 rights, bool enable);

    /// @notice Emitted when an address delegates or revokes rights for an amount of ERC20 tokens
    event DelegateERC20(address indexed from, address indexed to, address indexed contract_, bytes32 rights, uint256 amount);

    /// @notice Emitted when an address delegates or revokes rights for an amount of an ERC1155 tokenId
    event DelegateERC1155(address indexed from, address indexed to, address indexed contract_, uint256 tokenId, bytes32 rights, uint256 amount);

    /// @notice Thrown if multicall calldata is malformed
    error MulticallFailed();

    /**
     * -----------  WRITE -----------
     */

    /**
     * @notice Call multiple functions in the current contract and return the data from all of them if they all succeed
     * @param data The encoded function data for each of the calls to make to this contract
     * @return results The results from each of the calls passed in via data
     */
    function multicall(bytes[] calldata data) external payable returns (bytes[] memory results);

    /**
     * @notice Allow the delegate to act on behalf of `msg.sender` for all contracts
     * @param to The address to act as delegate
     * @param rights Specific subdelegation rights granted to the delegate, pass an empty bytestring to encompass all rights
     * @param enable Whether to enable or disable this delegation, true delegates and false revokes
     * @return delegationHash The unique identifier of the delegation
     */
    function delegateAll(address to, bytes32 rights, bool enable) external payable returns (bytes32 delegationHash);

    /**
     * @notice Allow the delegate to act on behalf of `msg.sender` for a specific contract
     * @param to The address to act as delegate
     * @param contract_ The contract whose rights are being delegated
     * @param rights Specific subdelegation rights granted to the delegate, pass an empty bytestring to encompass all rights
     * @param enable Whether to enable or disable this delegation, true delegates and false revokes
     * @return delegationHash The unique identifier of the delegation
     */
    function delegateContract(address to, address contract_, bytes32 rights, bool enable) external payable returns (bytes32 delegationHash);

    /**
     * @notice Allow the delegate to act on behalf of `msg.sender` for a specific ERC721 token
     * @param to The address to act as delegate
     * @param contract_ The contract whose rights are being delegated
     * @param tokenId The token id to delegate
     * @param rights Specific subdelegation rights granted to the delegate, pass an empty bytestring to encompass all rights
     * @param enable Whether to enable or disable this delegation, true delegates and false revokes
     * @return delegationHash The unique identifier of the delegation
     */
    function delegateERC721(address to, address contract_, uint256 tokenId, bytes32 rights, bool enable) external payable returns (bytes32 delegationHash);

    /**
     * @notice Allow the delegate to act on behalf of `msg.sender` for a specific amount of ERC20 tokens
     * @dev The actual amount is not encoded in the hash, just the existence of a amount (since it is an upper bound)
     * @param to The address to act as delegate
     * @param contract_ The address for the fungible token contract
     * @param rights Specific subdelegation rights granted to the delegate, pass an empty bytestring to encompass all rights
     * @param amount The amount to delegate, > 0 delegates and 0 revokes
     * @return delegationHash The unique identifier of the delegation
     */
    function delegateERC20(address to, address contract_, bytes32 rights, uint256 amount) external payable returns (bytes32 delegationHash);

    /**
     * @notice Allow the delegate to act on behalf of `msg.sender` for a specific amount of ERC1155 tokens
     * @dev The actual amount is not encoded in the hash, just the existence of a amount (since it is an upper bound)
     * @param to The address to act as delegate
     * @param contract_ The address of the contract that holds the token
     * @param tokenId The token id to delegate
     * @param rights Specific subdelegation rights granted to the delegate, pass an empty bytestring to encompass all rights
     * @param amount The amount of that token id to delegate, > 0 delegates and 0 revokes
     * @return delegationHash The unique identifier of the delegation
     */
    function delegateERC1155(address to, address contract_, uint256 tokenId, bytes32 rights, uint256 amount) external payable returns (bytes32 delegationHash);

    /**
     * ----------- CHECKS -----------
     */

    /**
     * @notice Check if `to` is a delegate of `from` for the entire wallet
     * @param to The potential delegate address
     * @param from The potential address who delegated rights
     * @param rights Specific rights to check for, pass the zero value to ignore subdelegations and check full delegations only
     * @return valid Whether delegate is granted to act on the from's behalf
     */
    function checkDelegateForAll(address to, address from, bytes32 rights) external view returns (bool);

    /**
     * @notice Check if `to` is a delegate of `from` for the specified `contract_` or the entire wallet
     * @param to The delegated address to check
     * @param contract_ The specific contract address being checked
     * @param from The cold wallet who issued the delegation
     * @param rights Specific rights to check for, pass the zero value to ignore subdelegations and check full delegations only
     * @return valid Whether delegate is granted to act on from's behalf for entire wallet or that specific contract
     */
    function checkDelegateForContract(address to, address from, address contract_, bytes32 rights) external view returns (bool);

    /**
     * @notice Check if `to` is a delegate of `from` for the specific `contract` and `tokenId`, the entire `contract_`, or the entire wallet
     * @param to The delegated address to check
     * @param contract_ The specific contract address being checked
     * @param tokenId The token id for the token to delegating
     * @param from The wallet that issued the delegation
     * @param rights Specific rights to check for, pass the zero value to ignore subdelegations and check full delegations only
     * @return valid Whether delegate is granted to act on from's behalf for entire wallet, that contract, or that specific tokenId
     */
    function checkDelegateForERC721(address to, address from, address contract_, uint256 tokenId, bytes32 rights) external view returns (bool);

    /**
     * @notice Returns the amount of ERC20 tokens the delegate is granted rights to act on the behalf of
     * @param to The delegated address to check
     * @param contract_ The address of the token contract
     * @param from The cold wallet who issued the delegation
     * @param rights Specific rights to check for, pass the zero value to ignore subdelegations and check full delegations only
     * @return balance The delegated balance, which will be 0 if the delegation does not exist
     */
    function checkDelegateForERC20(address to, address from, address contract_, bytes32 rights) external view returns (uint256);

    /**
     * @notice Returns the amount of a ERC1155 tokens the delegate is granted rights to act on the behalf of
     * @param to The delegated address to check
     * @param contract_ The address of the token contract
     * @param tokenId The token id to check the delegated amount of
     * @param from The cold wallet who issued the delegation
     * @param rights Specific rights to check for, pass the zero value to ignore subdelegations and check full delegations only
     * @return balance The delegated balance, which will be 0 if the delegation does not exist
     */
    function checkDelegateForERC1155(address to, address from, address contract_, uint256 tokenId, bytes32 rights) external view returns (uint256);

    /**
     * ----------- ENUMERATIONS -----------
     */

    /**
     * @notice Returns all enabled delegations a given delegate has received
     * @param to The address to retrieve delegations for
     * @return delegations Array of Delegation structs
     */
    function getIncomingDelegations(address to) external view returns (Delegation[] memory delegations);

    /**
     * @notice Returns all enabled delegations an address has given out
     * @param from The address to retrieve delegations for
     * @return delegations Array of Delegation structs
     */
    function getOutgoingDelegations(address from) external view returns (Delegation[] memory delegations);

    /**
     * @notice Returns all hashes associated with enabled delegations an address has received
     * @param to The address to retrieve incoming delegation hashes for
     * @return delegationHashes Array of delegation hashes
     */
    function getIncomingDelegationHashes(address to) external view returns (bytes32[] memory delegationHashes);

    /**
     * @notice Returns all hashes associated with enabled delegations an address has given out
     * @param from The address to retrieve outgoing delegation hashes for
     * @return delegationHashes Array of delegation hashes
     */
    function getOutgoingDelegationHashes(address from) external view returns (bytes32[] memory delegationHashes);

    /**
     * @notice Returns the delegations for a given array of delegation hashes
     * @param delegationHashes is an array of hashes that correspond to delegations
     * @return delegations Array of Delegation structs, return empty structs for nonexistent or revoked delegations
     */
    function getDelegationsFromHashes(bytes32[] calldata delegationHashes) external view returns (Delegation[] memory delegations);

    /**
     * ----------- STORAGE ACCESS -----------
     */

    /**
     * @notice Allows external contracts to read arbitrary storage slots
     */
    function readSlot(bytes32 location) external view returns (bytes32);

    /**
     * @notice Allows external contracts to read an arbitrary array of storage slots
     */
    function readSlots(bytes32[] calldata locations) external view returns (bytes32[] memory);
}

// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.17;

/**
 * @title An immutable registry contract to be deployed as a standalone primitive
 * @dev See EIP-5639, new project launches can read previous cold wallet -> hot wallet delegations
 * from here and integrate those permissions into their flow
 */
interface IDelegationRegistry {
    /// @notice Delegation type
    enum DelegationType {
        NONE,
        ALL,
        CONTRACT,
        TOKEN
    }

    /// @notice Info about a single delegation, used for onchain enumeration
    struct DelegationInfo {
        DelegationType type_;
        address vault;
        address delegate;
        address contract_;
        uint256 tokenId;
    }

    /// @notice Info about a single contract-level delegation
    struct ContractDelegation {
        address contract_;
        address delegate;
    }

    /// @notice Info about a single token-level delegation
    struct TokenDelegation {
        address contract_;
        uint256 tokenId;
        address delegate;
    }

    /// @notice Emitted when a user delegates their entire wallet
    event DelegateForAll(address vault, address delegate, bool value);

    /// @notice Emitted when a user delegates a specific contract
    event DelegateForContract(address vault, address delegate, address contract_, bool value);

    /// @notice Emitted when a user delegates a specific token
    event DelegateForToken(address vault, address delegate, address contract_, uint256 tokenId, bool value);

    /// @notice Emitted when a user revokes all delegations
    event RevokeAllDelegates(address vault);

    /// @notice Emitted when a user revoes all delegations for a given delegate
    event RevokeDelegate(address vault, address delegate);

    /**
     * -----------  WRITE -----------
     */

    /**
     * @notice Allow the delegate to act on your behalf for all contracts
     * @param delegate The hotwallet to act on your behalf
     * @param value Whether to enable or disable delegation for this address, true for setting and false for revoking
     */
    function delegateForAll(address delegate, bool value) external;

    /**
     * @notice Allow the delegate to act on your behalf for a specific contract
     * @param delegate The hotwallet to act on your behalf
     * @param contract_ The address for the contract you're delegating
     * @param value Whether to enable or disable delegation for this address, true for setting and false for revoking
     */
    function delegateForContract(address delegate, address contract_, bool value) external;

    /**
     * @notice Allow the delegate to act on your behalf for a specific token
     * @param delegate The hotwallet to act on your behalf
     * @param contract_ The address for the contract you're delegating
     * @param tokenId The token id for the token you're delegating
     * @param value Whether to enable or disable delegation for this address, true for setting and false for revoking
     */
    function delegateForToken(address delegate, address contract_, uint256 tokenId, bool value) external;

    /**
     * @notice Revoke all delegates
     */
    function revokeAllDelegates() external;

    /**
     * @notice Revoke a specific delegate for all their permissions
     * @param delegate The hotwallet to revoke
     */
    function revokeDelegate(address delegate) external;

    /**
     * @notice Remove yourself as a delegate for a specific vault
     * @param vault The vault which delegated to the msg.sender, and should be removed
     */
    function revokeSelf(address vault) external;

    /**
     * -----------  READ -----------
     */

    /**
     * @notice Returns all active delegations a given delegate is able to claim on behalf of
     * @param delegate The delegate that you would like to retrieve delegations for
     * @return info Array of DelegationInfo structs
     */
    function getDelegationsByDelegate(address delegate) external view returns (DelegationInfo[] memory);

    /**
     * @notice Returns an array of wallet-level delegates for a given vault
     * @param vault The cold wallet who issued the delegation
     * @return addresses Array of wallet-level delegates for a given vault
     */
    function getDelegatesForAll(address vault) external view returns (address[] memory);

    /**
     * @notice Returns an array of contract-level delegates for a given vault and contract
     * @param vault The cold wallet who issued the delegation
     * @param contract_ The address for the contract you're delegating
     * @return addresses Array of contract-level delegates for a given vault and contract
     */
    function getDelegatesForContract(address vault, address contract_) external view returns (address[] memory);

    /**
     * @notice Returns an array of contract-level delegates for a given vault's token
     * @param vault The cold wallet who issued the delegation
     * @param contract_ The address for the contract holding the token
     * @param tokenId The token id for the token you're delegating
     * @return addresses Array of contract-level delegates for a given vault's token
     */
    function getDelegatesForToken(address vault, address contract_, uint256 tokenId)
        external
        view
        returns (address[] memory);

    /**
     * @notice Returns all contract-level delegations for a given vault
     * @param vault The cold wallet who issued the delegations
     * @return delegations Array of ContractDelegation structs
     */
    function getContractLevelDelegations(address vault)
        external
        view
        returns (ContractDelegation[] memory delegations);

    /**
     * @notice Returns all token-level delegations for a given vault
     * @param vault The cold wallet who issued the delegations
     * @return delegations Array of TokenDelegation structs
     */
    function getTokenLevelDelegations(address vault) external view returns (TokenDelegation[] memory delegations);

    /**
     * @notice Returns true if the address is delegated to act on the entire vault
     * @param delegate The hotwallet to act on your behalf
     * @param vault The cold wallet who issued the delegation
     */
    function checkDelegateForAll(address delegate, address vault) external view returns (bool);

    /**
     * @notice Returns true if the address is delegated to act on your behalf for a token contract or an entire vault
     * @param delegate The hotwallet to act on your behalf
     * @param contract_ The address for the contract you're delegating
     * @param vault The cold wallet who issued the delegation
     */
    function checkDelegateForContract(address delegate, address vault, address contract_)
        external
        view
        returns (bool);

    /**
     * @notice Returns true if the address is delegated to act on your behalf for a specific token, the token's contract or an entire vault
     * @param delegate The hotwallet to act on your behalf
     * @param contract_ The address for the contract you're delegating
     * @param tokenId The token id for the token you're delegating
     * @param vault The cold wallet who issued the delegation
     */
    function checkDelegateForToken(address delegate, address vault, address contract_, uint256 tokenId)
        external
        view
        returns (bool);
}

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 200,
    "details": {
      "yul": true
    }
  },
  "viaIR": true,
  "evmVersion": "paris",
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "libraries": {}
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"address","name":"_nftAddress","type":"address"},{"internalType":"address","name":"_tokenAddress","type":"address"},{"internalType":"address","name":"_vrfCoordinator","type":"address"},{"internalType":"uint256","name":"_subscriptionId","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyLaunched","type":"error"},{"inputs":[],"name":"ExceedsPurchaseCap","type":"error"},{"inputs":[],"name":"IncorrectPrice","type":"error"},{"inputs":[],"name":"NFTOwner","type":"error"},{"inputs":[],"name":"NotEnabled","type":"error"},{"inputs":[{"internalType":"address","name":"have","type":"address"},{"internalType":"address","name":"want","type":"address"}],"name":"OnlyCoordinatorCanFulfill","type":"error"},{"inputs":[],"name":"OutsideTimeWindow","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"Whitelist","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[],"name":"KOLCap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"KOLPurchasedTotal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"KOLWhitelist","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"callbackGasLimit","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claimTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cliffDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"coordinator","outputs":[{"internalType":"contract IVRFCoordinatorV2Plus","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"delegateRegistryV1","outputs":[{"internalType":"contract IDelegationRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"delegateRegistryV2","outputs":[{"internalType":"contract IDelegateRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"numDraws","type":"uint256"}],"name":"draw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"emergencyWithdrawTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"enableClaims","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"enableRefunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"initialUnlockPercent","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"keyHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_phaseOneRatio","type":"uint256"},{"internalType":"uint256","name":"_phaseTwoRatio","type":"uint256"},{"internalType":"uint256","name":"_phaseOneCap","type":"uint256"},{"internalType":"uint256","name":"_KOLCap","type":"uint256"},{"internalType":"uint256","name":"_superKOLCap","type":"uint256"},{"internalType":"uint256","name":"_rafflePrice","type":"uint256"},{"internalType":"uint256","name":"_raffleAmount","type":"uint256"}],"name":"launch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"launchTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nftAddress","outputs":[{"internalType":"contract IERC721","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"phaseOneCap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"phaseOneEnded","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"nftIds","type":"uint256[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"name":"phaseOnePurchase","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"phaseOnePurchased","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"phaseOnePurchasedTotal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"phaseOneRatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"phaseOneSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"phaseOneTwoETH","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"numTickets","type":"uint256"}],"name":"phaseThreePurchase","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"phaseThreePurchasedTotal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"phaseThreeSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"phaseTwoEnded","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"phaseTwoKOLPurchase","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"phaseTwoRatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"phaseTwoSuperKOLPurchase","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"phaseTwoSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"raffleAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"raffleEntries","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"raffleLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rafflePrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"requestId","type":"uint256"},{"internalType":"uint256[]","name":"randomWords","type":"uint256[]"}],"name":"rawFulfillRandomWords","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"refundRaffle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"refundsEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"requestConfirmations","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"limit","type":"uint256"}],"name":"setGasLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"users","type":"address[]"},{"internalType":"bool","name":"value","type":"bool"}],"name":"setKOLWhitelist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"newHash","type":"bytes32"}],"name":"setKeyHash","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"setRaffleAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"setRafflePrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"setSubId","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"users","type":"address[]"},{"internalType":"bool","name":"value","type":"bool"}],"name":"setSuperKOLWhitelist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"subscriptionId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"superKOLCap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"superKOLPurchasedTotal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"superKOLWhitelist","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokenAddress","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalTokensPurchased","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"usersInfo","outputs":[{"internalType":"uint256","name":"KOLPurchased","type":"uint256"},{"internalType":"uint256","name":"superKOLPurchased","type":"uint256"},{"internalType":"uint256","name":"totalPurchased","type":"uint256"},{"internalType":"uint256","name":"rafflesWon","type":"uint256"},{"internalType":"uint256","name":"rafflesPurchased","type":"uint256"},{"internalType":"uint256","name":"amountClaimed","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"totalPurchased","type":"uint256"}],"name":"vestedAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vestingPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdrawETH","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawETHNoRaffle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawETHNoRefunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]

0x60e0346101e957601f61206f38819003918201601f19168301916001600160401b038311848410176101ee578084926080946040528339810103126101e95761004781610204565b9061005460208201610204565b90606061006360408301610204565b910151928160805233156101d35760008054336001600160a01b031982168117835560405196640300e4e1c0949390926001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09080a36a1b4c0595a86aa1c10000006006556a6d301656a1aa8704000000600855601460175562127500601a5561a8c0601b55604b601c557f3fd2fec10d06ee8f65e7f2e95f5c56511359ece3f33960ad8a866ae24a8ff10b602055602180546c447e69651d841bd8d104bed49360a0526d76a84fef008cdabe6409d2fe638b60c052601f80546001600160a01b03199081166001600160a01b0398891617909155601e939093556001600160d01b0319169390931760309290921b600160301b600160d01b0316919091179091556022805490911692909116919091179055611e569081610219823960805181611500015260a0518181816105f10152611cde015260c051818181610aa90152611d490152f35b631e4fbdf760e01b600052600060045260246000fd5b600080fd5b634e487b7160e01b600052604160045260246000fd5b51906001600160a01b03821682036101e95756fe6080604052600436101561001b575b361561001957600080fd5b005b60003560e01c8063019948851461190757806303b4a479146118e957806303c669e3146118bd57806303ebbf341461189f57806308ac900a1461188157806309c1ba2e146118635780630a0090971461183a57806318643d371461181c5780631a96ab2b146117fb5780631bfce853146117d55780631cecfaad146116af5780631fe543e31461148e57806324f746971461146a57806327b3bf111461144c5780632866ed211461142957806329687c53146114035780632a29e67a146113a157806332b7ac641461138357806334fccc1d1461136557806336ffc8b0146113475780633b3041471461117557806348a93a0d1461113f5780634c846e46146110fd5780634e71d92d1461105b57806352bca4c31461103d578063532f11791461101757806353d1f59d14610fb557806355a16c2414610f97578063595d221314610f795780635bf8633a14610f4c5780635d0eaaaf14610edb57806361728f3914610ebe578063715018a614610e655780637313ee5a14610e47578063790ca41314610e295780637d7af28014610e0b5780637d7bc63914610dda5780638007634f14610c815780638098004314610c6057806380c028a814610ad8578063856ed8c914610a935780638c52dc4114610a675780638da5cb5b14610a3e5780639755e04e146109ff57806398544710146109de5780639b27349d146108695780639d76ea5814610840578063a277d5b114610822578063a4bfb13014610804578063b0fb162f146107e0578063b2af127c1461071a578063baa39fbe146106db578063bcf257291461067a578063c94028c21461065c578063d1abca7a1461063e578063d85349f714610620578063db584d25146105db578063dbe65f59146105bd578063e086e5ec14610592578063e259f636146104f5578063e365d863146104d7578063ea28edad146103f7578063ec9cd924146103d4578063ee7d72b4146103a2578063f2fde38b146103195763f8d867940361000e5734610314576000366003190112610314576020601554604051908152f35b600080fd5b34610314576020366003190112610314576103326119b3565b61033a611c2c565b6001600160a01b0316801561038c57600080546001600160a01b03198116831782556001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09080a3005b631e4fbdf760e01b600052600060045260246000fd5b34610314576020366003190112610314576103bb611c2c565b6021805463ffffffff191660043563ffffffff16179055005b3461031457600036600319011261031457602060ff601d54166040519015158152f35b3461031457600036600319011261031457610410611c2c565b600f54620189c081018091116104c15742106104b057600160ff196010541617601055426011556000602060018060a01b03602254166064600d5460405194859384926323b872dd60e01b845233600485015230602485015260448401525af180156104a45761047c57005b6100199060203d60201161049d575b6104958183611979565b810190611bf5565b503d61048b565b6040513d6000823e3d90fd5b63ae20f3a560e01b60005260046000fd5b634e487b7160e01b600052601160045260246000fd5b34610314576000366003190112610314576020600e54604051908152f35b346103145760003660031901126103145760ff601d5460101c16156105815733600090815260016020526040902060048101546003909101546105459161053c9190611ae8565b60155490611ad5565b6103cf8102908082046103cf14901517156104c157600080806103e88194338352600160205282600460408220015504335af150610019611af5565b633f54562b60e11b60005260046000fd5b34610314576000366003190112610314576105ab611c2c565b600080808047335af150610019611af5565b34610314576000366003190112610314576020601354604051908152f35b34610314576000366003190112610314576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b34610314576000366003190112610314576020601b54604051908152f35b34610314576000366003190112610314576020600c54604051908152f35b34610314576000366003190112610314576020601654604051908152f35b346103145760e036600319011261031457610693611c2c565b600f546106ca5742600f5560043560185560243560195560443560125560643560135560843560145560a43560155560c435601655005b6319f4db0f60e31b60005260046000fd5b34610314576020366003190112610314576001600160a01b036106fc6119b3565b166000526004602052602060ff604060002054166040519015158152f35b34610314576020366003190112610314576107336119b3565b61073b611c2c565b6040516370a0823160e01b8152306004820152906001600160a01b0316602082602481845afa9182156104a4576000926107aa575b5060405163a9059cbb60e01b81523360048201526024810192909252602090829081600081604481015b03925af180156104a45761047c57005b91506020823d6020116107d8575b816107c560209383611979565b810103126103145790519061079a610770565b3d91506107b8565b3461031457600036600319011261031457602061ffff602154821c16604051908152f35b34610314576000366003190112610314576020600954604051908152f35b34610314576000366003190112610314576020600d54604051908152f35b34610314576000366003190112610314576022546040516001600160a01b039091168152602090f35b602036600319011261031457600435600f5461384081018082116104c15742109081156109c7575b506104b057601d5460ff8160081c161561098b575b506108b381601554611ad5565b340361097a573360005260016020526108d481600460406000200154611ac8565b601754106109695733600052600160205260046040600020016108f8828254611ac8565b905560005b81811061090657005b60055490680100000000000000008210156109535761094d61092f836001809501600555611a66565b81546001600160a01b0360039290921b91821b19163390911b179055565b016108fd565b634e487b7160e01b600052604160045260246000fd5b63b1c0823160e01b60005260046000fd5b6399b5cb1d60e01b60005260046000fd5b610100906109b56109ad6008546109a7600954600a5490611ac8565b90611ae8565b600b54611ac8565b600b5561ff00191617601d55816108a6565b9050620189c081018091116104c157421182610891565b34610314576020366003190112610314576109f7611c2c565b600435602055005b34610314576020366003190112610314576001600160a01b03610a206119b3565b166000526003602052602060ff604060002054166040519015158152f35b34610314576000366003190112610314576000546040516001600160a01b039091168152602090f35b3461031457600036600319011261031457610a80611c2c565b601d805462ff0000191662010000179055005b34610314576000366003190112610314576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b60403660031901126103145760043567ffffffffffffffff811161031457610b04903690600401611a97565b60243567ffffffffffffffff811161031457610b24903690600401611a97565b919092600f54611c2081018091116104c15742116104b0576000805b848110610c405750340361097a5760005b828110610b6957610b6434600e54611ac8565b600e55005b610b74818484611c0d565b3590610b81818688611c0d565b35610b8b83611c55565b15610c2f57601854610b9c91611ad5565b91806000526002602052610bb583604060002054611ac8565b6012541061096957610bc983600754611ac8565b6006541061096957600192610c269133600052846020526002604060002001610bf3838254611ac8565b905560005260026020526040600020610c0d828254611ac8565b9055610c1b81600754611ac8565b600755600d54611ac8565b600d5501610b51565b635f68eddf60e11b60005260046000fd5b90610c59600191610c5284888a611c0d565b3590611ac8565b9101610b40565b3461031457602036600319011261031457610c79611c2c565b600435601e55005b600036600319011261031457600f54611c2081018082116104c1574210908115610dc4575b506104b057601d5460ff811615610d96575b5033600052600460205260ff6040600020541615610d8557610cdc60195434611ad5565b336000526001602052610cf781600160406000200154611ac8565b6014541061096957610d1781610d12600954600a5490611ac8565b611ac8565b6008541061096957610d76903360005260016020526001604060002001610d3f828254611ac8565b90553360005260016020526002604060002001610d5d828254611ac8565b9055610d6b81600a54611ac8565b600a55600d54611ac8565b600d55610b6434600e54611ac8565b634f5fb6c960e11b60005260046000fd5b600190610db3610dab60065460075490611ae8565b600854611ac8565b60085560ff191617601d5580610cb8565b905061384081018091116104c157421181610ca6565b3461031457600036600319011261031457610df3611c2c565b6000808080600e5481600e55335af150610019611af5565b34610314576000366003190112610314576020601854604051908152f35b34610314576000366003190112610314576020600f54604051908152f35b34610314576000366003190112610314576020601a54604051908152f35b3461031457600036600319011261031457610e7e611c2c565b600080546001600160a01b0319811682556001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b346103145760003660031901126103145760208054604051908152f35b34610314576020366003190112610314576001600160a01b03610efc6119b3565b16600052600160205260c0604060002080549060018101549060028101546003820154906005600484015493015493604051958652602086015260408501526060840152608083015260a0820152f35b346103145760003660031901126103145760215460405160309190911c6001600160a01b03168152602090f35b34610314576000366003190112610314576020600854604051908152f35b34610314576000366003190112610314576020600654604051908152f35b3461031457610fc3366119c9565b90610fcc611c2c565b60005b8151811015610019576001906001600160a01b03610fed8285611be1565b511660005260046020526110118460406000209060ff801983541691151516179055565b01610fcf565b3461031457600036600319011261031457602060ff601d5460101c166040519015158152f35b34610314576000366003190112610314576020601254604051908152f35b346103145760003660031901126103145760ff6010541615610581573360005260016020526000602061079a6110976002604085200154611b35565b338452600183526110af600560408620015482611ae8565b3380865260018552604080872060050193909355602254925163a9059cbb60e01b8152600481019190915260248101919091529384926001600160a01b039092169183919082906044820190565b346103145760203660031901126103145760043560055481101561031457611126602091611a66565b905460405160039290921b1c6001600160a01b03168152f35b3461031457602036600319011261031457611158611c2c565b600f5461384081018091116104c15742116104b057600435601555005b3461031457602036600319011261031457600435611191611c2c565b600f54620189c081018091116104c15742106104b0576111bf6111b660165483611ad5565b600c5490611ac8565b600b541061096957602154906040516020810181811067ffffffffffffffff82111761095357604052600081526040519063125fa26760e31b6020830152511515602482015260248152611214604482611979565b602054601e54926040519460c086019086821067ffffffffffffffff831117610953579391869363ffffffff9260405284526020840195865281604085019561ffff8160201c16875281606087019116815281608087019316835260a0860194855261ffff60018060a01b03601f541697604051998a98634d8e1c2f60e11b8a52602060048b01525160248a01525160448901525116606487015251166084850152511660a48301525160c060c48301528051908160e484015260005b82811061132e575050918160006101048286838360209984010152601f801991011681010301925af180156104a45761130657005b6100199060203d602011611327575b61131f8183611979565b810190611c1d565b503d611315565b60208282018101516101048884010152869450016112d1565b34610314576000366003190112610314576020600754604051908152f35b34610314576000366003190112610314576020601c54604051908152f35b34610314576000366003190112610314576020601454604051908152f35b34610314576113af366119c9565b906113b8611c2c565b60005b8151811015610019576001906001600160a01b036113d98285611be1565b511660005260036020526113fd8460406000209060ff801983541691151516179055565b016113bb565b3461031457600036600319011261031457602060ff601d5460081c166040519015158152f35b3461031457600036600319011261031457602060ff601054166040519015158152f35b34610314576000366003190112610314576020601154604051908152f35b3461031457600036600319011261031457602063ffffffff60215416604051908152f35b346103145760403660031901126103145760243567ffffffffffffffff81116103145736602382011215610314578060040135906114cb8261199b565b916114d96040519384611979565b8083526024602084019160051b8301019136831161031457602401905b82821061169f57837f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031633819003611687575060005b8151811015610019576115478183611be1565b51600554908115611671570661155c81611a66565b60018060a01b0391549060031b1c1660165481600052600160205261158a6002604060002001918254611ac8565b90556115a960165461159e81600d54611ac8565b600d55600c54611ac8565b600c5560005260016020526003604060002001805490600182018092116104c157556005546000198101919082116104c1576116026115ea61162693611a66565b905460039190911b1c6001600160a01b031691611a66565b81546001600160a01b0393841660039290921b91821b9390911b1916919091179055565b60055490811561165b576001916000190161164081611a66565b815490858060a01b039060031b1b1916905560055501611534565b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b63073e64fd60e21b6000523360045260245260446000fd5b81358152602091820191016114f6565b600036600319011261031457600f54611c2081018082116104c15742109081156117bf575b506104b057601d5460ff811615611799575b5033600052600360205260ff6040600020541615610d855761170a60195434611ad5565b33600052600160205261172281604060002054611ac8565b601354106109695761173d81610d12600954600a5490611ac8565b6008541061096957610d76903360005260016020526040600020611762828254611ac8565b90553360005260016020526002604060002001611780828254611ac8565b905561178e81600954611ac8565b600955600d54611ac8565b6001906117ae610dab60065460075490611ae8565b60085560ff191617601d55806116e6565b905061384081018091116104c1574211816116d4565b346103145760203660031901126103145760206117f3600435611b35565b604051908152f35b3461031457602036600319011261031457611814611c2c565b600435601655005b34610314576000366003190112610314576020601754604051908152f35b3461031457600036600319011261031457601f546040516001600160a01b039091168152602090f35b34610314576000366003190112610314576020601e54604051908152f35b34610314576000366003190112610314576020601954604051908152f35b34610314576000366003190112610314576020600a54604051908152f35b346103145760203660031901126103145760043560005260026020526020604060002054604051908152f35b34610314576000366003190112610314576020600b54604051908152f35b3461031457600036600319011261031457611920611c2c565b600f54620189c081018091116104c15742106104b05761194560055460155490611ad5565b6103cf8102908082046103cf14901517156104c1576000808061196d6103e882950447611ae8565b335af150610019611af5565b90601f8019910116810190811067ffffffffffffffff82111761095357604052565b67ffffffffffffffff81116109535760051b60200190565b600435906001600160a01b038216820361031457565b6040600319820112610314576004359067ffffffffffffffff8211610314578060238301121561031457816004013590611a028261199b565b92611a106040519485611979565b8284526024602085019360051b82010191821161031457602401915b818310611a46575050509060243580151581036103145790565b82356001600160a01b038116810361031457815260209283019201611a2c565b600554811015611a8157600560005260206000200190600090565b634e487b7160e01b600052603260045260246000fd5b9181601f840112156103145782359167ffffffffffffffff8311610314576020808501948460051b01011161031457565b919082018092116104c157565b818102929181159184041417156104c157565b919082039182116104c157565b3d15611b30573d9067ffffffffffffffff82116109535760405191611b24601f8201601f191660200184611979565b82523d6000602084013e565b606090565b601154908115611bda57611b498242611ae8565b601c546064611b588285611ad5565b0493601b5490818410600014611b7057505050505090565b601a54949593611b808684611ac8565b11611b8d57505050505090565b611ba491611b9e9196949596611ac8565b42611ae8565b90606403606481116104c157611bbf606491611bc594611ad5565b04611ad5565b91801561167157611bd7920490611ac8565b90565b5050600090565b8051821015611a815760209160051b010190565b90816020910312610314575180151581036103145790565b9190811015611a815760051b0190565b90816020910312610314575190565b6000546001600160a01b03163303611c4057565b63118cdaa760e01b6000523360045260246000fd5b6021546040516331a9108f60e11b81526004810183905260309190911c6001600160a01b03169190602081602481865afa9081156104a457600091611dd7575b506001600160a01b031691338314611db057604051632e7cda1d60e21b81523360048201526024810184905260448101829052606481018390526000608482015260208160a4817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa9081156104a457600091611db8575b50611db057604051631574d39f60e31b81523360048201526024810193909352604483015260648201526020816084817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa9081156104a457600091611d91575b50611d8c57600090565b600190565b611daa915060203d60201161049d576104958183611979565b38611d82565b505050600190565b611dd1915060203d60201161049d576104958183611979565b38611d17565b6020813d602011611e18575b81611df060209383611979565b81010312611e145751906001600160a01b0382168203611e11575038611c95565b80fd5b5080fd5b3d9150611de356fea2646970667358221220750f3b635c6a5b231aad4a74db8a5d18531a18fbffe87b6ca0007cb9a2a6374064736f6c634300081a0033000000000000000000000000ee03aecbf056865d1365cad76aeef305238bd1dc00000000000000000000000057926998725cbcf319373550307c67830abf6187000000000000000000000000d7f86b4b8cae7d942340ff628f82735b7a20893a0000000000000000000000000000000000000000000000000000000000000000

Deployed Bytecode

0x6080604052600436101561001b575b361561001957600080fd5b005b60003560e01c8063019948851461190757806303b4a479146118e957806303c669e3146118bd57806303ebbf341461189f57806308ac900a1461188157806309c1ba2e146118635780630a0090971461183a57806318643d371461181c5780631a96ab2b146117fb5780631bfce853146117d55780631cecfaad146116af5780631fe543e31461148e57806324f746971461146a57806327b3bf111461144c5780632866ed211461142957806329687c53146114035780632a29e67a146113a157806332b7ac641461138357806334fccc1d1461136557806336ffc8b0146113475780633b3041471461117557806348a93a0d1461113f5780634c846e46146110fd5780634e71d92d1461105b57806352bca4c31461103d578063532f11791461101757806353d1f59d14610fb557806355a16c2414610f97578063595d221314610f795780635bf8633a14610f4c5780635d0eaaaf14610edb57806361728f3914610ebe578063715018a614610e655780637313ee5a14610e47578063790ca41314610e295780637d7af28014610e0b5780637d7bc63914610dda5780638007634f14610c815780638098004314610c6057806380c028a814610ad8578063856ed8c914610a935780638c52dc4114610a675780638da5cb5b14610a3e5780639755e04e146109ff57806398544710146109de5780639b27349d146108695780639d76ea5814610840578063a277d5b114610822578063a4bfb13014610804578063b0fb162f146107e0578063b2af127c1461071a578063baa39fbe146106db578063bcf257291461067a578063c94028c21461065c578063d1abca7a1461063e578063d85349f714610620578063db584d25146105db578063dbe65f59146105bd578063e086e5ec14610592578063e259f636146104f5578063e365d863146104d7578063ea28edad146103f7578063ec9cd924146103d4578063ee7d72b4146103a2578063f2fde38b146103195763f8d867940361000e5734610314576000366003190112610314576020601554604051908152f35b600080fd5b34610314576020366003190112610314576103326119b3565b61033a611c2c565b6001600160a01b0316801561038c57600080546001600160a01b03198116831782556001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09080a3005b631e4fbdf760e01b600052600060045260246000fd5b34610314576020366003190112610314576103bb611c2c565b6021805463ffffffff191660043563ffffffff16179055005b3461031457600036600319011261031457602060ff601d54166040519015158152f35b3461031457600036600319011261031457610410611c2c565b600f54620189c081018091116104c15742106104b057600160ff196010541617601055426011556000602060018060a01b03602254166064600d5460405194859384926323b872dd60e01b845233600485015230602485015260448401525af180156104a45761047c57005b6100199060203d60201161049d575b6104958183611979565b810190611bf5565b503d61048b565b6040513d6000823e3d90fd5b63ae20f3a560e01b60005260046000fd5b634e487b7160e01b600052601160045260246000fd5b34610314576000366003190112610314576020600e54604051908152f35b346103145760003660031901126103145760ff601d5460101c16156105815733600090815260016020526040902060048101546003909101546105459161053c9190611ae8565b60155490611ad5565b6103cf8102908082046103cf14901517156104c157600080806103e88194338352600160205282600460408220015504335af150610019611af5565b633f54562b60e11b60005260046000fd5b34610314576000366003190112610314576105ab611c2c565b600080808047335af150610019611af5565b34610314576000366003190112610314576020601354604051908152f35b34610314576000366003190112610314576040517f00000000000000000000000000000000000000447e69651d841bd8d104bed4936001600160a01b03168152602090f35b34610314576000366003190112610314576020601b54604051908152f35b34610314576000366003190112610314576020600c54604051908152f35b34610314576000366003190112610314576020601654604051908152f35b346103145760e036600319011261031457610693611c2c565b600f546106ca5742600f5560043560185560243560195560443560125560643560135560843560145560a43560155560c435601655005b6319f4db0f60e31b60005260046000fd5b34610314576020366003190112610314576001600160a01b036106fc6119b3565b166000526004602052602060ff604060002054166040519015158152f35b34610314576020366003190112610314576107336119b3565b61073b611c2c565b6040516370a0823160e01b8152306004820152906001600160a01b0316602082602481845afa9182156104a4576000926107aa575b5060405163a9059cbb60e01b81523360048201526024810192909252602090829081600081604481015b03925af180156104a45761047c57005b91506020823d6020116107d8575b816107c560209383611979565b810103126103145790519061079a610770565b3d91506107b8565b3461031457600036600319011261031457602061ffff602154821c16604051908152f35b34610314576000366003190112610314576020600954604051908152f35b34610314576000366003190112610314576020600d54604051908152f35b34610314576000366003190112610314576022546040516001600160a01b039091168152602090f35b602036600319011261031457600435600f5461384081018082116104c15742109081156109c7575b506104b057601d5460ff8160081c161561098b575b506108b381601554611ad5565b340361097a573360005260016020526108d481600460406000200154611ac8565b601754106109695733600052600160205260046040600020016108f8828254611ac8565b905560005b81811061090657005b60055490680100000000000000008210156109535761094d61092f836001809501600555611a66565b81546001600160a01b0360039290921b91821b19163390911b179055565b016108fd565b634e487b7160e01b600052604160045260246000fd5b63b1c0823160e01b60005260046000fd5b6399b5cb1d60e01b60005260046000fd5b610100906109b56109ad6008546109a7600954600a5490611ac8565b90611ae8565b600b54611ac8565b600b5561ff00191617601d55816108a6565b9050620189c081018091116104c157421182610891565b34610314576020366003190112610314576109f7611c2c565b600435602055005b34610314576020366003190112610314576001600160a01b03610a206119b3565b166000526003602052602060ff604060002054166040519015158152f35b34610314576000366003190112610314576000546040516001600160a01b039091168152602090f35b3461031457600036600319011261031457610a80611c2c565b601d805462ff0000191662010000179055005b34610314576000366003190112610314576040517f00000000000000000000000000000000000076a84fef008cdabe6409d2fe638b6001600160a01b03168152602090f35b60403660031901126103145760043567ffffffffffffffff811161031457610b04903690600401611a97565b60243567ffffffffffffffff811161031457610b24903690600401611a97565b919092600f54611c2081018091116104c15742116104b0576000805b848110610c405750340361097a5760005b828110610b6957610b6434600e54611ac8565b600e55005b610b74818484611c0d565b3590610b81818688611c0d565b35610b8b83611c55565b15610c2f57601854610b9c91611ad5565b91806000526002602052610bb583604060002054611ac8565b6012541061096957610bc983600754611ac8565b6006541061096957600192610c269133600052846020526002604060002001610bf3838254611ac8565b905560005260026020526040600020610c0d828254611ac8565b9055610c1b81600754611ac8565b600755600d54611ac8565b600d5501610b51565b635f68eddf60e11b60005260046000fd5b90610c59600191610c5284888a611c0d565b3590611ac8565b9101610b40565b3461031457602036600319011261031457610c79611c2c565b600435601e55005b600036600319011261031457600f54611c2081018082116104c1574210908115610dc4575b506104b057601d5460ff811615610d96575b5033600052600460205260ff6040600020541615610d8557610cdc60195434611ad5565b336000526001602052610cf781600160406000200154611ac8565b6014541061096957610d1781610d12600954600a5490611ac8565b611ac8565b6008541061096957610d76903360005260016020526001604060002001610d3f828254611ac8565b90553360005260016020526002604060002001610d5d828254611ac8565b9055610d6b81600a54611ac8565b600a55600d54611ac8565b600d55610b6434600e54611ac8565b634f5fb6c960e11b60005260046000fd5b600190610db3610dab60065460075490611ae8565b600854611ac8565b60085560ff191617601d5580610cb8565b905061384081018091116104c157421181610ca6565b3461031457600036600319011261031457610df3611c2c565b6000808080600e5481600e55335af150610019611af5565b34610314576000366003190112610314576020601854604051908152f35b34610314576000366003190112610314576020600f54604051908152f35b34610314576000366003190112610314576020601a54604051908152f35b3461031457600036600319011261031457610e7e611c2c565b600080546001600160a01b0319811682556001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b346103145760003660031901126103145760208054604051908152f35b34610314576020366003190112610314576001600160a01b03610efc6119b3565b16600052600160205260c0604060002080549060018101549060028101546003820154906005600484015493015493604051958652602086015260408501526060840152608083015260a0820152f35b346103145760003660031901126103145760215460405160309190911c6001600160a01b03168152602090f35b34610314576000366003190112610314576020600854604051908152f35b34610314576000366003190112610314576020600654604051908152f35b3461031457610fc3366119c9565b90610fcc611c2c565b60005b8151811015610019576001906001600160a01b03610fed8285611be1565b511660005260046020526110118460406000209060ff801983541691151516179055565b01610fcf565b3461031457600036600319011261031457602060ff601d5460101c166040519015158152f35b34610314576000366003190112610314576020601254604051908152f35b346103145760003660031901126103145760ff6010541615610581573360005260016020526000602061079a6110976002604085200154611b35565b338452600183526110af600560408620015482611ae8565b3380865260018552604080872060050193909355602254925163a9059cbb60e01b8152600481019190915260248101919091529384926001600160a01b039092169183919082906044820190565b346103145760203660031901126103145760043560055481101561031457611126602091611a66565b905460405160039290921b1c6001600160a01b03168152f35b3461031457602036600319011261031457611158611c2c565b600f5461384081018091116104c15742116104b057600435601555005b3461031457602036600319011261031457600435611191611c2c565b600f54620189c081018091116104c15742106104b0576111bf6111b660165483611ad5565b600c5490611ac8565b600b541061096957602154906040516020810181811067ffffffffffffffff82111761095357604052600081526040519063125fa26760e31b6020830152511515602482015260248152611214604482611979565b602054601e54926040519460c086019086821067ffffffffffffffff831117610953579391869363ffffffff9260405284526020840195865281604085019561ffff8160201c16875281606087019116815281608087019316835260a0860194855261ffff60018060a01b03601f541697604051998a98634d8e1c2f60e11b8a52602060048b01525160248a01525160448901525116606487015251166084850152511660a48301525160c060c48301528051908160e484015260005b82811061132e575050918160006101048286838360209984010152601f801991011681010301925af180156104a45761130657005b6100199060203d602011611327575b61131f8183611979565b810190611c1d565b503d611315565b60208282018101516101048884010152869450016112d1565b34610314576000366003190112610314576020600754604051908152f35b34610314576000366003190112610314576020601c54604051908152f35b34610314576000366003190112610314576020601454604051908152f35b34610314576113af366119c9565b906113b8611c2c565b60005b8151811015610019576001906001600160a01b036113d98285611be1565b511660005260036020526113fd8460406000209060ff801983541691151516179055565b016113bb565b3461031457600036600319011261031457602060ff601d5460081c166040519015158152f35b3461031457600036600319011261031457602060ff601054166040519015158152f35b34610314576000366003190112610314576020601154604051908152f35b3461031457600036600319011261031457602063ffffffff60215416604051908152f35b346103145760403660031901126103145760243567ffffffffffffffff81116103145736602382011215610314578060040135906114cb8261199b565b916114d96040519384611979565b8083526024602084019160051b8301019136831161031457602401905b82821061169f57837f000000000000000000000000d7f86b4b8cae7d942340ff628f82735b7a20893a6001600160a01b031633819003611687575060005b8151811015610019576115478183611be1565b51600554908115611671570661155c81611a66565b60018060a01b0391549060031b1c1660165481600052600160205261158a6002604060002001918254611ac8565b90556115a960165461159e81600d54611ac8565b600d55600c54611ac8565b600c5560005260016020526003604060002001805490600182018092116104c157556005546000198101919082116104c1576116026115ea61162693611a66565b905460039190911b1c6001600160a01b031691611a66565b81546001600160a01b0393841660039290921b91821b9390911b1916919091179055565b60055490811561165b576001916000190161164081611a66565b815490858060a01b039060031b1b1916905560055501611534565b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b63073e64fd60e21b6000523360045260245260446000fd5b81358152602091820191016114f6565b600036600319011261031457600f54611c2081018082116104c15742109081156117bf575b506104b057601d5460ff811615611799575b5033600052600360205260ff6040600020541615610d855761170a60195434611ad5565b33600052600160205261172281604060002054611ac8565b601354106109695761173d81610d12600954600a5490611ac8565b6008541061096957610d76903360005260016020526040600020611762828254611ac8565b90553360005260016020526002604060002001611780828254611ac8565b905561178e81600954611ac8565b600955600d54611ac8565b6001906117ae610dab60065460075490611ae8565b60085560ff191617601d55806116e6565b905061384081018091116104c1574211816116d4565b346103145760203660031901126103145760206117f3600435611b35565b604051908152f35b3461031457602036600319011261031457611814611c2c565b600435601655005b34610314576000366003190112610314576020601754604051908152f35b3461031457600036600319011261031457601f546040516001600160a01b039091168152602090f35b34610314576000366003190112610314576020601e54604051908152f35b34610314576000366003190112610314576020601954604051908152f35b34610314576000366003190112610314576020600a54604051908152f35b346103145760203660031901126103145760043560005260026020526020604060002054604051908152f35b34610314576000366003190112610314576020600b54604051908152f35b3461031457600036600319011261031457611920611c2c565b600f54620189c081018091116104c15742106104b05761194560055460155490611ad5565b6103cf8102908082046103cf14901517156104c1576000808061196d6103e882950447611ae8565b335af150610019611af5565b90601f8019910116810190811067ffffffffffffffff82111761095357604052565b67ffffffffffffffff81116109535760051b60200190565b600435906001600160a01b038216820361031457565b6040600319820112610314576004359067ffffffffffffffff8211610314578060238301121561031457816004013590611a028261199b565b92611a106040519485611979565b8284526024602085019360051b82010191821161031457602401915b818310611a46575050509060243580151581036103145790565b82356001600160a01b038116810361031457815260209283019201611a2c565b600554811015611a8157600560005260206000200190600090565b634e487b7160e01b600052603260045260246000fd5b9181601f840112156103145782359167ffffffffffffffff8311610314576020808501948460051b01011161031457565b919082018092116104c157565b818102929181159184041417156104c157565b919082039182116104c157565b3d15611b30573d9067ffffffffffffffff82116109535760405191611b24601f8201601f191660200184611979565b82523d6000602084013e565b606090565b601154908115611bda57611b498242611ae8565b601c546064611b588285611ad5565b0493601b5490818410600014611b7057505050505090565b601a54949593611b808684611ac8565b11611b8d57505050505090565b611ba491611b9e9196949596611ac8565b42611ae8565b90606403606481116104c157611bbf606491611bc594611ad5565b04611ad5565b91801561167157611bd7920490611ac8565b90565b5050600090565b8051821015611a815760209160051b010190565b90816020910312610314575180151581036103145790565b9190811015611a815760051b0190565b90816020910312610314575190565b6000546001600160a01b03163303611c4057565b63118cdaa760e01b6000523360045260246000fd5b6021546040516331a9108f60e11b81526004810183905260309190911c6001600160a01b03169190602081602481865afa9081156104a457600091611dd7575b506001600160a01b031691338314611db057604051632e7cda1d60e21b81523360048201526024810184905260448101829052606481018390526000608482015260208160a4817f00000000000000000000000000000000000000447e69651d841bd8d104bed4936001600160a01b03165afa9081156104a457600091611db8575b50611db057604051631574d39f60e31b81523360048201526024810193909352604483015260648201526020816084817f00000000000000000000000000000000000076a84fef008cdabe6409d2fe638b6001600160a01b03165afa9081156104a457600091611d91575b50611d8c57600090565b600190565b611daa915060203d60201161049d576104958183611979565b38611d82565b505050600190565b611dd1915060203d60201161049d576104958183611979565b38611d17565b6020813d602011611e18575b81611df060209383611979565b81010312611e145751906001600160a01b0382168203611e11575038611c95565b80fd5b5080fd5b3d9150611de356fea2646970667358221220750f3b635c6a5b231aad4a74db8a5d18531a18fbffe87b6ca0007cb9a2a6374064736f6c634300081a0033

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

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