Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00Latest 25 from a total of 28 transactions
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Withdraw Payment... | 15639642 | 1257 days ago | IN | 0 ETH | 0.00092843 | ||||
| Transfer ETH To ... | 15639641 | 1257 days ago | IN | 0 ETH | 0.0014629 | ||||
| Transfer NFT To ... | 15639639 | 1257 days ago | IN | 0 ETH | 0.00206203 | ||||
| Purchase Ticket | 15638848 | 1258 days ago | IN | 0.07 ETH | 0.0014224 | ||||
| Purchase Ticket | 15638831 | 1258 days ago | IN | 0.01 ETH | 0.00188902 | ||||
| Purchase Ticket | 15638828 | 1258 days ago | IN | 0.005 ETH | 0.0010649 | ||||
| Purchase Ticket | 15638811 | 1258 days ago | IN | 0.01 ETH | 0.00093677 | ||||
| Purchase Ticket | 15638793 | 1258 days ago | IN | 0.1 ETH | 0.00134367 | ||||
| Purchase Ticket | 15638748 | 1258 days ago | IN | 0.105 ETH | 0.00168637 | ||||
| Giveaway Ticket | 15638736 | 1258 days ago | IN | 0 ETH | 0.00210734 | ||||
| Purchase Ticket | 15638717 | 1258 days ago | IN | 0.005 ETH | 0.00135706 | ||||
| Purchase Ticket | 15638139 | 1258 days ago | IN | 0.025 ETH | 0.00136456 | ||||
| Purchase Ticket | 15637875 | 1258 days ago | IN | 0.05 ETH | 0.00170845 | ||||
| Purchase Ticket | 15637810 | 1258 days ago | IN | 0.025 ETH | 0.0016628 | ||||
| Purchase Ticket | 15637689 | 1258 days ago | IN | 0.075 ETH | 0.00156073 | ||||
| Purchase Ticket | 15633949 | 1258 days ago | IN | 0.05 ETH | 0.00246916 | ||||
| Purchase Ticket | 15631993 | 1258 days ago | IN | 0.04 ETH | 0.00135407 | ||||
| Purchase Ticket | 15631179 | 1259 days ago | IN | 0.01 ETH | 0.00158651 | ||||
| Purchase Ticket | 15630875 | 1259 days ago | IN | 0.005 ETH | 0.00107277 | ||||
| Purchase Ticket | 15630297 | 1259 days ago | IN | 0.005 ETH | 0.0021613 | ||||
| Purchase Ticket | 15629921 | 1259 days ago | IN | 0.005 ETH | 0.00167905 | ||||
| Purchase Ticket | 15626656 | 1259 days ago | IN | 0.005 ETH | 0.00318722 | ||||
| Purchase Ticket | 15626433 | 1259 days ago | IN | 0.005 ETH | 0.00299754 | ||||
| Purchase Ticket | 15626416 | 1259 days ago | IN | 0.005 ETH | 0.00353255 | ||||
| Purchase Ticket | 15626397 | 1259 days ago | IN | 0.005 ETH | 0.00330311 |
Latest 3 internal transactions
Advanced mode:
| Parent Transaction Hash | Method | Block |
From
|
|
To
|
||
|---|---|---|---|---|---|---|---|
| Deposit | 15639641 | 1257 days ago | 0.635 ETH | ||||
| 0x60806040 | 15624268 | 1260 days ago | Contract Creation | 0 ETH | |||
| 0x61020060 | 15624268 | 1260 days ago | Contract Creation | 0 ETH |
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
Raffle
Compiler Version
v0.8.9+commit.e5eed63a
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
import "contracts/ICryptoPunk.sol";
import "contracts/TicketStorage.sol";
import "@chainlink/contracts/src/v0.8/interfaces/VRFCoordinatorV2Interface.sol";
import "@chainlink/contracts/src/v0.8/VRFConsumerBaseV2.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/token/ERC1155/utils/ERC1155Holder.sol";
import "@openzeppelin/contracts/token/ERC1155/IERC1155.sol";
import "@openzeppelin/contracts/token/ERC721/utils/ERC721Holder.sol";
import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import "@openzeppelin/contracts/security/PullPayment.sol";
/**
* @dev This contract is used to represent BoredLucky raffle. It supports CryptoPunks, ERC721 and ERC1155 NFTs.
*
* Raffle relies on Chainlink VRF to draw the winner.
*
* Raffle ensures that buyers will get a fair chance of winning (proportional to the number of purchased tickets), or
* a way to get ETH back if raffle gets cancelled.
*
* Raffle can start only after the correct NFT is transferred to the account.
*
* Each raffle has an `owner`, the admin account that has the following abilities:
* - gets ETH after the raffle is completed
* - gets back the NFT if raffle is cancelled
* - able to giveaway tickets
* - able to cancel raffle before it has started (e.g. created with wrong parameters)
*
* Raffle gets cancelled if:
* - not all tickets are sold before `endTimestamp`
* - `owner` cancels it before start
* - for some reason we do not have response from Chainlink VRF for one day after we request random number
*
* In any scenario, raffle cannot get stuck and users have a fair chance to win or get ETH back.
*
* `PullPayments` are used where possible to increase security.
*
* The lifecycle of raffle consist of following states:
* - WaitingForNFT: after raffle is created, it waits for
* - WaitingForStart: correct NFT is transferred and we wait for `startTimestamp`
* - SellingTickets: it possible to purchase tickets
* - WaitingForRNG: all tickets are sold, we wait for Chainlink VRF to send random number
* - Completed (terminal) -- we know the winner, it can get NFT, raffle owner can get ETH
* - Cancelled (terminal) -- raffle cancelled, buyers can get back their ETH, owner can get NFT
*/
contract Raffle is Ownable, TicketStorage, ERC1155Holder, ERC721Holder, PullPayment, VRFConsumerBaseV2 {
event WinnerDrawn(uint16 ticketNumber, address owner);
enum State {
WaitingForNFT,
WaitingForStart,
SellingTickets,
WaitingForRNG,
Completed,
Cancelled
}
State private _state;
address public immutable nftContract;
uint256 public immutable nftTokenId;
enum NFTStandard {
CryptoPunks,
ERC721,
ERC1155
}
NFTStandard public immutable nftStandard;
uint256 public immutable ticketPrice;
uint256 public immutable startTimestamp;
uint256 public immutable endTimestamp;
uint16 private _soldTickets;
uint16 private _giveawayTickets;
mapping(address => uint16) private _addressToPurchasedCountMap;
uint256 private _cancelTimestamp;
uint256 private _transferNFTToWinnerTimestamp;
uint256 private _winnerDrawTimestamp;
uint16 private _winnerTicketNumber;
address private _winnerAddress;
VRFCoordinatorV2Interface immutable VRF_COORDINATOR;
uint64 immutable vrfSubscriptionId;
bytes32 immutable vrfKeyHash;
uint256[] public vrfRandomWords;
uint256 public vrfRequestId;
uint32 constant VRF_CALLBACK_GAS_LIMIT = 300_000;
uint16 constant VRF_REQUEST_CONFIRMATIONS = 20;
uint16 constant VRF_NUM_WORDS = 1;
constructor(
address _nftContract,
uint256 _nftTokenId,
uint256 _nftStandardId,
uint16 _tickets,
uint256 _ticketPrice,
uint256 _startTimestamp,
uint256 _endTimestamp,
uint64 _vrfSubscriptionId,
address _vrfCoordinator,
bytes32 _vrfKeyHash
) TicketStorage(_tickets) VRFConsumerBaseV2(_vrfCoordinator) {
require(block.timestamp < _startTimestamp, "Start timestamp cannot be in the past");
require(_endTimestamp > _startTimestamp, "End timestamp must be after start timestamp");
require(_nftContract != address(0), "NFT contract cannot be 0x0");
nftStandard = NFTStandard(_nftStandardId);
require(
nftStandard == NFTStandard.CryptoPunks || nftStandard == NFTStandard.ERC721 || nftStandard == NFTStandard.ERC1155,
"Not supported NFT standard"
);
nftContract = _nftContract;
nftTokenId = _nftTokenId;
ticketPrice = _ticketPrice;
startTimestamp = _startTimestamp;
endTimestamp = _endTimestamp;
VRF_COORDINATOR = VRFCoordinatorV2Interface(_vrfCoordinator);
vrfKeyHash = _vrfKeyHash;
vrfSubscriptionId = _vrfSubscriptionId;
_state = State.WaitingForNFT;
}
/**
* @dev Purchases raffle tickets.
*
* If last ticket is sold, triggers {_requestRandomWords} to request random number from Chainlink VRF.
*
* Requirements:
* - must be in SellingTickets state
* - cannot purchase after `endTimestamp`
* - cannot purchase 0 tickets
* - must have correct `value` of ETH
*/
function purchaseTicket(uint16 count) external payable {
if (_state == State.WaitingForStart) {
if (block.timestamp > startTimestamp && block.timestamp < endTimestamp) {
_state = State.SellingTickets;
}
}
require(_state == State.SellingTickets, "Must be in SellingTickets");
require(block.timestamp < endTimestamp, "End timestamp must be in the future");
require(count > 0, "Ticket count must be more than 0");
require(msg.value == ticketPrice * count, "Incorrect purchase amount (must be ticketPrice * count)");
_assignTickets(msg.sender, count);
_soldTickets += count;
assert(_tickets == _ticketsLeft + _soldTickets + _giveawayTickets);
_addressToPurchasedCountMap[msg.sender] += count;
if (_ticketsLeft == 0) {
_state = State.WaitingForRNG;
_requestRandomWords();
}
}
struct AddressAndCount {
address receiverAddress;
uint16 count;
}
/**
* @dev Giveaway tickets. `owner` of raffle can giveaway free tickets, used for promotion.
*
* It is possible to giveaway tickets before start, ensuring that promised tickets for promotions can be assigned,
* otherwise if raffle is quickly sold out, we may not able to do it in time.
*
* If last ticket is given out, triggers {_requestRandomWords} to request random number from Chainlink VRF.
*
* Requirements:
* - must be in WaitingForStart or SellingTickets state
* - cannot giveaway after `endTimestamp`
*/
function giveawayTicket(AddressAndCount[] memory receivers) external onlyOwner {
require(
_state == State.WaitingForStart || _state == State.SellingTickets,
"Must be in WaitingForStart or SellingTickets"
);
if (_state == State.WaitingForStart) {
if (block.timestamp > startTimestamp && block.timestamp < endTimestamp) {
_state = State.SellingTickets;
}
}
require(block.timestamp < endTimestamp, "End timestamp must be in the future");
for (uint256 i = 0; i < receivers.length; i++) {
AddressAndCount memory item = receivers[i];
_assignTickets(item.receiverAddress, item.count);
_giveawayTickets += item.count;
assert(_tickets == _ticketsLeft + _soldTickets + _giveawayTickets);
}
if (_ticketsLeft == 0) {
_state = State.WaitingForRNG;
_requestRandomWords();
}
}
/**
* @dev After the correct NFT (specified in raffle constructor) is transferred to raffle contract,
* this method must be invoked to verify it and move raffle into WaitingForStart state.
*
* Requirements:
* - must be in WaitingForNFT state
*/
function verifyNFTPresenceBeforeStart() external {
require(_state == State.WaitingForNFT, "Must be in WaitingForNFT");
if (nftStandard == NFTStandard.CryptoPunks) {
if (ICryptoPunk(nftContract).punkIndexToAddress(nftTokenId) == address(this)) {
_state = State.WaitingForStart;
}
}
else if (nftStandard == NFTStandard.ERC721) {
if (IERC721(nftContract).ownerOf(nftTokenId) == address(this)) {
_state = State.WaitingForStart;
}
}
else if (nftStandard == NFTStandard.ERC1155) {
if (IERC1155(nftContract).balanceOf(address(this), nftTokenId) == 1) {
_state = State.WaitingForStart;
}
}
}
/**
* @dev Cancels raffle before it has started.
*
* Only raffle `owner` can do it and it is needed in case raffle was created incorrectly.
*
* Requirements:
* - must be in WaitingForNFT or WaitingForStart state
*/
function cancelBeforeStart() external onlyOwner {
require(
_state == State.WaitingForNFT || _state == State.WaitingForStart,
"Must be in WaitingForNFT or WaitingForStart"
);
_state = State.Cancelled;
_cancelTimestamp = block.timestamp;
}
/**
* @dev Cancels raffle if not all tickets were sold.
*
* Anyone can call this method after `endTimestamp`.
*
* Requirements:
* - must be in SellingTickets state
*/
function cancelIfUnsold() external {
require(
_state == State.WaitingForStart || _state == State.SellingTickets,
"Must be in WaitingForStart or SellingTickets"
);
require(block.timestamp > endTimestamp, "End timestamp must be in the past");
_state = State.Cancelled;
_cancelTimestamp = block.timestamp;
}
/**
* @dev Cancels raffle if there is no response from Chainlink VRF.
*
* Anyone can call this method after `endTimestamp` + 1 day.
*
* Requirements:
* - must be in WaitingForRNG state
*/
function cancelIfNoRNG() external {
require(_state == State.WaitingForRNG, "Must be in WaitingForRNG");
require(block.timestamp > endTimestamp + 1 days, "End timestamp + 1 day must be in the past");
_state = State.Cancelled;
_cancelTimestamp = block.timestamp;
}
/**
* @dev Transfers purchased ticket refund into internal escrow, after that user can claim ETH
* using {PullPayment-withdrawPayments}.
*
* Requirements:
* - must be in Cancelled state
*/
function transferTicketRefundIfCancelled() external {
require(_state == State.Cancelled, "Must be in Cancelled");
uint256 refundAmount = _addressToPurchasedCountMap[msg.sender] * ticketPrice;
if (refundAmount > 0) {
_addressToPurchasedCountMap[msg.sender] = 0;
_asyncTransfer(msg.sender, refundAmount);
}
}
/**
* @dev Transfers specified NFT to raffle `owner`. This method is used to recover NFT (including other NFTs,
* that could have been transferred to raffle by mistake) if raffle gets cancelled.
*
* Requirements:
* - must be in Cancelled state
*/
function transferNFTToOwnerIfCancelled(NFTStandard nftStandard, address contractAddress, uint256 tokenId) external {
require(_state == State.Cancelled, "Must be in Cancelled");
if (nftStandard == NFTStandard.CryptoPunks) {
ICryptoPunk(contractAddress).transferPunk(address(owner()), tokenId);
}
else if (nftStandard == NFTStandard.ERC721) {
IERC721(contractAddress).safeTransferFrom(address(this), owner(), tokenId);
}
else if (nftStandard == NFTStandard.ERC1155) {
IERC1155(contractAddress).safeTransferFrom(address(this), owner(), tokenId, 1, "");
}
}
/**
* @dev Transfers raffle NFT to `_winnerAddress` after the raffle has completed.
*
* Requirements:
* - must be in Completed state
*/
function transferNFTToWinnerIfCompleted() external {
require(_state == State.Completed, "Must be in Completed");
assert(_winnerAddress != address(0));
_transferNFTToWinnerTimestamp = block.timestamp;
if (nftStandard == NFTStandard.CryptoPunks) {
ICryptoPunk(nftContract).transferPunk(_winnerAddress, nftTokenId);
}
else if (nftStandard == NFTStandard.ERC721) {
IERC721(nftContract).safeTransferFrom(address(this), _winnerAddress, nftTokenId);
}
else if (nftStandard == NFTStandard.ERC1155) {
IERC1155(nftContract).safeTransferFrom(address(this), _winnerAddress, nftTokenId, 1, "");
}
}
/**
* @dev Transfers raffle ETHinto internal escrow, after that raffle `owner` can claim it
* using {PullPayment-withdrawPayments}.
*
* Requirements:
* - must be in Completed state
*/
function transferETHToOwnerIfCompleted() external {
require(_state == State.Completed, "Must be in Completed");
_asyncTransfer(owner(), address(this).balance);
}
/**
* @dev Returns the number of purchased tickets for given `owner`.
*/
function getPurchasedTicketCount(address owner) public view returns (uint16) {
return _addressToPurchasedCountMap[owner];
}
/**
* @dev Returns raffle state.
*
* If `Completed`, it is possible to use {getWinnerAddress}, {getWinnerDrawTimestamp} and {getWinnerTicketNumber}.
*/
function getState() public view returns (State) {
return _state;
}
function getCancelTimestamp() public view returns (uint256) {
return _cancelTimestamp;
}
function getTransferNFTToWinnerTimestamp() public view returns (uint256) {
return _transferNFTToWinnerTimestamp;
}
function getWinnerAddress() public view returns (address) {
return _winnerAddress;
}
function getWinnerDrawTimestamp() public view returns (uint256) {
return _winnerDrawTimestamp;
}
function getWinnerTicketNumber() public view returns (uint16) {
return _winnerTicketNumber;
}
/**
* @dev Chainlink VRF callback function.
*
* Returned `randomWords` are stored in `vrfRandomWords`, we determine winner and store all relevant information in
* `_winnerTicketNumber`, `_winnerDrawTimestamp` and `_winnerAddress`.
*
* Requirements:
* - must have correct `requestId`
* - must be in WaitingForRNG state
*
* Emits a {WinnerDrawn} event.
*/
function fulfillRandomWords(uint256 requestId, uint256[] memory randomWords) internal override {
require(vrfRequestId == requestId, "Unexpected VRF request id");
require(_state == State.WaitingForRNG, "Must be in WaitingForRNG");
vrfRandomWords = randomWords;
_winnerTicketNumber = uint16(randomWords[0] % _tickets);
_winnerDrawTimestamp = block.timestamp;
_winnerAddress = findOwnerOfTicketNumber(_winnerTicketNumber);
_state = State.Completed;
emit WinnerDrawn(_winnerTicketNumber, _winnerAddress);
}
/**
* @dev Requests random number from Chainlink VRF. Called when last ticked is sold or given out.
*
* Requirements:
* - must be in WaitingForRNG state
*/
function _requestRandomWords() private {
require(_state == State.WaitingForRNG, "Must be in WaitingForRNG");
vrfRequestId = VRF_COORDINATOR.requestRandomWords(
vrfKeyHash,
vrfSubscriptionId,
VRF_REQUEST_CONFIRMATIONS,
VRF_CALLBACK_GAS_LIMIT,
VRF_NUM_WORDS
);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
/**
* @dev This contract is used to represent `CryptoPunksMarket` and interact with CryptoPunk NFTs.
*/
interface ICryptoPunk {
function punkIndexToAddress(uint256 punkIndex) external view returns (address);
function transferPunk(address to, uint256 punkIndex) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
import "@openzeppelin/contracts/access/Ownable.sol";
/**
* @dev This contract is used to store numbered ticket ranges and their owners.
*
* Ticket range is represented using {TicketNumberRange}, a struct of `owner, `from` and `to`. If account `0x1` buys
* first ticket, then we store it as `(0x1, 0, 0)`, if then account `0x2` buys ten tickets, then we store next record as
* `(0x2, 1, 10)`. If after that third account `0x3` buys ten tickets, we store it as `(0x3, 11, 20)`. And so on.
*
* Storing ticket numbers in such way allows compact representation of accounts who buy a lot of tickets at once.
*
* We set 25000 as limit of how many tickets we can support.
*/
abstract contract TicketStorage {
event TicketsAssigned(TicketNumberRange ticketNumberRange, uint16 ticketsLeft);
struct TicketNumberRange {
address owner;
uint16 from;
uint16 to;
}
uint16 internal immutable _tickets;
uint16 internal _ticketsLeft;
TicketNumberRange[] private _ticketNumberRanges;
mapping(address => uint16) private _addressToAssignedCountMap;
mapping(address => uint16[]) private _addressToAssignedTicketNumberRangesMap;
constructor(uint16 tickets) {
require(tickets > 0, "Number of tickets must be greater than 0");
require(tickets <= 25_000, "Number of tickets cannot exceed 25_000");
_tickets = tickets;
_ticketsLeft = tickets;
}
/**
* @dev Returns total amount of tickets.
*/
function getTickets() public view returns (uint16) {
return _tickets;
}
/**
* @dev Returns amount of unassigned tickets.
*/
function getTicketsLeft() public view returns (uint16) {
return _ticketsLeft;
}
/**
* @dev Returns {TicketNumberRange} for given `index`.
*/
function getTicketNumberRange(uint16 index) public view returns (TicketNumberRange memory) {
return _ticketNumberRanges[index];
}
/**
* @dev Returns how many tickets are assigned to given `owner`.
*/
function getAssignedTicketCount(address owner) public view returns (uint16) {
return _addressToAssignedCountMap[owner];
}
/**
* @dev Returns the index of {TicketNumberRange} in `_ticketNumberRanges` that is assigned to `owner`.
*
* For example, if `owner` purchased tickets three times ({getAssignedTicketNumberRanges} will return `3`),
* we can use this method with `index` of 0, 1 and 2, to get indexes of {TicketNumberRange} in `_ticketNumberRanges`.
*/
function getAssignedTicketNumberRange(address owner, uint16 index) public view returns (uint16) {
return _addressToAssignedTicketNumberRangesMap[owner][index];
}
/**
* @dev Returns how many {TicketNumberRange} are assigned for given `owner`.
*
* Can be used in combination with {getAssignedTicketNumberRange} and {getTicketNumberRange} to show
* all actual ticket numbers that are assigned to the `owner`.
*/
function getAssignedTicketNumberRanges(address owner) public view returns (uint16) {
return uint16(_addressToAssignedTicketNumberRangesMap[owner].length);
}
/**
* @dev Assigns `count` amount of tickets to `owner` address.
*
* Requirements:
* - there must be enough tickets left
*
* Emits a {TicketsAssigned} event.
*/
function _assignTickets(address owner, uint16 count) internal {
require(_ticketsLeft > 0, "All tickets are assigned");
require(_ticketsLeft >= count, "Assigning too many tickets at once");
uint16 from = _tickets - _ticketsLeft;
_ticketsLeft -= count;
TicketNumberRange memory ticketNumberRange = TicketNumberRange({
owner: owner,
from: from,
to: from + count - 1
});
_ticketNumberRanges.push(ticketNumberRange);
_addressToAssignedCountMap[owner] += count;
_addressToAssignedTicketNumberRangesMap[owner].push(uint16(_ticketNumberRanges.length - 1));
assert(_ticketNumberRanges[_ticketNumberRanges.length - 1].to == _tickets - _ticketsLeft - 1);
emit TicketsAssigned(ticketNumberRange, _ticketsLeft);
}
/**
* @dev Returns address of the `owner` of given ticket number.
*
* Uses binary search on `_ticketNumberRanges` to find it.
*
* Requirements:
* - all tickets must be assigned
*/
function findOwnerOfTicketNumber(uint16 ticketNumber) public view returns (address) {
require(ticketNumber < _tickets, "Ticket number does not exist");
require(_ticketsLeft == 0, "Not all tickets are assigned");
uint16 ticketNumberRangesLength = uint16(_ticketNumberRanges.length);
assert(_ticketNumberRanges[0].from == 0);
assert(_ticketNumberRanges[ticketNumberRangesLength - 1].to == _tickets - 1);
uint16 left = 0;
uint16 right = ticketNumberRangesLength - 1;
uint16 pivot = (left + right) / 2;
address ownerAddress = address(0);
while (ownerAddress == address(0)) {
pivot = (left + right) / 2;
TicketNumberRange memory ticketNumberRange = _ticketNumberRanges[pivot];
if (ticketNumberRange.to < ticketNumber) {
left = pivot + 1;
} else if (ticketNumberRange.from > ticketNumber) {
right = pivot - 1;
} else {
ownerAddress = ticketNumberRange.owner;
}
}
return ownerAddress;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface VRFCoordinatorV2Interface {
/**
* @notice Get configuration relevant for making requests
* @return minimumRequestConfirmations global min for request confirmations
* @return maxGasLimit global max for request gas limit
* @return s_provingKeyHashes list of registered key hashes
*/
function getRequestConfig()
external
view
returns (
uint16,
uint32,
bytes32[] memory
);
/**
* @notice Request a set of random words.
* @param 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.
* @param subId - The ID of the VRF subscription. Must be funded
* with the minimum subscription balance required for the selected keyHash.
* @param minimumRequestConfirmations - 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].
* @param 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]
* @param 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.
* @return requestId - A unique identifier of the request. Can be used to match
* a request to a response in fulfillRandomWords.
*/
function requestRandomWords(
bytes32 keyHash,
uint64 subId,
uint16 minimumRequestConfirmations,
uint32 callbackGasLimit,
uint32 numWords
) external returns (uint256 requestId);
/**
* @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, use transferAndCall. For example
* @dev LINKTOKEN.transferAndCall(
* @dev address(COORDINATOR),
* @dev amount,
* @dev abi.encode(subId));
*/
function createSubscription() external returns (uint64 subId);
/**
* @notice Get a VRF subscription.
* @param subId - ID of the subscription
* @return balance - LINK balance of the subscription in juels.
* @return reqCount - number of requests for this subscription, determines fee tier.
* @return owner - owner of the subscription.
* @return consumers - list of consumer address which are able to use this subscription.
*/
function getSubscription(uint64 subId)
external
view
returns (
uint96 balance,
uint64 reqCount,
address owner,
address[] memory consumers
);
/**
* @notice Request subscription owner transfer.
* @param subId - ID of the subscription
* @param newOwner - proposed new owner of the subscription
*/
function requestSubscriptionOwnerTransfer(uint64 subId, address newOwner) external;
/**
* @notice Request 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(uint64 subId) external;
/**
* @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(uint64 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(uint64 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(uint64 subId, address to) external;
/*
* @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(uint64 subId) external view returns (bool);
}// 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);
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
*/
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 v4.7.0) (access/Ownable.sol)
pragma solidity ^0.8.0;
import "../utils/Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor() {
_transferOwnership(_msgSender());
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/utils/ERC1155Holder.sol)
pragma solidity ^0.8.0;
import "./ERC1155Receiver.sol";
/**
* Simple implementation of `ERC1155Receiver` that will allow a contract to hold ERC1155 tokens.
*
* IMPORTANT: When inheriting this contract, you must include a way to use the received tokens, otherwise they will be
* stuck.
*
* @dev _Available since v3.1._
*/
contract ERC1155Holder is ERC1155Receiver {
function onERC1155Received(
address,
address,
uint256,
uint256,
bytes memory
) public virtual override returns (bytes4) {
return this.onERC1155Received.selector;
}
function onERC1155BatchReceived(
address,
address,
uint256[] memory,
uint256[] memory,
bytes memory
) public virtual override returns (bytes4) {
return this.onERC1155BatchReceived.selector;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC1155/IERC1155.sol)
pragma solidity ^0.8.0;
import "../../utils/introspection/IERC165.sol";
/**
* @dev Required interface of an ERC1155 compliant contract, as defined in the
* https://eips.ethereum.org/EIPS/eip-1155[EIP].
*
* _Available since v3.1._
*/
interface IERC1155 is IERC165 {
/**
* @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.
*/
event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);
/**
* @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all
* transfers.
*/
event TransferBatch(
address indexed operator,
address indexed from,
address indexed to,
uint256[] ids,
uint256[] values
);
/**
* @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to
* `approved`.
*/
event ApprovalForAll(address indexed account, address indexed operator, bool approved);
/**
* @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.
*
* If an {URI} event was emitted for `id`, the standard
* https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value
* returned by {IERC1155MetadataURI-uri}.
*/
event URI(string value, uint256 indexed id);
/**
* @dev Returns the amount of tokens of token type `id` owned by `account`.
*
* Requirements:
*
* - `account` cannot be the zero address.
*/
function balanceOf(address account, uint256 id) external view returns (uint256);
/**
* @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.
*
* Requirements:
*
* - `accounts` and `ids` must have the same length.
*/
function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids)
external
view
returns (uint256[] memory);
/**
* @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,
*
* Emits an {ApprovalForAll} event.
*
* Requirements:
*
* - `operator` cannot be the caller.
*/
function setApprovalForAll(address operator, bool approved) external;
/**
* @dev Returns true if `operator` is approved to transfer ``account``'s tokens.
*
* See {setApprovalForAll}.
*/
function isApprovedForAll(address account, address operator) external view returns (bool);
/**
* @dev Transfers `amount` tokens of token type `id` from `from` to `to`.
*
* Emits a {TransferSingle} event.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.
* - `from` must have a balance of tokens of type `id` of at least `amount`.
* - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the
* acceptance magic value.
*/
function safeTransferFrom(
address from,
address to,
uint256 id,
uint256 amount,
bytes calldata data
) external;
/**
* @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.
*
* Emits a {TransferBatch} event.
*
* Requirements:
*
* - `ids` and `amounts` must have the same length.
* - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the
* acceptance magic value.
*/
function safeBatchTransferFrom(
address from,
address to,
uint256[] calldata ids,
uint256[] calldata amounts,
bytes calldata data
) external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC721/utils/ERC721Holder.sol)
pragma solidity ^0.8.0;
import "../IERC721Receiver.sol";
/**
* @dev Implementation of the {IERC721Receiver} interface.
*
* Accepts all token transfers.
* Make sure the contract is able to use its token with {IERC721-safeTransferFrom}, {IERC721-approve} or {IERC721-setApprovalForAll}.
*/
contract ERC721Holder is IERC721Receiver {
/**
* @dev See {IERC721Receiver-onERC721Received}.
*
* Always returns `IERC721Receiver.onERC721Received.selector`.
*/
function onERC721Received(
address,
address,
uint256,
bytes memory
) public virtual override returns (bytes4) {
return this.onERC721Received.selector;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC721/IERC721.sol)
pragma solidity ^0.8.0;
import "../../utils/introspection/IERC165.sol";
/**
* @dev Required interface of an ERC721 compliant contract.
*/
interface IERC721 is IERC165 {
/**
* @dev Emitted when `tokenId` token is transferred from `from` to `to`.
*/
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
*/
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
*/
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
/**
* @dev Returns the number of tokens in ``owner``'s account.
*/
function balanceOf(address owner) external view returns (uint256 balance);
/**
* @dev Returns the owner of the `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function ownerOf(uint256 tokenId) external view returns (address owner);
/**
* @dev Safely transfers `tokenId` token from `from` to `to`.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes calldata data
) external;
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
* are aware of the ERC721 protocol to prevent tokens from being forever locked.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) external;
/**
* @dev Transfers `tokenId` token from `from` to `to`.
*
* WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address from,
address to,
uint256 tokenId
) external;
/**
* @dev Gives permission to `to` to transfer `tokenId` token to another account.
* The approval is cleared when the token is transferred.
*
* Only a single account can be approved at a time, so approving the zero address clears previous approvals.
*
* Requirements:
*
* - The caller must own the token or be an approved operator.
* - `tokenId` must exist.
*
* Emits an {Approval} event.
*/
function approve(address to, uint256 tokenId) external;
/**
* @dev Approve or remove `operator` as an operator for the caller.
* Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
*
* Requirements:
*
* - The `operator` cannot be the caller.
*
* Emits an {ApprovalForAll} event.
*/
function setApprovalForAll(address operator, bool _approved) external;
/**
* @dev Returns the account approved for `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function getApproved(uint256 tokenId) external view returns (address operator);
/**
* @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
*
* See {setApprovalForAll}
*/
function isApprovedForAll(address owner, address operator) external view returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (security/PullPayment.sol)
pragma solidity ^0.8.0;
import "../utils/escrow/Escrow.sol";
/**
* @dev Simple implementation of a
* https://consensys.github.io/smart-contract-best-practices/recommendations/#favor-pull-over-push-for-external-calls[pull-payment]
* strategy, where the paying contract doesn't interact directly with the
* receiver account, which must withdraw its payments itself.
*
* Pull-payments are often considered the best practice when it comes to sending
* Ether, security-wise. It prevents recipients from blocking execution, and
* eliminates reentrancy concerns.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*
* To use, derive from the `PullPayment` contract, and use {_asyncTransfer}
* instead of Solidity's `transfer` function. Payees can query their due
* payments with {payments}, and retrieve them with {withdrawPayments}.
*/
abstract contract PullPayment {
Escrow private immutable _escrow;
constructor() {
_escrow = new Escrow();
}
/**
* @dev Withdraw accumulated payments, forwarding all gas to the recipient.
*
* Note that _any_ account can call this function, not just the `payee`.
* This means that contracts unaware of the `PullPayment` protocol can still
* receive funds this way, by having a separate account call
* {withdrawPayments}.
*
* WARNING: Forwarding all gas opens the door to reentrancy vulnerabilities.
* Make sure you trust the recipient, or are either following the
* checks-effects-interactions pattern or using {ReentrancyGuard}.
*
* @param payee Whose payments will be withdrawn.
*
* Causes the `escrow` to emit a {Withdrawn} event.
*/
function withdrawPayments(address payable payee) public virtual {
_escrow.withdraw(payee);
}
/**
* @dev Returns the payments owed to an address.
* @param dest The creditor's address.
*/
function payments(address dest) public view returns (uint256) {
return _escrow.depositsOf(dest);
}
/**
* @dev Called by the payer to store the sent amount as credit to be pulled.
* Funds sent in this way are stored in an intermediate {Escrow} contract, so
* there is no danger of them being spent before withdrawal.
*
* @param dest The destination address of the funds.
* @param amount The amount to transfer.
*
* Causes the `escrow` to emit a {Deposited} event.
*/
function _asyncTransfer(address dest, uint256 amount) internal virtual {
_escrow.deposit{value: amount}(dest);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
pragma solidity ^0.8.0;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC1155/utils/ERC1155Receiver.sol)
pragma solidity ^0.8.0;
import "../IERC1155Receiver.sol";
import "../../../utils/introspection/ERC165.sol";
/**
* @dev _Available since v3.1._
*/
abstract contract ERC1155Receiver is ERC165, IERC1155Receiver {
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
return interfaceId == type(IERC1155Receiver).interfaceId || super.supportsInterface(interfaceId);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)
pragma solidity ^0.8.0;
import "../../utils/introspection/IERC165.sol";
/**
* @dev _Available since v3.1._
*/
interface IERC1155Receiver is IERC165 {
/**
* @dev Handles the receipt of a single ERC1155 token type. This function is
* called at the end of a `safeTransferFrom` after the balance has been updated.
*
* NOTE: To accept the transfer, this must return
* `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))`
* (i.e. 0xf23a6e61, or its own function selector).
*
* @param operator The address which initiated the transfer (i.e. msg.sender)
* @param from The address which previously owned the token
* @param id The ID of the token being transferred
* @param value The amount of tokens being transferred
* @param data Additional data with no specified format
* @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed
*/
function onERC1155Received(
address operator,
address from,
uint256 id,
uint256 value,
bytes calldata data
) external returns (bytes4);
/**
* @dev Handles the receipt of a multiple ERC1155 token types. This function
* is called at the end of a `safeBatchTransferFrom` after the balances have
* been updated.
*
* NOTE: To accept the transfer(s), this must return
* `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))`
* (i.e. 0xbc197c81, or its own function selector).
*
* @param operator The address which initiated the batch transfer (i.e. msg.sender)
* @param from The address which previously owned the token
* @param ids An array containing ids of each token being transferred (order and length must match values array)
* @param values An array containing amounts of each token being transferred (order and length must match ids array)
* @param data Additional data with no specified format
* @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed
*/
function onERC1155BatchReceived(
address operator,
address from,
uint256[] calldata ids,
uint256[] calldata values,
bytes calldata data
) external returns (bytes4);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)
pragma solidity ^0.8.0;
import "./IERC165.sol";
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
* for the additional interface id that will be supported. For example:
*
* ```solidity
* function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
* return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
* }
* ```
*
* Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
*/
abstract contract ERC165 is IERC165 {
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)
pragma solidity ^0.8.0;
/**
* @title ERC721 token receiver interface
* @dev Interface for any contract that wants to support safeTransfers
* from ERC721 asset contracts.
*/
interface IERC721Receiver {
/**
* @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
* by `operator` from `from`, this function is called.
*
* It must return its Solidity selector to confirm the token transfer.
* If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.
*
* The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.
*/
function onERC721Received(
address operator,
address from,
uint256 tokenId,
bytes calldata data
) external returns (bytes4);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (utils/escrow/Escrow.sol)
pragma solidity ^0.8.0;
import "../../access/Ownable.sol";
import "../Address.sol";
/**
* @title Escrow
* @dev Base escrow contract, holds funds designated for a payee until they
* withdraw them.
*
* Intended usage: This contract (and derived escrow contracts) should be a
* standalone contract, that only interacts with the contract that instantiated
* it. That way, it is guaranteed that all Ether will be handled according to
* the `Escrow` rules, and there is no need to check for payable functions or
* transfers in the inheritance tree. The contract that uses the escrow as its
* payment method should be its owner, and provide public methods redirecting
* to the escrow's deposit and withdraw.
*/
contract Escrow is Ownable {
using Address for address payable;
event Deposited(address indexed payee, uint256 weiAmount);
event Withdrawn(address indexed payee, uint256 weiAmount);
mapping(address => uint256) private _deposits;
function depositsOf(address payee) public view returns (uint256) {
return _deposits[payee];
}
/**
* @dev Stores the sent amount as credit to be withdrawn.
* @param payee The destination address of the funds.
*
* Emits a {Deposited} event.
*/
function deposit(address payee) public payable virtual onlyOwner {
uint256 amount = msg.value;
_deposits[payee] += amount;
emit Deposited(payee, amount);
}
/**
* @dev Withdraw accumulated balance for a payee, forwarding all gas to the
* recipient.
*
* WARNING: Forwarding all gas opens the door to reentrancy vulnerabilities.
* Make sure you trust the recipient, or are either following the
* checks-effects-interactions pattern or using {ReentrancyGuard}.
*
* @param payee The address whose funds will be withdrawn and transferred to.
*
* Emits a {Withdrawn} event.
*/
function withdraw(address payable payee) public virtual onlyOwner {
uint256 payment = _deposits[payee];
_deposits[payee] = 0;
payee.sendValue(payment);
emit Withdrawn(payee, payment);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
require(isContract(target), "Address: delegate call to non-contract");
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}{
"optimizer": {
"enabled": true,
"runs": 200
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_nftContract","type":"address"},{"internalType":"uint256","name":"_nftTokenId","type":"uint256"},{"internalType":"uint256","name":"_nftStandardId","type":"uint256"},{"internalType":"uint16","name":"_tickets","type":"uint16"},{"internalType":"uint256","name":"_ticketPrice","type":"uint256"},{"internalType":"uint256","name":"_startTimestamp","type":"uint256"},{"internalType":"uint256","name":"_endTimestamp","type":"uint256"},{"internalType":"uint64","name":"_vrfSubscriptionId","type":"uint64"},{"internalType":"address","name":"_vrfCoordinator","type":"address"},{"internalType":"bytes32","name":"_vrfKeyHash","type":"bytes32"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"have","type":"address"},{"internalType":"address","name":"want","type":"address"}],"name":"OnlyCoordinatorCanFulfill","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"},{"anonymous":false,"inputs":[{"components":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint16","name":"from","type":"uint16"},{"internalType":"uint16","name":"to","type":"uint16"}],"indexed":false,"internalType":"struct TicketStorage.TicketNumberRange","name":"ticketNumberRange","type":"tuple"},{"indexed":false,"internalType":"uint16","name":"ticketsLeft","type":"uint16"}],"name":"TicketsAssigned","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"ticketNumber","type":"uint16"},{"indexed":false,"internalType":"address","name":"owner","type":"address"}],"name":"WinnerDrawn","type":"event"},{"inputs":[],"name":"cancelBeforeStart","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"cancelIfNoRNG","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"cancelIfUnsold","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"endTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"ticketNumber","type":"uint16"}],"name":"findOwnerOfTicketNumber","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"getAssignedTicketCount","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint16","name":"index","type":"uint16"}],"name":"getAssignedTicketNumberRange","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"getAssignedTicketNumberRanges","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCancelTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"getPurchasedTicketCount","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getState","outputs":[{"internalType":"enum Raffle.State","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"index","type":"uint16"}],"name":"getTicketNumberRange","outputs":[{"components":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint16","name":"from","type":"uint16"},{"internalType":"uint16","name":"to","type":"uint16"}],"internalType":"struct TicketStorage.TicketNumberRange","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTickets","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTicketsLeft","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTransferNFTToWinnerTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getWinnerAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getWinnerDrawTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getWinnerTicketNumber","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"receiverAddress","type":"address"},{"internalType":"uint16","name":"count","type":"uint16"}],"internalType":"struct Raffle.AddressAndCount[]","name":"receivers","type":"tuple[]"}],"name":"giveawayTicket","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"nftContract","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nftStandard","outputs":[{"internalType":"enum Raffle.NFTStandard","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nftTokenId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155BatchReceived","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"dest","type":"address"}],"name":"payments","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"count","type":"uint16"}],"name":"purchaseTicket","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"requestId","type":"uint256"},{"internalType":"uint256[]","name":"randomWords","type":"uint256[]"}],"name":"rawFulfillRandomWords","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"startTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ticketPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"transferETHToOwnerIfCompleted","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"enum Raffle.NFTStandard","name":"nftStandard","type":"uint8"},{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferNFTToOwnerIfCancelled","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"transferNFTToWinnerIfCompleted","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"transferTicketRefundIfCancelled","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"verifyNFTPresenceBeforeStart","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"vrfRandomWords","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vrfRequestId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address payable","name":"payee","type":"address"}],"name":"withdrawPayments","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
6102006040523480156200001257600080fd5b5060405162003bc838038062003bc883398101604081905262000035916200044f565b81876200004233620003d4565b60008161ffff1611620000ad5760405162461bcd60e51b815260206004820152602860248201527f4e756d626572206f66207469636b657473206d75737420626520677265617465604482015267072207468616e20360c41b60648201526084015b60405180910390fd5b6161a88161ffff161115620001145760405162461bcd60e51b815260206004820152602660248201527f4e756d626572206f66207469636b6574732063616e6e6f742065786365656420604482015265032355f3030360d41b6064820152608401620000a4565b61ffff1660808190526000805461ffff60a01b1916600160a01b909202919091179055604051620001459062000424565b604051809103906000f08015801562000162573d6000803e3d6000fd5b506001600160a01b0390811660a0521660c052428511620001d45760405162461bcd60e51b815260206004820152602560248201527f53746172742074696d657374616d702063616e6e6f7420626520696e20746865604482015264081c185cdd60da1b6064820152608401620000a4565b848411620002395760405162461bcd60e51b815260206004820152602b60248201527f456e642074696d657374616d70206d757374206265206166746572207374617260448201526a0742074696d657374616d760ac1b6064820152608401620000a4565b6001600160a01b038a16620002915760405162461bcd60e51b815260206004820152601a60248201527f4e465420636f6e74726163742063616e6e6f74206265203078300000000000006044820152606401620000a4565b876002811115620002a657620002a6620004ff565b6002811115620002ba57620002ba620004ff565b610120816002811115620002d257620002d2620004ff565b9052506000610120516002811115620002ef57620002ef620004ff565b14806200031357506001610120516002811115620003115762000311620004ff565b145b806200033657506002610120516002811115620003345762000334620004ff565b145b620003845760405162461bcd60e51b815260206004820152601a60248201527f4e6f7420737570706f72746564204e4654207374616e646172640000000000006044820152606401620000a4565b6001600160a01b03998a1660e0526101009890985261014094909452610160929092526101805294166101a05250506101e0526001600160401b03166101c0526004805460ff1916905562000515565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b61058b806200363d83390190565b80516001600160a01b03811681146200044a57600080fd5b919050565b6000806000806000806000806000806101408b8d0312156200047057600080fd5b6200047b8b62000432565b995060208b0151985060408b0151975060608b015161ffff81168114620004a157600080fd5b60808c015160a08d015160c08e015160e08f0151939a50919850965094506001600160401b0381168114620004d557600080fd5b9250620004e66101008c0162000432565b91506101208b015190509295989b9194979a5092959850565b634e487b7160e01b600052602160045260246000fd5b60805160a05160c05160e05161010051610120516101405161016051610180516101a0516101c0516101e051612f8c620006b160003960006124f2015260006125210152600061255f01526000818161065801528181610a6001528181610a970152818161106d0152818161110a015281816118c80152611ce901526000818161080601528181610a3601526110430152600081816102d501528181610fcf01526111a501526000818161041201528181610d0101528181610de901528181610ea7015281816115ad015281816116bf01526117670152600081816105ae01528181610d6001528181610e4e01528181610f2f015281816115f20152818161170401526117b101526000818161074701528181610d8601528181610e7401528181610ef7015281816116220152818161173401526117d70152600081816108b601526108f801526000818161095701528181611e36015261260701526000818161047001528181610b88015281816112bc01528181611a2701528181611b3601528181611fe60152818161221101526123e80152612f8c6000f3fe6080604052600436106102515760003560e01c8063797ad67911610139578063becc142f116100b6578063e068add71161007a578063e068add71461079f578063e2982c21146107b4578063e4c2a473146107d4578063e6fd48bc146107f4578063f23a6e6114610828578063f2fde38b1461085457600080fd5b8063becc142f146106c6578063cc8cd37e146106e6578063d03ceff014610720578063d56d229d14610735578063d78ed8931461076957600080fd5b8063994324a5116100fd578063994324a51461061857806399ced7691461062d578063a85adeab14610646578063b8967b1c1461067a578063bc197c811461069a57600080fd5b8063797ad6791461057c5780637e8305741461059c5780638aa2cbbb146105d05780638da5cb5b146105e55780638ed6431f1461060357600080fd5b8063349c6e4d116101d2578063594b367e11610196578063594b367e146104d05780635950af3c1461050a578063608f13ca1461051f578063646f22c5146105345780636f624d1614610554578063715018a61461056757600080fd5b8063349c6e4d146103eb5780633e5cb5f614610400578063489c17ef146104415780634ed0262214610461578063525c3510146104a357600080fd5b806318a7ea5f1161021957806318a7ea5f14610369578063196569e21461037f5780631fe543e3146103945780633191f0eb146103b657806331b3eb94146103cb57600080fd5b806301ffc9a71461025657806310a37c261461028b5780631209b1f6146102c3578063150b7a02146103055780631865c57d14610349575b600080fd5b34801561026257600080fd5b506102766102713660046126fc565b610874565b60405190151581526020015b60405180910390f35b34801561029757600080fd5b506009546201000090046001600160a01b03165b6040516001600160a01b039091168152602001610282565b3480156102cf57600080fd5b506102f77f000000000000000000000000000000000000000000000000000000000000000081565b604051908152602001610282565b34801561031157600080fd5b50610330610320366004612822565b630a85bd0160e11b949350505050565b6040516001600160e01b03199091168152602001610282565b34801561035557600080fd5b5060045460ff1660405161028291906128a4565b34801561037557600080fd5b506102f7600b5481565b34801561038b57600080fd5b506006546102f7565b3480156103a057600080fd5b506103b46103af36600461294d565b6108ab565b005b3480156103c257600080fd5b506008546102f7565b3480156103d757600080fd5b506103b46103e6366004612994565b610938565b3480156103f757600080fd5b506007546102f7565b34801561040c57600080fd5b506104347f000000000000000000000000000000000000000000000000000000000000000081565b60405161028291906129b1565b34801561044d57600080fd5b506103b461045c3660046129dc565b6109b6565b34801561046d57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000005b60405161ffff9091168152602001610282565b3480156104af57600080fd5b506104c36104be366004612aa3565b610bfe565b6040516102829190612abe565b3480156104dc57600080fd5b506104906104eb366004612994565b6001600160a01b031660009081526002602052604090205461ffff1690565b34801561051657600080fd5b506103b4610c7f565b34801561052b57600080fd5b506103b4610f5c565b34801561054057600080fd5b50600054600160a01b900461ffff16610490565b6103b4610562366004612aa3565b611022565b34801561057357600080fd5b506103b461135a565b34801561058857600080fd5b506103b4610597366004612af3565b61136c565b3480156105a857600080fd5b506102f77f000000000000000000000000000000000000000000000000000000000000000081565b3480156105dc57600080fd5b506103b4611543565b3480156105f157600080fd5b506000546001600160a01b03166102ab565b34801561060f57600080fd5b506103b461186f565b34801561062457600080fd5b506103b4611952565b34801561063957600080fd5b5060095461ffff16610490565b34801561065257600080fd5b506102f77f000000000000000000000000000000000000000000000000000000000000000081565b34801561068657600080fd5b50610490610695366004612b38565b6119c9565b3480156106a657600080fd5b506103306106b5366004612b6d565b63bc197c8160e01b95945050505050565b3480156106d257600080fd5b506102ab6106e1366004612aa3565b611a23565b3480156106f257600080fd5b50610490610701366004612994565b6001600160a01b031660009081526005602052604090205461ffff1690565b34801561072c57600080fd5b506103b4611cae565b34801561074157600080fd5b506102ab7f000000000000000000000000000000000000000000000000000000000000000081565b34801561077557600080fd5b50610490610784366004612994565b6001600160a01b031660009081526003602052604090205490565b3480156107ab57600080fd5b506103b4611d71565b3480156107c057600080fd5b506102f76107cf366004612994565b611e14565b3480156107e057600080fd5b506102f76107ef366004612c1b565b611eb2565b34801561080057600080fd5b506102f77f000000000000000000000000000000000000000000000000000000000000000081565b34801561083457600080fd5b50610330610843366004612c34565b63f23a6e6160e01b95945050505050565b34801561086057600080fd5b506103b461086f366004612994565b611ed3565b60006001600160e01b03198216630271189760e51b14806108a557506301ffc9a760e01b6001600160e01b03198316145b92915050565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461092a5760405163073e64fd60e21b81523360048201526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001660248201526044015b60405180910390fd5b6109348282611f49565b5050565b6040516351cff8d960e01b81526001600160a01b0382811660048301527f000000000000000000000000000000000000000000000000000000000000000016906351cff8d990602401600060405180830381600087803b15801561099b57600080fd5b505af11580156109af573d6000803e3d6000fd5b5050505050565b6109be6120dd565b600160045460ff1660058111156109d7576109d761288e565b14806109f95750600260045460ff1660058111156109f7576109f761288e565b145b610a155760405162461bcd60e51b815260040161092190612c9d565b600160045460ff166005811115610a2e57610a2e61288e565b1415610a95577f000000000000000000000000000000000000000000000000000000000000000042118015610a8257507f000000000000000000000000000000000000000000000000000000000000000042105b15610a95576004805460ff191660021790555b7f00000000000000000000000000000000000000000000000000000000000000004210610ad45760405162461bcd60e51b815260040161092190612ce9565b60005b8151811015610bcb576000828281518110610af457610af4612d2c565b60200260200101519050610b1081600001518260200151612137565b602081015160048054600390610b329084906301000000900461ffff16612d58565b825461ffff91821661010093840a90810290830219909116179092556004546000546301000000820484169450610b789392909104821691600160a01b90910416612d58565b610b829190612d58565b61ffff167f000000000000000000000000000000000000000000000000000000000000000061ffff1614610bb857610bb8612d7e565b5080610bc381612d94565b915050610ad7565b50600054600160a01b900461ffff16610bfb57600480546003919060ff19166001835b0217905550610bfb6124ad565b50565b604080516060810182526000808252602082018190529181019190915260018261ffff1681548110610c3257610c32612d2c565b60009182526020918290206040805160608101825291909201546001600160a01b038116825261ffff600160a01b8204811694830194909452600160b01b90049092169082015292915050565b6004805460ff166005811115610c9757610c9761288e565b14610cdb5760405162461bcd60e51b8152602060048201526014602482015273135d5cdd081899481a5b8810dbdb5c1b195d195960621b6044820152606401610921565b6009546201000090046001600160a01b0316610cf957610cf9612d7e565b4260075560007f00000000000000000000000000000000000000000000000000000000000000006002811115610d3157610d3161288e565b1415610de5576009546040516322dca8bb60e21b8152620100009091046001600160a01b0390811660048301527f000000000000000000000000000000000000000000000000000000000000000060248301527f00000000000000000000000000000000000000000000000000000000000000001690638b72a2ec906044015b600060405180830381600087803b158015610dcb57600080fd5b505af1158015610ddf573d6000803e3d6000fd5b50505050565b60017f00000000000000000000000000000000000000000000000000000000000000006002811115610e1957610e1961288e565b1415610ea357600954604051632142170760e11b8152306004820152620100009091046001600160a01b0390811660248301527f000000000000000000000000000000000000000000000000000000000000000060448301527f000000000000000000000000000000000000000000000000000000000000000016906342842e0e90606401610db1565b60027f00000000000000000000000000000000000000000000000000000000000000006002811115610ed757610ed761288e565b1415610f5a57600954604051637921219560e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081169263f242432a92610db192309262010000900416907f000000000000000000000000000000000000000000000000000000000000000090600190600401612daf565b565b600560045460ff166005811115610f7557610f7561288e565b14610fb95760405162461bcd60e51b8152602060048201526014602482015273135d5cdd081899481a5b8810d85b98d95b1b195960621b6044820152606401610921565b33600090815260056020526040812054610ff8907f00000000000000000000000000000000000000000000000000000000000000009061ffff16612de7565b90508015610bfb57336000818152600560205260409020805461ffff19169055610bfb90826125e8565b600160045460ff16600581111561103b5761103b61288e565b14156110a2577f00000000000000000000000000000000000000000000000000000000000000004211801561108f57507f000000000000000000000000000000000000000000000000000000000000000042105b156110a2576004805460ff191660021790555b600260045460ff1660058111156110bb576110bb61288e565b146111085760405162461bcd60e51b815260206004820152601960248201527f4d75737420626520696e2053656c6c696e675469636b657473000000000000006044820152606401610921565b7f000000000000000000000000000000000000000000000000000000000000000042106111475760405162461bcd60e51b815260040161092190612ce9565b60008161ffff161161119b5760405162461bcd60e51b815260206004820181905260248201527f5469636b657420636f756e74206d757374206265206d6f7265207468616e20306044820152606401610921565b6111c961ffff82167f0000000000000000000000000000000000000000000000000000000000000000612de7565b341461123d5760405162461bcd60e51b815260206004820152603760248201527f496e636f727265637420707572636861736520616d6f756e7420286d7573742060448201527f6265207469636b65745072696365202a20636f756e74290000000000000000006064820152608401610921565b6112473382612137565b80600460018282829054906101000a900461ffff166112669190612d58565b825461ffff91821661010093840a908102908302199091161790925560045460005463010000008204841694506112ac9392909104821691600160a01b90910416612d58565b6112b69190612d58565b61ffff167f000000000000000000000000000000000000000000000000000000000000000061ffff16146112ec576112ec612d7e565b336000908152600560205260408120805483929061130f90849061ffff16612d58565b92506101000a81548161ffff021916908361ffff160217905550600060149054906101000a900461ffff1661ffff1660001415610bfb57600480546003919060ff1916600183610bee565b6113626120dd565b610f5a600061264c565b600560045460ff1660058111156113855761138561288e565b146113c95760405162461bcd60e51b8152602060048201526014602482015273135d5cdd081899481a5b8810d85b98d95b1b195960621b6044820152606401610921565b60008360028111156113dd576113dd61288e565b141561146a57816001600160a01b0316638b72a2ec6114046000546001600160a01b031690565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602481018490526044015b600060405180830381600087803b15801561144d57600080fd5b505af1158015611461573d6000803e3d6000fd5b50505050505050565b600183600281111561147e5761147e61288e565b14156114e057816001600160a01b03166342842e0e306114a66000546001600160a01b031690565b6040516001600160e01b031960e085901b1681526001600160a01b0392831660048201529116602482015260448101849052606401611433565b60028360028111156114f4576114f461288e565b141561153e57816001600160a01b031663f242432a3061151c6000546001600160a01b031690565b8460016040518563ffffffff1660e01b81526004016114339493929190612daf565b505050565b600060045460ff16600581111561155c5761155c61288e565b146115a95760405162461bcd60e51b815260206004820152601860248201527f4d75737420626520696e2057616974696e67466f724e465400000000000000006044820152606401610921565b60007f000000000000000000000000000000000000000000000000000000000000000060028111156115dd576115dd61288e565b14156116bb57604051630b02f02d60e31b81527f0000000000000000000000000000000000000000000000000000000000000000600482015230906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906358178168906024015b60206040518083038186803b15801561166557600080fd5b505afa158015611679573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061169d9190612e06565b6001600160a01b03161415610f5a576004805460ff19166001179055565b60017f000000000000000000000000000000000000000000000000000000000000000060028111156116ef576116ef61288e565b1415611763576040516331a9108f60e11b81527f0000000000000000000000000000000000000000000000000000000000000000600482015230906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636352211e9060240161164d565b60027f000000000000000000000000000000000000000000000000000000000000000060028111156117975761179761288e565b1415610f5a57604051627eeac760e11b81523060048201527f000000000000000000000000000000000000000000000000000000000000000060248201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169062fdd58e9060440160206040518083038186803b15801561182057600080fd5b505afa158015611834573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118589190612e23565b60011415610f5a576004805460ff19166001179055565b600160045460ff1660058111156118885761188861288e565b14806118aa5750600260045460ff1660058111156118a8576118a861288e565b145b6118c65760405162461bcd60e51b815260040161092190612c9d565b7f0000000000000000000000000000000000000000000000000000000000000000421161193f5760405162461bcd60e51b815260206004820152602160248201527f456e642074696d657374616d70206d75737420626520696e20746865207061736044820152601d60fa1b6064820152608401610921565b6004805460ff1916600517905542600655565b6004805460ff16600581111561196a5761196a61288e565b146119ae5760405162461bcd60e51b8152602060048201526014602482015273135d5cdd081899481a5b8810dbdb5c1b195d195960621b6044820152606401610921565b610f5a6119c36000546001600160a01b031690565b476125e8565b6001600160a01b0382166000908152600360205260408120805461ffff84169081106119f7576119f7612d2c565b90600052602060002090601091828204019190066002029054906101000a900461ffff16905092915050565b60007f000000000000000000000000000000000000000000000000000000000000000061ffff168261ffff1610611a9c5760405162461bcd60e51b815260206004820152601c60248201527f5469636b6574206e756d62657220646f6573206e6f74206578697374000000006044820152606401610921565b600054600160a01b900461ffff1615611af75760405162461bcd60e51b815260206004820152601c60248201527f4e6f7420616c6c207469636b657473206172652061737369676e6564000000006044820152606401610921565b6001805490600082611b0b57611b0b612d2c565b600091825260209091200154600160a01b900461ffff1615611b2f57611b2f612d7e565b611b5a60017f0000000000000000000000000000000000000000000000000000000000000000612e3c565b61ffff166001611b6a8184612e3c565b61ffff1681548110611b7e57611b7e612d2c565b600091825260209091200154600160b01b900461ffff1614611ba257611ba2612d7e565b600080611bb0600184612e3c565b905060006002611bc08385612d58565b611bca9190612e75565b905060005b6001600160a01b038116611ca4576002611be98486612d58565b611bf39190612e75565b9150600060018361ffff1681548110611c0e57611c0e612d2c565b60009182526020918290206040805160608101825291909201546001600160a01b038116825261ffff600160a01b8204811694830194909452600160b01b9004831691810182905292509089161115611c7357611c6c836001612d58565b9450611c9e565b8761ffff16816020015161ffff161115611c9957611c92600184612e3c565b9350611c9e565b805191505b50611bcf565b9695505050505050565b600360045460ff166005811115611cc757611cc761288e565b14611ce45760405162461bcd60e51b815260040161092190612e96565b611d117f000000000000000000000000000000000000000000000000000000000000000062015180612ecd565b421161193f5760405162461bcd60e51b815260206004820152602960248201527f456e642074696d657374616d70202b203120646179206d75737420626520696e604482015268081d1a19481c185cdd60ba1b6064820152608401610921565b611d796120dd565b600060045460ff166005811115611d9257611d9261288e565b1480611db45750600160045460ff166005811115611db257611db261288e565b145b61193f5760405162461bcd60e51b815260206004820152602b60248201527f4d75737420626520696e2057616974696e67466f724e4654206f72205761697460448201526a1a5b99d19bdc94dd185c9d60aa1b6064820152608401610921565b6040516371d4ed8d60e11b81526001600160a01b0382811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063e3a9db1a9060240160206040518083038186803b158015611e7a57600080fd5b505afa158015611e8e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108a59190612e23565b600a8181548110611ec257600080fd5b600091825260209091200154905081565b611edb6120dd565b6001600160a01b038116611f405760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610921565b610bfb8161264c565b81600b5414611f9a5760405162461bcd60e51b815260206004820152601960248201527f556e6578706563746564205652462072657175657374206964000000000000006044820152606401610921565b600360045460ff166005811115611fb357611fb361288e565b14611fd05760405162461bcd60e51b815260040161092190612e96565b8051611fe390600a90602084019061269c565b507f000000000000000000000000000000000000000000000000000000000000000061ffff168160008151811061201c5761201c612d2c565b602002602001015161202e9190612ee5565b6009805461ffff191661ffff9290921691821790554260085561205090611a23565b600980546001600160a01b0392909216620100000262010000600160b01b031990921691909117905560048054819060ff191660018202179055506009546040805161ffff83168152620100009092046001600160a01b031660208301527f5dd912dc54929cbc09a82704cdaa1151371e72253f6638fc3789736507a42c55910160405180910390a15050565b6000546001600160a01b03163314610f5a5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610921565b600054600160a01b900461ffff166121915760405162461bcd60e51b815260206004820152601860248201527f416c6c207469636b657473206172652061737369676e656400000000000000006044820152606401610921565b60005461ffff808316600160a01b9092041610156121fc5760405162461bcd60e51b815260206004820152602260248201527f41737369676e696e6720746f6f206d616e79207469636b657473206174206f6e604482015261636560f01b6064820152608401610921565b6000805461223590600160a01b900461ffff167f0000000000000000000000000000000000000000000000000000000000000000612e3c565b905081600060148282829054906101000a900461ffff166122569190612e3c565b92506101000a81548161ffff021916908361ffff16021790555060006040518060600160405280856001600160a01b031681526020018361ffff168152602001600185856122a49190612d58565b6122ae9190612e3c565b61ffff908116909152600180548082018255600091825283517fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf690910180546020808701516040808901518816600160b01b0261ffff60b01b19928916600160a01b026001600160b01b03199095166001600160a01b0397881617949094179190911692909217909255918916835260029052812080549394508693909261235891859116612d58565b825461ffff9182166101009390930a9283029190920219909116179055506001600160a01b03841660009081526003602052604090206001805461239c9190612ef9565b81546001808201845560009384526020842060108304018054600f9093166002026101000a61ffff8181021990941694841602939093179092559154909161240c91600160a01b9004167f0000000000000000000000000000000000000000000000000000000000000000612e3c565b6124169190612e3c565b61ffff16600180808054905061242c9190612ef9565b8154811061243c5761243c612d2c565b600091825260209091200154600160b01b900461ffff161461246057612460612d7e565b6000546040517fc2284c58b533cfe15152f2cae6e261e7581e6afc140305068771b617e8056d669161249f918491600160a01b900461ffff1690612f10565b60405180910390a150505050565b600360045460ff1660058111156124c6576124c661288e565b146124e35760405162461bcd60e51b815260040161092190612e96565b6040516305d3b1d360e41b81527f0000000000000000000000000000000000000000000000000000000000000000600482015267ffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016602482015260146044820152620493e06064820152600160848201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690635d3b1d309060a401602060405180830381600087803b1580156125ab57600080fd5b505af11580156125bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125e39190612e23565b600b55565b60405163f340fa0160e01b81526001600160a01b0383811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063f340fa019083906024016000604051808303818588803b15801561144d57600080fd5b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b8280548282559060005260206000209081019282156126d7579160200282015b828111156126d75782518255916020019190600101906126bc565b506126e39291506126e7565b5090565b5b808211156126e357600081556001016126e8565b60006020828403121561270e57600080fd5b81356001600160e01b03198116811461272657600080fd5b9392505050565b6001600160a01b0381168114610bfb57600080fd5b634e487b7160e01b600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561277b5761277b612742565b60405290565b604051601f8201601f1916810167ffffffffffffffff811182821017156127aa576127aa612742565b604052919050565b600082601f8301126127c357600080fd5b813567ffffffffffffffff8111156127dd576127dd612742565b6127f0601f8201601f1916602001612781565b81815284602083860101111561280557600080fd5b816020850160208301376000918101602001919091529392505050565b6000806000806080858703121561283857600080fd5b84356128438161272d565b935060208501356128538161272d565b925060408501359150606085013567ffffffffffffffff81111561287657600080fd5b612882878288016127b2565b91505092959194509250565b634e487b7160e01b600052602160045260246000fd5b60208101600683106128b8576128b861288e565b91905290565b600067ffffffffffffffff8211156128d8576128d8612742565b5060051b60200190565b600082601f8301126128f357600080fd5b81356020612908612903836128be565b612781565b82815260059290921b8401810191818101908684111561292757600080fd5b8286015b84811015612942578035835291830191830161292b565b509695505050505050565b6000806040838503121561296057600080fd5b82359150602083013567ffffffffffffffff81111561297e57600080fd5b61298a858286016128e2565b9150509250929050565b6000602082840312156129a657600080fd5b81356127268161272d565b60208101600383106128b8576128b861288e565b803561ffff811681146129d757600080fd5b919050565b600060208083850312156129ef57600080fd5b823567ffffffffffffffff811115612a0657600080fd5b8301601f81018513612a1757600080fd5b8035612a25612903826128be565b81815260069190911b82018301908381019087831115612a4457600080fd5b928401925b82841015612a985760408489031215612a625760008081fd5b612a6a612758565b8435612a758161272d565b8152612a828587016129c5565b8187015282526040939093019290840190612a49565b979650505050505050565b600060208284031215612ab557600080fd5b612726826129c5565b606081016108a5828480516001600160a01b0316825260208082015161ffff9081169184019190915260409182015116910152565b600080600060608486031215612b0857600080fd5b833560038110612b1757600080fd5b92506020840135612b278161272d565b929592945050506040919091013590565b60008060408385031215612b4b57600080fd5b8235612b568161272d565b9150612b64602084016129c5565b90509250929050565b600080600080600060a08688031215612b8557600080fd5b8535612b908161272d565b94506020860135612ba08161272d565b9350604086013567ffffffffffffffff80821115612bbd57600080fd5b612bc989838a016128e2565b94506060880135915080821115612bdf57600080fd5b612beb89838a016128e2565b93506080880135915080821115612c0157600080fd5b50612c0e888289016127b2565b9150509295509295909350565b600060208284031215612c2d57600080fd5b5035919050565b600080600080600060a08688031215612c4c57600080fd5b8535612c578161272d565b94506020860135612c678161272d565b93506040860135925060608601359150608086013567ffffffffffffffff811115612c9157600080fd5b612c0e888289016127b2565b6020808252602c908201527f4d75737420626520696e2057616974696e67466f725374617274206f7220536560408201526b6c6c696e675469636b65747360a01b606082015260800190565b60208082526023908201527f456e642074696d657374616d70206d75737420626520696e207468652066757460408201526275726560e81b606082015260800190565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600061ffff808316818516808303821115612d7557612d75612d42565b01949350505050565b634e487b7160e01b600052600160045260246000fd5b6000600019821415612da857612da8612d42565b5060010190565b6001600160a01b0394851681529290931660208301526040820152606081019190915260a06080820181905260009082015260c00190565b6000816000190483118215151615612e0157612e01612d42565b500290565b600060208284031215612e1857600080fd5b81516127268161272d565b600060208284031215612e3557600080fd5b5051919050565b600061ffff83811690831681811015612e5757612e57612d42565b039392505050565b634e487b7160e01b600052601260045260246000fd5b600061ffff80841680612e8a57612e8a612e5f565b92169190910492915050565b60208082526018908201527f4d75737420626520696e2057616974696e67466f72524e470000000000000000604082015260600190565b60008219821115612ee057612ee0612d42565b500190565b600082612ef457612ef4612e5f565b500690565b600082821015612f0b57612f0b612d42565b500390565b60808101612f45828580516001600160a01b0316825260208082015161ffff9081169184019190915260409182015116910152565b61ffff83166060830152939250505056fea26469706673582212209e20cca5f58c2375982aee914856a0b233a7a97827f1851fa1d8cf8cf59ae97664736f6c63430008090033608060405234801561001057600080fd5b5061001a3361001f565b61006f565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b61050d8061007e6000396000f3fe6080604052600436106100555760003560e01c806351cff8d91461005a578063715018a61461007c5780638da5cb5b14610091578063e3a9db1a146100be578063f2fde38b14610102578063f340fa0114610122575b600080fd5b34801561006657600080fd5b5061007a61007536600461048d565b610135565b005b34801561008857600080fd5b5061007a6101ac565b34801561009d57600080fd5b506000546040516001600160a01b0390911681526020015b60405180910390f35b3480156100ca57600080fd5b506100f46100d936600461048d565b6001600160a01b031660009081526001602052604090205490565b6040519081526020016100b5565b34801561010e57600080fd5b5061007a61011d36600461048d565b6101c0565b61007a61013036600461048d565b61023e565b61013d6102b0565b6001600160a01b0381166000818152600160205260408120805491905590610165908261030a565b816001600160a01b03167f7084f5476618d8e60b11ef0d7d3f06914655adb8793e28ff7f018d4c76d505d5826040516101a091815260200190565b60405180910390a25050565b6101b46102b0565b6101be6000610428565b565b6101c86102b0565b6001600160a01b0381166102325760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b61023b81610428565b50565b6102466102b0565b6001600160a01b0381166000908152600160205260408120805434928392916102709084906104b1565b90915550506040518181526001600160a01b038316907f2da466a7b24304f47e87fa2e1e5a81b9831ce54fec19055ce277ca2f39ba42c4906020016101a0565b6000546001600160a01b031633146101be5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610229565b8047101561035a5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e63650000006044820152606401610229565b6000826001600160a01b03168260405160006040518083038185875af1925050503d80600081146103a7576040519150601f19603f3d011682016040523d82523d6000602084013e6103ac565b606091505b50509050806104235760405162461bcd60e51b815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d617920686176652072657665727465640000000000006064820152608401610229565b505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b038116811461023b57600080fd5b60006020828403121561049f57600080fd5b81356104aa81610478565b9392505050565b600082198211156104d257634e487b7160e01b600052601160045260246000fd5b50019056fea264697066735822122063ae0c3808e18a13e63645a9fe953b7ca67d729c62a6409afb1590cf1d5890d064736f6c63430008090033000000000000000000000000b852c6b5892256c264cc2c888ea462189154d8d700000000000000000000000000000000000000000000000000000000000009f3000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000820000000000000000000000000000000000000000000000000011c37937e08000000000000000000000000000000000000000000000000000000000006332e5c000000000000000000000000000000000000000000000000000000000633588c00000000000000000000000000000000000000000000000000000000000000149000000000000000000000000271682deb8c4e0901d1a1550ad2e64d568e69909ff8dedfbfa60af186cf3c830acbc32c05aae823045ae5ea7da1e45fbfaba4f92
Deployed Bytecode
0x6080604052600436106102515760003560e01c8063797ad67911610139578063becc142f116100b6578063e068add71161007a578063e068add71461079f578063e2982c21146107b4578063e4c2a473146107d4578063e6fd48bc146107f4578063f23a6e6114610828578063f2fde38b1461085457600080fd5b8063becc142f146106c6578063cc8cd37e146106e6578063d03ceff014610720578063d56d229d14610735578063d78ed8931461076957600080fd5b8063994324a5116100fd578063994324a51461061857806399ced7691461062d578063a85adeab14610646578063b8967b1c1461067a578063bc197c811461069a57600080fd5b8063797ad6791461057c5780637e8305741461059c5780638aa2cbbb146105d05780638da5cb5b146105e55780638ed6431f1461060357600080fd5b8063349c6e4d116101d2578063594b367e11610196578063594b367e146104d05780635950af3c1461050a578063608f13ca1461051f578063646f22c5146105345780636f624d1614610554578063715018a61461056757600080fd5b8063349c6e4d146103eb5780633e5cb5f614610400578063489c17ef146104415780634ed0262214610461578063525c3510146104a357600080fd5b806318a7ea5f1161021957806318a7ea5f14610369578063196569e21461037f5780631fe543e3146103945780633191f0eb146103b657806331b3eb94146103cb57600080fd5b806301ffc9a71461025657806310a37c261461028b5780631209b1f6146102c3578063150b7a02146103055780631865c57d14610349575b600080fd5b34801561026257600080fd5b506102766102713660046126fc565b610874565b60405190151581526020015b60405180910390f35b34801561029757600080fd5b506009546201000090046001600160a01b03165b6040516001600160a01b039091168152602001610282565b3480156102cf57600080fd5b506102f77f0000000000000000000000000000000000000000000000000011c37937e0800081565b604051908152602001610282565b34801561031157600080fd5b50610330610320366004612822565b630a85bd0160e11b949350505050565b6040516001600160e01b03199091168152602001610282565b34801561035557600080fd5b5060045460ff1660405161028291906128a4565b34801561037557600080fd5b506102f7600b5481565b34801561038b57600080fd5b506006546102f7565b3480156103a057600080fd5b506103b46103af36600461294d565b6108ab565b005b3480156103c257600080fd5b506008546102f7565b3480156103d757600080fd5b506103b46103e6366004612994565b610938565b3480156103f757600080fd5b506007546102f7565b34801561040c57600080fd5b506104347f000000000000000000000000000000000000000000000000000000000000000181565b60405161028291906129b1565b34801561044d57600080fd5b506103b461045c3660046129dc565b6109b6565b34801561046d57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000825b60405161ffff9091168152602001610282565b3480156104af57600080fd5b506104c36104be366004612aa3565b610bfe565b6040516102829190612abe565b3480156104dc57600080fd5b506104906104eb366004612994565b6001600160a01b031660009081526002602052604090205461ffff1690565b34801561051657600080fd5b506103b4610c7f565b34801561052b57600080fd5b506103b4610f5c565b34801561054057600080fd5b50600054600160a01b900461ffff16610490565b6103b4610562366004612aa3565b611022565b34801561057357600080fd5b506103b461135a565b34801561058857600080fd5b506103b4610597366004612af3565b61136c565b3480156105a857600080fd5b506102f77f00000000000000000000000000000000000000000000000000000000000009f381565b3480156105dc57600080fd5b506103b4611543565b3480156105f157600080fd5b506000546001600160a01b03166102ab565b34801561060f57600080fd5b506103b461186f565b34801561062457600080fd5b506103b4611952565b34801561063957600080fd5b5060095461ffff16610490565b34801561065257600080fd5b506102f77f00000000000000000000000000000000000000000000000000000000633588c081565b34801561068657600080fd5b50610490610695366004612b38565b6119c9565b3480156106a657600080fd5b506103306106b5366004612b6d565b63bc197c8160e01b95945050505050565b3480156106d257600080fd5b506102ab6106e1366004612aa3565b611a23565b3480156106f257600080fd5b50610490610701366004612994565b6001600160a01b031660009081526005602052604090205461ffff1690565b34801561072c57600080fd5b506103b4611cae565b34801561074157600080fd5b506102ab7f000000000000000000000000b852c6b5892256c264cc2c888ea462189154d8d781565b34801561077557600080fd5b50610490610784366004612994565b6001600160a01b031660009081526003602052604090205490565b3480156107ab57600080fd5b506103b4611d71565b3480156107c057600080fd5b506102f76107cf366004612994565b611e14565b3480156107e057600080fd5b506102f76107ef366004612c1b565b611eb2565b34801561080057600080fd5b506102f77f000000000000000000000000000000000000000000000000000000006332e5c081565b34801561083457600080fd5b50610330610843366004612c34565b63f23a6e6160e01b95945050505050565b34801561086057600080fd5b506103b461086f366004612994565b611ed3565b60006001600160e01b03198216630271189760e51b14806108a557506301ffc9a760e01b6001600160e01b03198316145b92915050565b336001600160a01b037f000000000000000000000000271682deb8c4e0901d1a1550ad2e64d568e69909161461092a5760405163073e64fd60e21b81523360048201526001600160a01b037f000000000000000000000000271682deb8c4e0901d1a1550ad2e64d568e699091660248201526044015b60405180910390fd5b6109348282611f49565b5050565b6040516351cff8d960e01b81526001600160a01b0382811660048301527f00000000000000000000000076ce272bc7e95df4f3ae42416b990f00bb3319df16906351cff8d990602401600060405180830381600087803b15801561099b57600080fd5b505af11580156109af573d6000803e3d6000fd5b5050505050565b6109be6120dd565b600160045460ff1660058111156109d7576109d761288e565b14806109f95750600260045460ff1660058111156109f7576109f761288e565b145b610a155760405162461bcd60e51b815260040161092190612c9d565b600160045460ff166005811115610a2e57610a2e61288e565b1415610a95577f000000000000000000000000000000000000000000000000000000006332e5c042118015610a8257507f00000000000000000000000000000000000000000000000000000000633588c042105b15610a95576004805460ff191660021790555b7f00000000000000000000000000000000000000000000000000000000633588c04210610ad45760405162461bcd60e51b815260040161092190612ce9565b60005b8151811015610bcb576000828281518110610af457610af4612d2c565b60200260200101519050610b1081600001518260200151612137565b602081015160048054600390610b329084906301000000900461ffff16612d58565b825461ffff91821661010093840a90810290830219909116179092556004546000546301000000820484169450610b789392909104821691600160a01b90910416612d58565b610b829190612d58565b61ffff167f000000000000000000000000000000000000000000000000000000000000008261ffff1614610bb857610bb8612d7e565b5080610bc381612d94565b915050610ad7565b50600054600160a01b900461ffff16610bfb57600480546003919060ff19166001835b0217905550610bfb6124ad565b50565b604080516060810182526000808252602082018190529181019190915260018261ffff1681548110610c3257610c32612d2c565b60009182526020918290206040805160608101825291909201546001600160a01b038116825261ffff600160a01b8204811694830194909452600160b01b90049092169082015292915050565b6004805460ff166005811115610c9757610c9761288e565b14610cdb5760405162461bcd60e51b8152602060048201526014602482015273135d5cdd081899481a5b8810dbdb5c1b195d195960621b6044820152606401610921565b6009546201000090046001600160a01b0316610cf957610cf9612d7e565b4260075560007f00000000000000000000000000000000000000000000000000000000000000016002811115610d3157610d3161288e565b1415610de5576009546040516322dca8bb60e21b8152620100009091046001600160a01b0390811660048301527f00000000000000000000000000000000000000000000000000000000000009f360248301527f000000000000000000000000b852c6b5892256c264cc2c888ea462189154d8d71690638b72a2ec906044015b600060405180830381600087803b158015610dcb57600080fd5b505af1158015610ddf573d6000803e3d6000fd5b50505050565b60017f00000000000000000000000000000000000000000000000000000000000000016002811115610e1957610e1961288e565b1415610ea357600954604051632142170760e11b8152306004820152620100009091046001600160a01b0390811660248301527f00000000000000000000000000000000000000000000000000000000000009f360448301527f000000000000000000000000b852c6b5892256c264cc2c888ea462189154d8d716906342842e0e90606401610db1565b60027f00000000000000000000000000000000000000000000000000000000000000016002811115610ed757610ed761288e565b1415610f5a57600954604051637921219560e11b81526001600160a01b037f000000000000000000000000b852c6b5892256c264cc2c888ea462189154d8d781169263f242432a92610db192309262010000900416907f00000000000000000000000000000000000000000000000000000000000009f390600190600401612daf565b565b600560045460ff166005811115610f7557610f7561288e565b14610fb95760405162461bcd60e51b8152602060048201526014602482015273135d5cdd081899481a5b8810d85b98d95b1b195960621b6044820152606401610921565b33600090815260056020526040812054610ff8907f0000000000000000000000000000000000000000000000000011c37937e080009061ffff16612de7565b90508015610bfb57336000818152600560205260409020805461ffff19169055610bfb90826125e8565b600160045460ff16600581111561103b5761103b61288e565b14156110a2577f000000000000000000000000000000000000000000000000000000006332e5c04211801561108f57507f00000000000000000000000000000000000000000000000000000000633588c042105b156110a2576004805460ff191660021790555b600260045460ff1660058111156110bb576110bb61288e565b146111085760405162461bcd60e51b815260206004820152601960248201527f4d75737420626520696e2053656c6c696e675469636b657473000000000000006044820152606401610921565b7f00000000000000000000000000000000000000000000000000000000633588c042106111475760405162461bcd60e51b815260040161092190612ce9565b60008161ffff161161119b5760405162461bcd60e51b815260206004820181905260248201527f5469636b657420636f756e74206d757374206265206d6f7265207468616e20306044820152606401610921565b6111c961ffff82167f0000000000000000000000000000000000000000000000000011c37937e08000612de7565b341461123d5760405162461bcd60e51b815260206004820152603760248201527f496e636f727265637420707572636861736520616d6f756e7420286d7573742060448201527f6265207469636b65745072696365202a20636f756e74290000000000000000006064820152608401610921565b6112473382612137565b80600460018282829054906101000a900461ffff166112669190612d58565b825461ffff91821661010093840a908102908302199091161790925560045460005463010000008204841694506112ac9392909104821691600160a01b90910416612d58565b6112b69190612d58565b61ffff167f000000000000000000000000000000000000000000000000000000000000008261ffff16146112ec576112ec612d7e565b336000908152600560205260408120805483929061130f90849061ffff16612d58565b92506101000a81548161ffff021916908361ffff160217905550600060149054906101000a900461ffff1661ffff1660001415610bfb57600480546003919060ff1916600183610bee565b6113626120dd565b610f5a600061264c565b600560045460ff1660058111156113855761138561288e565b146113c95760405162461bcd60e51b8152602060048201526014602482015273135d5cdd081899481a5b8810d85b98d95b1b195960621b6044820152606401610921565b60008360028111156113dd576113dd61288e565b141561146a57816001600160a01b0316638b72a2ec6114046000546001600160a01b031690565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602481018490526044015b600060405180830381600087803b15801561144d57600080fd5b505af1158015611461573d6000803e3d6000fd5b50505050505050565b600183600281111561147e5761147e61288e565b14156114e057816001600160a01b03166342842e0e306114a66000546001600160a01b031690565b6040516001600160e01b031960e085901b1681526001600160a01b0392831660048201529116602482015260448101849052606401611433565b60028360028111156114f4576114f461288e565b141561153e57816001600160a01b031663f242432a3061151c6000546001600160a01b031690565b8460016040518563ffffffff1660e01b81526004016114339493929190612daf565b505050565b600060045460ff16600581111561155c5761155c61288e565b146115a95760405162461bcd60e51b815260206004820152601860248201527f4d75737420626520696e2057616974696e67466f724e465400000000000000006044820152606401610921565b60007f000000000000000000000000000000000000000000000000000000000000000160028111156115dd576115dd61288e565b14156116bb57604051630b02f02d60e31b81527f00000000000000000000000000000000000000000000000000000000000009f3600482015230906001600160a01b037f000000000000000000000000b852c6b5892256c264cc2c888ea462189154d8d716906358178168906024015b60206040518083038186803b15801561166557600080fd5b505afa158015611679573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061169d9190612e06565b6001600160a01b03161415610f5a576004805460ff19166001179055565b60017f000000000000000000000000000000000000000000000000000000000000000160028111156116ef576116ef61288e565b1415611763576040516331a9108f60e11b81527f00000000000000000000000000000000000000000000000000000000000009f3600482015230906001600160a01b037f000000000000000000000000b852c6b5892256c264cc2c888ea462189154d8d71690636352211e9060240161164d565b60027f000000000000000000000000000000000000000000000000000000000000000160028111156117975761179761288e565b1415610f5a57604051627eeac760e11b81523060048201527f00000000000000000000000000000000000000000000000000000000000009f360248201527f000000000000000000000000b852c6b5892256c264cc2c888ea462189154d8d76001600160a01b03169062fdd58e9060440160206040518083038186803b15801561182057600080fd5b505afa158015611834573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118589190612e23565b60011415610f5a576004805460ff19166001179055565b600160045460ff1660058111156118885761188861288e565b14806118aa5750600260045460ff1660058111156118a8576118a861288e565b145b6118c65760405162461bcd60e51b815260040161092190612c9d565b7f00000000000000000000000000000000000000000000000000000000633588c0421161193f5760405162461bcd60e51b815260206004820152602160248201527f456e642074696d657374616d70206d75737420626520696e20746865207061736044820152601d60fa1b6064820152608401610921565b6004805460ff1916600517905542600655565b6004805460ff16600581111561196a5761196a61288e565b146119ae5760405162461bcd60e51b8152602060048201526014602482015273135d5cdd081899481a5b8810dbdb5c1b195d195960621b6044820152606401610921565b610f5a6119c36000546001600160a01b031690565b476125e8565b6001600160a01b0382166000908152600360205260408120805461ffff84169081106119f7576119f7612d2c565b90600052602060002090601091828204019190066002029054906101000a900461ffff16905092915050565b60007f000000000000000000000000000000000000000000000000000000000000008261ffff168261ffff1610611a9c5760405162461bcd60e51b815260206004820152601c60248201527f5469636b6574206e756d62657220646f6573206e6f74206578697374000000006044820152606401610921565b600054600160a01b900461ffff1615611af75760405162461bcd60e51b815260206004820152601c60248201527f4e6f7420616c6c207469636b657473206172652061737369676e6564000000006044820152606401610921565b6001805490600082611b0b57611b0b612d2c565b600091825260209091200154600160a01b900461ffff1615611b2f57611b2f612d7e565b611b5a60017f0000000000000000000000000000000000000000000000000000000000000082612e3c565b61ffff166001611b6a8184612e3c565b61ffff1681548110611b7e57611b7e612d2c565b600091825260209091200154600160b01b900461ffff1614611ba257611ba2612d7e565b600080611bb0600184612e3c565b905060006002611bc08385612d58565b611bca9190612e75565b905060005b6001600160a01b038116611ca4576002611be98486612d58565b611bf39190612e75565b9150600060018361ffff1681548110611c0e57611c0e612d2c565b60009182526020918290206040805160608101825291909201546001600160a01b038116825261ffff600160a01b8204811694830194909452600160b01b9004831691810182905292509089161115611c7357611c6c836001612d58565b9450611c9e565b8761ffff16816020015161ffff161115611c9957611c92600184612e3c565b9350611c9e565b805191505b50611bcf565b9695505050505050565b600360045460ff166005811115611cc757611cc761288e565b14611ce45760405162461bcd60e51b815260040161092190612e96565b611d117f00000000000000000000000000000000000000000000000000000000633588c062015180612ecd565b421161193f5760405162461bcd60e51b815260206004820152602960248201527f456e642074696d657374616d70202b203120646179206d75737420626520696e604482015268081d1a19481c185cdd60ba1b6064820152608401610921565b611d796120dd565b600060045460ff166005811115611d9257611d9261288e565b1480611db45750600160045460ff166005811115611db257611db261288e565b145b61193f5760405162461bcd60e51b815260206004820152602b60248201527f4d75737420626520696e2057616974696e67466f724e4654206f72205761697460448201526a1a5b99d19bdc94dd185c9d60aa1b6064820152608401610921565b6040516371d4ed8d60e11b81526001600160a01b0382811660048301526000917f00000000000000000000000076ce272bc7e95df4f3ae42416b990f00bb3319df9091169063e3a9db1a9060240160206040518083038186803b158015611e7a57600080fd5b505afa158015611e8e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108a59190612e23565b600a8181548110611ec257600080fd5b600091825260209091200154905081565b611edb6120dd565b6001600160a01b038116611f405760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610921565b610bfb8161264c565b81600b5414611f9a5760405162461bcd60e51b815260206004820152601960248201527f556e6578706563746564205652462072657175657374206964000000000000006044820152606401610921565b600360045460ff166005811115611fb357611fb361288e565b14611fd05760405162461bcd60e51b815260040161092190612e96565b8051611fe390600a90602084019061269c565b507f000000000000000000000000000000000000000000000000000000000000008261ffff168160008151811061201c5761201c612d2c565b602002602001015161202e9190612ee5565b6009805461ffff191661ffff9290921691821790554260085561205090611a23565b600980546001600160a01b0392909216620100000262010000600160b01b031990921691909117905560048054819060ff191660018202179055506009546040805161ffff83168152620100009092046001600160a01b031660208301527f5dd912dc54929cbc09a82704cdaa1151371e72253f6638fc3789736507a42c55910160405180910390a15050565b6000546001600160a01b03163314610f5a5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610921565b600054600160a01b900461ffff166121915760405162461bcd60e51b815260206004820152601860248201527f416c6c207469636b657473206172652061737369676e656400000000000000006044820152606401610921565b60005461ffff808316600160a01b9092041610156121fc5760405162461bcd60e51b815260206004820152602260248201527f41737369676e696e6720746f6f206d616e79207469636b657473206174206f6e604482015261636560f01b6064820152608401610921565b6000805461223590600160a01b900461ffff167f0000000000000000000000000000000000000000000000000000000000000082612e3c565b905081600060148282829054906101000a900461ffff166122569190612e3c565b92506101000a81548161ffff021916908361ffff16021790555060006040518060600160405280856001600160a01b031681526020018361ffff168152602001600185856122a49190612d58565b6122ae9190612e3c565b61ffff908116909152600180548082018255600091825283517fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf690910180546020808701516040808901518816600160b01b0261ffff60b01b19928916600160a01b026001600160b01b03199095166001600160a01b0397881617949094179190911692909217909255918916835260029052812080549394508693909261235891859116612d58565b825461ffff9182166101009390930a9283029190920219909116179055506001600160a01b03841660009081526003602052604090206001805461239c9190612ef9565b81546001808201845560009384526020842060108304018054600f9093166002026101000a61ffff8181021990941694841602939093179092559154909161240c91600160a01b9004167f0000000000000000000000000000000000000000000000000000000000000082612e3c565b6124169190612e3c565b61ffff16600180808054905061242c9190612ef9565b8154811061243c5761243c612d2c565b600091825260209091200154600160b01b900461ffff161461246057612460612d7e565b6000546040517fc2284c58b533cfe15152f2cae6e261e7581e6afc140305068771b617e8056d669161249f918491600160a01b900461ffff1690612f10565b60405180910390a150505050565b600360045460ff1660058111156124c6576124c661288e565b146124e35760405162461bcd60e51b815260040161092190612e96565b6040516305d3b1d360e41b81527fff8dedfbfa60af186cf3c830acbc32c05aae823045ae5ea7da1e45fbfaba4f92600482015267ffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000014916602482015260146044820152620493e06064820152600160848201527f000000000000000000000000271682deb8c4e0901d1a1550ad2e64d568e699096001600160a01b031690635d3b1d309060a401602060405180830381600087803b1580156125ab57600080fd5b505af11580156125bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125e39190612e23565b600b55565b60405163f340fa0160e01b81526001600160a01b0383811660048301527f00000000000000000000000076ce272bc7e95df4f3ae42416b990f00bb3319df169063f340fa019083906024016000604051808303818588803b15801561144d57600080fd5b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b8280548282559060005260206000209081019282156126d7579160200282015b828111156126d75782518255916020019190600101906126bc565b506126e39291506126e7565b5090565b5b808211156126e357600081556001016126e8565b60006020828403121561270e57600080fd5b81356001600160e01b03198116811461272657600080fd5b9392505050565b6001600160a01b0381168114610bfb57600080fd5b634e487b7160e01b600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561277b5761277b612742565b60405290565b604051601f8201601f1916810167ffffffffffffffff811182821017156127aa576127aa612742565b604052919050565b600082601f8301126127c357600080fd5b813567ffffffffffffffff8111156127dd576127dd612742565b6127f0601f8201601f1916602001612781565b81815284602083860101111561280557600080fd5b816020850160208301376000918101602001919091529392505050565b6000806000806080858703121561283857600080fd5b84356128438161272d565b935060208501356128538161272d565b925060408501359150606085013567ffffffffffffffff81111561287657600080fd5b612882878288016127b2565b91505092959194509250565b634e487b7160e01b600052602160045260246000fd5b60208101600683106128b8576128b861288e565b91905290565b600067ffffffffffffffff8211156128d8576128d8612742565b5060051b60200190565b600082601f8301126128f357600080fd5b81356020612908612903836128be565b612781565b82815260059290921b8401810191818101908684111561292757600080fd5b8286015b84811015612942578035835291830191830161292b565b509695505050505050565b6000806040838503121561296057600080fd5b82359150602083013567ffffffffffffffff81111561297e57600080fd5b61298a858286016128e2565b9150509250929050565b6000602082840312156129a657600080fd5b81356127268161272d565b60208101600383106128b8576128b861288e565b803561ffff811681146129d757600080fd5b919050565b600060208083850312156129ef57600080fd5b823567ffffffffffffffff811115612a0657600080fd5b8301601f81018513612a1757600080fd5b8035612a25612903826128be565b81815260069190911b82018301908381019087831115612a4457600080fd5b928401925b82841015612a985760408489031215612a625760008081fd5b612a6a612758565b8435612a758161272d565b8152612a828587016129c5565b8187015282526040939093019290840190612a49565b979650505050505050565b600060208284031215612ab557600080fd5b612726826129c5565b606081016108a5828480516001600160a01b0316825260208082015161ffff9081169184019190915260409182015116910152565b600080600060608486031215612b0857600080fd5b833560038110612b1757600080fd5b92506020840135612b278161272d565b929592945050506040919091013590565b60008060408385031215612b4b57600080fd5b8235612b568161272d565b9150612b64602084016129c5565b90509250929050565b600080600080600060a08688031215612b8557600080fd5b8535612b908161272d565b94506020860135612ba08161272d565b9350604086013567ffffffffffffffff80821115612bbd57600080fd5b612bc989838a016128e2565b94506060880135915080821115612bdf57600080fd5b612beb89838a016128e2565b93506080880135915080821115612c0157600080fd5b50612c0e888289016127b2565b9150509295509295909350565b600060208284031215612c2d57600080fd5b5035919050565b600080600080600060a08688031215612c4c57600080fd5b8535612c578161272d565b94506020860135612c678161272d565b93506040860135925060608601359150608086013567ffffffffffffffff811115612c9157600080fd5b612c0e888289016127b2565b6020808252602c908201527f4d75737420626520696e2057616974696e67466f725374617274206f7220536560408201526b6c6c696e675469636b65747360a01b606082015260800190565b60208082526023908201527f456e642074696d657374616d70206d75737420626520696e207468652066757460408201526275726560e81b606082015260800190565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600061ffff808316818516808303821115612d7557612d75612d42565b01949350505050565b634e487b7160e01b600052600160045260246000fd5b6000600019821415612da857612da8612d42565b5060010190565b6001600160a01b0394851681529290931660208301526040820152606081019190915260a06080820181905260009082015260c00190565b6000816000190483118215151615612e0157612e01612d42565b500290565b600060208284031215612e1857600080fd5b81516127268161272d565b600060208284031215612e3557600080fd5b5051919050565b600061ffff83811690831681811015612e5757612e57612d42565b039392505050565b634e487b7160e01b600052601260045260246000fd5b600061ffff80841680612e8a57612e8a612e5f565b92169190910492915050565b60208082526018908201527f4d75737420626520696e2057616974696e67466f72524e470000000000000000604082015260600190565b60008219821115612ee057612ee0612d42565b500190565b600082612ef457612ef4612e5f565b500690565b600082821015612f0b57612f0b612d42565b500390565b60808101612f45828580516001600160a01b0316825260208082015161ffff9081169184019190915260409182015116910152565b61ffff83166060830152939250505056fea26469706673582212209e20cca5f58c2375982aee914856a0b233a7a97827f1851fa1d8cf8cf59ae97664736f6c63430008090033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000b852c6b5892256c264cc2c888ea462189154d8d700000000000000000000000000000000000000000000000000000000000009f3000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000820000000000000000000000000000000000000000000000000011c37937e08000000000000000000000000000000000000000000000000000000000006332e5c000000000000000000000000000000000000000000000000000000000633588c00000000000000000000000000000000000000000000000000000000000000149000000000000000000000000271682deb8c4e0901d1a1550ad2e64d568e69909ff8dedfbfa60af186cf3c830acbc32c05aae823045ae5ea7da1e45fbfaba4f92
-----Decoded View---------------
Arg [0] : _nftContract (address): 0xB852c6b5892256C264Cc2C888eA462189154D8d7
Arg [1] : _nftTokenId (uint256): 2547
Arg [2] : _nftStandardId (uint256): 1
Arg [3] : _tickets (uint16): 130
Arg [4] : _ticketPrice (uint256): 5000000000000000
Arg [5] : _startTimestamp (uint256): 1664280000
Arg [6] : _endTimestamp (uint256): 1664452800
Arg [7] : _vrfSubscriptionId (uint64): 329
Arg [8] : _vrfCoordinator (address): 0x271682DEB8C4E0901D1a1550aD2e64D568E69909
Arg [9] : _vrfKeyHash (bytes32): 0xff8dedfbfa60af186cf3c830acbc32c05aae823045ae5ea7da1e45fbfaba4f92
-----Encoded View---------------
10 Constructor Arguments found :
Arg [0] : 000000000000000000000000b852c6b5892256c264cc2c888ea462189154d8d7
Arg [1] : 00000000000000000000000000000000000000000000000000000000000009f3
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000082
Arg [4] : 0000000000000000000000000000000000000000000000000011c37937e08000
Arg [5] : 000000000000000000000000000000000000000000000000000000006332e5c0
Arg [6] : 00000000000000000000000000000000000000000000000000000000633588c0
Arg [7] : 0000000000000000000000000000000000000000000000000000000000000149
Arg [8] : 000000000000000000000000271682deb8c4e0901d1a1550ad2e64d568e69909
Arg [9] : ff8dedfbfa60af186cf3c830acbc32c05aae823045ae5ea7da1e45fbfaba4f92
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 33 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
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.