Feature Tip: Add private address tag to any address under My Name Tag !
Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 2 internal transactions
Advanced mode:
Parent Transaction Hash | Block |
From
|
To
|
|||
---|---|---|---|---|---|---|
16747332 | 675 days ago | Contract Creation | 0 ETH | |||
16747332 | 675 days ago | Contract Creation | 0 ETH |
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 // 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.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 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) (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 (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 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 // 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 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 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 (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); } } } }
// 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 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 (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); }
{ "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
[{"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
6102006040523480156200001257600080fd5b5060405162003bc838038062003bc883398101604081905262000035916200044f565b81876200004233620003d4565b60008161ffff1611620000ad5760405162461bcd60e51b815260206004820152602860248201527f4e756d626572206f66207469636b657473206d75737420626520677265617465604482015267072207468616e20360c41b60648201526084015b60405180910390fd5b6161a88161ffff161115620001145760405162461bcd60e51b815260206004820152602660248201527f4e756d626572206f66207469636b6574732063616e6e6f742065786365656420604482015265032355f3030360d41b6064820152608401620000a4565b61ffff1660808190526000805461ffff60a01b1916600160a01b909202919091179055604051620001459062000424565b604051809103906000f08015801562000162573d6000803e3d6000fd5b506001600160a01b0390811660a0521660c052428511620001d45760405162461bcd60e51b815260206004820152602560248201527f53746172742074696d657374616d702063616e6e6f7420626520696e20746865604482015264081c185cdd60da1b6064820152608401620000a4565b848411620002395760405162461bcd60e51b815260206004820152602b60248201527f456e642074696d657374616d70206d757374206265206166746572207374617260448201526a0742074696d657374616d760ac1b6064820152608401620000a4565b6001600160a01b038a16620002915760405162461bcd60e51b815260206004820152601a60248201527f4e465420636f6e74726163742063616e6e6f74206265203078300000000000006044820152606401620000a4565b876002811115620002a657620002a6620004ff565b6002811115620002ba57620002ba620004ff565b610120816002811115620002d257620002d2620004ff565b9052506000610120516002811115620002ef57620002ef620004ff565b14806200031357506001610120516002811115620003115762000311620004ff565b145b806200033657506002610120516002811115620003345762000334620004ff565b145b620003845760405162461bcd60e51b815260206004820152601a60248201527f4e6f7420737570706f72746564204e4654207374616e646172640000000000006044820152606401620000a4565b6001600160a01b03998a1660e0526101009890985261014094909452610160929092526101805294166101a05250506101e0526001600160401b03166101c0526004805460ff1916905562000515565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b61058b806200363d83390190565b80516001600160a01b03811681146200044a57600080fd5b919050565b6000806000806000806000806000806101408b8d0312156200047057600080fd5b6200047b8b62000432565b995060208b0151985060408b0151975060608b015161ffff81168114620004a157600080fd5b60808c015160a08d015160c08e015160e08f0151939a50919850965094506001600160401b0381168114620004d557600080fd5b9250620004e66101008c0162000432565b91506101208b015190509295989b9194979a5092959850565b634e487b7160e01b600052602160045260246000fd5b60805160a05160c05160e05161010051610120516101405161016051610180516101a0516101c0516101e051612f8c620006b160003960006124f2015260006125210152600061255f01526000818161065801528181610a6001528181610a970152818161106d0152818161110a015281816118c80152611ce901526000818161080601528181610a3601526110430152600081816102d501528181610fcf01526111a501526000818161041201528181610d0101528181610de901528181610ea7015281816115ad015281816116bf01526117670152600081816105ae01528181610d6001528181610e4e01528181610f2f015281816115f20152818161170401526117b101526000818161074701528181610d8601528181610e7401528181610ef7015281816116220152818161173401526117d70152600081816108b601526108f801526000818161095701528181611e36015261260701526000818161047001528181610b88015281816112bc01528181611a2701528181611b3601528181611fe60152818161221101526123e80152612f8c6000f3fe6080604052600436106102515760003560e01c8063797ad67911610139578063becc142f116100b6578063e068add71161007a578063e068add71461079f578063e2982c21146107b4578063e4c2a473146107d4578063e6fd48bc146107f4578063f23a6e6114610828578063f2fde38b1461085457600080fd5b8063becc142f146106c6578063cc8cd37e146106e6578063d03ceff014610720578063d56d229d14610735578063d78ed8931461076957600080fd5b8063994324a5116100fd578063994324a51461061857806399ced7691461062d578063a85adeab14610646578063b8967b1c1461067a578063bc197c811461069a57600080fd5b8063797ad6791461057c5780637e8305741461059c5780638aa2cbbb146105d05780638da5cb5b146105e55780638ed6431f1461060357600080fd5b8063349c6e4d116101d2578063594b367e11610196578063594b367e146104d05780635950af3c1461050a578063608f13ca1461051f578063646f22c5146105345780636f624d1614610554578063715018a61461056757600080fd5b8063349c6e4d146103eb5780633e5cb5f614610400578063489c17ef146104415780634ed0262214610461578063525c3510146104a357600080fd5b806318a7ea5f1161021957806318a7ea5f14610369578063196569e21461037f5780631fe543e3146103945780633191f0eb146103b657806331b3eb94146103cb57600080fd5b806301ffc9a71461025657806310a37c261461028b5780631209b1f6146102c3578063150b7a02146103055780631865c57d14610349575b600080fd5b34801561026257600080fd5b506102766102713660046126fc565b610874565b60405190151581526020015b60405180910390f35b34801561029757600080fd5b506009546201000090046001600160a01b03165b6040516001600160a01b039091168152602001610282565b3480156102cf57600080fd5b506102f77f000000000000000000000000000000000000000000000000000000000000000081565b604051908152602001610282565b34801561031157600080fd5b50610330610320366004612822565b630a85bd0160e11b949350505050565b6040516001600160e01b03199091168152602001610282565b34801561035557600080fd5b5060045460ff1660405161028291906128a4565b34801561037557600080fd5b506102f7600b5481565b34801561038b57600080fd5b506006546102f7565b3480156103a057600080fd5b506103b46103af36600461294d565b6108ab565b005b3480156103c257600080fd5b506008546102f7565b3480156103d757600080fd5b506103b46103e6366004612994565b610938565b3480156103f757600080fd5b506007546102f7565b34801561040c57600080fd5b506104347f000000000000000000000000000000000000000000000000000000000000000081565b60405161028291906129b1565b34801561044d57600080fd5b506103b461045c3660046129dc565b6109b6565b34801561046d57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000005b60405161ffff9091168152602001610282565b3480156104af57600080fd5b506104c36104be366004612aa3565b610bfe565b6040516102829190612abe565b3480156104dc57600080fd5b506104906104eb366004612994565b6001600160a01b031660009081526002602052604090205461ffff1690565b34801561051657600080fd5b506103b4610c7f565b34801561052b57600080fd5b506103b4610f5c565b34801561054057600080fd5b50600054600160a01b900461ffff16610490565b6103b4610562366004612aa3565b611022565b34801561057357600080fd5b506103b461135a565b34801561058857600080fd5b506103b4610597366004612af3565b61136c565b3480156105a857600080fd5b506102f77f000000000000000000000000000000000000000000000000000000000000000081565b3480156105dc57600080fd5b506103b4611543565b3480156105f157600080fd5b506000546001600160a01b03166102ab565b34801561060f57600080fd5b506103b461186f565b34801561062457600080fd5b506103b4611952565b34801561063957600080fd5b5060095461ffff16610490565b34801561065257600080fd5b506102f77f000000000000000000000000000000000000000000000000000000000000000081565b34801561068657600080fd5b50610490610695366004612b38565b6119c9565b3480156106a657600080fd5b506103306106b5366004612b6d565b63bc197c8160e01b95945050505050565b3480156106d257600080fd5b506102ab6106e1366004612aa3565b611a23565b3480156106f257600080fd5b50610490610701366004612994565b6001600160a01b031660009081526005602052604090205461ffff1690565b34801561072c57600080fd5b506103b4611cae565b34801561074157600080fd5b506102ab7f000000000000000000000000000000000000000000000000000000000000000081565b34801561077557600080fd5b50610490610784366004612994565b6001600160a01b031660009081526003602052604090205490565b3480156107ab57600080fd5b506103b4611d71565b3480156107c057600080fd5b506102f76107cf366004612994565b611e14565b3480156107e057600080fd5b506102f76107ef366004612c1b565b611eb2565b34801561080057600080fd5b506102f77f000000000000000000000000000000000000000000000000000000000000000081565b34801561083457600080fd5b50610330610843366004612c34565b63f23a6e6160e01b95945050505050565b34801561086057600080fd5b506103b461086f366004612994565b611ed3565b60006001600160e01b03198216630271189760e51b14806108a557506301ffc9a760e01b6001600160e01b03198316145b92915050565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461092a5760405163073e64fd60e21b81523360048201526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001660248201526044015b60405180910390fd5b6109348282611f49565b5050565b6040516351cff8d960e01b81526001600160a01b0382811660048301527f000000000000000000000000000000000000000000000000000000000000000016906351cff8d990602401600060405180830381600087803b15801561099b57600080fd5b505af11580156109af573d6000803e3d6000fd5b5050505050565b6109be6120dd565b600160045460ff1660058111156109d7576109d761288e565b14806109f95750600260045460ff1660058111156109f7576109f761288e565b145b610a155760405162461bcd60e51b815260040161092190612c9d565b600160045460ff166005811115610a2e57610a2e61288e565b1415610a95577f000000000000000000000000000000000000000000000000000000000000000042118015610a8257507f000000000000000000000000000000000000000000000000000000000000000042105b15610a95576004805460ff191660021790555b7f00000000000000000000000000000000000000000000000000000000000000004210610ad45760405162461bcd60e51b815260040161092190612ce9565b60005b8151811015610bcb576000828281518110610af457610af4612d2c565b60200260200101519050610b1081600001518260200151612137565b602081015160048054600390610b329084906301000000900461ffff16612d58565b825461ffff91821661010093840a90810290830219909116179092556004546000546301000000820484169450610b789392909104821691600160a01b90910416612d58565b610b829190612d58565b61ffff167f000000000000000000000000000000000000000000000000000000000000000061ffff1614610bb857610bb8612d7e565b5080610bc381612d94565b915050610ad7565b50600054600160a01b900461ffff16610bfb57600480546003919060ff19166001835b0217905550610bfb6124ad565b50565b604080516060810182526000808252602082018190529181019190915260018261ffff1681548110610c3257610c32612d2c565b60009182526020918290206040805160608101825291909201546001600160a01b038116825261ffff600160a01b8204811694830194909452600160b01b90049092169082015292915050565b6004805460ff166005811115610c9757610c9761288e565b14610cdb5760405162461bcd60e51b8152602060048201526014602482015273135d5cdd081899481a5b8810dbdb5c1b195d195960621b6044820152606401610921565b6009546201000090046001600160a01b0316610cf957610cf9612d7e565b4260075560007f00000000000000000000000000000000000000000000000000000000000000006002811115610d3157610d3161288e565b1415610de5576009546040516322dca8bb60e21b8152620100009091046001600160a01b0390811660048301527f000000000000000000000000000000000000000000000000000000000000000060248301527f00000000000000000000000000000000000000000000000000000000000000001690638b72a2ec906044015b600060405180830381600087803b158015610dcb57600080fd5b505af1158015610ddf573d6000803e3d6000fd5b50505050565b60017f00000000000000000000000000000000000000000000000000000000000000006002811115610e1957610e1961288e565b1415610ea357600954604051632142170760e11b8152306004820152620100009091046001600160a01b0390811660248301527f000000000000000000000000000000000000000000000000000000000000000060448301527f000000000000000000000000000000000000000000000000000000000000000016906342842e0e90606401610db1565b60027f00000000000000000000000000000000000000000000000000000000000000006002811115610ed757610ed761288e565b1415610f5a57600954604051637921219560e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081169263f242432a92610db192309262010000900416907f000000000000000000000000000000000000000000000000000000000000000090600190600401612daf565b565b600560045460ff166005811115610f7557610f7561288e565b14610fb95760405162461bcd60e51b8152602060048201526014602482015273135d5cdd081899481a5b8810d85b98d95b1b195960621b6044820152606401610921565b33600090815260056020526040812054610ff8907f00000000000000000000000000000000000000000000000000000000000000009061ffff16612de7565b90508015610bfb57336000818152600560205260409020805461ffff19169055610bfb90826125e8565b600160045460ff16600581111561103b5761103b61288e565b14156110a2577f00000000000000000000000000000000000000000000000000000000000000004211801561108f57507f000000000000000000000000000000000000000000000000000000000000000042105b156110a2576004805460ff191660021790555b600260045460ff1660058111156110bb576110bb61288e565b146111085760405162461bcd60e51b815260206004820152601960248201527f4d75737420626520696e2053656c6c696e675469636b657473000000000000006044820152606401610921565b7f000000000000000000000000000000000000000000000000000000000000000042106111475760405162461bcd60e51b815260040161092190612ce9565b60008161ffff161161119b5760405162461bcd60e51b815260206004820181905260248201527f5469636b657420636f756e74206d757374206265206d6f7265207468616e20306044820152606401610921565b6111c961ffff82167f0000000000000000000000000000000000000000000000000000000000000000612de7565b341461123d5760405162461bcd60e51b815260206004820152603760248201527f496e636f727265637420707572636861736520616d6f756e7420286d7573742060448201527f6265207469636b65745072696365202a20636f756e74290000000000000000006064820152608401610921565b6112473382612137565b80600460018282829054906101000a900461ffff166112669190612d58565b825461ffff91821661010093840a908102908302199091161790925560045460005463010000008204841694506112ac9392909104821691600160a01b90910416612d58565b6112b69190612d58565b61ffff167f000000000000000000000000000000000000000000000000000000000000000061ffff16146112ec576112ec612d7e565b336000908152600560205260408120805483929061130f90849061ffff16612d58565b92506101000a81548161ffff021916908361ffff160217905550600060149054906101000a900461ffff1661ffff1660001415610bfb57600480546003919060ff1916600183610bee565b6113626120dd565b610f5a600061264c565b600560045460ff1660058111156113855761138561288e565b146113c95760405162461bcd60e51b8152602060048201526014602482015273135d5cdd081899481a5b8810d85b98d95b1b195960621b6044820152606401610921565b60008360028111156113dd576113dd61288e565b141561146a57816001600160a01b0316638b72a2ec6114046000546001600160a01b031690565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602481018490526044015b600060405180830381600087803b15801561144d57600080fd5b505af1158015611461573d6000803e3d6000fd5b50505050505050565b600183600281111561147e5761147e61288e565b14156114e057816001600160a01b03166342842e0e306114a66000546001600160a01b031690565b6040516001600160e01b031960e085901b1681526001600160a01b0392831660048201529116602482015260448101849052606401611433565b60028360028111156114f4576114f461288e565b141561153e57816001600160a01b031663f242432a3061151c6000546001600160a01b031690565b8460016040518563ffffffff1660e01b81526004016114339493929190612daf565b505050565b600060045460ff16600581111561155c5761155c61288e565b146115a95760405162461bcd60e51b815260206004820152601860248201527f4d75737420626520696e2057616974696e67466f724e465400000000000000006044820152606401610921565b60007f000000000000000000000000000000000000000000000000000000000000000060028111156115dd576115dd61288e565b14156116bb57604051630b02f02d60e31b81527f0000000000000000000000000000000000000000000000000000000000000000600482015230906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906358178168906024015b60206040518083038186803b15801561166557600080fd5b505afa158015611679573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061169d9190612e06565b6001600160a01b03161415610f5a576004805460ff19166001179055565b60017f000000000000000000000000000000000000000000000000000000000000000060028111156116ef576116ef61288e565b1415611763576040516331a9108f60e11b81527f0000000000000000000000000000000000000000000000000000000000000000600482015230906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636352211e9060240161164d565b60027f000000000000000000000000000000000000000000000000000000000000000060028111156117975761179761288e565b1415610f5a57604051627eeac760e11b81523060048201527f000000000000000000000000000000000000000000000000000000000000000060248201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169062fdd58e9060440160206040518083038186803b15801561182057600080fd5b505afa158015611834573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118589190612e23565b60011415610f5a576004805460ff19166001179055565b600160045460ff1660058111156118885761188861288e565b14806118aa5750600260045460ff1660058111156118a8576118a861288e565b145b6118c65760405162461bcd60e51b815260040161092190612c9d565b7f0000000000000000000000000000000000000000000000000000000000000000421161193f5760405162461bcd60e51b815260206004820152602160248201527f456e642074696d657374616d70206d75737420626520696e20746865207061736044820152601d60fa1b6064820152608401610921565b6004805460ff1916600517905542600655565b6004805460ff16600581111561196a5761196a61288e565b146119ae5760405162461bcd60e51b8152602060048201526014602482015273135d5cdd081899481a5b8810dbdb5c1b195d195960621b6044820152606401610921565b610f5a6119c36000546001600160a01b031690565b476125e8565b6001600160a01b0382166000908152600360205260408120805461ffff84169081106119f7576119f7612d2c565b90600052602060002090601091828204019190066002029054906101000a900461ffff16905092915050565b60007f000000000000000000000000000000000000000000000000000000000000000061ffff168261ffff1610611a9c5760405162461bcd60e51b815260206004820152601c60248201527f5469636b6574206e756d62657220646f6573206e6f74206578697374000000006044820152606401610921565b600054600160a01b900461ffff1615611af75760405162461bcd60e51b815260206004820152601c60248201527f4e6f7420616c6c207469636b657473206172652061737369676e6564000000006044820152606401610921565b6001805490600082611b0b57611b0b612d2c565b600091825260209091200154600160a01b900461ffff1615611b2f57611b2f612d7e565b611b5a60017f0000000000000000000000000000000000000000000000000000000000000000612e3c565b61ffff166001611b6a8184612e3c565b61ffff1681548110611b7e57611b7e612d2c565b600091825260209091200154600160b01b900461ffff1614611ba257611ba2612d7e565b600080611bb0600184612e3c565b905060006002611bc08385612d58565b611bca9190612e75565b905060005b6001600160a01b038116611ca4576002611be98486612d58565b611bf39190612e75565b9150600060018361ffff1681548110611c0e57611c0e612d2c565b60009182526020918290206040805160608101825291909201546001600160a01b038116825261ffff600160a01b8204811694830194909452600160b01b9004831691810182905292509089161115611c7357611c6c836001612d58565b9450611c9e565b8761ffff16816020015161ffff161115611c9957611c92600184612e3c565b9350611c9e565b805191505b50611bcf565b9695505050505050565b600360045460ff166005811115611cc757611cc761288e565b14611ce45760405162461bcd60e51b815260040161092190612e96565b611d117f000000000000000000000000000000000000000000000000000000000000000062015180612ecd565b421161193f5760405162461bcd60e51b815260206004820152602960248201527f456e642074696d657374616d70202b203120646179206d75737420626520696e604482015268081d1a19481c185cdd60ba1b6064820152608401610921565b611d796120dd565b600060045460ff166005811115611d9257611d9261288e565b1480611db45750600160045460ff166005811115611db257611db261288e565b145b61193f5760405162461bcd60e51b815260206004820152602b60248201527f4d75737420626520696e2057616974696e67466f724e4654206f72205761697460448201526a1a5b99d19bdc94dd185c9d60aa1b6064820152608401610921565b6040516371d4ed8d60e11b81526001600160a01b0382811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063e3a9db1a9060240160206040518083038186803b158015611e7a57600080fd5b505afa158015611e8e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108a59190612e23565b600a8181548110611ec257600080fd5b600091825260209091200154905081565b611edb6120dd565b6001600160a01b038116611f405760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610921565b610bfb8161264c565b81600b5414611f9a5760405162461bcd60e51b815260206004820152601960248201527f556e6578706563746564205652462072657175657374206964000000000000006044820152606401610921565b600360045460ff166005811115611fb357611fb361288e565b14611fd05760405162461bcd60e51b815260040161092190612e96565b8051611fe390600a90602084019061269c565b507f000000000000000000000000000000000000000000000000000000000000000061ffff168160008151811061201c5761201c612d2c565b602002602001015161202e9190612ee5565b6009805461ffff191661ffff9290921691821790554260085561205090611a23565b600980546001600160a01b0392909216620100000262010000600160b01b031990921691909117905560048054819060ff191660018202179055506009546040805161ffff83168152620100009092046001600160a01b031660208301527f5dd912dc54929cbc09a82704cdaa1151371e72253f6638fc3789736507a42c55910160405180910390a15050565b6000546001600160a01b03163314610f5a5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610921565b600054600160a01b900461ffff166121915760405162461bcd60e51b815260206004820152601860248201527f416c6c207469636b657473206172652061737369676e656400000000000000006044820152606401610921565b60005461ffff808316600160a01b9092041610156121fc5760405162461bcd60e51b815260206004820152602260248201527f41737369676e696e6720746f6f206d616e79207469636b657473206174206f6e604482015261636560f01b6064820152608401610921565b6000805461223590600160a01b900461ffff167f0000000000000000000000000000000000000000000000000000000000000000612e3c565b905081600060148282829054906101000a900461ffff166122569190612e3c565b92506101000a81548161ffff021916908361ffff16021790555060006040518060600160405280856001600160a01b031681526020018361ffff168152602001600185856122a49190612d58565b6122ae9190612e3c565b61ffff908116909152600180548082018255600091825283517fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf690910180546020808701516040808901518816600160b01b0261ffff60b01b19928916600160a01b026001600160b01b03199095166001600160a01b0397881617949094179190911692909217909255918916835260029052812080549394508693909261235891859116612d58565b825461ffff9182166101009390930a9283029190920219909116179055506001600160a01b03841660009081526003602052604090206001805461239c9190612ef9565b81546001808201845560009384526020842060108304018054600f9093166002026101000a61ffff8181021990941694841602939093179092559154909161240c91600160a01b9004167f0000000000000000000000000000000000000000000000000000000000000000612e3c565b6124169190612e3c565b61ffff16600180808054905061242c9190612ef9565b8154811061243c5761243c612d2c565b600091825260209091200154600160b01b900461ffff161461246057612460612d7e565b6000546040517fc2284c58b533cfe15152f2cae6e261e7581e6afc140305068771b617e8056d669161249f918491600160a01b900461ffff1690612f10565b60405180910390a150505050565b600360045460ff1660058111156124c6576124c661288e565b146124e35760405162461bcd60e51b815260040161092190612e96565b6040516305d3b1d360e41b81527f0000000000000000000000000000000000000000000000000000000000000000600482015267ffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016602482015260146044820152620493e06064820152600160848201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690635d3b1d309060a401602060405180830381600087803b1580156125ab57600080fd5b505af11580156125bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125e39190612e23565b600b55565b60405163f340fa0160e01b81526001600160a01b0383811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063f340fa019083906024016000604051808303818588803b15801561144d57600080fd5b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b8280548282559060005260206000209081019282156126d7579160200282015b828111156126d75782518255916020019190600101906126bc565b506126e39291506126e7565b5090565b5b808211156126e357600081556001016126e8565b60006020828403121561270e57600080fd5b81356001600160e01b03198116811461272657600080fd5b9392505050565b6001600160a01b0381168114610bfb57600080fd5b634e487b7160e01b600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561277b5761277b612742565b60405290565b604051601f8201601f1916810167ffffffffffffffff811182821017156127aa576127aa612742565b604052919050565b600082601f8301126127c357600080fd5b813567ffffffffffffffff8111156127dd576127dd612742565b6127f0601f8201601f1916602001612781565b81815284602083860101111561280557600080fd5b816020850160208301376000918101602001919091529392505050565b6000806000806080858703121561283857600080fd5b84356128438161272d565b935060208501356128538161272d565b925060408501359150606085013567ffffffffffffffff81111561287657600080fd5b612882878288016127b2565b91505092959194509250565b634e487b7160e01b600052602160045260246000fd5b60208101600683106128b8576128b861288e565b91905290565b600067ffffffffffffffff8211156128d8576128d8612742565b5060051b60200190565b600082601f8301126128f357600080fd5b81356020612908612903836128be565b612781565b82815260059290921b8401810191818101908684111561292757600080fd5b8286015b84811015612942578035835291830191830161292b565b509695505050505050565b6000806040838503121561296057600080fd5b82359150602083013567ffffffffffffffff81111561297e57600080fd5b61298a858286016128e2565b9150509250929050565b6000602082840312156129a657600080fd5b81356127268161272d565b60208101600383106128b8576128b861288e565b803561ffff811681146129d757600080fd5b919050565b600060208083850312156129ef57600080fd5b823567ffffffffffffffff811115612a0657600080fd5b8301601f81018513612a1757600080fd5b8035612a25612903826128be565b81815260069190911b82018301908381019087831115612a4457600080fd5b928401925b82841015612a985760408489031215612a625760008081fd5b612a6a612758565b8435612a758161272d565b8152612a828587016129c5565b8187015282526040939093019290840190612a49565b979650505050505050565b600060208284031215612ab557600080fd5b612726826129c5565b606081016108a5828480516001600160a01b0316825260208082015161ffff9081169184019190915260409182015116910152565b600080600060608486031215612b0857600080fd5b833560038110612b1757600080fd5b92506020840135612b278161272d565b929592945050506040919091013590565b60008060408385031215612b4b57600080fd5b8235612b568161272d565b9150612b64602084016129c5565b90509250929050565b600080600080600060a08688031215612b8557600080fd5b8535612b908161272d565b94506020860135612ba08161272d565b9350604086013567ffffffffffffffff80821115612bbd57600080fd5b612bc989838a016128e2565b94506060880135915080821115612bdf57600080fd5b612beb89838a016128e2565b93506080880135915080821115612c0157600080fd5b50612c0e888289016127b2565b9150509295509295909350565b600060208284031215612c2d57600080fd5b5035919050565b600080600080600060a08688031215612c4c57600080fd5b8535612c578161272d565b94506020860135612c678161272d565b93506040860135925060608601359150608086013567ffffffffffffffff811115612c9157600080fd5b612c0e888289016127b2565b6020808252602c908201527f4d75737420626520696e2057616974696e67466f725374617274206f7220536560408201526b6c6c696e675469636b65747360a01b606082015260800190565b60208082526023908201527f456e642074696d657374616d70206d75737420626520696e207468652066757460408201526275726560e81b606082015260800190565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600061ffff808316818516808303821115612d7557612d75612d42565b01949350505050565b634e487b7160e01b600052600160045260246000fd5b6000600019821415612da857612da8612d42565b5060010190565b6001600160a01b0394851681529290931660208301526040820152606081019190915260a06080820181905260009082015260c00190565b6000816000190483118215151615612e0157612e01612d42565b500290565b600060208284031215612e1857600080fd5b81516127268161272d565b600060208284031215612e3557600080fd5b5051919050565b600061ffff83811690831681811015612e5757612e57612d42565b039392505050565b634e487b7160e01b600052601260045260246000fd5b600061ffff80841680612e8a57612e8a612e5f565b92169190910492915050565b60208082526018908201527f4d75737420626520696e2057616974696e67466f72524e470000000000000000604082015260600190565b60008219821115612ee057612ee0612d42565b500190565b600082612ef457612ef4612e5f565b500690565b600082821015612f0b57612f0b612d42565b500390565b60808101612f45828580516001600160a01b0316825260208082015161ffff9081169184019190915260409182015116910152565b61ffff83166060830152939250505056fea26469706673582212209e20cca5f58c2375982aee914856a0b233a7a97827f1851fa1d8cf8cf59ae97664736f6c63430008090033608060405234801561001057600080fd5b5061001a3361001f565b61006f565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b61050d8061007e6000396000f3fe6080604052600436106100555760003560e01c806351cff8d91461005a578063715018a61461007c5780638da5cb5b14610091578063e3a9db1a146100be578063f2fde38b14610102578063f340fa0114610122575b600080fd5b34801561006657600080fd5b5061007a61007536600461048d565b610135565b005b34801561008857600080fd5b5061007a6101ac565b34801561009d57600080fd5b506000546040516001600160a01b0390911681526020015b60405180910390f35b3480156100ca57600080fd5b506100f46100d936600461048d565b6001600160a01b031660009081526001602052604090205490565b6040519081526020016100b5565b34801561010e57600080fd5b5061007a61011d36600461048d565b6101c0565b61007a61013036600461048d565b61023e565b61013d6102b0565b6001600160a01b0381166000818152600160205260408120805491905590610165908261030a565b816001600160a01b03167f7084f5476618d8e60b11ef0d7d3f06914655adb8793e28ff7f018d4c76d505d5826040516101a091815260200190565b60405180910390a25050565b6101b46102b0565b6101be6000610428565b565b6101c86102b0565b6001600160a01b0381166102325760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b61023b81610428565b50565b6102466102b0565b6001600160a01b0381166000908152600160205260408120805434928392916102709084906104b1565b90915550506040518181526001600160a01b038316907f2da466a7b24304f47e87fa2e1e5a81b9831ce54fec19055ce277ca2f39ba42c4906020016101a0565b6000546001600160a01b031633146101be5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610229565b8047101561035a5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e63650000006044820152606401610229565b6000826001600160a01b03168260405160006040518083038185875af1925050503d80600081146103a7576040519150601f19603f3d011682016040523d82523d6000602084013e6103ac565b606091505b50509050806104235760405162461bcd60e51b815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d617920686176652072657665727465640000000000006064820152608401610229565b505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b038116811461023b57600080fd5b60006020828403121561049f57600080fd5b81356104aa81610478565b9392505050565b600082198211156104d257634e487b7160e01b600052601160045260246000fd5b50019056fea264697066735822122063ae0c3808e18a13e63645a9fe953b7ca67d729c62a6409afb1590cf1d5890d064736f6c634300080900330000000000000000000000001cb1a5e65610aeff2551a50f76a87a7d3fb649c600000000000000000000000000000000000000000000000000000000000005640000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000016345785d8a000000000000000000000000000000000000000000000000000000000000640340d200000000000000000000000000000000000000000000000000000000644520180000000000000000000000000000000000000000000000000000000000000149000000000000000000000000271682deb8c4e0901d1a1550ad2e64d568e69909ff8dedfbfa60af186cf3c830acbc32c05aae823045ae5ea7da1e45fbfaba4f92
Deployed Bytecode
0x6080604052600436106102515760003560e01c8063797ad67911610139578063becc142f116100b6578063e068add71161007a578063e068add71461079f578063e2982c21146107b4578063e4c2a473146107d4578063e6fd48bc146107f4578063f23a6e6114610828578063f2fde38b1461085457600080fd5b8063becc142f146106c6578063cc8cd37e146106e6578063d03ceff014610720578063d56d229d14610735578063d78ed8931461076957600080fd5b8063994324a5116100fd578063994324a51461061857806399ced7691461062d578063a85adeab14610646578063b8967b1c1461067a578063bc197c811461069a57600080fd5b8063797ad6791461057c5780637e8305741461059c5780638aa2cbbb146105d05780638da5cb5b146105e55780638ed6431f1461060357600080fd5b8063349c6e4d116101d2578063594b367e11610196578063594b367e146104d05780635950af3c1461050a578063608f13ca1461051f578063646f22c5146105345780636f624d1614610554578063715018a61461056757600080fd5b8063349c6e4d146103eb5780633e5cb5f614610400578063489c17ef146104415780634ed0262214610461578063525c3510146104a357600080fd5b806318a7ea5f1161021957806318a7ea5f14610369578063196569e21461037f5780631fe543e3146103945780633191f0eb146103b657806331b3eb94146103cb57600080fd5b806301ffc9a71461025657806310a37c261461028b5780631209b1f6146102c3578063150b7a02146103055780631865c57d14610349575b600080fd5b34801561026257600080fd5b506102766102713660046126fc565b610874565b60405190151581526020015b60405180910390f35b34801561029757600080fd5b506009546201000090046001600160a01b03165b6040516001600160a01b039091168152602001610282565b3480156102cf57600080fd5b506102f77f000000000000000000000000000000000000000000000000016345785d8a000081565b604051908152602001610282565b34801561031157600080fd5b50610330610320366004612822565b630a85bd0160e11b949350505050565b6040516001600160e01b03199091168152602001610282565b34801561035557600080fd5b5060045460ff1660405161028291906128a4565b34801561037557600080fd5b506102f7600b5481565b34801561038b57600080fd5b506006546102f7565b3480156103a057600080fd5b506103b46103af36600461294d565b6108ab565b005b3480156103c257600080fd5b506008546102f7565b3480156103d757600080fd5b506103b46103e6366004612994565b610938565b3480156103f757600080fd5b506007546102f7565b34801561040c57600080fd5b506104347f000000000000000000000000000000000000000000000000000000000000000181565b60405161028291906129b1565b34801561044d57600080fd5b506103b461045c3660046129dc565b6109b6565b34801561046d57600080fd5b507f000000000000000000000000000000000000000000000000000000000000000d5b60405161ffff9091168152602001610282565b3480156104af57600080fd5b506104c36104be366004612aa3565b610bfe565b6040516102829190612abe565b3480156104dc57600080fd5b506104906104eb366004612994565b6001600160a01b031660009081526002602052604090205461ffff1690565b34801561051657600080fd5b506103b4610c7f565b34801561052b57600080fd5b506103b4610f5c565b34801561054057600080fd5b50600054600160a01b900461ffff16610490565b6103b4610562366004612aa3565b611022565b34801561057357600080fd5b506103b461135a565b34801561058857600080fd5b506103b4610597366004612af3565b61136c565b3480156105a857600080fd5b506102f77f000000000000000000000000000000000000000000000000000000000000056481565b3480156105dc57600080fd5b506103b4611543565b3480156105f157600080fd5b506000546001600160a01b03166102ab565b34801561060f57600080fd5b506103b461186f565b34801561062457600080fd5b506103b4611952565b34801561063957600080fd5b5060095461ffff16610490565b34801561065257600080fd5b506102f77f000000000000000000000000000000000000000000000000000000006445201881565b34801561068657600080fd5b50610490610695366004612b38565b6119c9565b3480156106a657600080fd5b506103306106b5366004612b6d565b63bc197c8160e01b95945050505050565b3480156106d257600080fd5b506102ab6106e1366004612aa3565b611a23565b3480156106f257600080fd5b50610490610701366004612994565b6001600160a01b031660009081526005602052604090205461ffff1690565b34801561072c57600080fd5b506103b4611cae565b34801561074157600080fd5b506102ab7f0000000000000000000000001cb1a5e65610aeff2551a50f76a87a7d3fb649c681565b34801561077557600080fd5b50610490610784366004612994565b6001600160a01b031660009081526003602052604090205490565b3480156107ab57600080fd5b506103b4611d71565b3480156107c057600080fd5b506102f76107cf366004612994565b611e14565b3480156107e057600080fd5b506102f76107ef366004612c1b565b611eb2565b34801561080057600080fd5b506102f77f00000000000000000000000000000000000000000000000000000000640340d281565b34801561083457600080fd5b50610330610843366004612c34565b63f23a6e6160e01b95945050505050565b34801561086057600080fd5b506103b461086f366004612994565b611ed3565b60006001600160e01b03198216630271189760e51b14806108a557506301ffc9a760e01b6001600160e01b03198316145b92915050565b336001600160a01b037f000000000000000000000000271682deb8c4e0901d1a1550ad2e64d568e69909161461092a5760405163073e64fd60e21b81523360048201526001600160a01b037f000000000000000000000000271682deb8c4e0901d1a1550ad2e64d568e699091660248201526044015b60405180910390fd5b6109348282611f49565b5050565b6040516351cff8d960e01b81526001600160a01b0382811660048301527f0000000000000000000000002d3a215e81fc59c01cf56b917b5a7ecf1ac2571f16906351cff8d990602401600060405180830381600087803b15801561099b57600080fd5b505af11580156109af573d6000803e3d6000fd5b5050505050565b6109be6120dd565b600160045460ff1660058111156109d7576109d761288e565b14806109f95750600260045460ff1660058111156109f7576109f761288e565b145b610a155760405162461bcd60e51b815260040161092190612c9d565b600160045460ff166005811115610a2e57610a2e61288e565b1415610a95577f00000000000000000000000000000000000000000000000000000000640340d242118015610a8257507f000000000000000000000000000000000000000000000000000000006445201842105b15610a95576004805460ff191660021790555b7f00000000000000000000000000000000000000000000000000000000644520184210610ad45760405162461bcd60e51b815260040161092190612ce9565b60005b8151811015610bcb576000828281518110610af457610af4612d2c565b60200260200101519050610b1081600001518260200151612137565b602081015160048054600390610b329084906301000000900461ffff16612d58565b825461ffff91821661010093840a90810290830219909116179092556004546000546301000000820484169450610b789392909104821691600160a01b90910416612d58565b610b829190612d58565b61ffff167f000000000000000000000000000000000000000000000000000000000000000d61ffff1614610bb857610bb8612d7e565b5080610bc381612d94565b915050610ad7565b50600054600160a01b900461ffff16610bfb57600480546003919060ff19166001835b0217905550610bfb6124ad565b50565b604080516060810182526000808252602082018190529181019190915260018261ffff1681548110610c3257610c32612d2c565b60009182526020918290206040805160608101825291909201546001600160a01b038116825261ffff600160a01b8204811694830194909452600160b01b90049092169082015292915050565b6004805460ff166005811115610c9757610c9761288e565b14610cdb5760405162461bcd60e51b8152602060048201526014602482015273135d5cdd081899481a5b8810dbdb5c1b195d195960621b6044820152606401610921565b6009546201000090046001600160a01b0316610cf957610cf9612d7e565b4260075560007f00000000000000000000000000000000000000000000000000000000000000016002811115610d3157610d3161288e565b1415610de5576009546040516322dca8bb60e21b8152620100009091046001600160a01b0390811660048301527f000000000000000000000000000000000000000000000000000000000000056460248301527f0000000000000000000000001cb1a5e65610aeff2551a50f76a87a7d3fb649c61690638b72a2ec906044015b600060405180830381600087803b158015610dcb57600080fd5b505af1158015610ddf573d6000803e3d6000fd5b50505050565b60017f00000000000000000000000000000000000000000000000000000000000000016002811115610e1957610e1961288e565b1415610ea357600954604051632142170760e11b8152306004820152620100009091046001600160a01b0390811660248301527f000000000000000000000000000000000000000000000000000000000000056460448301527f0000000000000000000000001cb1a5e65610aeff2551a50f76a87a7d3fb649c616906342842e0e90606401610db1565b60027f00000000000000000000000000000000000000000000000000000000000000016002811115610ed757610ed761288e565b1415610f5a57600954604051637921219560e11b81526001600160a01b037f0000000000000000000000001cb1a5e65610aeff2551a50f76a87a7d3fb649c681169263f242432a92610db192309262010000900416907f000000000000000000000000000000000000000000000000000000000000056490600190600401612daf565b565b600560045460ff166005811115610f7557610f7561288e565b14610fb95760405162461bcd60e51b8152602060048201526014602482015273135d5cdd081899481a5b8810d85b98d95b1b195960621b6044820152606401610921565b33600090815260056020526040812054610ff8907f000000000000000000000000000000000000000000000000016345785d8a00009061ffff16612de7565b90508015610bfb57336000818152600560205260409020805461ffff19169055610bfb90826125e8565b600160045460ff16600581111561103b5761103b61288e565b14156110a2577f00000000000000000000000000000000000000000000000000000000640340d24211801561108f57507f000000000000000000000000000000000000000000000000000000006445201842105b156110a2576004805460ff191660021790555b600260045460ff1660058111156110bb576110bb61288e565b146111085760405162461bcd60e51b815260206004820152601960248201527f4d75737420626520696e2053656c6c696e675469636b657473000000000000006044820152606401610921565b7f000000000000000000000000000000000000000000000000000000006445201842106111475760405162461bcd60e51b815260040161092190612ce9565b60008161ffff161161119b5760405162461bcd60e51b815260206004820181905260248201527f5469636b657420636f756e74206d757374206265206d6f7265207468616e20306044820152606401610921565b6111c961ffff82167f000000000000000000000000000000000000000000000000016345785d8a0000612de7565b341461123d5760405162461bcd60e51b815260206004820152603760248201527f496e636f727265637420707572636861736520616d6f756e7420286d7573742060448201527f6265207469636b65745072696365202a20636f756e74290000000000000000006064820152608401610921565b6112473382612137565b80600460018282829054906101000a900461ffff166112669190612d58565b825461ffff91821661010093840a908102908302199091161790925560045460005463010000008204841694506112ac9392909104821691600160a01b90910416612d58565b6112b69190612d58565b61ffff167f000000000000000000000000000000000000000000000000000000000000000d61ffff16146112ec576112ec612d7e565b336000908152600560205260408120805483929061130f90849061ffff16612d58565b92506101000a81548161ffff021916908361ffff160217905550600060149054906101000a900461ffff1661ffff1660001415610bfb57600480546003919060ff1916600183610bee565b6113626120dd565b610f5a600061264c565b600560045460ff1660058111156113855761138561288e565b146113c95760405162461bcd60e51b8152602060048201526014602482015273135d5cdd081899481a5b8810d85b98d95b1b195960621b6044820152606401610921565b60008360028111156113dd576113dd61288e565b141561146a57816001600160a01b0316638b72a2ec6114046000546001600160a01b031690565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602481018490526044015b600060405180830381600087803b15801561144d57600080fd5b505af1158015611461573d6000803e3d6000fd5b50505050505050565b600183600281111561147e5761147e61288e565b14156114e057816001600160a01b03166342842e0e306114a66000546001600160a01b031690565b6040516001600160e01b031960e085901b1681526001600160a01b0392831660048201529116602482015260448101849052606401611433565b60028360028111156114f4576114f461288e565b141561153e57816001600160a01b031663f242432a3061151c6000546001600160a01b031690565b8460016040518563ffffffff1660e01b81526004016114339493929190612daf565b505050565b600060045460ff16600581111561155c5761155c61288e565b146115a95760405162461bcd60e51b815260206004820152601860248201527f4d75737420626520696e2057616974696e67466f724e465400000000000000006044820152606401610921565b60007f000000000000000000000000000000000000000000000000000000000000000160028111156115dd576115dd61288e565b14156116bb57604051630b02f02d60e31b81527f0000000000000000000000000000000000000000000000000000000000000564600482015230906001600160a01b037f0000000000000000000000001cb1a5e65610aeff2551a50f76a87a7d3fb649c616906358178168906024015b60206040518083038186803b15801561166557600080fd5b505afa158015611679573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061169d9190612e06565b6001600160a01b03161415610f5a576004805460ff19166001179055565b60017f000000000000000000000000000000000000000000000000000000000000000160028111156116ef576116ef61288e565b1415611763576040516331a9108f60e11b81527f0000000000000000000000000000000000000000000000000000000000000564600482015230906001600160a01b037f0000000000000000000000001cb1a5e65610aeff2551a50f76a87a7d3fb649c61690636352211e9060240161164d565b60027f000000000000000000000000000000000000000000000000000000000000000160028111156117975761179761288e565b1415610f5a57604051627eeac760e11b81523060048201527f000000000000000000000000000000000000000000000000000000000000056460248201527f0000000000000000000000001cb1a5e65610aeff2551a50f76a87a7d3fb649c66001600160a01b03169062fdd58e9060440160206040518083038186803b15801561182057600080fd5b505afa158015611834573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118589190612e23565b60011415610f5a576004805460ff19166001179055565b600160045460ff1660058111156118885761188861288e565b14806118aa5750600260045460ff1660058111156118a8576118a861288e565b145b6118c65760405162461bcd60e51b815260040161092190612c9d565b7f0000000000000000000000000000000000000000000000000000000064452018421161193f5760405162461bcd60e51b815260206004820152602160248201527f456e642074696d657374616d70206d75737420626520696e20746865207061736044820152601d60fa1b6064820152608401610921565b6004805460ff1916600517905542600655565b6004805460ff16600581111561196a5761196a61288e565b146119ae5760405162461bcd60e51b8152602060048201526014602482015273135d5cdd081899481a5b8810dbdb5c1b195d195960621b6044820152606401610921565b610f5a6119c36000546001600160a01b031690565b476125e8565b6001600160a01b0382166000908152600360205260408120805461ffff84169081106119f7576119f7612d2c565b90600052602060002090601091828204019190066002029054906101000a900461ffff16905092915050565b60007f000000000000000000000000000000000000000000000000000000000000000d61ffff168261ffff1610611a9c5760405162461bcd60e51b815260206004820152601c60248201527f5469636b6574206e756d62657220646f6573206e6f74206578697374000000006044820152606401610921565b600054600160a01b900461ffff1615611af75760405162461bcd60e51b815260206004820152601c60248201527f4e6f7420616c6c207469636b657473206172652061737369676e6564000000006044820152606401610921565b6001805490600082611b0b57611b0b612d2c565b600091825260209091200154600160a01b900461ffff1615611b2f57611b2f612d7e565b611b5a60017f000000000000000000000000000000000000000000000000000000000000000d612e3c565b61ffff166001611b6a8184612e3c565b61ffff1681548110611b7e57611b7e612d2c565b600091825260209091200154600160b01b900461ffff1614611ba257611ba2612d7e565b600080611bb0600184612e3c565b905060006002611bc08385612d58565b611bca9190612e75565b905060005b6001600160a01b038116611ca4576002611be98486612d58565b611bf39190612e75565b9150600060018361ffff1681548110611c0e57611c0e612d2c565b60009182526020918290206040805160608101825291909201546001600160a01b038116825261ffff600160a01b8204811694830194909452600160b01b9004831691810182905292509089161115611c7357611c6c836001612d58565b9450611c9e565b8761ffff16816020015161ffff161115611c9957611c92600184612e3c565b9350611c9e565b805191505b50611bcf565b9695505050505050565b600360045460ff166005811115611cc757611cc761288e565b14611ce45760405162461bcd60e51b815260040161092190612e96565b611d117f000000000000000000000000000000000000000000000000000000006445201862015180612ecd565b421161193f5760405162461bcd60e51b815260206004820152602960248201527f456e642074696d657374616d70202b203120646179206d75737420626520696e604482015268081d1a19481c185cdd60ba1b6064820152608401610921565b611d796120dd565b600060045460ff166005811115611d9257611d9261288e565b1480611db45750600160045460ff166005811115611db257611db261288e565b145b61193f5760405162461bcd60e51b815260206004820152602b60248201527f4d75737420626520696e2057616974696e67466f724e4654206f72205761697460448201526a1a5b99d19bdc94dd185c9d60aa1b6064820152608401610921565b6040516371d4ed8d60e11b81526001600160a01b0382811660048301526000917f0000000000000000000000002d3a215e81fc59c01cf56b917b5a7ecf1ac2571f9091169063e3a9db1a9060240160206040518083038186803b158015611e7a57600080fd5b505afa158015611e8e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108a59190612e23565b600a8181548110611ec257600080fd5b600091825260209091200154905081565b611edb6120dd565b6001600160a01b038116611f405760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610921565b610bfb8161264c565b81600b5414611f9a5760405162461bcd60e51b815260206004820152601960248201527f556e6578706563746564205652462072657175657374206964000000000000006044820152606401610921565b600360045460ff166005811115611fb357611fb361288e565b14611fd05760405162461bcd60e51b815260040161092190612e96565b8051611fe390600a90602084019061269c565b507f000000000000000000000000000000000000000000000000000000000000000d61ffff168160008151811061201c5761201c612d2c565b602002602001015161202e9190612ee5565b6009805461ffff191661ffff9290921691821790554260085561205090611a23565b600980546001600160a01b0392909216620100000262010000600160b01b031990921691909117905560048054819060ff191660018202179055506009546040805161ffff83168152620100009092046001600160a01b031660208301527f5dd912dc54929cbc09a82704cdaa1151371e72253f6638fc3789736507a42c55910160405180910390a15050565b6000546001600160a01b03163314610f5a5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610921565b600054600160a01b900461ffff166121915760405162461bcd60e51b815260206004820152601860248201527f416c6c207469636b657473206172652061737369676e656400000000000000006044820152606401610921565b60005461ffff808316600160a01b9092041610156121fc5760405162461bcd60e51b815260206004820152602260248201527f41737369676e696e6720746f6f206d616e79207469636b657473206174206f6e604482015261636560f01b6064820152608401610921565b6000805461223590600160a01b900461ffff167f000000000000000000000000000000000000000000000000000000000000000d612e3c565b905081600060148282829054906101000a900461ffff166122569190612e3c565b92506101000a81548161ffff021916908361ffff16021790555060006040518060600160405280856001600160a01b031681526020018361ffff168152602001600185856122a49190612d58565b6122ae9190612e3c565b61ffff908116909152600180548082018255600091825283517fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf690910180546020808701516040808901518816600160b01b0261ffff60b01b19928916600160a01b026001600160b01b03199095166001600160a01b0397881617949094179190911692909217909255918916835260029052812080549394508693909261235891859116612d58565b825461ffff9182166101009390930a9283029190920219909116179055506001600160a01b03841660009081526003602052604090206001805461239c9190612ef9565b81546001808201845560009384526020842060108304018054600f9093166002026101000a61ffff8181021990941694841602939093179092559154909161240c91600160a01b9004167f000000000000000000000000000000000000000000000000000000000000000d612e3c565b6124169190612e3c565b61ffff16600180808054905061242c9190612ef9565b8154811061243c5761243c612d2c565b600091825260209091200154600160b01b900461ffff161461246057612460612d7e565b6000546040517fc2284c58b533cfe15152f2cae6e261e7581e6afc140305068771b617e8056d669161249f918491600160a01b900461ffff1690612f10565b60405180910390a150505050565b600360045460ff1660058111156124c6576124c661288e565b146124e35760405162461bcd60e51b815260040161092190612e96565b6040516305d3b1d360e41b81527fff8dedfbfa60af186cf3c830acbc32c05aae823045ae5ea7da1e45fbfaba4f92600482015267ffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000014916602482015260146044820152620493e06064820152600160848201527f000000000000000000000000271682deb8c4e0901d1a1550ad2e64d568e699096001600160a01b031690635d3b1d309060a401602060405180830381600087803b1580156125ab57600080fd5b505af11580156125bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125e39190612e23565b600b55565b60405163f340fa0160e01b81526001600160a01b0383811660048301527f0000000000000000000000002d3a215e81fc59c01cf56b917b5a7ecf1ac2571f169063f340fa019083906024016000604051808303818588803b15801561144d57600080fd5b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b8280548282559060005260206000209081019282156126d7579160200282015b828111156126d75782518255916020019190600101906126bc565b506126e39291506126e7565b5090565b5b808211156126e357600081556001016126e8565b60006020828403121561270e57600080fd5b81356001600160e01b03198116811461272657600080fd5b9392505050565b6001600160a01b0381168114610bfb57600080fd5b634e487b7160e01b600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561277b5761277b612742565b60405290565b604051601f8201601f1916810167ffffffffffffffff811182821017156127aa576127aa612742565b604052919050565b600082601f8301126127c357600080fd5b813567ffffffffffffffff8111156127dd576127dd612742565b6127f0601f8201601f1916602001612781565b81815284602083860101111561280557600080fd5b816020850160208301376000918101602001919091529392505050565b6000806000806080858703121561283857600080fd5b84356128438161272d565b935060208501356128538161272d565b925060408501359150606085013567ffffffffffffffff81111561287657600080fd5b612882878288016127b2565b91505092959194509250565b634e487b7160e01b600052602160045260246000fd5b60208101600683106128b8576128b861288e565b91905290565b600067ffffffffffffffff8211156128d8576128d8612742565b5060051b60200190565b600082601f8301126128f357600080fd5b81356020612908612903836128be565b612781565b82815260059290921b8401810191818101908684111561292757600080fd5b8286015b84811015612942578035835291830191830161292b565b509695505050505050565b6000806040838503121561296057600080fd5b82359150602083013567ffffffffffffffff81111561297e57600080fd5b61298a858286016128e2565b9150509250929050565b6000602082840312156129a657600080fd5b81356127268161272d565b60208101600383106128b8576128b861288e565b803561ffff811681146129d757600080fd5b919050565b600060208083850312156129ef57600080fd5b823567ffffffffffffffff811115612a0657600080fd5b8301601f81018513612a1757600080fd5b8035612a25612903826128be565b81815260069190911b82018301908381019087831115612a4457600080fd5b928401925b82841015612a985760408489031215612a625760008081fd5b612a6a612758565b8435612a758161272d565b8152612a828587016129c5565b8187015282526040939093019290840190612a49565b979650505050505050565b600060208284031215612ab557600080fd5b612726826129c5565b606081016108a5828480516001600160a01b0316825260208082015161ffff9081169184019190915260409182015116910152565b600080600060608486031215612b0857600080fd5b833560038110612b1757600080fd5b92506020840135612b278161272d565b929592945050506040919091013590565b60008060408385031215612b4b57600080fd5b8235612b568161272d565b9150612b64602084016129c5565b90509250929050565b600080600080600060a08688031215612b8557600080fd5b8535612b908161272d565b94506020860135612ba08161272d565b9350604086013567ffffffffffffffff80821115612bbd57600080fd5b612bc989838a016128e2565b94506060880135915080821115612bdf57600080fd5b612beb89838a016128e2565b93506080880135915080821115612c0157600080fd5b50612c0e888289016127b2565b9150509295509295909350565b600060208284031215612c2d57600080fd5b5035919050565b600080600080600060a08688031215612c4c57600080fd5b8535612c578161272d565b94506020860135612c678161272d565b93506040860135925060608601359150608086013567ffffffffffffffff811115612c9157600080fd5b612c0e888289016127b2565b6020808252602c908201527f4d75737420626520696e2057616974696e67466f725374617274206f7220536560408201526b6c6c696e675469636b65747360a01b606082015260800190565b60208082526023908201527f456e642074696d657374616d70206d75737420626520696e207468652066757460408201526275726560e81b606082015260800190565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600061ffff808316818516808303821115612d7557612d75612d42565b01949350505050565b634e487b7160e01b600052600160045260246000fd5b6000600019821415612da857612da8612d42565b5060010190565b6001600160a01b0394851681529290931660208301526040820152606081019190915260a06080820181905260009082015260c00190565b6000816000190483118215151615612e0157612e01612d42565b500290565b600060208284031215612e1857600080fd5b81516127268161272d565b600060208284031215612e3557600080fd5b5051919050565b600061ffff83811690831681811015612e5757612e57612d42565b039392505050565b634e487b7160e01b600052601260045260246000fd5b600061ffff80841680612e8a57612e8a612e5f565b92169190910492915050565b60208082526018908201527f4d75737420626520696e2057616974696e67466f72524e470000000000000000604082015260600190565b60008219821115612ee057612ee0612d42565b500190565b600082612ef457612ef4612e5f565b500690565b600082821015612f0b57612f0b612d42565b500390565b60808101612f45828580516001600160a01b0316825260208082015161ffff9081169184019190915260409182015116910152565b61ffff83166060830152939250505056fea26469706673582212209e20cca5f58c2375982aee914856a0b233a7a97827f1851fa1d8cf8cf59ae97664736f6c63430008090033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000001cb1a5e65610aeff2551a50f76a87a7d3fb649c600000000000000000000000000000000000000000000000000000000000005640000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000016345785d8a000000000000000000000000000000000000000000000000000000000000640340d200000000000000000000000000000000000000000000000000000000644520180000000000000000000000000000000000000000000000000000000000000149000000000000000000000000271682deb8c4e0901d1a1550ad2e64d568e69909ff8dedfbfa60af186cf3c830acbc32c05aae823045ae5ea7da1e45fbfaba4f92
-----Decoded View---------------
Arg [0] : _nftContract (address): 0x1CB1A5e65610AEFF2551A50f76a87a7d3fB649C6
Arg [1] : _nftTokenId (uint256): 1380
Arg [2] : _nftStandardId (uint256): 1
Arg [3] : _tickets (uint16): 13
Arg [4] : _ticketPrice (uint256): 100000000000000000
Arg [5] : _startTimestamp (uint256): 1677934802
Arg [6] : _endTimestamp (uint256): 1682251800
Arg [7] : _vrfSubscriptionId (uint64): 329
Arg [8] : _vrfCoordinator (address): 0x271682DEB8C4E0901D1a1550aD2e64D568E69909
Arg [9] : _vrfKeyHash (bytes32): 0xff8dedfbfa60af186cf3c830acbc32c05aae823045ae5ea7da1e45fbfaba4f92
-----Encoded View---------------
10 Constructor Arguments found :
Arg [0] : 0000000000000000000000001cb1a5e65610aeff2551a50f76a87a7d3fb649c6
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000564
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [3] : 000000000000000000000000000000000000000000000000000000000000000d
Arg [4] : 000000000000000000000000000000000000000000000000016345785d8a0000
Arg [5] : 00000000000000000000000000000000000000000000000000000000640340d2
Arg [6] : 0000000000000000000000000000000000000000000000000000000064452018
Arg [7] : 0000000000000000000000000000000000000000000000000000000000000149
Arg [8] : 000000000000000000000000271682deb8c4e0901d1a1550ad2e64d568e69909
Arg [9] : ff8dedfbfa60af186cf3c830acbc32c05aae823045ae5ea7da1e45fbfaba4f92
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
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.