Contract 0xb67896e760c8da449acc363e55953b74904c7a50

 
 
Txn Hash Method
Block
From
To
Value [Txn Fee]
0xd12b048d9dbf4c2b6b6ad4b04c01b9f275349c7d63d28656fc537fcc2b9614a8Select Contest W...279965822022-05-06 15:39:3913 days 19 hrs ago0x7c189051305b3f8f228374e4e624c28c38dc334a IN  0xb67896e760c8da449acc363e55953b74904c7a500 MATIC0.163937012284
0xe058e3dbd76aaf9e6cd6007ab0e25ba3b8b7cf1155edb88f6db93bed8728b992Create New Conte...279965622022-05-06 15:38:5913 days 19 hrs ago0x7c189051305b3f8f228374e4e624c28c38dc334a IN  0xb67896e760c8da449acc363e55953b74904c7a500 MATIC0.152314333324260.538738147
0xdceb7376f0b9c2cf91a4adf38bec1f76d6adac3a6396e45a22163c42b779537aSelect Contest W...279965362022-05-06 15:38:0313 days 19 hrs ago0x7c189051305b3f8f228374e4e624c28c38dc334a IN  0xb67896e760c8da449acc363e55953b74904c7a500 MATIC0.020914437332224.2787
0x636a6af5bc8c6de168699615fe99faed77b9d1bf6650d7e7090c0281c683189aSelect Contest W...279965322022-05-06 15:37:5513 days 19 hrs ago0x7c189051305b3f8f228374e4e624c28c38dc334a IN  0xb67896e760c8da449acc363e55953b74904c7a500 MATIC0.131776783762228.286499382
0x73d1329a2033d6b99f912fbfabf5f94560800da3bb5a8dfb31745ada931155e6Create New Conte...279965162022-05-06 15:37:2313 days 19 hrs ago0x7c189051305b3f8f228374e4e624c28c38dc334a IN  0xb67896e760c8da449acc363e55953b74904c7a500 MATIC0.120957286618206.897218933
0x24bdafc22cb3d491c3e6b248f6f7a794aa839c649e09b85c2f122644b66348f5Create New Conte...279958072022-05-06 15:10:5313 days 19 hrs ago0x7c189051305b3f8f228374e4e624c28c38dc334a IN  0xb67896e760c8da449acc363e55953b74904c7a500 MATIC0.14615325250
0x273f70a71b3421f6d8e6378f8b44ec386b42b53c4eccbfe10118ba9071e2bdeeSelect Contest W...275657702022-04-25 17:12:3824 days 17 hrs ago0x7c189051305b3f8f228374e4e624c28c38dc334a IN  0xb67896e760c8da449acc363e55953b74904c7a500 MATIC0.014098868645151.191059123
0xc420f66c064a108476a0f01f3e54609a3e1c2b393909363b8213e070276e8378Select Contest W...275657652022-04-25 17:12:2824 days 17 hrs ago0x7c189051305b3f8f228374e4e624c28c38dc334a IN  0xb67896e760c8da449acc363e55953b74904c7a500 MATIC0.020950645536148.593515543
0x77637dbc13cb4c180a59865069099897c8b060fce3412ae61931b8d76a121721Select Contest W...275657612022-04-25 17:12:2024 days 17 hrs ago0x7c189051305b3f8f228374e4e624c28c38dc334a IN  0xb67896e760c8da449acc363e55953b74904c7a500 MATIC0.041248583365145.130598682
0x270c57949b6df4caa05e42a6888f4d4626afd7377c6549f795d850b80d228806Select Contest W...275657592022-04-25 17:12:1224 days 17 hrs ago0x7c189051305b3f8f228374e4e624c28c38dc334a IN  0xb67896e760c8da449acc363e55953b74904c7a500 MATIC0.055901741715147.226077733
0x0730a6d1a8ae1806012a8b7c029bc1e86b5deddea56f1827360b2741c66a9113Select Contest W...275657552022-04-25 17:12:0424 days 17 hrs ago0x7c189051305b3f8f228374e4e624c28c38dc334a IN  0xb67896e760c8da449acc363e55953b74904c7a500 MATIC0.091916924085147.928376717
0xf9efd00ce41ac0caf3e84f21e86a26b1b279d1ee4654a883f59eca8fb0c34255Select Contest W...275657512022-04-25 17:11:5624 days 17 hrs ago0x7c189051305b3f8f228374e4e624c28c38dc334a IN  0xb67896e760c8da449acc363e55953b74904c7a500 MATIC0.180377473994145.230057354
0xe09c6cf183fece2f4ccde623def0ef51f707bb9963dd55830d5676fff6a4a738Select Contest W...275657472022-04-25 17:11:4824 days 17 hrs ago0x7c189051305b3f8f228374e4e624c28c38dc334a IN  0xb67896e760c8da449acc363e55953b74904c7a500 MATIC0.726300568667148.978314507
0x2c3eab901803c6c846108acbac1a35a9d80fc8012e1ee98857cc48eaf5a058b2Create New Conte...275657262022-04-25 17:11:0624 days 17 hrs ago0x7c189051305b3f8f228374e4e624c28c38dc334a IN  0xb67896e760c8da449acc363e55953b74904c7a500 MATIC0.089158748237152.546582004
0x81c23c36170a9fd30b04b4bd87c8dcf948dc01eea0420019040643d4ad29d9ceCreate New Conte...275655962022-04-25 17:05:2824 days 17 hrs ago0x7c189051305b3f8f228374e4e624c28c38dc334a IN  0xb67896e760c8da449acc363e55953b74904c7a500 MATIC0.099430527232170.121130859
0x7d3ec102b7e2342399b1330cd3196d46120ed8a607e9a32ee153420ea24e3720Create New Conte...275654632022-04-25 16:59:5624 days 17 hrs ago0x7c189051305b3f8f228374e4e624c28c38dc334a IN  0xb67896e760c8da449acc363e55953b74904c7a500 MATIC0.1168938200
0x65b63d2a69da54e6ff6f1f494e8d45259dc36df9d5fe4cff0f2c251cbcd38290Create New Conte...275654632022-04-25 16:59:5624 days 17 hrs ago0x7c189051305b3f8f228374e4e624c28c38dc334a IN  0xb67896e760c8da449acc363e55953b74904c7a500 MATIC0.11080427146189.581092342
0x10d5f4b41a0da88ff614f9d06b1174191aeee5eddbd09beac106332a4e26c711Create New Conte...275654632022-04-25 16:59:5624 days 17 hrs ago0x7c189051305b3f8f228374e4e624c28c38dc334a IN  0xb67896e760c8da449acc363e55953b74904c7a500 MATIC0.079137591414135.400836339
0x7d081a2063f76eaf1a9c1730130743f3fca52f51348805a1ea868203f63b4d24Create New Conte...275654632022-04-25 16:59:5624 days 17 hrs ago0x7c189051305b3f8f228374e4e624c28c38dc334a IN  0xb67896e760c8da449acc363e55953b74904c7a500 MATIC0.077538466648132.664806258
0xc617f8bcf7bc45c6c7d61aa8439829af1ce7e8945f529f9273a4141d52792649Create New Conte...275654632022-04-25 16:59:5624 days 17 hrs ago0x7c189051305b3f8f228374e4e624c28c38dc334a IN  0xb67896e760c8da449acc363e55953b74904c7a500 MATIC0.081709431098139.801137611
0xd8613c2fef3bb0cc43c30014cdbfe8b34559723677aa9e22d428fa57b5b11fa7Create New Conte...275654632022-04-25 16:59:5624 days 17 hrs ago0x7c189051305b3f8f228374e4e624c28c38dc334a IN  0xb67896e760c8da449acc363e55953b74904c7a500 MATIC0.087471469279149.65972409
0x6c4385ab17a4f29ad3ca349df1b9f2df2643c2810c0bdcd2a9b5444576afcf93Create New Conte...275654632022-04-25 16:59:5624 days 17 hrs ago0x7c189051305b3f8f228374e4e624c28c38dc334a IN  0xb67896e760c8da449acc363e55953b74904c7a500 MATIC0.067583296159115.631960223
0x944d08f1f70bebb376b2ed4541f4a8f82b5ca41ee315b0e7737f7705adf2ecdaCreate New Conte...275654632022-04-25 16:59:5624 days 17 hrs ago0x7c189051305b3f8f228374e4e624c28c38dc334a IN  0xb67896e760c8da449acc363e55953b74904c7a500 MATIC0.04725074306280.843882332
0xee7e8031e58895792967c7af807d28c11637ddc0fc3e1f03a95653df9e6a5b09Create New Conte...275654632022-04-25 16:59:5624 days 17 hrs ago0x7c189051305b3f8f228374e4e624c28c38dc334a IN  0xb67896e760c8da449acc363e55953b74904c7a500 MATIC0.076235771278130.435953452
0x22d9e6f2afc7bea0852b4b8260b3bef12ec3501b2a8531a6b4ec0be56d8070e5Select Contest W...275569962022-04-25 11:46:5324 days 22 hrs ago0x7c189051305b3f8f228374e4e624c28c38dc334a IN  0xb67896e760c8da449acc363e55953b74904c7a500 MATIC0.04237814970581.040588431
[ Download CSV Export 
Parent Txn Hash Block From To Value
Loading

Similar Match Source Code
Note: This contract matches the deployed ByteCode of the Source Code for Contract 0xC573F5BC04bd4C983995C0C265003B510A48E486

Contract Name:
GenericContestSelector

Compiler Version
v0.8.6+commit.11564f7e

Optimization Enabled:
Yes with 999999 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity Standard Json-Input format)

File 1 of 8 : GenericContestSelector.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.4;

import "./external/chainlink/VRFConsumerBase.sol";
import "./external/openzeppelin/EnumerableSet.sol";
import "./abstract/Ownable.sol";
import "./libraries/SafeERC20.sol";

contract GenericContestSelector is Ownable, VRFConsumerBase {
    using SafeERC20 for IERC20;
    using EnumerableSet for EnumerableSet.UintSet;

    // Modifiers

    /// @dev Verify if contest for given id exists
    modifier contestExists(uint256 contestId) {
        require(contests.length >= contestId, "Contest doesn't exist");
        _;
    }

    /// @dev Verify if contest is completed
    modifier contestPerformed(uint contestId) {
        require(!contests[contestId - 1].contestWinnersSelected, "Contest selection performed");
        _;
    }

    /// @notice Triggered after winners were selected
    event ContestWinnerSelected(uint256 contestId, uint256 timestamp, uint256 contestWinner);
    /// @notice Triggered when random number for contest was set
    event SetRandomNumberForContest(uint256 indexed contestId);
    /// @notice Triggered after new contest was added
    event AddedNewContest(uint256 contestId);

    // Chainlink + Randomness

    bytes32 internal keyHash;
    uint256 internal fee;

    /// @dev Array of all contests
    Contest[] public contests;

    /// @dev Key: contest.id, Value: winners in contest
    mapping(uint256 => EnumerableSet.UintSet) private contestWinners;
    /// @dev Key: contest.id, Value: steps completed in contest
    mapping(uint256 => EnumerableSet.UintSet) internal stepsBeforeContestSelection;
    /// @dev Key: Chainlink oracle request id, Value: contest.id
    mapping(bytes32 => uint256) private contestRandomNumberRequestId;

    struct Contest {
        uint256 id;
        string name;
        uint256 ticketsCount;
        string participantsListLink;
        string participantsListSha256;
        bool contestWinnersSelected;
        uint256 randomResult;
        uint256 previousWinnerSeed;
    }

    /**
     * Constructor inherits VRFConsumerBase
     */
    constructor(
        address _vrfCoordinator,
        address _link,
        bytes32 _keyHash,
        uint256 _fee
    )
        Ownable(msg.sender)
        VRFConsumerBase(
            _vrfCoordinator, // VRF Coordinator
            _link // LINK Token
        )
    {
        keyHash = _keyHash;
        fee = _fee; // LINK fee
    }

    /// @notice Allows owner to set the VRF keyHash
    /// @param _keyHash The keyHash to be used by the VRF
    function setKeyHash(bytes32 _keyHash) external onlyOwner {
        keyHash = _keyHash;
    }

    /// @notice Allows owner to set the fee per request required by the VRF
    /// @param _fee The fee to be charged for a request
    function setFee(uint256 _fee) external onlyOwner {
        fee = _fee;
    }

    /// @notice Create new contest with possibility to set all data and call
    /// @notice method to select winners
    /// @param name Name of the contest
    /// @param participantsListLink Link to participants sheet
    /// @param participantsListSha256 Link to participants sheet encoded in sha256
    /// @param ticketsCount Number of maximum winners in contest
    function createNewContest(
        string memory name,
        string memory participantsListLink,
        string memory participantsListSha256,
        uint256 ticketsCount
        ) external onlyOwner {

        // Add new empty contest
        contests.push();

        Contest storage contest = contests[contests.length - 1];
        contest.id = contests.length;
        contest.name = name;

        // Set random number for contest
        getRandomNumber(contest.id);

        // Check and set 'participantsListLink' for contest
        if(bytes(participantsListLink).length != 0)
            setParticipantsListLink(contest.id, participantsListLink);

        // Check and set 'participantsListSha256' for contest
        if(bytes(participantsListSha256).length != 0)
            setParticipantsListSha256(contest.id, participantsListSha256);

        // Check and set 'ticketsCount' for contest
        if(ticketsCount > 0)
            setTicketsNumber(contest.id, ticketsCount);

        emit AddedNewContest(contest.id);
    }

    /// @notice Return contest data for given 'contest.id'
    function getContestById(uint256 contestId) external view contestExists(contestId) returns(Contest memory) {
        Contest storage contest = contests[contestId - 1];

        return contest;
    }

    /**
     * Requests randomness
     */
    function getRandomNumber(uint256 contestId) public virtual contestExists(contestId) {
        require(LINK.balanceOf(address(this)) >= fee, "Not enough LINK - provide LINK to the contract");

        bytes32 requestId = requestRandomness(keyHash, fee);

        contestRandomNumberRequestId[requestId] = contestId;
    }

    /**
     * Callback function used by VRF Coordinator
     */
    function fulfillRandomness(bytes32 requestId, uint256 randomness) internal override {
        uint256 contestId = contestRandomNumberRequestId[requestId];

        Contest storage contest = contests[contestId - 1];
        contest.randomResult = randomness;

        emit SetRandomNumberForContest(contestId);

        if (!stepsBeforeContestSelection[contestId].contains(1)) {
            stepsBeforeContestSelection[contestId].add(1);
        }
    }

    /// @notice Set number of tickets for contest
    /// @param contestId Contest ID
    /// @param number Number of maximum winner in contest
    function setTicketsNumber(
        uint256 contestId,
        uint256 number
        ) public onlyOwner contestExists(contestId) contestPerformed(contestId) {
        Contest storage contest = contests[contestId - 1];
        contest.ticketsCount = number;
        if (!stepsBeforeContestSelection[contestId].contains(2)) {
            stepsBeforeContestSelection[contestId].add(2);
        }
    }

    /// @notice Set link for participants sheet
    /// @param contestId Contest ID
    /// @param link Participants sheet link
    function setParticipantsListLink(
        uint256 contestId,
        string memory link
        ) public onlyOwner contestExists(contestId) contestPerformed(contestId) {
        Contest storage contest = contests[contestId - 1];
        contest.participantsListLink = link;

        if (!stepsBeforeContestSelection[contestId].contains(3)) {
            stepsBeforeContestSelection[contestId].add(3);
        }
    }

    /// @notice Set encoded in sha256 participants sheet
    /// @param contestId Contest ID
    /// @param sha256Hash Hash of participants sheet
    function setParticipantsListSha256(
        uint256 contestId,
        string memory sha256Hash
        ) public onlyOwner contestExists(contestId) contestPerformed(contestId) {
        Contest storage contest = contests[contestId - 1];
        contest.participantsListSha256 = sha256Hash;

        if (!stepsBeforeContestSelection[contestId].contains(4)) {
            stepsBeforeContestSelection[contestId].add(4);
        }
    }

    /// @notice Select winners in contest
    /// @param contestId Contest ID
    /// @param count Winners to select in contest
    function selectContestWinners(uint256 contestId, uint256 count) public onlyOwner contestExists(contestId) {
        require(stepsBeforeContestSelection[contestId].length() == 4, "Contest: Not all steps performed");
        require(contests[contestId - 1].randomResult != 0, "Contest: Chainlink data recheck");
        require((count + contestWinners[contestId].length()) <= contests[contestId - 1].ticketsCount, "Contest: Outside of ticket range");

        Contest storage contest = contests[contestId - 1];

        if (contest.previousWinnerSeed == 0) {
            contest.previousWinnerSeed = contest.randomResult;
        }

        for (uint256 i = 0; i < count; i++) {
            uint256 winnerSeed;
            uint256 winnerIndex;

            bool winnerSelected = false;
            uint256 nonce = 0;
            do {
                winnerSeed = uint256(keccak256(abi.encodePacked(contest.previousWinnerSeed, i, nonce)));
                winnerIndex = (winnerSeed % contest.ticketsCount) + 1;
                nonce++;

                winnerSelected = !contestWinners[contestId].contains(winnerIndex);
            } while (!winnerSelected);

            contestWinners[contestId].add(winnerIndex);
            contest.previousWinnerSeed = winnerSeed;

            emit ContestWinnerSelected(contestId, block.timestamp, winnerIndex);
        }

        contest.contestWinnersSelected = true;
    }

    /// @notice Returns array of winners in contest
    /// @param contestId Contest ID
    function getContestWinners(uint256 contestId) external view contestExists(contestId) returns(uint256[] memory) {
        uint256[] memory winners = new uint256[](contestWinners[contestId].length());

        for (uint256 i = 0; i < contestWinners[contestId].length(); i++) {
            winners[i] = contestWinners[contestId].at(i);
        }

        return winners;
    }

    /// @notice Returns array of winners in contest in given range
    /// @param contestId Contest ID
    /// @param from Start index for contest winners
    /// @param to Last index for contest winners
    function getContestWinnersInRange(
        uint256 contestId,
        uint256 from,
        uint256 to
        ) external view contestExists(contestId) returns(uint256[] memory)  {
        require(from <= to, "Incorrect range");
        require(to < contestWinners[contestId].length(), "Incorrect range");

        uint256[] memory winners = new uint256[](to - from + 1);

        for (uint256 i = 0; i <= to - from; i++) {
            winners[i] = contestWinners[contestId].at(i + from);
        }

        return winners;
    }

    function recoverErc20(address token) external onlyOwner {
        uint256 amount = IERC20(token).balanceOf(address(this));
        if (amount > 0) {
            IERC20(token).safeTransfer(owner, amount);
        }
    }

    function recover() external onlyOwner {
        payable(owner).transfer(address(this).balance);
    }
}

File 2 of 8 : Ownable.sol
// SPDX-License-Identifier: MIT

// Source: https://github.com/boringcrypto/BoringSolidity/blob/master/contracts/BoringOwnable.sol

pragma solidity ^0.8.4;

abstract contract OwnableData {
    address public owner;
    address public pendingOwner;
}

abstract contract Ownable is OwnableData {
    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    constructor(address _owner) {
        require(_owner != address(0), "Ownable: zero address");
        owner = _owner;
        emit OwnershipTransferred(address(0), msg.sender);
    }

    /// @notice Transfers ownership to `newOwner`. Either directly or claimable by the new pending owner.
    /// Can only be invoked by the current `owner`.
    /// @param newOwner Address of the new owner.
    /// @param direct True if `newOwner` should be set immediately. False if `newOwner` needs to use `claimOwnership`.
    function transferOwnership(address newOwner, bool direct) public onlyOwner {
        if (direct) {
            // Checks
            require(newOwner != address(0), "Ownable: zero address");

            // Effects
            emit OwnershipTransferred(owner, newOwner);
            owner = newOwner;
            pendingOwner = address(0);
        } else {
            // Effects
            pendingOwner = newOwner;
        }
    }

    /// @notice Needs to be called by `pendingOwner` to claim ownership.
    function claimOwnership() public {
        address _pendingOwner = pendingOwner;

        // Checks
        require(msg.sender == _pendingOwner, "Ownable: caller != pending owner");

        // Effects
        emit OwnershipTransferred(owner, _pendingOwner);
        owner = _pendingOwner;
        pendingOwner = address(0);
    }

    modifier onlyOwner() {
        require(msg.sender == owner, "Ownable: caller is not the owner");
        _;
    }
}

File 3 of 8 : LinkTokenInterface.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface LinkTokenInterface {

  function allowance(
    address owner,
    address spender
  )
    external
    view
    returns (
      uint256 remaining
    );

  function approve(
    address spender,
    uint256 value
  )
    external
    returns (
      bool success
    );

  function balanceOf(
    address owner
  )
    external
    view
    returns (
      uint256 balance
    );

  function decimals()
    external
    view
    returns (
      uint8 decimalPlaces
    );

  function decreaseApproval(
    address spender,
    uint256 addedValue
  )
    external
    returns (
      bool success
    );

  function increaseApproval(
    address spender,
    uint256 subtractedValue
  ) external;

  function name()
    external
    view
    returns (
      string memory tokenName
    );

  function symbol()
    external
    view
    returns (
      string memory tokenSymbol
    );

  function totalSupply()
    external
    view
    returns (
      uint256 totalTokensIssued
    );

  function transfer(
    address to,
    uint256 value
  )
    external
    returns (
      bool success
    );

  function transferAndCall(
    address to,
    uint256 value,
    bytes calldata data
  )
    external
    returns (
      bool success
    );

  function transferFrom(
    address from,
    address to,
    uint256 value
  )
    external
    returns (
      bool success
    );

}

File 4 of 8 : VRFConsumerBase.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "./LinkTokenInterface.sol";

import "./VRFRequestIDBase.sol";

/** ****************************************************************************
 * @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.
 * *****************************************************************************
 * @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     constuctor(<other arguments>, address _vrfCoordinator, address _link)
 * @dev       VRFConsumerBase(_vrfCoordinator, _link) 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), and have told you the minimum LINK
 * @dev price for VRF service. Make sure your contract has sufficient LINK, and
 * @dev call requestRandomness(keyHash, fee, seed), where seed is the input you
 * @dev want to generate randomness from.
 *
 * @dev Once the VRFCoordinator has received and validated the oracle's response
 * @dev to your request, it will call your contract's fulfillRandomness method.
 *
 * @dev The randomness argument to fulfillRandomness is the actual random value
 * @dev generated from your seed.
 *
 * @dev The requestId argument is generated from the keyHash and the seed by
 * @dev makeRequestId(keyHash, seed). If your contract could have concurrent
 * @dev requests open, you can use the requestId to track which seed is
 * @dev associated with which randomness. See VRFRequestIDBase.sol for more
 * @dev details. (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. (Which is critical to making unpredictable randomness! See the
 * @dev next section.)
 *
 * *****************************************************************************
 * @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 ultimate input to the VRF is mixed with the block hash of the
 * @dev block in which the request is made, user-provided seeds have no impact
 * @dev on its economic security properties. They are only included for API
 * @dev compatability with previous versions of this contract.
 *
 * @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.
 */
abstract contract VRFConsumerBase is VRFRequestIDBase {
    /**
     * @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 VRFConsumerBase 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 randomness the VRF output
     */
    function fulfillRandomness(bytes32 requestId, uint256 randomness) internal virtual;

    /**
     * @dev In order to keep backwards compatibility we have kept the user
     * seed field around. We remove the use of it because given that the blockhash
     * enters later, it overrides whatever randomness the used seed provides.
     * Given that it adds no security, and can easily lead to misunderstandings,
     * we have removed it from usage and can now provide a simpler API.
     */
    uint256 private constant USER_SEED_PLACEHOLDER = 0;

    /**
     * @notice requestRandomness initiates a request for VRF output given _seed
     *
     * @dev The fulfillRandomness method receives the output, once it's provided
     * @dev by the Oracle, and verified by the vrfCoordinator.
     *
     * @dev The _keyHash must already be registered with the VRFCoordinator, and
     * @dev the _fee must exceed the fee specified during registration of the
     * @dev _keyHash.
     *
     * @dev The _seed parameter is vestigial, and is kept only for API
     * @dev compatibility with older versions. It can't *hurt* to mix in some of
     * @dev your own randomness, here, but it's not necessary because the VRF
     * @dev oracle will mix the hash of the block containing your request into the
     * @dev VRF seed it ultimately uses.
     *
     * @param _keyHash ID of public key against which randomness is generated
     * @param _fee The amount of LINK to send with the request
     *
     * @return requestId unique ID for this request
     *
     * @dev The returned requestId can be used to distinguish responses to
     * @dev concurrent requests. It is passed as the first argument to
     * @dev fulfillRandomness.
     */
    function requestRandomness(bytes32 _keyHash, uint256 _fee) internal returns (bytes32 requestId) {
        LINK.transferAndCall(vrfCoordinator, _fee, abi.encode(_keyHash, USER_SEED_PLACEHOLDER));
        // This is the seed passed to VRFCoordinator. The oracle will mix this with
        // the hash of the block containing this request to obtain the seed/input
        // which is finally passed to the VRF cryptographic machinery.
        uint256 vRFSeed = makeVRFInputSeed(_keyHash, USER_SEED_PLACEHOLDER, address(this), nonces[_keyHash]);
        // nonces[_keyHash] must stay in sync with
        // VRFCoordinator.nonces[_keyHash][this], which was incremented by the above
        // successful LINK.transferAndCall (in VRFCoordinator.randomnessRequest).
        // This provides protection against the user repeating their input seed,
        // which would result in a predictable/duplicate output, if multiple such
        // requests appeared in the same block.
        nonces[_keyHash] = nonces[_keyHash] + 1;
        return makeRequestId(_keyHash, vRFSeed);
    }

    LinkTokenInterface internal immutable LINK;
    address private immutable vrfCoordinator;

    // Nonces for each VRF key from which randomness has been requested.
    //
    // Must stay in sync with VRFCoordinator[_keyHash][this]
    mapping(bytes32 => uint256) /* keyHash */ /* nonce */
        private nonces;

    /**
     * @param _vrfCoordinator address of VRFCoordinator contract
     * @param _link address of LINK token contract
     *
     * @dev https://docs.chain.link/docs/link-token-contracts
     */
    constructor(address _vrfCoordinator, address _link) {
        vrfCoordinator = _vrfCoordinator;
        LINK = LinkTokenInterface(_link);
    }

    // rawFulfillRandomness is called by VRFCoordinator when it receives a valid VRF
    // proof. rawFulfillRandomness then calls fulfillRandomness, after validating
    // the origin of the call
    function rawFulfillRandomness(bytes32 requestId, uint256 randomness) external {
        require(msg.sender == vrfCoordinator, "Only VRFCoordinator can fulfill");
        fulfillRandomness(requestId, randomness);
    }
}

File 5 of 8 : VRFRequestIDBase.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract VRFRequestIDBase {

  /**
   * @notice returns the seed which is actually input to the VRF coordinator
   *
   * @dev To prevent repetition of VRF output due to repetition of the
   * @dev user-supplied seed, that seed is combined in a hash with the
   * @dev user-specific nonce, and the address of the consuming contract. The
   * @dev risk of repetition is mostly mitigated by inclusion of a blockhash in
   * @dev the final seed, but the nonce does protect against repetition in
   * @dev requests which are included in a single block.
   *
   * @param _userSeed VRF seed input provided by user
   * @param _requester Address of the requesting contract
   * @param _nonce User-specific nonce at the time of the request
   */
  function makeVRFInputSeed(
    bytes32 _keyHash,
    uint256 _userSeed,
    address _requester,
    uint256 _nonce
  )
    internal
    pure
    returns (
      uint256
    )
  {
    return uint256(keccak256(abi.encode(_keyHash, _userSeed, _requester, _nonce)));
  }

  /**
   * @notice Returns the id for this request
   * @param _keyHash The serviceAgreement ID to be used for this request
   * @param _vRFInputSeed The seed to be passed directly to the VRF
   * @return The id for this request
   *
   * @dev Note that _vRFInputSeed is not the seed passed by the consuming
   * @dev contract, but the one generated by makeVRFInputSeed
   */
  function makeRequestId(
    bytes32 _keyHash,
    uint256 _vRFInputSeed
  )
    internal
    pure
    returns (
      bytes32
    )
  {
    return keccak256(abi.encodePacked(_keyHash, _vRFInputSeed));
  }
}

File 6 of 8 : EnumerableSet.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @dev Library for managing
 * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
 * types.
 *
 * Sets have the following properties:
 *
 * - Elements are added, removed, and checked for existence in constant time
 * (O(1)).
 * - Elements are enumerated in O(n). No guarantees are made on the ordering.
 *
 * ```
 * contract Example {
 *     // Add the library methods
 *     using EnumerableSet for EnumerableSet.AddressSet;
 *
 *     // Declare a set state variable
 *     EnumerableSet.AddressSet private mySet;
 * }
 * ```
 *
 * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
 * and `uint256` (`UintSet`) are supported.
 */
library EnumerableSet {
    // To implement this library for multiple types with as little code
    // repetition as possible, we write it in terms of a generic Set type with
    // bytes32 values.
    // The Set implementation uses private functions, and user-facing
    // implementations (such as AddressSet) are just wrappers around the
    // underlying Set.
    // This means that we can only create new EnumerableSets for types that fit
    // in bytes32.

    struct Set {
        // Storage of set values
        bytes32[] _values;

        // Position of the value in the `values` array, plus 1 because index 0
        // means a value is not in the set.
        mapping (bytes32 => uint256) _indexes;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function _add(Set storage set, bytes32 value) private returns (bool) {
        if (!_contains(set, value)) {
            set._values.push(value);
            // The value is stored at length-1, but we add 1 to all indexes
            // and use 0 as a sentinel value
            set._indexes[value] = set._values.length;
            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function _remove(Set storage set, bytes32 value) private returns (bool) {
        // We read and store the value's index to prevent multiple reads from the same storage slot
        uint256 valueIndex = set._indexes[value];

        if (valueIndex != 0) { // Equivalent to contains(set, value)
            // To delete an element from the _values array in O(1), we swap the element to delete with the last one in
            // the array, and then remove the last element (sometimes called as 'swap and pop').
            // This modifies the order of the array, as noted in {at}.

            uint256 toDeleteIndex = valueIndex - 1;
            uint256 lastIndex = set._values.length - 1;

            // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs
            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.

            bytes32 lastvalue = set._values[lastIndex];

            // Move the last value to the index where the value to delete is
            set._values[toDeleteIndex] = lastvalue;
            // Update the index for the moved value
            set._indexes[lastvalue] = valueIndex; // Replace lastvalue's index to valueIndex

            // Delete the slot where the moved value was stored
            set._values.pop();

            // Delete the index for the deleted slot
            delete set._indexes[value];

            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function _contains(Set storage set, bytes32 value) private view returns (bool) {
        return set._indexes[value] != 0;
    }

    /**
     * @dev Returns the number of values on the set. O(1).
     */
    function _length(Set storage set) private view returns (uint256) {
        return set._values.length;
    }

   /**
    * @dev Returns the value stored at position `index` in the set. O(1).
    *
    * Note that there are no guarantees on the ordering of values inside the
    * array, and it may change when more values are added or removed.
    *
    * Requirements:
    *
    * - `index` must be strictly less than {length}.
    */
    function _at(Set storage set, uint256 index) private view returns (bytes32) {
        require(set._values.length > index, "EnumerableSet: index out of bounds");
        return set._values[index];
    }

    // Bytes32Set

    struct Bytes32Set {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
        return _add(set._inner, value);
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
        return _remove(set._inner, value);
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
        return _contains(set._inner, value);
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(Bytes32Set storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

   /**
    * @dev Returns the value stored at position `index` in the set. O(1).
    *
    * Note that there are no guarantees on the ordering of values inside the
    * array, and it may change when more values are added or removed.
    *
    * Requirements:
    *
    * - `index` must be strictly less than {length}.
    */
    function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
        return _at(set._inner, index);
    }

    // AddressSet

    struct AddressSet {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(AddressSet storage set, address value) internal returns (bool) {
        return _add(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(AddressSet storage set, address value) internal returns (bool) {
        return _remove(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(AddressSet storage set, address value) internal view returns (bool) {
        return _contains(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(AddressSet storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

   /**
    * @dev Returns the value stored at position `index` in the set. O(1).
    *
    * Note that there are no guarantees on the ordering of values inside the
    * array, and it may change when more values are added or removed.
    *
    * Requirements:
    *
    * - `index` must be strictly less than {length}.
    */
    function at(AddressSet storage set, uint256 index) internal view returns (address) {
        return address(uint160(uint256(_at(set._inner, index))));
    }


    // UintSet

    struct UintSet {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(UintSet storage set, uint256 value) internal returns (bool) {
        return _add(set._inner, bytes32(value));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(UintSet storage set, uint256 value) internal returns (bool) {
        return _remove(set._inner, bytes32(value));
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(UintSet storage set, uint256 value) internal view returns (bool) {
        return _contains(set._inner, bytes32(value));
    }

    /**
     * @dev Returns the number of values on the set. O(1).
     */
    function length(UintSet storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

   /**
    * @dev Returns the value stored at position `index` in the set. O(1).
    *
    * Note that there are no guarantees on the ordering of values inside the
    * array, and it may change when more values are added or removed.
    *
    * Requirements:
    *
    * - `index` must be strictly less than {length}.
    */
    function at(UintSet storage set, uint256 index) internal view returns (uint256) {
        return uint256(_at(set._inner, index));
    }
}

File 7 of 8 : IERC20.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

interface IERC20 {
    event Transfer(address indexed from, address indexed to, uint256 value);
    event Approval(address indexed owner, address indexed spender, uint256 value);

    function totalSupply() external view returns (uint256);
    function balanceOf(address account) external view returns (uint256);
    function allowance(address owner, address spender) external view returns (uint256);

    function approve(address spender, uint256 amount) external returns (bool);
    function transfer(address to, uint256 value) external returns (bool);
    function transferFrom(address from, address to, uint256 value) external returns (bool);

    // EIP 2612
    // solhint-disable-next-line func-name-mixedcase
    function DOMAIN_SEPARATOR() external view returns (bytes32);
    function nonces(address owner) external view returns (uint256);
    function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external;
}

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

import "../interfaces/IERC20.sol";

library SafeERC20 {
    function safeSymbol(IERC20 token) internal view returns (string memory) {
        (bool success, bytes memory data) = address(token).staticcall(abi.encodeWithSelector(0x95d89b41));
        return success && data.length > 0 ? abi.decode(data, (string)) : "???";
    }

    function safeName(IERC20 token) internal view returns (string memory) {
        (bool success, bytes memory data) = address(token).staticcall(abi.encodeWithSelector(0x06fdde03));
        return success && data.length > 0 ? abi.decode(data, (string)) : "???";
    }

    function safeDecimals(IERC20 token) internal view returns (uint8) {
        (bool success, bytes memory data) = address(token).staticcall(abi.encodeWithSelector(0x313ce567));
        return success && data.length == 32 ? abi.decode(data, (uint8)) : 18;
    }

    function safeTransfer(IERC20 token, address to, uint256 amount) internal {
        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory data) = address(token).call(abi.encodeWithSelector(0xa9059cbb, to, amount));
        require(success && (data.length == 0 || abi.decode(data, (bool))), "SafeERC20: Transfer failed");
    }

    function safeTransferFrom(IERC20 token, address from, uint256 amount) internal {
        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory data) = address(token).call(abi.encodeWithSelector(0x23b872dd, from, address(this), amount));
        require(success && (data.length == 0 || abi.decode(data, (bool))), "SafeERC20: TransferFrom failed");
    }
}

Settings
{
  "evmVersion": "berlin",
  "libraries": {},
  "metadata": {
    "bytecodeHash": "ipfs",
    "useLiteralContent": true
  },
  "optimizer": {
    "enabled": true,
    "runs": 999999
  },
  "remappings": [],
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "abi"
      ]
    }
  }
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"_vrfCoordinator","type":"address"},{"internalType":"address","name":"_link","type":"address"},{"internalType":"bytes32","name":"_keyHash","type":"bytes32"},{"internalType":"uint256","name":"_fee","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"contestId","type":"uint256"}],"name":"AddedNewContest","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"contestId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"contestWinner","type":"uint256"}],"name":"ContestWinnerSelected","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"contestId","type":"uint256"}],"name":"SetRandomNumberForContest","type":"event"},{"inputs":[],"name":"claimOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"contests","outputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"string","name":"name","type":"string"},{"internalType":"uint256","name":"ticketsCount","type":"uint256"},{"internalType":"string","name":"participantsListLink","type":"string"},{"internalType":"string","name":"participantsListSha256","type":"string"},{"internalType":"bool","name":"contestWinnersSelected","type":"bool"},{"internalType":"uint256","name":"randomResult","type":"uint256"},{"internalType":"uint256","name":"previousWinnerSeed","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"participantsListLink","type":"string"},{"internalType":"string","name":"participantsListSha256","type":"string"},{"internalType":"uint256","name":"ticketsCount","type":"uint256"}],"name":"createNewContest","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"contestId","type":"uint256"}],"name":"getContestById","outputs":[{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"string","name":"name","type":"string"},{"internalType":"uint256","name":"ticketsCount","type":"uint256"},{"internalType":"string","name":"participantsListLink","type":"string"},{"internalType":"string","name":"participantsListSha256","type":"string"},{"internalType":"bool","name":"contestWinnersSelected","type":"bool"},{"internalType":"uint256","name":"randomResult","type":"uint256"},{"internalType":"uint256","name":"previousWinnerSeed","type":"uint256"}],"internalType":"struct GenericContestSelector.Contest","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"contestId","type":"uint256"}],"name":"getContestWinners","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"contestId","type":"uint256"},{"internalType":"uint256","name":"from","type":"uint256"},{"internalType":"uint256","name":"to","type":"uint256"}],"name":"getContestWinnersInRange","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"contestId","type":"uint256"}],"name":"getRandomNumber","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"requestId","type":"bytes32"},{"internalType":"uint256","name":"randomness","type":"uint256"}],"name":"rawFulfillRandomness","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"recover","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"recoverErc20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"contestId","type":"uint256"},{"internalType":"uint256","name":"count","type":"uint256"}],"name":"selectContestWinners","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_fee","type":"uint256"}],"name":"setFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_keyHash","type":"bytes32"}],"name":"setKeyHash","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"contestId","type":"uint256"},{"internalType":"string","name":"link","type":"string"}],"name":"setParticipantsListLink","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"contestId","type":"uint256"},{"internalType":"string","name":"sha256Hash","type":"string"}],"name":"setParticipantsListSha256","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"contestId","type":"uint256"},{"internalType":"uint256","name":"number","type":"uint256"}],"name":"setTicketsNumber","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"},{"internalType":"bool","name":"direct","type":"bool"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60c06040523480156200001157600080fd5b5060405162002da238038062002da2833981016040819052620000349162000118565b83833380620000895760405162461bcd60e51b815260206004820152601560248201527f4f776e61626c653a207a65726f20616464726573730000000000000000000000604482015260640160405180910390fd5b600080546001600160a01b0319166001600160a01b0383161781556040513391907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3506001600160601b0319606092831b811660a052911b1660805260039190915560045550620001609050565b80516001600160a01b03811681146200011357600080fd5b919050565b600080600080608085870312156200012f57600080fd5b6200013a85620000fb565b93506200014a60208601620000fb565b6040860151606090960151949790965092505050565b60805160601c60a05160601c612c086200019a600039600081816112b901526120fa01526000818161199d01526120be0152612c086000f3fe608060405234801561001057600080fd5b50600436106101515760003560e01c806394985ddd116100cd578063b37217a411610081578063ce74602411610066578063ce746024146102d9578063e30c3978146102e1578063ed5f18b11461030157600080fd5b8063b37217a4146102b3578063b95e099e146102c657600080fd5b80639d7ed738116100b25780639d7ed73814610266578063af9476311461028d578063b242e534146102a057600080fd5b806394985ddd14610240578063985447101461025357600080fd5b806368abf590116101245780636bb20bf4116101095780636bb20bf4146101d5578063878ba934146101e85780638da5cb5b146101fb57600080fd5b806368abf590146101af57806369fe0e2d146101c257600080fd5b806306c7e11d1461015657806323746e871461016b5780633d4f0ed0146101945780634e71e0c8146101a7575b600080fd5b610169610164366004612794565b610321565b005b61017e6101793660046127db565b610538565b60405161018b91906128ab565b60405180910390f35b6101696101a23660046126c9565b61075b565b610169610954565b6101696101bd3660046126eb565b610a6a565b6101696101d03660046126b0565b610bc5565b6101696101e3366004612794565b610c4b565b6101696101f63660046126c9565b610e54565b60005461021b9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161018b565b61016961024e3660046126c9565b6112a1565b6101696102613660046126b0565b61134e565b6102796102743660046126b0565b6113d4565b60405161018b9897969594939291906129b1565b61017e61029b3660046126b0565b6115c6565b6101696102ae366004612655565b611705565b6101696102c13660046126b0565b6118e5565b6101696102d436600461263a565b611acb565b610169611c1b565b60015461021b9073ffffffffffffffffffffffffffffffffffffffff1681565b61031461030f3660046126b0565b611ce6565b60405161018b91906128ef565b60005473ffffffffffffffffffffffffffffffffffffffff1633146103a7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064015b60405180910390fd5b6005548290811115610415576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f436f6e7465737420646f65736e27742065786973740000000000000000000000604482015260640161039e565b826005610423600183612a32565b8154811061043357610433612b66565b600091825260209091206005600890920201015460ff16156104b1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f436f6e746573742073656c656374696f6e20706572666f726d65640000000000604482015260640161039e565b600060056104c0600187612a32565b815481106104d0576104d0612b66565b90600052602060002090600802019050838160030190805190602001906104f89291906124cd565b506000858152600760205260409020610512906003611fd0565b61053157600085815260076020526040902061052f906003611fed565b505b5050505050565b6060838060058054905010156105aa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f436f6e7465737420646f65736e27742065786973740000000000000000000000604482015260640161039e565b82841115610614576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f496e636f72726563742072616e67650000000000000000000000000000000000604482015260640161039e565b600085815260066020526040902061062b90611ff9565b8310610693576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f496e636f72726563742072616e67650000000000000000000000000000000000604482015260640161039e565b600061069f8585612a32565b6106aa906001612a1a565b67ffffffffffffffff8111156106c2576106c2612b95565b6040519080825280602002602001820160405280156106eb578160200160208202803683370190505b50905060005b6106fb8686612a32565b81116107515761072261070e8783612a1a565b600089815260066020526040902090612003565b82828151811061073457610734612b66565b60209081029190910101528061074981612ac3565b9150506106f1565b5095945050505050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146107dc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161039e565b600554829081111561084a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f436f6e7465737420646f65736e27742065786973740000000000000000000000604482015260640161039e565b826005610858600183612a32565b8154811061086857610868612b66565b600091825260209091206005600890920201015460ff16156108e6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f436f6e746573742073656c656374696f6e20706572666f726d65640000000000604482015260640161039e565b600060056108f5600187612a32565b8154811061090557610905612b66565b600091825260208083206002600890930201828101889055888452600790915260409092209192506109379190611fd0565b61053157600085815260076020526040902061052f906002611fed565b60015473ffffffffffffffffffffffffffffffffffffffff163381146109d6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c657220213d2070656e64696e67206f776e6572604482015260640161039e565b6000805460405173ffffffffffffffffffffffffffffffffffffffff808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a36000805473ffffffffffffffffffffffffffffffffffffffff9092167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316179055600180549091169055565b60005473ffffffffffffffffffffffffffffffffffffffff163314610aeb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161039e565b60058054600190810180835560008381529291610b0791612a32565b81548110610b1757610b17612b66565b60009182526020918290206005546008909202019081558651909250610b45916001840191908801906124cd565b508054610b51906118e5565b835115610b64578054610b649085610321565b825115610b77578054610b779084610c4b565b8115610b89578054610b89908361075b565b80546040519081527f6e62913ae888e75414725c66f7160198f98f117e770186cd16187fa9c1e0ce229060200160405180910390a15050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610c46576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161039e565b600455565b60005473ffffffffffffffffffffffffffffffffffffffff163314610ccc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161039e565b6005548290811115610d3a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f436f6e7465737420646f65736e27742065786973740000000000000000000000604482015260640161039e565b826005610d48600183612a32565b81548110610d5857610d58612b66565b600091825260209091206005600890920201015460ff1615610dd6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f436f6e746573742073656c656374696f6e20706572666f726d65640000000000604482015260640161039e565b60006005610de5600187612a32565b81548110610df557610df5612b66565b9060005260206000209060080201905083816004019080519060200190610e1d9291906124cd565b506000858152600760205260409020610e37906004611fd0565b61053157600085815260076020526040902061052f906004611fed565b60005473ffffffffffffffffffffffffffffffffffffffff163314610ed5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161039e565b6005548290811115610f43576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f436f6e7465737420646f65736e27742065786973740000000000000000000000604482015260640161039e565b6000838152600760205260409020610f5a90611ff9565b600414610fc3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f436f6e746573743a204e6f7420616c6c20737465707320706572666f726d6564604482015260640161039e565b6005610fd0600185612a32565b81548110610fe057610fe0612b66565b9060005260206000209060080201600601546000141561105c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f436f6e746573743a20436861696e6c696e6b2064617461207265636865636b00604482015260640161039e565b6005611069600185612a32565b8154811061107957611079612b66565b9060005260206000209060080201600201546110a660066000868152602001908152602001600020611ff9565b6110b09084612a1a565b1115611118576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f436f6e746573743a204f757473696465206f66207469636b65742072616e6765604482015260640161039e565b60006005611127600186612a32565b8154811061113757611137612b66565b9060005260206000209060080201905080600701546000141561115f57600681015460078201555b60005b8381101561126f576000806000805b60078601546040805160208101929092528101869052606081018290526080016040516020818303038152906040528051906020012060001c93508560020154846111bc9190612afc565b6111c7906001612a1a565b9250806111d381612ac3565b60008b81526006602052604090209092506111ef915084611fd0565b15915081156111715760008981526006602052604090206112109084611fed565b5060078601849055604080518a81524260208201529081018490527f5ed2bf5b554f94b8dbae95bc26ac1acdea6128354f938e0df08b7b0adc8da5c59060600160405180910390a150505050808061126790612ac3565b915050611162565b5060050180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055505050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614611340576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f4f6e6c7920565246436f6f7264696e61746f722063616e2066756c66696c6c00604482015260640161039e565b61134a828261200f565b5050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146113cf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161039e565b600355565b600581815481106113e457600080fd5b6000918252602090912060089091020180546001820180549193509061140990612a75565b80601f016020809104026020016040519081016040528092919081815260200182805461143590612a75565b80156114825780601f1061145757610100808354040283529160200191611482565b820191906000526020600020905b81548152906001019060200180831161146557829003601f168201915b50505050509080600201549080600301805461149d90612a75565b80601f01602080910402602001604051908101604052809291908181526020018280546114c990612a75565b80156115165780601f106114eb57610100808354040283529160200191611516565b820191906000526020600020905b8154815290600101906020018083116114f957829003601f168201915b50505050509080600401805461152b90612a75565b80601f016020809104026020016040519081016040528092919081815260200182805461155790612a75565b80156115a45780601f10611579576101008083540402835291602001916115a4565b820191906000526020600020905b81548152906001019060200180831161158757829003601f168201915b5050505060058301546006840154600790940154929360ff9091169290915088565b606081806005805490501015611638576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f436f6e7465737420646f65736e27742065786973740000000000000000000000604482015260640161039e565b600083815260066020526040812061164f90611ff9565b67ffffffffffffffff81111561166757611667612b95565b604051908082528060200260200182016040528015611690578160200160208202803683370190505b50905060005b60008581526006602052604090206116ad90611ff9565b8110156116fb5760008581526006602052604090206116cc9082612003565b8282815181106116de576116de612b66565b6020908102919091010152806116f381612ac3565b915050611696565b5091505b50919050565b60005473ffffffffffffffffffffffffffffffffffffffff163314611786576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161039e565b801561189f5773ffffffffffffffffffffffffffffffffffffffff8216611809576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4f776e61626c653a207a65726f20616464726573730000000000000000000000604482015260640161039e565b6000805460405173ffffffffffffffffffffffffffffffffffffffff808616939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a36000805473ffffffffffffffffffffffffffffffffffffffff84167fffffffffffffffffffffffff0000000000000000000000000000000000000000918216179091556001805490911690555050565b6001805473ffffffffffffffffffffffffffffffffffffffff84167fffffffffffffffffffffffff00000000000000000000000000000000000000009091161790555050565b6005548190811115611953576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f436f6e7465737420646f65736e27742065786973740000000000000000000000604482015260640161039e565b600480546040517f70a0823100000000000000000000000000000000000000000000000000000000815230928101929092529073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906370a082319060240160206040518083038186803b1580156119df57600080fd5b505afa1580156119f3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a17919061277b565b1015611aa5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f4e6f7420656e6f756768204c494e4b202d2070726f76696465204c494e4b207460448201527f6f2074686520636f6e7472616374000000000000000000000000000000000000606482015260840161039e565b6000611ab56003546004546120ba565b6000908152600860205260409020929092555050565b60005473ffffffffffffffffffffffffffffffffffffffff163314611b4c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161039e565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8316906370a082319060240160206040518083038186803b158015611bb457600080fd5b505afa158015611bc8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bec919061277b565b9050801561134a5760005461134a9073ffffffffffffffffffffffffffffffffffffffff84811691168361225a565b60005473ffffffffffffffffffffffffffffffffffffffff163314611c9c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161039e565b6000805460405173ffffffffffffffffffffffffffffffffffffffff909116914780156108fc02929091818181858888f19350505050158015611ce3573d6000803e3d6000fd5b50565b611d30604051806101000160405280600081526020016060815260200160008152602001606081526020016060815260200160001515815260200160008152602001600081525090565b6005548290811115611d9e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f436f6e7465737420646f65736e27742065786973740000000000000000000000604482015260640161039e565b60006005611dad600186612a32565b81548110611dbd57611dbd612b66565b90600052602060002090600802019050806040518061010001604052908160008201548152602001600182018054611df490612a75565b80601f0160208091040260200160405190810160405280929190818152602001828054611e2090612a75565b8015611e6d5780601f10611e4257610100808354040283529160200191611e6d565b820191906000526020600020905b815481529060010190602001808311611e5057829003601f168201915b5050505050815260200160028201548152602001600382018054611e9090612a75565b80601f0160208091040260200160405190810160405280929190818152602001828054611ebc90612a75565b8015611f095780601f10611ede57610100808354040283529160200191611f09565b820191906000526020600020905b815481529060010190602001808311611eec57829003601f168201915b50505050508152602001600482018054611f2290612a75565b80601f0160208091040260200160405190810160405280929190818152602001828054611f4e90612a75565b8015611f9b5780601f10611f7057610100808354040283529160200191611f9b565b820191906000526020600020905b815481529060010190602001808311611f7e57829003601f168201915b5050509183525050600582015460ff161515602082015260068201546040820152600790910154606090910152949350505050565b600081815260018301602052604081205415155b90505b92915050565b6000611fe483836123c3565b6000611fe7825490565b6000611fe48383612412565b60008281526008602052604081205490600561202c600184612a32565b8154811061203c5761203c612b66565b600091825260208220600660089092020190810185905560405190925083917fb2e345e84b97cf32fa298eb7fda2cb8e2cd543eb241529ae276b51b4b5cd25f091a26000828152600760205260409020612097906001611fd0565b6120b4576000828152600760205260409020610531906001611fed565b50505050565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16634000aea07f000000000000000000000000000000000000000000000000000000000000000084866000604051602001612137929190918252602082015260400190565b6040516020818303038152906040526040518463ffffffff1660e01b81526004016121649392919061286d565b602060405180830381600087803b15801561217e57600080fd5b505af1158015612192573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121b6919061268c565b50600083815260026020818152604080842054815180840189905280830186905230606082015260808082018390528351808303909101815260a090910190925281519183019190912093879052919052612212906001612a1a565b6000858152600260205260409020556122528482604080516020808201949094528082019290925280518083038201815260609092019052805191012090565b949350505050565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905291516000928392908716916122f19190612851565b6000604051808303816000865af19150503d806000811461232e576040519150601f19603f3d011682016040523d82523d6000602084013e612333565b606091505b509150915081801561235d57508051158061235d57508080602001905181019061235d919061268c565b610531576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f5361666545524332303a205472616e73666572206661696c6564000000000000604482015260640161039e565b600081815260018301602052604081205461240a57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155611fe7565b506000611fe7565b815460009082106124a5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f456e756d657261626c655365743a20696e646578206f7574206f6620626f756e60448201527f6473000000000000000000000000000000000000000000000000000000000000606482015260840161039e565b8260000182815481106124ba576124ba612b66565b9060005260206000200154905092915050565b8280546124d990612a75565b90600052602060002090601f0160209004810192826124fb5760008555612541565b82601f1061251457805160ff1916838001178555612541565b82800160010185558215612541579182015b82811115612541578251825591602001919060010190612526565b5061254d929150612551565b5090565b5b8082111561254d5760008155600101612552565b803573ffffffffffffffffffffffffffffffffffffffff8116811461258a57600080fd5b919050565b600082601f8301126125a057600080fd5b813567ffffffffffffffff808211156125bb576125bb612b95565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561260157612601612b95565b8160405283815286602085880101111561261a57600080fd5b836020870160208301376000602085830101528094505050505092915050565b60006020828403121561264c57600080fd5b611fe482612566565b6000806040838503121561266857600080fd5b61267183612566565b9150602083013561268181612bc4565b809150509250929050565b60006020828403121561269e57600080fd5b81516126a981612bc4565b9392505050565b6000602082840312156126c257600080fd5b5035919050565b600080604083850312156126dc57600080fd5b50508035926020909101359150565b6000806000806080858703121561270157600080fd5b843567ffffffffffffffff8082111561271957600080fd5b6127258883890161258f565b9550602087013591508082111561273b57600080fd5b6127478883890161258f565b9450604087013591508082111561275d57600080fd5b5061276a8782880161258f565b949793965093946060013593505050565b60006020828403121561278d57600080fd5b5051919050565b600080604083850312156127a757600080fd5b82359150602083013567ffffffffffffffff8111156127c557600080fd5b6127d18582860161258f565b9150509250929050565b6000806000606084860312156127f057600080fd5b505081359360208301359350604090920135919050565b6000815180845261281f816020860160208601612a49565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60008251612863818460208701612a49565b9190910192915050565b73ffffffffffffffffffffffffffffffffffffffff841681528260208201526060604082015260006128a26060830184612807565b95945050505050565b6020808252825182820181905260009190848201906040850190845b818110156128e3578351835292840192918401916001016128c7565b50909695505050505050565b602081528151602082015260006020830151610100806040850152612918610120850183612807565b91506040850151606085015260608501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08086850301608087015261295e8483612807565b935060808701519150808685030160a08701525061297c8382612807565b92505060a085015161299260c086018215159052565b5060c085015160e085015260e085015181850152508091505092915050565b60006101008a83528060208401526129cb8184018b612807565b905088604084015282810360608401526129e58189612807565b905082810360808401526129f98188612807565b95151560a0840152505060c081019290925260e09091015295945050505050565b60008219821115612a2d57612a2d612b37565b500190565b600082821015612a4457612a44612b37565b500390565b60005b83811015612a64578181015183820152602001612a4c565b838111156120b45750506000910152565b600181811c90821680612a8957607f821691505b602082108114156116ff577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415612af557612af5612b37565b5060010190565b600082612b32577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500690565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b8015158114611ce357600080fdfea2646970667358221220fd7ec7149515314306a7cc39abc9fbd5299f0198ff6608f4705e3ec1279280f364736f6c634300080600330000000000000000000000003d2341adb2d31f1c5530cdc622016af293177ae0000000000000000000000000b0897686c545045afc77cf20ec7a532e3120e0f1f86195cf7690c55907b2b611ebb7343a6f649bff128701cc542f0569e2c549da00000000000000000000000000000000000000000000000000005af3107a4000

Block Transaction Gas Used Reward
Age Block Fee Address BC Fee Address Voting Power Jailed Incoming
Block Uncle Number Difficulty Gas Used Reward
Loading
Loading
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.