Feature Tip: Add private address tag to any address under My Name Tag !
Source Code
Latest 25 from a total of 254 transactions
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Set Winner | 17234006 | 1021 days ago | IN | 0 ETH | 0.01145432 | ||||
| Buy Entry | 17233974 | 1021 days ago | IN | 0.15 ETH | 0.00467101 | ||||
| Buy Entry | 17233814 | 1021 days ago | IN | 0.015 ETH | 0.00513956 | ||||
| Buy Entry | 17233598 | 1021 days ago | IN | 0.3 ETH | 0.00686099 | ||||
| Buy Entry | 17233568 | 1021 days ago | IN | 0.015 ETH | 0.00734024 | ||||
| Buy Entry | 17233345 | 1021 days ago | IN | 0.015 ETH | 0.00719903 | ||||
| Buy Entry | 17233294 | 1021 days ago | IN | 0.015 ETH | 0.00581776 | ||||
| Buy Entry | 17233253 | 1021 days ago | IN | 0.015 ETH | 0.00641953 | ||||
| Buy Entry | 17232959 | 1021 days ago | IN | 0.015 ETH | 0.00580753 | ||||
| Buy Entry | 17232912 | 1021 days ago | IN | 0.3 ETH | 0.00528249 | ||||
| Buy Entry | 17232612 | 1022 days ago | IN | 0.015 ETH | 0.00855379 | ||||
| Buy Entry | 17230368 | 1022 days ago | IN | 0.075 ETH | 0.00668572 | ||||
| Buy Entry | 17230294 | 1022 days ago | IN | 0.015 ETH | 0.00655719 | ||||
| Buy Entry | 17229331 | 1022 days ago | IN | 0.015 ETH | 0.00492813 | ||||
| Buy Entry | 17228725 | 1022 days ago | IN | 0.015 ETH | 0.00349678 | ||||
| Set Winner | 17228683 | 1022 days ago | IN | 0 ETH | 0.00945086 | ||||
| Buy Entry | 17228447 | 1022 days ago | IN | 0.05 ETH | 0.00362763 | ||||
| Buy Entry | 17228374 | 1022 days ago | IN | 0.05 ETH | 0.00368507 | ||||
| Buy Entry | 17228294 | 1022 days ago | IN | 0.015 ETH | 0.00340229 | ||||
| Buy Entry | 17228288 | 1022 days ago | IN | 0.01 ETH | 0.00362845 | ||||
| Buy Entry | 17228189 | 1022 days ago | IN | 0.05 ETH | 0.00418821 | ||||
| Buy Entry | 17228128 | 1022 days ago | IN | 0.05 ETH | 0.0040876 | ||||
| Buy Entry | 17227937 | 1022 days ago | IN | 0.05 ETH | 0.00349189 | ||||
| Buy Entry | 17227782 | 1022 days ago | IN | 0.015 ETH | 0.00359384 | ||||
| Buy Entry | 17227773 | 1022 days ago | IN | 0.01 ETH | 0.0036952 |
Latest 25 internal transactions (View All)
Advanced mode:
| Parent Transaction Hash | Method | Block |
From
|
|
To
|
||
|---|---|---|---|---|---|---|---|
| Transfer | 17234017 | 1021 days ago | 1.095 ETH | ||||
| Transfer | 17234017 | 1021 days ago | 1 ETH | ||||
| Transfer | 17228694 | 1022 days ago | 0.48 ETH | ||||
| Transfer | 17228694 | 1022 days ago | 0.5 ETH | ||||
| Transfer | 17226912 | 1022 days ago | 0.99 ETH | ||||
| Transfer | 17226912 | 1022 days ago | 1 ETH | ||||
| Transfer | 17221578 | 1023 days ago | 0.54 ETH | ||||
| Transfer | 17221578 | 1023 days ago | 0.5 ETH | ||||
| Transfer | 17219797 | 1023 days ago | 1.185 ETH | ||||
| Transfer | 17219797 | 1023 days ago | 1 ETH | ||||
| Transfer | 17214459 | 1024 days ago | 0.72 ETH | ||||
| Transfer | 17214459 | 1024 days ago | 0.5 ETH | ||||
| Transfer | 17212390 | 1024 days ago | 1.08 ETH | ||||
| Transfer | 17212390 | 1024 days ago | 1 ETH | ||||
| Transfer | 17208832 | 1025 days ago | 0.45 ETH | ||||
| Transfer | 17208832 | 1025 days ago | 0.5 ETH | ||||
| Transfer | 17205277 | 1025 days ago | 1.2 ETH | ||||
| Transfer | 17205277 | 1025 days ago | 1 ETH | ||||
| Transfer | 17201718 | 1026 days ago | 0.56 ETH | ||||
| Transfer | 17201718 | 1026 days ago | 0.5 ETH | ||||
| Transfer | 17197275 | 1026 days ago | 0.56 ETH | ||||
| Transfer | 17197275 | 1026 days ago | 0.5 ETH | ||||
| Transfer | 17194897 | 1027 days ago | 1.245 ETH | ||||
| Transfer | 17194897 | 1027 days ago | 1 ETH | ||||
| Transfer | 17187768 | 1028 days ago | 0.81 ETH |
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
ETHFixedLean
Compiler Version
v0.8.4+commit.c7e474f2
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.4;
import "@openzeppelin/contracts/access/AccessControl.sol";
import "@chainlink/contracts/src/v0.8/VRFConsumerBase.sol";
import "@openzeppelin/contracts/utils/math/Math.sol";
/// @title Raffles manager (lean, single winner and a fixed amount of ETH as prize)
/// @author Luis Pando
/// @notice It consumes VRF v1 from Chainlink. It has the role
/// "operator" that is the one used by a backend app to make some calls
/// @dev It saves in an ordered array the player wallet and the current
/// entries count. So buying entries has a complexity of O(1)
/// For calculating the winner, from the huge random number generated by Chainlink
/// a normalized random is generated by using the module method, adding 1 to have
/// a random from 1 to entriesCount.
/// So next step is to perform a binary search on the ordered array to get the
/// player O(log n)
/// Example:
/// 0 -> { 1, player1} as player1 buys 1 entry
/// 1 -> {51, player2} as player2 buys 50 entries
/// 2 -> {52, player3} as player3 buys 1 entry
/// 3 -> {53, player4} as player4 buys 1 entry
/// 4 -> {153, player5} as player5 buys 100 entries
/// So the setWinner method performs a binary search on that sorted array to get the upper bound.
/// If the random number generated is 150, the winner is player5. If the random number is 20, winner is player2
contract ETHFixedLean is AccessControl, VRFConsumerBase {
////////// CHAINLINK VRF v1 /////////////////
bytes32 internal keyHash; // chainlink
uint256 internal fee; // fee paid in LINK to chainlink. 0.1 in Rinkeby, 2 in mainnet
struct RandomResult {
uint256 randomNumber; // random number generated by chainlink.
uint256 nomalizedRandomNumber; // random number % entriesLength + 1. So between 1 and entries.length
}
// event sent when the random number is generated by the VRF
event RandomNumberCreated(
uint256 indexed idFromMetawin,
uint256 randomNumber,
uint256 normalizedRandomNumber
);
struct RaffleInfo {
uint256 id; // raffleId
uint256 size; // length of the entries array of that raffle
}
mapping(uint256 => RandomResult) public requests;
// map the requestId created by chainlink with the raffle info passed as param when calling getRandomNumber()
mapping(bytes32 => RaffleInfo) public chainlinkRaffleInfo;
/////////////// END CHAINKINK VRF V1 //////////////
error EntryNotAllowed(string errorType);
// Event sent when the raffle is created by the operator
event RaffleCreated(uint256 indexed raffleId, uint256 indexed nftId);
// Event sent when the owner of the nft stakes it for the raffle
event RaffleStarted(uint256 indexed raffleId, address indexed seller);
// Event sent when the raffle is finished (either early cashout or successful completion)
event RaffleEnded(
uint256 indexed raffleId,
address indexed winner,
uint256 amountRaised,
uint256 randomNumber
);
// Event sent when one or more entries are sold (info from the price structure)
event EntrySold(
uint256 indexed raffleId,
address indexed buyer,
uint256 currentSize,
uint256 priceStructureId
);
// Event sent when a free entry is added by the operator
event FreeEntry(
uint256 indexed raffleId,
address[] buyer,
uint256 amount,
uint256 currentSize
);
// Event sent when a raffle is asked to cancel by the operator
event RaffleCancelled(uint256 indexed raffleId, uint256 amountRaised);
// The raffle is closed successfully and the platform receives the fee
event FeeTransferredToPlatform(
uint256 indexed raffleId,
uint256 amountTransferred
);
// When the raffle is asked to be cancelled and 30 days have passed, the operator can call a method
// to transfer the remaining funds and this event is emitted
event RemainingFundsTransferred(
uint256 indexed raffleId,
uint256 amountInWeis
);
// When the raffle is asked to be cancelled and 30 days have not passed yet, the players can call a
// method to refund the amount spent on the raffle and this event is emitted
event Refund(
uint256 indexed raffleId,
uint256 amountInWeis,
address indexed player
);
event EarlyCashoutTriggered(uint256 indexed raffleId, uint256 amountRaised);
event SetWinnerTriggered(uint256 indexed raffleId, uint256 amountRaised);
event StatusChangedInEmergency(uint256 indexed raffleId, uint256 newStatus);
// Emitted when an entry is cancelled
event EntryCancelled(
uint256 indexed raffleId,
uint256 amountOfEntriesCanceled,
address player
);
struct PriceStructure {
uint256 id;
uint48 numEntries;
uint256 price;
}
mapping(uint256 => PriceStructure) public pricesList;
// Every raffle has a funding structure.
struct FundingStructure {
uint128 minimumFundsInWeis;
uint128 desiredFundsInWeis;
}
mapping(uint256 => FundingStructure) public fundingList;
// In order to calculate the winner, in this struct is saved for each bought the data
struct EntriesBought {
uint48 currentEntriesLength; // current amount of entries bought in the raffle
address player; // wallet address of the player
}
// every raffle has a sorted array of EntriesBought. Each element is created when calling
// either buyEntry or giveBatchEntriesForFree
mapping(uint256 => EntriesBought[]) public entriesList;
// Main raffle data struct
struct RaffleStruct {
uint48 platformPercentage; // percentage of the funds raised that goes to the platform
uint256 prizeNumber; // number (can be a percentage, an id, an amount, etc. depending on the competition)
address winner; // address of thed winner of the raffle. Address(0) if no winner yet
address seller; // address of the seller of the NFT
uint256 randomNumber; // normalized (0-Entries array size) random number generated by the VRF
}
// The main structure is an array of raffles
RaffleStruct[] public raffles;
struct EntryInfoStruct {
STATUS status; // status of the raffle. Can be created, accepted, ended, etc
ENTRY_TYPE entryType;
uint48 entriesLength; // to easy frontend, the length of the entries array is saved here
uint128 amountRaised; // funds raised so far in wei
}
// The main structure is an array of raffles
EntryInfoStruct[] public rafflesEntryInfo;
// All the different status a rafVRFCoordinatorfle can have
enum STATUS {
CREATED, // the operator creates the raffle
ACCEPTED, // the seller stakes the nft for the raffle
EARLY_CASHOUT, // the seller wants to cashout early
CANCELLED, // the operator cancels the raffle and transfer the remaining funds after 30 days passes
CLOSING_REQUESTED, // the operator sets a winner
ENDED, // the raffle is finished, and NFT and funds were transferred
CANCEL_REQUESTED // operator asks to cancel the raffle. Players has 30 days to ask for a refund
}
enum ENTRY_TYPE {
ONLY_DIRECTLY,
ONLY_EXTERNAL_CONTRACT,
MIXED
}
// The operator role is operated by a backend application
bytes32 public constant OPERATOR_ROLE = keccak256("OPERATOR");
// requested by Hamburger. Role for the buy method of the hamburger (only that contract)
bytes32 public constant MINTERCONTRACT_ROLE = keccak256("MINTERCONTRACT");
// address of the wallet controlled by the platform that will receive the platform fee
address payable public destinationWallet =
payable(0x52a032cF59eA274f9D745f29b6D514fe95Ba192D);
constructor(
address _vrfCoordinator,
address _linkToken,
bytes32 _keyHash,
bool _mainetFee
)
VRFConsumerBase(
_vrfCoordinator, // VRF Coordinator
_linkToken // LINK Token
)
{
_setupRole(OPERATOR_ROLE, 0x13503B622abC0bD30A7e9687057DF6E8c42Fb928);
_setupRole(DEFAULT_ADMIN_ROLE, msg.sender);
keyHash = _keyHash;
if (_mainetFee == true)
fee = 2 * 10 ** 18; // in mainnet, the fee must be 2 LINK
else fee = 0.1 * 10 ** 18; // 0.1 LINK In Rinkeby and Goerli
}
function callVRFAndGetRequestId() internal returns (bytes32 requestId) {
require(
LINK.balanceOf(address(this)) >= fee,
"Not enough LINK - fill contract with faucet"
);
bytes32 result = requestRandomness(keyHash, fee);
return result;
}
/// @dev this is the method that will be called by the smart contract to get a random number
/// @param _id Id of the raffle
/// @param _entriesSize length of the entries array of that raffle
/// @param _requestId id generated by Chainlink
function getRandomNumber(
uint256 _id,
uint256 _entriesSize,
bytes32 _requestId
) internal {
chainlinkRaffleInfo[_requestId] = RaffleInfo({
id: _id,
size: _entriesSize
});
}
/// @dev Callback function used by VRF Coordinator. Is called by chainlink
/// the random number generated is normalized to the size of the entries array, and an event is
/// generated, that will be listened by the platform backend to be checked if corresponds to a
/// member of the MW community, and if true will call transferNFTAndFunds
/// @param requestId id generated previously (on method getRandomNumber by chainlink)
/// @param randomness random number (huge) generated by chainlink
function fulfillRandomness(
bytes32 requestId,
uint256 randomness
) internal override {
// randomness is the actual random number. Now extract from the aux map the original param id of the call
RaffleInfo memory raffleInfo = chainlinkRaffleInfo[requestId];
// save the random number on the map with the original id as key
uint256 normalizedRandomNumber = (randomness % raffleInfo.size) + 1;
RandomResult memory result = RandomResult({
randomNumber: randomness,
nomalizedRandomNumber: normalizedRandomNumber
});
requests[raffleInfo.id] = result;
// send the event with the original id and the random number
emit RandomNumberCreated(
raffleInfo.id,
randomness,
normalizedRandomNumber
);
transferPrizesAndFunds(raffleInfo.id, normalizedRandomNumber);
}
//////////////////////////////////////////////
/// @param _desiredFundsInWeis the amount the seller would like to get from the raffle
/// @param _collateralAddress The address of the NFT of the raffle
/// @param _collateralId The id of the NFT (ERC721)
/// @param _minimumFundsInWeis The mininum amount required for the raffle to set a winner
/// @param _prices Array of prices and amount of entries the customer could purchase
// /// @param _commissionInBasicPoints commission for the platform, in basic points
/// @notice Creates a raffle
/// @dev creates a raffle struct and push it to the raffles array. Some data is stored in the funding data structure
/// sends an event when finished
/// @return raffleId
function createRaffle(
uint128 _desiredFundsInWeis,
uint256 _prizeNumber,
uint128 _minimumFundsInWeis,
PriceStructure[] calldata _prices,
uint48 _commissionInBasicPoints,
ENTRY_TYPE _entryType
) external onlyRole(OPERATOR_ROLE) returns (uint256) {
require(_commissionInBasicPoints <= 5000, "commission too high");
RaffleStruct memory raffle = RaffleStruct({
prizeNumber: _prizeNumber,
winner: address(0),
randomNumber: 0,
seller: address(0),
platformPercentage: _commissionInBasicPoints
});
raffles.push(raffle);
saveEntryInfo(_entryType);
uint256 idRaffle = raffles.length - 1;
require(_prices.length > 0, "No prices");
for (uint256 i = 0; i < _prices.length; i++) {
require(_prices[i].numEntries > 0, "numEntries is 0");
PriceStructure memory p = PriceStructure({
id: idRaffle,
numEntries: _prices[i].numEntries,
price: _prices[i].price
});
pricesList[_prices[i].id] = p;
}
fundingList[idRaffle] = FundingStructure({
minimumFundsInWeis: _minimumFundsInWeis,
desiredFundsInWeis: _desiredFundsInWeis
});
emit RaffleCreated(idRaffle, _prizeNumber);
// Initialize the entries list array, by adding a player and removing it
EntriesBought memory entryBought = EntriesBought({
player: msg.sender,
currentEntriesLength: uint48(1)
});
entriesList[idRaffle].push(entryBought);
delete entriesList[idRaffle][0];
return idRaffle;
}
function saveEntryInfo(ENTRY_TYPE _entryType) internal {
EntryInfoStruct memory entryInfo = EntryInfoStruct({
status: STATUS.CREATED,
amountRaised: 0,
entriesLength: 0,
entryType: _entryType
});
rafflesEntryInfo.push(entryInfo);
}
/// @param _raffleId Id of the raffle
function stakeETH(uint256 _raffleId) external payable {
EntryInfoStruct storage entryInfo = rafflesEntryInfo[_raffleId];
RaffleStruct storage raffle = raffles[_raffleId];
// Check if the raffle is already created
require(entryInfo.status == STATUS.CREATED, "Raffle not CREATED");
// check the amount staked is the correct
require(raffle.prizeNumber == msg.value, "Prize not staked");
entryInfo.status = STATUS.ACCEPTED;
raffle.seller = msg.sender;
emit RaffleStarted(_raffleId, msg.sender);
}
/// @dev callable by players. Depending on the number of entries assigned to the price structure the player buys (_id parameter)
/// one or more entries will be assigned to the player.
/// Also it is checked the maximum number of entries per user is not reached
/// As the method is payable, in msg.value there will be the amount paid by the user
/// @notice If the operator set requiredNFTs when creating the raffle, only the owners of nft on that collection can make a call to this method. This will be
/// used for special raffles
/// @param _raffleId: id of the raffle
/// @param _id: id of the price structure
function buyEntry(
uint256 _raffleId,
uint256 _id
) external payable /*nonReentrant*/ {
EntryInfoStruct storage entryInfo = rafflesEntryInfo[_raffleId];
// Not callable if the contract is only using hamburgers (150 gas)
if (entryInfo.entryType == ENTRY_TYPE.ONLY_EXTERNAL_CONTRACT)
revert EntryNotAllowed("Entry type not allowed");
// Price checks
if (_id == 0) revert EntryNotAllowed("howMany is 0");
PriceStructure memory priceStruct = pricesList[_id];
if (priceStruct.id != _raffleId) revert EntryNotAllowed("Id not in raffleId");
uint48 numEntries = priceStruct.numEntries;
if (numEntries == 0) revert EntryNotAllowed("Id not supported");
if (msg.value != priceStruct.price)
revert EntryNotAllowed("msg.value must be equal to the price");
// save the entries onchain
uint48 entriesLength = entryInfo.entriesLength;
EntriesBought memory entryBought = EntriesBought({
player: msg.sender,
currentEntriesLength: uint48(entriesLength + numEntries)
});
entriesList[_raffleId].push(entryBought);
// update raffle variables
entryInfo.amountRaised += uint128(msg.value);
entryInfo.entriesLength = entriesLength + numEntries;
emit EntrySold(_raffleId, msg.sender, entryInfo.entriesLength, _id);
}
// The operator can add free entries to the raffle
/// @param _raffleId Id of the raffle
/// @param _freePlayers array of addresses corresponding to the wallet of the users that won a free entrie
/// @dev only operator can make this call. Assigns a single entry per user, except if that user already reached the max limit of entries per user
function giveBatchEntriesForFree(
uint256 _raffleId,
address[] memory _freePlayers
) external onlyRole(OPERATOR_ROLE) {
EntryInfoStruct storage entryInfo = rafflesEntryInfo[_raffleId];
require(
entryInfo.status == STATUS.ACCEPTED,
"Raffle is not in accepted"
);
uint256 freePlayersLength = _freePlayers.length;
uint48 validPlayersCount = 0;
for (uint256 i = 0; i < freePlayersLength; i++) {
address entry = _freePlayers[i];
// add a new element to the entriesBought array.
// as this method only adds 1 entry per call, the amountbought is always 1
EntriesBought memory entryBought = EntriesBought({
player: entry,
currentEntriesLength: uint48(entryInfo.entriesLength + i + 1)
});
entriesList[_raffleId].push(entryBought);
++validPlayersCount;
}
entryInfo.entriesLength = entryInfo.entriesLength + validPlayersCount;
emit FreeEntry(
_raffleId,
_freePlayers,
freePlayersLength,
entryInfo.entriesLength
);
}
// helper method to get the winner address of a raffle
/// @param _raffleId Id of the raffle
/// @param _normalizedRandomNumber Generated by chainlink
/// @return the wallet that won the raffle
/// @dev Uses a binary search on the sorted array to retreive the winner
/// but if the winner candidate is blacklisted, loop through the left looking for
/// a candidate not blacklisted
function getWinnerAddressFromRandom(
uint256 _raffleId,
uint256 _normalizedRandomNumber
) public view returns (address) {
uint256 position = findUpperBound(
entriesList[_raffleId],
_normalizedRandomNumber
);
address candidate = entriesList[_raffleId][position].player;
// general case
if (candidate != address(0)) return candidate;
// special case. The user is blacklisted, so try next on the left until find a non-blacklisted
else {
bool ended = false;
uint256 i = position;
while (
ended == false && entriesList[_raffleId][i].player == address(0)
) {
if (i == 0) i = entriesList[_raffleId].length - 1;
else i = i - 1;
// we came to the beginning without finding a non blacklisted player
if (i == position) ended == true;
}
require(!ended, "All users blacklisted");
return entriesList[_raffleId][i].player;
}
}
/// @param array sorted array of EntriesBought. CurrentEntriesLength is the numeric field used to sort
/// @param element uint256 to find. Goes from 1 to entriesLength
/// @dev based on openzeppelin code (v4.0), modified to use an array of EntriesBought
/// Searches a sorted array and returns the first index that contains a value greater or equal to element.
/// If no such index exists (i.e. all values in the array are strictly less than element), the array length is returned. Time complexity O(log n).
/// array is expected to be sorted in ascending order, and to contain no repeated elements.
/// https://docs.openzeppelin.com/contracts/3.x/api/utils#Arrays-findUpperBound-uint256---uint256-
function findUpperBound(
EntriesBought[] storage array,
uint256 element
) internal view returns (uint256) {
if (array.length == 0) {
return 0;
}
uint256 low = 0;
uint256 high = array.length;
while (low < high) {
uint256 mid = Math.average(low, high);
// Note that mid will always be strictly less than high (i.e. it will be a valid array index)
// because Math.average rounds down (it does integer division with truncation).
if (array[mid].currentEntriesLength > element) {
high = mid;
} else {
low = mid + 1;
}
}
// At this point `low` is the exclusive upper bound. We will return the inclusive upper bound.
if (low > 0 && array[low - 1].currentEntriesLength == element) {
return low - 1;
} else {
return low;
}
}
// The operator can call this method once they receive the event "RandomNumberCreated"
// triggered by the VRF v1 consumer contract (RandomNumber.sol)
/// @param _raffleId Id of the raffle
/// @param _normalizedRandomNumber index of the array that contains the winner of the raffle. Generated by chainlink
/// @notice it is the method that sets the winner and transfers funds and nft
/// @dev called by Chainlink callback
function transferPrizesAndFunds(
uint256 _raffleId,
uint256 _normalizedRandomNumber
) internal {
RaffleStruct storage raffle = raffles[_raffleId];
EntryInfoStruct storage entryInfo = rafflesEntryInfo[_raffleId];
// Only when the raffle has been asked to be closed and the platform
require(
entryInfo.status == STATUS.EARLY_CASHOUT ||
entryInfo.status == STATUS.CLOSING_REQUESTED,
"Raffle in wrong status"
);
raffle.randomNumber = _normalizedRandomNumber;
raffle.winner = getWinnerAddressFromRandom(
_raffleId,
_normalizedRandomNumber
);
entryInfo.status = STATUS.ENDED;
// send the ETH to the winner
(bool sentPrize, ) = raffle.winner.call{value: raffle.prizeNumber}("");
require(sentPrize, "Failed to send Ether");
uint256 amountForPlatform = (entryInfo.amountRaised *
raffle.platformPercentage) / 10000;
uint256 amountForSeller = entryInfo.amountRaised - amountForPlatform;
// transfer amount (75%) to the seller.
(bool sent, ) = raffle.seller.call{value: amountForSeller}("");
require(sent, "Failed to send Ether");
// transfer the amount to the platform
(bool sent2, ) = destinationWallet.call{value: amountForPlatform}("");
require(sent2, "Failed send Eth to MW");
emit FeeTransferredToPlatform(_raffleId, amountForPlatform);
emit RaffleEnded(
_raffleId,
raffle.winner,
entryInfo.amountRaised,
_normalizedRandomNumber
);
}
function setCashOutActions(
uint256 _raffleId
) internal returns (EntryInfoStruct memory) {
RaffleStruct memory raffle = raffles[_raffleId];
EntryInfoStruct storage entryInfo = rafflesEntryInfo[_raffleId];
FundingStructure memory funding = fundingList[_raffleId];
require(raffle.seller == msg.sender, "Not the seller");
// Check if the raffle is already accepted
require(
entryInfo.status == STATUS.ACCEPTED,
"Raffle not in accepted status"
);
require(
entryInfo.amountRaised >= funding.minimumFundsInWeis,
"Not enough funds raised"
);
entryInfo.status = STATUS.EARLY_CASHOUT;
emit EarlyCashoutTriggered(_raffleId, entryInfo.amountRaised);
return entryInfo;
}
// can be called by the seller at every moment once enough funds has been raised
/// @param _raffleId Id of the raffle
/// @notice the seller of the nft, if the minimum amount has been reached, can call an early cashout, finishing the raffle
/// @dev it triggers Chainlink VRF1 consumer, and generates a random number that is normalized and checked that corresponds to a MW player
function earlyCashOut(uint256 _raffleId) external {
EntryInfoStruct memory raffle = setWinnerActions(_raffleId);
bytes32 requestId = callVRFAndGetRequestId();
getRandomNumber(_raffleId, raffle.entriesLength, requestId);
}
function setWinnerActions(
uint256 _raffleId
) internal returns (EntryInfoStruct memory) {
EntryInfoStruct storage entryInfo = rafflesEntryInfo[_raffleId];
// RaffleStruct storage raffle = raffles[_raffleId];
FundingStructure storage funding = fundingList[_raffleId];
// Check if the raffle is already accepted or is called again because early cashout failed
require(entryInfo.status == STATUS.ACCEPTED, "Raffle in wrong status");
require(
entryInfo.amountRaised >= funding.minimumFundsInWeis,
"Not enough funds raised"
);
require(
funding.desiredFundsInWeis <= entryInfo.amountRaised,
"Desired funds not raised"
);
entryInfo.status = STATUS.CLOSING_REQUESTED;
emit SetWinnerTriggered(_raffleId, entryInfo.amountRaised);
return entryInfo;
}
/// @param _raffleId Id of the raffle
/// @notice the operator finish the raffle, if the desired funds has been reached
/// @dev it triggers Chainlink VRF1 consumer, and generates a random number that is normalized and checked that corresponds to a MW player
function setWinner(uint256 _raffleId) external onlyRole(OPERATOR_ROLE) {
EntryInfoStruct memory raffle = setWinnerActions(_raffleId);
// this call trigers the VRF v1 process from Chainlink
bytes32 requestId = callVRFAndGetRequestId();
getRandomNumber(_raffleId, raffle.entriesLength, requestId);
}
/// @param _newAddress new address of the platform
/// @dev Change the wallet of the platform. The one that will receive the platform fee when the raffle is closed.
/// Only the admin can change this
function setDestinationAddress(
address payable _newAddress
) external onlyRole(DEFAULT_ADMIN_ROLE) {
destinationWallet = _newAddress;
}
/// @param _raffleId Id of the raffle
/// @dev The operator can cancel the raffle. The NFT is sent back to the seller
/// The raised funds are send to the destination wallet. The buyers will
/// be refunded offchain in the metawin wallet
function cancelRaffle(uint256 _raffleId) external onlyRole(OPERATOR_ROLE) {
RaffleStruct storage raffle = raffles[_raffleId];
EntryInfoStruct storage entryInfo = rafflesEntryInfo[_raffleId];
// Dont cancel twice, or cancel an already ended raffle
require(
entryInfo.status != STATUS.ENDED &&
entryInfo.status != STATUS.CANCELLED &&
entryInfo.status != STATUS.EARLY_CASHOUT &&
entryInfo.status != STATUS.CLOSING_REQUESTED &&
entryInfo.status != STATUS.CANCEL_REQUESTED,
"Wrong status"
);
// only if the raffle is in accepted status the ETH is staked and could have entries sold
if (entryInfo.status == STATUS.ACCEPTED) {
// transfer ETH to the owner
(bool sentPrize, ) = raffle.seller.call{value: raffle.prizeNumber}(
""
);
require(sentPrize, "Failed to send Ether");
}
entryInfo.status = STATUS.CANCEL_REQUESTED;
emit RaffleCancelled(_raffleId, entryInfo.amountRaised);
}
/// @param _raffleId Id of the raffle
function transferRemainingFunds(
uint256 _raffleId
) external onlyRole(OPERATOR_ROLE) {
EntryInfoStruct storage entryInfo = rafflesEntryInfo[_raffleId];
require(
entryInfo.status == STATUS.CANCEL_REQUESTED ||
entryInfo.status == STATUS.CANCELLED,
"Wrong status"
);
entryInfo.status = STATUS.CANCELLED;
(bool sent, ) = destinationWallet.call{value: entryInfo.amountRaised}(
""
);
require(sent, "Fail send Eth to MW");
emit RemainingFundsTransferred(_raffleId, entryInfo.amountRaised);
entryInfo.amountRaised = 0;
}
/// @param _raffleId Id of the raffle
/// @return array of entries bougth of that particular raffle
function getEntriesBought(
uint256 _raffleId
) external view returns (EntriesBought[] memory) {
return entriesList[_raffleId];
}
/// @dev for different reasons player entries should be void
/// this has a cost in gas, but this makes cheaper in gas the callback from chainlink
/// This method has to be called for every raffle of the blacklisted player
/// @param _raffleId Id of the raffle
/// @param entriesToCancel array that contains the index of the entries to cancel. 0 based
/// @param _player player who owns the entry to be voided
function cancelEntry(
uint256 _raffleId,
uint256[] calldata entriesToCancel,
address _player
) external onlyRole(OPERATOR_ROLE) {
uint256 totalEntriesBoughtCancelled = 0;
for (uint256 i = 0; i < entriesToCancel.length; i++) {
EntriesBought storage entry = entriesList[_raffleId][
entriesToCancel[i] + 1
];
require(entry.player == _player, "Entry did not belong to player");
entry.player = address(0);
uint256 previousTotalEntriesLength;
if (entriesToCancel[i] == 0) previousTotalEntriesLength = 0;
else
previousTotalEntriesLength = entriesList[_raffleId][
entriesToCancel[i] /* - 1*/
].currentEntriesLength;
totalEntriesBoughtCancelled +=
entry.currentEntriesLength -
previousTotalEntriesLength;
}
emit EntryCancelled(_raffleId, totalEntriesBoughtCancelled, _player);
}
// Requested by Valerio Di Napoli.
/// @param _raffleId id of the raffle
/// @param _amountOfEntries amount of entries. Must be lower than maxEntriesPerUser
/// @param _player The address of the player
/// @notice Called by other contract created by Valerio, that minted an NFT and after that call this method
/// @dev add entries but they are free so no payable
function createFreeEntriesFromExternalContract(
uint256 _raffleId,
uint48 _amountOfEntries,
address _player
) external onlyRole(MINTERCONTRACT_ROLE) {
// if can buy run this code.
EntryInfoStruct storage entryInfo = rafflesEntryInfo[_raffleId];
require(
entryInfo.entryType == ENTRY_TYPE.ONLY_EXTERNAL_CONTRACT ||
entryInfo.entryType == ENTRY_TYPE.MIXED,
"Entry type not allowed"
);
EntriesBought memory entryBought = EntriesBought({
player: _player,
currentEntriesLength: entryInfo.entriesLength + _amountOfEntries
});
entriesList[_raffleId].push(entryBought);
// update the field entriesLength.
entryInfo.entriesLength += _amountOfEntries;
address[] memory players = new address[](1);
players[0] = _player;
emit FreeEntry(
_raffleId,
players,
_amountOfEntries,
entryInfo.entriesLength
);
}
function getRafflesEntryInfo(
uint256 _raffleId
) public view returns (EntryInfoStruct memory) {
return rafflesEntryInfo[_raffleId];
}
function playerIsBlacklisted(address _player) external pure returns (bool) {
// return blackListManager.isBlackListed(_player);
return false;
}
function raffleNotInAcceptedState(
uint256 _raffleId
) external view returns (bool) {
EntryInfoStruct memory entryInfo = rafflesEntryInfo[_raffleId];
return (entryInfo.status != STATUS.ACCEPTED);
}
function playerIsSeller(
address _player,
uint256 _raffleId
) external view returns (bool) {
RaffleStruct memory raffle = raffles[_raffleId];
return (raffle.seller == _player);
}
function playerReachedMaxEntries(
address _player,
uint256 _raffleId,
uint256 _amountOfEntries
) external pure returns (bool) {
return false;
}
/* Requested by Valerio Di Napoli.
@param _player The address of the player
@param _raffleId id of the raffle
@param _colection Address of the required collection, if any
@param _tokenIdUsed Id of the token of the required collection the player says he has and want to use in the raffle
@returns bool if the player can buy or not, and string with the cause of the rejection. "" if can buy
@notice Method that returns if the user can or cannot buy entries because the player owns an nft in the case or required collections.
*/
function playerHasRequiredNFTs(
address _player,
uint256 _raffleId,
address _collection,
uint256 _tokenIdUsed
) external pure returns (bool canBuy, string memory cause) {
return (true, "");
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (utils/math/Math.sol)
pragma solidity ^0.8.0;
/**
* @dev Standard math utilities missing in the Solidity language.
*/
library Math {
enum Rounding {
Down, // Toward negative infinity
Up, // Toward infinity
Zero // Toward zero
}
/**
* @dev Returns the largest of two numbers.
*/
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a >= b ? a : b;
}
/**
* @dev Returns the smallest of two numbers.
*/
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two numbers. The result is rounded towards
* zero.
*/
function average(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b) / 2 can overflow.
return (a & b) + (a ^ b) / 2;
}
/**
* @dev Returns the ceiling of the division of two numbers.
*
* This differs from standard division with `/` in that it rounds up instead
* of rounding down.
*/
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b - 1) / b can overflow on addition, so we distribute.
return a == 0 ? 0 : (a - 1) / b + 1;
}
/**
* @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
* @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
* with further edits by Uniswap Labs also under MIT license.
*/
function mulDiv(
uint256 x,
uint256 y,
uint256 denominator
) internal pure returns (uint256 result) {
unchecked {
// 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
// use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
// variables such that product = prod1 * 2^256 + prod0.
uint256 prod0; // Least significant 256 bits of the product
uint256 prod1; // Most significant 256 bits of the product
assembly {
let mm := mulmod(x, y, not(0))
prod0 := mul(x, y)
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
// Handle non-overflow cases, 256 by 256 division.
if (prod1 == 0) {
return prod0 / denominator;
}
// Make sure the result is less than 2^256. Also prevents denominator == 0.
require(denominator > prod1);
///////////////////////////////////////////////
// 512 by 256 division.
///////////////////////////////////////////////
// Make division exact by subtracting the remainder from [prod1 prod0].
uint256 remainder;
assembly {
// Compute remainder using mulmod.
remainder := mulmod(x, y, denominator)
// Subtract 256 bit number from 512 bit number.
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
// Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
// See https://cs.stackexchange.com/q/138556/92363.
// Does not overflow because the denominator cannot be zero at this stage in the function.
uint256 twos = denominator & (~denominator + 1);
assembly {
// Divide denominator by twos.
denominator := div(denominator, twos)
// Divide [prod1 prod0] by twos.
prod0 := div(prod0, twos)
// Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
twos := add(div(sub(0, twos), twos), 1)
}
// Shift in bits from prod1 into prod0.
prod0 |= prod1 * twos;
// Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
// that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
// four bits. That is, denominator * inv = 1 mod 2^4.
uint256 inverse = (3 * denominator) ^ 2;
// Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
// in modular arithmetic, doubling the correct bits in each step.
inverse *= 2 - denominator * inverse; // inverse mod 2^8
inverse *= 2 - denominator * inverse; // inverse mod 2^16
inverse *= 2 - denominator * inverse; // inverse mod 2^32
inverse *= 2 - denominator * inverse; // inverse mod 2^64
inverse *= 2 - denominator * inverse; // inverse mod 2^128
inverse *= 2 - denominator * inverse; // inverse mod 2^256
// Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
// This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
// less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
// is no longer required.
result = prod0 * inverse;
return result;
}
}
/**
* @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
*/
function mulDiv(
uint256 x,
uint256 y,
uint256 denominator,
Rounding rounding
) internal pure returns (uint256) {
uint256 result = mulDiv(x, y, denominator);
if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
result += 1;
}
return result;
}
/**
* @dev Returns the square root of a number. It the number is not a perfect square, the value is rounded down.
*
* Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
*/
function sqrt(uint256 a) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
// For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
// We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
// `msb(a) <= a < 2*msb(a)`.
// We also know that `k`, the position of the most significant bit, is such that `msb(a) = 2**k`.
// This gives `2**k < a <= 2**(k+1)` → `2**(k/2) <= sqrt(a) < 2 ** (k/2+1)`.
// Using an algorithm similar to the msb conmputation, we are able to compute `result = 2**(k/2)` which is a
// good first aproximation of `sqrt(a)` with at least 1 correct bit.
uint256 result = 1;
uint256 x = a;
if (x >> 128 > 0) {
x >>= 128;
result <<= 64;
}
if (x >> 64 > 0) {
x >>= 64;
result <<= 32;
}
if (x >> 32 > 0) {
x >>= 32;
result <<= 16;
}
if (x >> 16 > 0) {
x >>= 16;
result <<= 8;
}
if (x >> 8 > 0) {
x >>= 8;
result <<= 4;
}
if (x >> 4 > 0) {
x >>= 4;
result <<= 2;
}
if (x >> 2 > 0) {
result <<= 1;
}
// At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
// since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
// every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
// into the expected uint128 result.
unchecked {
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
return min(result, a / result);
}
}
/**
* @notice Calculates sqrt(a), following the selected rounding direction.
*/
function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
uint256 result = sqrt(a);
if (rounding == Rounding.Up && result * result < a) {
result += 1;
}
return result;
}
}// 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 (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.7.0) (utils/Strings.sol)
pragma solidity ^0.8.0;
/**
* @dev String operations.
*/
library Strings {
bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";
uint8 private constant _ADDRESS_LENGTH = 20;
/**
* @dev Converts a `uint256` to its ASCII `string` decimal representation.
*/
function toString(uint256 value) internal pure returns (string memory) {
// Inspired by OraclizeAPI's implementation - MIT licence
// https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol
if (value == 0) {
return "0";
}
uint256 temp = value;
uint256 digits;
while (temp != 0) {
digits++;
temp /= 10;
}
bytes memory buffer = new bytes(digits);
while (value != 0) {
digits -= 1;
buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
value /= 10;
}
return string(buffer);
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
*/
function toHexString(uint256 value) internal pure returns (string memory) {
if (value == 0) {
return "0x00";
}
uint256 temp = value;
uint256 length = 0;
while (temp != 0) {
length++;
temp >>= 8;
}
return toHexString(value, length);
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
*/
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = _HEX_SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
/**
* @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.
*/
function toHexString(address addr) internal pure returns (string memory) {
return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
pragma solidity ^0.8.0;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)
pragma solidity ^0.8.0;
/**
* @dev External interface of AccessControl declared to support ERC165 detection.
*/
interface IAccessControl {
/**
* @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
*
* `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
* {RoleAdminChanged} not being emitted signaling this.
*
* _Available since v3.1._
*/
event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);
/**
* @dev Emitted when `account` is granted `role`.
*
* `sender` is the account that originated the contract call, an admin role
* bearer except when using {AccessControl-_setupRole}.
*/
event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Emitted when `account` is revoked `role`.
*
* `sender` is the account that originated the contract call:
* - if using `revokeRole`, it is the admin role bearer
* - if using `renounceRole`, it is the role bearer (i.e. `account`)
*/
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) external view returns (bool);
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {AccessControl-_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) external view returns (bytes32);
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function grantRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function revokeRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from the calling account.
*
* Roles are often managed via {grantRole} and {revokeRole}: this function's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* If the calling account had been granted `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `account`.
*/
function renounceRole(bytes32 role, address account) external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (access/AccessControl.sol)
pragma solidity ^0.8.0;
import "./IAccessControl.sol";
import "../utils/Context.sol";
import "../utils/Strings.sol";
import "../utils/introspection/ERC165.sol";
/**
* @dev Contract module that allows children to implement role-based access
* control mechanisms. This is a lightweight version that doesn't allow enumerating role
* members except through off-chain means by accessing the contract event logs. Some
* applications may benefit from on-chain enumerability, for those cases see
* {AccessControlEnumerable}.
*
* Roles are referred to by their `bytes32` identifier. These should be exposed
* in the external API and be unique. The best way to achieve this is by
* using `public constant` hash digests:
*
* ```
* bytes32 public constant MY_ROLE = keccak256("MY_ROLE");
* ```
*
* Roles can be used to represent a set of permissions. To restrict access to a
* function call, use {hasRole}:
*
* ```
* function foo() public {
* require(hasRole(MY_ROLE, msg.sender));
* ...
* }
* ```
*
* Roles can be granted and revoked dynamically via the {grantRole} and
* {revokeRole} functions. Each role has an associated admin role, and only
* accounts that have a role's admin role can call {grantRole} and {revokeRole}.
*
* By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means
* that only accounts with this role will be able to grant or revoke other
* roles. More complex role relationships can be created by using
* {_setRoleAdmin}.
*
* WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to
* grant and revoke this role. Extra precautions should be taken to secure
* accounts that have been granted it.
*/
abstract contract AccessControl is Context, IAccessControl, ERC165 {
struct RoleData {
mapping(address => bool) members;
bytes32 adminRole;
}
mapping(bytes32 => RoleData) private _roles;
bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;
/**
* @dev Modifier that checks that an account has a specific role. Reverts
* with a standardized message including the required role.
*
* The format of the revert reason is given by the following regular expression:
*
* /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
*
* _Available since v4.1._
*/
modifier onlyRole(bytes32 role) {
_checkRole(role);
_;
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);
}
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) public view virtual override returns (bool) {
return _roles[role].members[account];
}
/**
* @dev Revert with a standard message if `_msgSender()` is missing `role`.
* Overriding this function changes the behavior of the {onlyRole} modifier.
*
* Format of the revert message is described in {_checkRole}.
*
* _Available since v4.6._
*/
function _checkRole(bytes32 role) internal view virtual {
_checkRole(role, _msgSender());
}
/**
* @dev Revert with a standard message if `account` is missing `role`.
*
* The format of the revert reason is given by the following regular expression:
*
* /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
*/
function _checkRole(bytes32 role, address account) internal view virtual {
if (!hasRole(role, account)) {
revert(
string(
abi.encodePacked(
"AccessControl: account ",
Strings.toHexString(uint160(account), 20),
" is missing role ",
Strings.toHexString(uint256(role), 32)
)
)
);
}
}
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) {
return _roles[role].adminRole;
}
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*
* May emit a {RoleGranted} event.
*/
function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
_grantRole(role, account);
}
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*
* May emit a {RoleRevoked} event.
*/
function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
_revokeRole(role, account);
}
/**
* @dev Revokes `role` from the calling account.
*
* Roles are often managed via {grantRole} and {revokeRole}: this function's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* If the calling account had been revoked `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `account`.
*
* May emit a {RoleRevoked} event.
*/
function renounceRole(bytes32 role, address account) public virtual override {
require(account == _msgSender(), "AccessControl: can only renounce roles for self");
_revokeRole(role, account);
}
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event. Note that unlike {grantRole}, this function doesn't perform any
* checks on the calling account.
*
* May emit a {RoleGranted} event.
*
* [WARNING]
* ====
* This function should only be called from the constructor when setting
* up the initial roles for the system.
*
* Using this function in any other way is effectively circumventing the admin
* system imposed by {AccessControl}.
* ====
*
* NOTE: This function is deprecated in favor of {_grantRole}.
*/
function _setupRole(bytes32 role, address account) internal virtual {
_grantRole(role, account);
}
/**
* @dev Sets `adminRole` as ``role``'s admin role.
*
* Emits a {RoleAdminChanged} event.
*/
function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
bytes32 previousAdminRole = getRoleAdmin(role);
_roles[role].adminRole = adminRole;
emit RoleAdminChanged(role, previousAdminRole, adminRole);
}
/**
* @dev Grants `role` to `account`.
*
* Internal function without access restriction.
*
* May emit a {RoleGranted} event.
*/
function _grantRole(bytes32 role, address account) internal virtual {
if (!hasRole(role, account)) {
_roles[role].members[account] = true;
emit RoleGranted(role, account, _msgSender());
}
}
/**
* @dev Revokes `role` from `account`.
*
* Internal function without access restriction.
*
* May emit a {RoleRevoked} event.
*/
function _revokeRole(bytes32 role, address account) internal virtual {
if (hasRole(role, account)) {
_roles[role].members[account] = false;
emit RoleRevoked(role, account, _msgSender());
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface LinkTokenInterface {
function allowance(address owner, address spender) external view returns (uint256 remaining);
function approve(address spender, uint256 value) external returns (bool success);
function balanceOf(address owner) external view returns (uint256 balance);
function decimals() external view returns (uint8 decimalPlaces);
function decreaseApproval(address spender, uint256 addedValue) external returns (bool success);
function increaseApproval(address spender, uint256 subtractedValue) external;
function name() external view returns (string memory tokenName);
function symbol() external view returns (string memory tokenSymbol);
function totalSupply() external view returns (uint256 totalTokensIssued);
function transfer(address to, uint256 value) external returns (bool success);
function transferAndCall(
address to,
uint256 value,
bytes calldata data
) external returns (bool success);
function transferFrom(
address from,
address to,
uint256 value
) external returns (bool success);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract VRFRequestIDBase {
/**
* @notice returns the seed which is actually input to the VRF coordinator
*
* @dev To prevent repetition of VRF output due to repetition of the
* @dev user-supplied seed, that seed is combined in a hash with the
* @dev user-specific nonce, and the address of the consuming contract. The
* @dev risk of repetition is mostly mitigated by inclusion of a blockhash in
* @dev the final seed, but the nonce does protect against repetition in
* @dev requests which are included in a single block.
*
* @param _userSeed VRF seed input provided by user
* @param _requester Address of the requesting contract
* @param _nonce User-specific nonce at the time of the request
*/
function makeVRFInputSeed(
bytes32 _keyHash,
uint256 _userSeed,
address _requester,
uint256 _nonce
) internal pure returns (uint256) {
return uint256(keccak256(abi.encode(_keyHash, _userSeed, _requester, _nonce)));
}
/**
* @notice Returns the id for this request
* @param _keyHash The serviceAgreement ID to be used for this request
* @param _vRFInputSeed The seed to be passed directly to the VRF
* @return The id for this request
*
* @dev Note that _vRFInputSeed is not the seed passed by the consuming
* @dev contract, but the one generated by makeVRFInputSeed
*/
function makeRequestId(bytes32 _keyHash, uint256 _vRFInputSeed) internal pure returns (bytes32) {
return keccak256(abi.encodePacked(_keyHash, _vRFInputSeed));
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./interfaces/LinkTokenInterface.sol";
import "./VRFRequestIDBase.sol";
/** ****************************************************************************
* @notice Interface for contracts using VRF randomness
* *****************************************************************************
* @dev PURPOSE
*
* @dev Reggie the Random Oracle (not his real job) wants to provide randomness
* @dev to Vera the verifier in such a way that Vera can be sure he's not
* @dev making his output up to suit himself. Reggie provides Vera a public key
* @dev to which he knows the secret key. Each time Vera provides a seed to
* @dev Reggie, he gives back a value which is computed completely
* @dev deterministically from the seed and the secret key.
*
* @dev Reggie provides a proof by which Vera can verify that the output was
* @dev correctly computed once Reggie tells it to her, but without that proof,
* @dev the output is indistinguishable to her from a uniform random sample
* @dev from the output space.
*
* @dev The purpose of this contract is to make it easy for unrelated contracts
* @dev to talk to Vera the verifier about the work Reggie is doing, to provide
* @dev simple access to a verifiable source of randomness.
* *****************************************************************************
* @dev USAGE
*
* @dev Calling contracts must inherit from VRFConsumerBase, and can
* @dev initialize VRFConsumerBase's attributes in their constructor as
* @dev shown:
*
* @dev contract VRFConsumer {
* @dev constructor(<other arguments>, address _vrfCoordinator, address _link)
* @dev VRFConsumerBase(_vrfCoordinator, _link) public {
* @dev <initialization with other arguments goes here>
* @dev }
* @dev }
*
* @dev The oracle will have given you an ID for the VRF keypair they have
* @dev committed to (let's call it keyHash), and have told you the minimum LINK
* @dev price for VRF service. Make sure your contract has sufficient LINK, and
* @dev call requestRandomness(keyHash, fee, seed), where seed is the input you
* @dev want to generate randomness from.
*
* @dev Once the VRFCoordinator has received and validated the oracle's response
* @dev to your request, it will call your contract's fulfillRandomness method.
*
* @dev The randomness argument to fulfillRandomness is the actual random value
* @dev generated from your seed.
*
* @dev The requestId argument is generated from the keyHash and the seed by
* @dev makeRequestId(keyHash, seed). If your contract could have concurrent
* @dev requests open, you can use the requestId to track which seed is
* @dev associated with which randomness. See VRFRequestIDBase.sol for more
* @dev details. (See "SECURITY CONSIDERATIONS" for principles to keep in mind,
* @dev if your contract could have multiple requests in flight simultaneously.)
*
* @dev Colliding `requestId`s are cryptographically impossible as long as seeds
* @dev differ. (Which is critical to making unpredictable randomness! See the
* @dev next section.)
*
* *****************************************************************************
* @dev SECURITY CONSIDERATIONS
*
* @dev A method with the ability to call your fulfillRandomness method directly
* @dev could spoof a VRF response with any random value, so it's critical that
* @dev it cannot be directly called by anything other than this base contract
* @dev (specifically, by the VRFConsumerBase.rawFulfillRandomness method).
*
* @dev For your users to trust that your contract's random behavior is free
* @dev from malicious interference, it's best if you can write it so that all
* @dev behaviors implied by a VRF response are executed *during* your
* @dev fulfillRandomness method. If your contract must store the response (or
* @dev anything derived from it) and use it later, you must ensure that any
* @dev user-significant behavior which depends on that stored value cannot be
* @dev manipulated by a subsequent VRF request.
*
* @dev Similarly, both miners and the VRF oracle itself have some influence
* @dev over the order in which VRF responses appear on the blockchain, so if
* @dev your contract could have multiple VRF requests in flight simultaneously,
* @dev you must ensure that the order in which the VRF responses arrive cannot
* @dev be used to manipulate your contract's user-significant behavior.
*
* @dev Since the ultimate input to the VRF is mixed with the block hash of the
* @dev block in which the request is made, user-provided seeds have no impact
* @dev on its economic security properties. They are only included for API
* @dev compatability with previous versions of this contract.
*
* @dev Since the block hash of the block which contains the requestRandomness
* @dev call is mixed into the input to the VRF *last*, a sufficiently powerful
* @dev miner could, in principle, fork the blockchain to evict the block
* @dev containing the request, forcing the request to be included in a
* @dev different block with a different hash, and therefore a different input
* @dev to the VRF. However, such an attack would incur a substantial economic
* @dev cost. This cost scales with the number of blocks the VRF oracle waits
* @dev until it calls responds to a request.
*/
abstract contract VRFConsumerBase is VRFRequestIDBase {
/**
* @notice fulfillRandomness handles the VRF response. Your contract must
* @notice implement it. See "SECURITY CONSIDERATIONS" above for important
* @notice principles to keep in mind when implementing your fulfillRandomness
* @notice method.
*
* @dev VRFConsumerBase expects its subcontracts to have a method with this
* @dev signature, and will call it once it has verified the proof
* @dev associated with the randomness. (It is triggered via a call to
* @dev rawFulfillRandomness, below.)
*
* @param requestId The Id initially returned by requestRandomness
* @param randomness the VRF output
*/
function fulfillRandomness(bytes32 requestId, uint256 randomness) internal virtual;
/**
* @dev In order to keep backwards compatibility we have kept the user
* seed field around. We remove the use of it because given that the blockhash
* enters later, it overrides whatever randomness the used seed provides.
* Given that it adds no security, and can easily lead to misunderstandings,
* we have removed it from usage and can now provide a simpler API.
*/
uint256 private constant USER_SEED_PLACEHOLDER = 0;
/**
* @notice requestRandomness initiates a request for VRF output given _seed
*
* @dev The fulfillRandomness method receives the output, once it's provided
* @dev by the Oracle, and verified by the vrfCoordinator.
*
* @dev The _keyHash must already be registered with the VRFCoordinator, and
* @dev the _fee must exceed the fee specified during registration of the
* @dev _keyHash.
*
* @dev The _seed parameter is vestigial, and is kept only for API
* @dev compatibility with older versions. It can't *hurt* to mix in some of
* @dev your own randomness, here, but it's not necessary because the VRF
* @dev oracle will mix the hash of the block containing your request into the
* @dev VRF seed it ultimately uses.
*
* @param _keyHash ID of public key against which randomness is generated
* @param _fee The amount of LINK to send with the request
*
* @return requestId unique ID for this request
*
* @dev The returned requestId can be used to distinguish responses to
* @dev concurrent requests. It is passed as the first argument to
* @dev fulfillRandomness.
*/
function requestRandomness(bytes32 _keyHash, uint256 _fee) internal returns (bytes32 requestId) {
LINK.transferAndCall(vrfCoordinator, _fee, abi.encode(_keyHash, USER_SEED_PLACEHOLDER));
// This is the seed passed to VRFCoordinator. The oracle will mix this with
// the hash of the block containing this request to obtain the seed/input
// which is finally passed to the VRF cryptographic machinery.
uint256 vRFSeed = makeVRFInputSeed(_keyHash, USER_SEED_PLACEHOLDER, address(this), nonces[_keyHash]);
// nonces[_keyHash] must stay in sync with
// VRFCoordinator.nonces[_keyHash][this], which was incremented by the above
// successful LINK.transferAndCall (in VRFCoordinator.randomnessRequest).
// This provides protection against the user repeating their input seed,
// which would result in a predictable/duplicate output, if multiple such
// requests appeared in the same block.
nonces[_keyHash] = nonces[_keyHash] + 1;
return makeRequestId(_keyHash, vRFSeed);
}
LinkTokenInterface internal immutable LINK;
address private immutable vrfCoordinator;
// Nonces for each VRF key from which randomness has been requested.
//
// Must stay in sync with VRFCoordinator[_keyHash][this]
mapping(bytes32 => uint256) /* keyHash */ /* nonce */
private nonces;
/**
* @param _vrfCoordinator address of VRFCoordinator contract
* @param _link address of LINK token contract
*
* @dev https://docs.chain.link/docs/link-token-contracts
*/
constructor(address _vrfCoordinator, address _link) {
vrfCoordinator = _vrfCoordinator;
LINK = LinkTokenInterface(_link);
}
// rawFulfillRandomness is called by VRFCoordinator when it receives a valid VRF
// proof. rawFulfillRandomness then calls fulfillRandomness, after validating
// the origin of the call
function rawFulfillRandomness(bytes32 requestId, uint256 randomness) external {
require(msg.sender == vrfCoordinator, "Only VRFCoordinator can fulfill");
fulfillRandomness(requestId, randomness);
}
}{
"remappings": [],
"optimizer": {
"enabled": true,
"runs": 200
},
"evmVersion": "istanbul",
"libraries": {},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_vrfCoordinator","type":"address"},{"internalType":"address","name":"_linkToken","type":"address"},{"internalType":"bytes32","name":"_keyHash","type":"bytes32"},{"internalType":"bool","name":"_mainetFee","type":"bool"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"string","name":"errorType","type":"string"}],"name":"EntryNotAllowed","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"raffleId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountRaised","type":"uint256"}],"name":"EarlyCashoutTriggered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"raffleId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountOfEntriesCanceled","type":"uint256"},{"indexed":false,"internalType":"address","name":"player","type":"address"}],"name":"EntryCancelled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"raffleId","type":"uint256"},{"indexed":true,"internalType":"address","name":"buyer","type":"address"},{"indexed":false,"internalType":"uint256","name":"currentSize","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"priceStructureId","type":"uint256"}],"name":"EntrySold","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"raffleId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountTransferred","type":"uint256"}],"name":"FeeTransferredToPlatform","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"raffleId","type":"uint256"},{"indexed":false,"internalType":"address[]","name":"buyer","type":"address[]"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"currentSize","type":"uint256"}],"name":"FreeEntry","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"raffleId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountRaised","type":"uint256"}],"name":"RaffleCancelled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"raffleId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"nftId","type":"uint256"}],"name":"RaffleCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"raffleId","type":"uint256"},{"indexed":true,"internalType":"address","name":"winner","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountRaised","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"randomNumber","type":"uint256"}],"name":"RaffleEnded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"raffleId","type":"uint256"},{"indexed":true,"internalType":"address","name":"seller","type":"address"}],"name":"RaffleStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"idFromMetawin","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"randomNumber","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"normalizedRandomNumber","type":"uint256"}],"name":"RandomNumberCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"raffleId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountInWeis","type":"uint256"},{"indexed":true,"internalType":"address","name":"player","type":"address"}],"name":"Refund","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"raffleId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountInWeis","type":"uint256"}],"name":"RemainingFundsTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"raffleId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountRaised","type":"uint256"}],"name":"SetWinnerTriggered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"raffleId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newStatus","type":"uint256"}],"name":"StatusChangedInEmergency","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MINTERCONTRACT_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"OPERATOR_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_raffleId","type":"uint256"},{"internalType":"uint256","name":"_id","type":"uint256"}],"name":"buyEntry","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_raffleId","type":"uint256"},{"internalType":"uint256[]","name":"entriesToCancel","type":"uint256[]"},{"internalType":"address","name":"_player","type":"address"}],"name":"cancelEntry","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_raffleId","type":"uint256"}],"name":"cancelRaffle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"chainlinkRaffleInfo","outputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"size","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_raffleId","type":"uint256"},{"internalType":"uint48","name":"_amountOfEntries","type":"uint48"},{"internalType":"address","name":"_player","type":"address"}],"name":"createFreeEntriesFromExternalContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint128","name":"_desiredFundsInWeis","type":"uint128"},{"internalType":"uint256","name":"_prizeNumber","type":"uint256"},{"internalType":"uint128","name":"_minimumFundsInWeis","type":"uint128"},{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint48","name":"numEntries","type":"uint48"},{"internalType":"uint256","name":"price","type":"uint256"}],"internalType":"struct ETHFixedLean.PriceStructure[]","name":"_prices","type":"tuple[]"},{"internalType":"uint48","name":"_commissionInBasicPoints","type":"uint48"},{"internalType":"enum ETHFixedLean.ENTRY_TYPE","name":"_entryType","type":"uint8"}],"name":"createRaffle","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"destinationWallet","outputs":[{"internalType":"address payable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_raffleId","type":"uint256"}],"name":"earlyCashOut","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"entriesList","outputs":[{"internalType":"uint48","name":"currentEntriesLength","type":"uint48"},{"internalType":"address","name":"player","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"fundingList","outputs":[{"internalType":"uint128","name":"minimumFundsInWeis","type":"uint128"},{"internalType":"uint128","name":"desiredFundsInWeis","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_raffleId","type":"uint256"}],"name":"getEntriesBought","outputs":[{"components":[{"internalType":"uint48","name":"currentEntriesLength","type":"uint48"},{"internalType":"address","name":"player","type":"address"}],"internalType":"struct ETHFixedLean.EntriesBought[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_raffleId","type":"uint256"}],"name":"getRafflesEntryInfo","outputs":[{"components":[{"internalType":"enum ETHFixedLean.STATUS","name":"status","type":"uint8"},{"internalType":"enum ETHFixedLean.ENTRY_TYPE","name":"entryType","type":"uint8"},{"internalType":"uint48","name":"entriesLength","type":"uint48"},{"internalType":"uint128","name":"amountRaised","type":"uint128"}],"internalType":"struct ETHFixedLean.EntryInfoStruct","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_raffleId","type":"uint256"},{"internalType":"uint256","name":"_normalizedRandomNumber","type":"uint256"}],"name":"getWinnerAddressFromRandom","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_raffleId","type":"uint256"},{"internalType":"address[]","name":"_freePlayers","type":"address[]"}],"name":"giveBatchEntriesForFree","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_player","type":"address"},{"internalType":"uint256","name":"_raffleId","type":"uint256"},{"internalType":"address","name":"_collection","type":"address"},{"internalType":"uint256","name":"_tokenIdUsed","type":"uint256"}],"name":"playerHasRequiredNFTs","outputs":[{"internalType":"bool","name":"canBuy","type":"bool"},{"internalType":"string","name":"cause","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"_player","type":"address"}],"name":"playerIsBlacklisted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"_player","type":"address"},{"internalType":"uint256","name":"_raffleId","type":"uint256"}],"name":"playerIsSeller","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_player","type":"address"},{"internalType":"uint256","name":"_raffleId","type":"uint256"},{"internalType":"uint256","name":"_amountOfEntries","type":"uint256"}],"name":"playerReachedMaxEntries","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"pricesList","outputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint48","name":"numEntries","type":"uint48"},{"internalType":"uint256","name":"price","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_raffleId","type":"uint256"}],"name":"raffleNotInAcceptedState","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"raffles","outputs":[{"internalType":"uint48","name":"platformPercentage","type":"uint48"},{"internalType":"uint256","name":"prizeNumber","type":"uint256"},{"internalType":"address","name":"winner","type":"address"},{"internalType":"address","name":"seller","type":"address"},{"internalType":"uint256","name":"randomNumber","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"rafflesEntryInfo","outputs":[{"internalType":"enum ETHFixedLean.STATUS","name":"status","type":"uint8"},{"internalType":"enum ETHFixedLean.ENTRY_TYPE","name":"entryType","type":"uint8"},{"internalType":"uint48","name":"entriesLength","type":"uint48"},{"internalType":"uint128","name":"amountRaised","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"requestId","type":"bytes32"},{"internalType":"uint256","name":"randomness","type":"uint256"}],"name":"rawFulfillRandomness","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"requests","outputs":[{"internalType":"uint256","name":"randomNumber","type":"uint256"},{"internalType":"uint256","name":"nomalizedRandomNumber","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"_newAddress","type":"address"}],"name":"setDestinationAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_raffleId","type":"uint256"}],"name":"setWinner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_raffleId","type":"uint256"}],"name":"stakeETH","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_raffleId","type":"uint256"}],"name":"transferRemainingFunds","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
60c0604052600b80546001600160a01b0319167352a032cf59ea274f9d745f29b6d514fe95ba192d1790553480156200003757600080fd5b50604051620041cd380380620041cd8339810160408190526200005a91620001c8565b6001600160601b0319606085811b821660a05284901b16608052620000b47f523a704056dcd17bcf83bed8b68c59416dac1119be77755efe3bde0a64e46e0c7313503b622abc0bd30a7e9687057df6e8c42fb928620000fb565b620000c1600033620000fb565b600282905560018115151415620000e457671bc16d674ec80000600355620000f1565b67016345785d8a00006003555b5050505062000220565b6200010782826200010b565b5050565b6000828152602081815260408083206001600160a01b038516845290915290205460ff1662000107576000828152602081815260408083206001600160a01b03851684529091529020805460ff19166001179055620001673390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b80516001600160a01b0381168114620001c357600080fd5b919050565b60008060008060808587031215620001de578384fd5b620001e985620001ab565b9350620001f960208601620001ab565b9250604085015191506060850151801515811462000215578182fd5b939692955090935050565b60805160601c60a05160601c613f736200025a600039600081816121fa0152612ec00152600081816129660152612e910152613f736000f3fe60806040526004361061021a5760003560e01c806353b7a59b1161012357806393a75d02116100ab578063d649214c1161006f578063d649214c1461078b578063ddba6e6b146107ab578063eb99038c14610811578063f369145514610835578063f5b541a61461085557600080fd5b806393a75d02146106c557806394985ddd146106f2578063a217fddf14610712578063babdf60b14610727578063d547741f1461076b57600080fd5b80636ecc20da116100f25780636ecc20da1461060a5780637c903fc01461061d5780637fa4cacb1461065157806381d12c581461067157806391d14854146106a557600080fd5b806353b7a59b146105355780635d4bc0ce1461056d5780635fba3171146105ca5780636371ba0d146105ea57600080fd5b8063248a9ca3116101a657806336568abe1161017557806336568abe14610478578063365e36581461049857806336734e34146104c55780633a3956c2146104e55780634239a50c1461051557600080fd5b8063248a9ca3146103b15780632a596800146103ef5780632f2ff15d14610438578063317f30591461045857600080fd5b80630b148ff0116101ed5780630b148ff01461031b5780630df716021461033d5780631e6cd3951461035d5780631fe968571461037d578063236854961461039e57600080fd5b8063013805c51461021f57806301ffc9a71461026a578063039be5581461029a578063043a1c9a146102fb575b600080fd5b34801561022b57600080fd5b5061023f61023a366004613755565b610877565b6040805165ffffffffffff90931683526001600160a01b039091166020830152015b60405180910390f35b34801561027657600080fd5b5061028a610285366004613776565b6108bf565b6040519015158152602001610261565b3480156102a657600080fd5b506102db6102b536600461370e565b6007602052600090815260409020546001600160801b0380821691600160801b90041682565b604080516001600160801b03938416815292909116602083015201610261565b34801561030757600080fd5b5061028a610316366004613648565b6108f6565b34801561032757600080fd5b5061033b6103363660046139d3565b61098f565b005b34801561034957600080fd5b5061033b61035836600461370e565b610c4b565b34801561036957600080fd5b5061028a61037836600461370e565b610cc0565b34801561038957600080fd5b5061028a61039836600461362c565b50600090565b61033b6103ac366004613755565b610deb565b3480156103bd57600080fd5b506103e16103cc36600461370e565b60009081526020819052604090206001015490565b604051908152602001610261565b3480156103fb57600080fd5b5061042361040a36600461370e565b6005602052600090815260409020805460019091015482565b60408051928352602083019190915201610261565b34801561044457600080fd5b5061033b610453366004613726565b611150565b34801561046457600080fd5b5061033b61047336600461370e565b61117a565b34801561048457600080fd5b5061033b610493366004613726565b611366565b3480156104a457600080fd5b506104b86104b336600461370e565b6113e4565b6040516102619190613bc7565b3480156104d157600080fd5b5061033b6104e0366004613873565b611472565b3480156104f157600080fd5b5061050561050036600461370e565b6116bb565b6040516102619493929190613c42565b34801561052157600080fd5b5061033b61053036600461370e565b611707565b34801561054157600080fd5b50600b54610555906001600160a01b031681565b6040516001600160a01b039091168152602001610261565b34801561057957600080fd5b5061058d61058836600461370e565b61175e565b6040805165ffffffffffff909616865260208601949094526001600160a01b0392831693850193909352166060830152608082015260a001610261565b3480156105d657600080fd5b5061033b6105e536600461370e565b6117b5565b3480156105f657600080fd5b506103e161060536600461379e565b611a54565b61033b61061836600461370e565b611f0a565b34801561062957600080fd5b506103e17fde5ee446972f4e39ab62c03aa34b2096680a875c3fdb3eb2f947cbb93341c05881565b34801561065d57600080fd5b5061033b61066c36600461362c565b61206c565b34801561067d57600080fd5b5061042361068c36600461370e565b6004602052600090815260409020805460019091015482565b3480156106b157600080fd5b5061028a6106c0366004613726565b61209a565b3480156106d157600080fd5b506106e56106e036600461370e565b6120c3565b6040516102619190613cc4565b3480156106fe57600080fd5b5061033b61070d366004613755565b6121ef565b34801561071e57600080fd5b506103e1600081565b34801561073357600080fd5b5061075d610742366004613673565b60408051602081019091526000815260019094509492505050565b604051610261929190613c27565b34801561077757600080fd5b5061033b610786366004613726565b612271565b34801561079757600080fd5b5061033b6107a6366004613946565b612296565b3480156107b757600080fd5b506107ef6107c636600461370e565b600660205260009081526040902080546001820154600290920154909165ffffffffffff169083565b6040805193845265ffffffffffff909216602084015290820152606001610261565b34801561081d57600080fd5b5061028a61082c3660046136ba565b60009392505050565b34801561084157600080fd5b50610555610850366004613755565b6124b8565b34801561086157600080fd5b506103e1600080516020613f1e83398151915281565b6008602052816000526040600020818154811061089357600080fd5b60009182526020909120015465ffffffffffff81169250600160301b90046001600160a01b0316905082565b60006001600160e01b03198216637965db0b60e01b14806108f057506301ffc9a760e01b6001600160e01b03198316145b92915050565b6000806009838154811061091a57634e487b7160e01b600052603260045260246000fd5b60009182526020918290206040805160a0810182526005909302909101805465ffffffffffff16835260018101549383019390935260028301546001600160a01b0390811691830191909152600383015481166060830181905260049093015460809092019190915285161491505092915050565b7fde5ee446972f4e39ab62c03aa34b2096680a875c3fdb3eb2f947cbb93341c0586109b98161265e565b6000600a85815481106109dc57634e487b7160e01b600052603260045260246000fd5b6000918252602090912001905060018154610100900460ff166002811115610a1457634e487b7160e01b600052602160045260246000fd5b1480610a48575060028154610100900460ff166002811115610a4657634e487b7160e01b600052602160045260246000fd5b145b610a925760405162461bcd60e51b8152602060048201526016602482015275115b9d1c9e481d1e5c19481b9bdd08185b1b1bddd95960521b60448201526064015b60405180910390fd5b60006040518060400160405280868460000160029054906101000a900465ffffffffffff16610ac19190613d58565b65ffffffffffff90811682526001600160a01b0380881660209384015260008a8152600884526040812080546001810182559082529084902085519101805494860151909216600160301b026001600160d01b03199094169083161792909217909155835491925086918491600291610b4291859162010000900416613d58565b92506101000a81548165ffffffffffff021916908365ffffffffffff1602179055506000600167ffffffffffffffff811115610b8e57634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015610bb7578160200160208202803683370190505b5090508481600081518110610bdc57634e487b7160e01b600052603260045260246000fd5b6001600160a01b0390921660209283029190910190910152825460405188917f4da4f5fab0816c65315b6f5d15f879f96b98661133d7b3787788f291367604fb91610c3a9185918b9165ffffffffffff620100009091041690613b95565b60405180910390a250505050505050565b600080516020613f1e833981519152610c638161265e565b6000610c6e8361266b565b90506000610c7a612942565b9050610cba84836040015165ffffffffffff1683604080518082018252938452602080850193845260009283526005905290209151825551600190910155565b50505050565b600080600a8381548110610ce457634e487b7160e01b600052603260045260246000fd5b60009182526020909120604080516080810190915291018054829060ff166006811115610d2157634e487b7160e01b600052602160045260246000fd5b6006811115610d4057634e487b7160e01b600052602160045260246000fd5b81528154602090910190610100900460ff166002811115610d7157634e487b7160e01b600052602160045260246000fd5b6002811115610d9057634e487b7160e01b600052602160045260246000fd5b8152905462010000810465ffffffffffff166020830152600160401b90046001600160801b03166040909101529050600181516006811115610de257634e487b7160e01b600052602160045260246000fd5b14159392505050565b6000600a8381548110610e0e57634e487b7160e01b600052603260045260246000fd5b6000918252602090912001905060018154610100900460ff166002811115610e4657634e487b7160e01b600052602160045260246000fd5b1415610e8e5760405163efeb42cf60e01b8152602060048201526016602482015275115b9d1c9e481d1e5c19481b9bdd08185b1b1bddd95960521b6044820152606401610a89565b81610ecb5760405163efeb42cf60e01b815260206004820152600c60248201526b0686f774d616e7920697320360a41b6044820152606401610a89565b60008281526006602090815260409182902082516060810184528154808252600183015465ffffffffffff1693820193909352600290910154928101929092528414610f4f5760405163efeb42cf60e01b81526020600482015260126024820152711259081b9bdd081a5b881c9859999b19525960721b6044820152606401610a89565b602081015165ffffffffffff8116610f9d5760405163efeb42cf60e01b815260206004820152601060248201526f1259081b9bdd081cdd5c1c1bdc9d195960821b6044820152606401610a89565b81604001513414610ffd5760405163efeb42cf60e01b8152602060048201526024808201527f6d73672e76616c7565206d75737420626520657175616c20746f2074686520706044820152637269636560e01b6064820152608401610a89565b8254604080518082019091526201000090910465ffffffffffff1690600090806110278585613d58565b65ffffffffffff90811682523360209283015260008a8152600880845260408220805460018101825590835291849020855192018054948601516001600160a01b0316600160301b026001600160d01b03199095169290931691909117929092179055865491925034918791906110b09084906001600160801b03600160401b90910416613d15565b92506101000a8154816001600160801b0302191690836001600160801b0316021790555082826110e09190613d58565b855467ffffffffffff000019166201000065ffffffffffff9283168102919091178088556040805192909104909216815260208101889052339189917fd746af8dc82f9bed98cea0fe0264eb1c3d2e5f7bcc77fc5efb429c79df407887910160405180910390a350505050505050565b60008281526020819052604090206001015461116b8161265e565b6111758383612a52565b505050565b600080516020613f1e8339815191526111928161265e565b6000600a83815481106111b557634e487b7160e01b600052603260045260246000fd5b600091825260209091200190506006815460ff1660068111156111e857634e487b7160e01b600052602160045260246000fd5b148061121757506003815460ff16600681111561121557634e487b7160e01b600052602160045260246000fd5b145b6112525760405162461bcd60e51b815260206004820152600c60248201526b57726f6e672073746174757360a01b6044820152606401610a89565b805460ff1916600317808255600b546040516000926001600160a01b03909216916001600160801b03600160401b90910416908381818185875af1925050503d80600081146112bd576040519150601f19603f3d011682016040523d82523d6000602084013e6112c2565b606091505b50509050806113095760405162461bcd60e51b81526020600482015260136024820152724661696c2073656e642045746820746f204d5760681b6044820152606401610a89565b8154604051600160401b9091046001600160801b0316815284907fcdef6558dae40f2699846eedf449462daab85b1224ad7f077569ba91aaa949259060200160405180910390a2508054600160401b600160c01b03191690555050565b6001600160a01b03811633146113d65760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b6064820152608401610a89565b6113e08282612ad6565b5050565b606060086000838152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b82821015611467576000848152602090819020604080518082019091529084015465ffffffffffff81168252600160301b90046001600160a01b031681830152825260019092019101611419565b505050509050919050565b600080516020613f1e83398151915261148a8161265e565b6000600a84815481106114ad57634e487b7160e01b600052603260045260246000fd5b600091825260209091200190506001815460ff1660068111156114e057634e487b7160e01b600052602160045260246000fd5b1461152d5760405162461bcd60e51b815260206004820152601960248201527f526166666c65206973206e6f7420696e206163636570746564000000000000006044820152606401610a89565b82516000805b8281101561162f57600086828151811061155d57634e487b7160e01b600052603260045260246000fd5b6020026020010151905060006040518060400160405280848860000160029054906101000a900465ffffffffffff1665ffffffffffff1661159e9190613d40565b6115a9906001613d40565b65ffffffffffff90811682526001600160a01b0380861660209384015260008d8152600884526040812080546001810182559082529084902085519101805494860151909216600160301b026001600160d01b0319909416921691909117919091179055905061161884613e76565b93505050808061162790613e5b565b915050611533565b50825461164b90829062010000900465ffffffffffff16613d58565b835467ffffffffffff000019166201000065ffffffffffff92831681029190911780865560405189937f4da4f5fab0816c65315b6f5d15f879f96b98661133d7b3787788f291367604fb936116ab938b9389939290910490911690613b64565b60405180910390a2505050505050565b600a81815481106116cb57600080fd5b60009182526020909120015460ff80821692506101008204169062010000810465ffffffffffff1690600160401b90046001600160801b031684565b60006117128261266b565b9050600061171e612942565b905061117583836040015165ffffffffffff1683604080518082018252938452602080850193845260009283526005905290209151825551600190910155565b6009818154811061176e57600080fd5b60009182526020909120600590910201805460018201546002830154600384015460049094015465ffffffffffff909316945090926001600160a01b039182169291169085565b600080516020613f1e8339815191526117cd8161265e565b6000600983815481106117f057634e487b7160e01b600052603260045260246000fd5b906000526020600020906005020190506000600a848154811061182357634e487b7160e01b600052603260045260246000fd5b600091825260209091200190506005815460ff16600681111561185657634e487b7160e01b600052602160045260246000fd5b1415801561188857506003815460ff16600681111561188557634e487b7160e01b600052602160045260246000fd5b14155b80156118b857506002815460ff1660068111156118b557634e487b7160e01b600052602160045260246000fd5b14155b80156118e857506004815460ff1660068111156118e557634e487b7160e01b600052602160045260246000fd5b14155b801561191857506006815460ff16600681111561191557634e487b7160e01b600052602160045260246000fd5b14155b6119535760405162461bcd60e51b815260206004820152600c60248201526b57726f6e672073746174757360a01b6044820152606401610a89565b6001815460ff16600681111561197957634e487b7160e01b600052602160045260246000fd5b14156119fa57600382015460018301546040516000926001600160a01b031691908381818185875af1925050503d80600081146119d2576040519150601f19603f3d011682016040523d82523d6000602084013e6119d7565b606091505b50509050806119f85760405162461bcd60e51b8152600401610a8990613c96565b505b805460ff19166006178082556040516001600160801b03600160401b90920491909116815284907fd512a34b0f0618078770fcd85d974df1ab46a7882e8b3d45aa91764f4961aed29060200160405180910390a250505050565b6000600080516020613f1e833981519152611a6e8161265e565b6113888465ffffffffffff161115611abe5760405162461bcd60e51b81526020600482015260136024820152720c6dedadad2e6e6d2dedc40e8dede40d0d2ced606b1b6044820152606401610a89565b6040805160a08101825265ffffffffffff8681168252602082018b81526000938301848152606084018581526080850186815260098054600181018255975285517f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7af6005909802978801805465ffffffffffff1916919096161790945591517f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7b0860155517f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7b1850180546001600160a01b03199081166001600160a01b039384161790915591517f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7b2860180549093169116179055517f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7b390920191909155611c0384612b3b565b600954600090611c1590600190613e01565b905086611c505760405162461bcd60e51b81526020600482015260096024820152684e6f2070726963657360b81b6044820152606401610a89565b60005b87811015611de9576000898983818110611c7d57634e487b7160e01b600052603260045260246000fd5b9050606002016020016020810190611c959190613a12565b65ffffffffffff1611611cdc5760405162461bcd60e51b815260206004820152600f60248201526e06e756d456e7472696573206973203608c1b6044820152606401610a89565b600060405180606001604052808481526020018b8b85818110611d0f57634e487b7160e01b600052603260045260246000fd5b9050606002016020016020810190611d279190613a12565b65ffffffffffff1681526020018b8b85818110611d5457634e487b7160e01b600052603260045260246000fd5b90506060020160400135815250905080600660008c8c86818110611d8857634e487b7160e01b600052603260045260246000fd5b60600291909101358252506020808201929092526040908101600020835181559183015160018301805465ffffffffffff191665ffffffffffff90921691909117905591909101516002909101555080611de181613e5b565b915050611c53565b506040805180820182526001600160801b03808c1682528d8116602080840191825260008681526007909152848120935191518316600160801b02919092161790915590518b9183917ff6f5afeb49bc62176d1efaa06a1753999cc29bf378f1004ea916f37f41d7638a9190a360408051808201825260018082523360208084019182526000868152600882529485208054938401815580865290852084519301805492516001600160a01b0316600160301b026001600160d01b031990931665ffffffffffff949094169390931791909117909155838352805491929091611ee257634e487b7160e01b600052603260045260246000fd5b600091825260209091200180546001600160d01b0319169055509a9950505050505050505050565b6000600a8281548110611f2d57634e487b7160e01b600052603260045260246000fd5b906000526020600020019050600060098381548110611f5c57634e487b7160e01b600052603260045260246000fd5b6000918252602082206005909102019150825460ff166006811115611f9157634e487b7160e01b600052602160045260246000fd5b14611fd35760405162461bcd60e51b8152602060048201526012602482015271149859999b19481b9bdd0810d4915055115160721b6044820152606401610a89565b348160010154146120195760405162461bcd60e51b815260206004820152601060248201526f141c9a5e99481b9bdd081cdd185ad95960821b6044820152606401610a89565b815460ff19166001178255600381018054336001600160a01b0319909116811790915560405184907f8bb509eedfd1c4847b0a8a2b4493cf2ebb9970dc367e477cd2a8523e212dc1db90600090a3505050565b60006120778161265e565b50600b80546001600160a01b0319166001600160a01b0392909216919091179055565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b6120ef604080516080810190915280600081526020016000815260006020820181905260409091015290565b600a828154811061211057634e487b7160e01b600052603260045260246000fd5b60009182526020909120604080516080810190915291018054829060ff16600681111561214d57634e487b7160e01b600052602160045260246000fd5b600681111561216c57634e487b7160e01b600052602160045260246000fd5b81528154602090910190610100900460ff16600281111561219d57634e487b7160e01b600052602160045260246000fd5b60028111156121bc57634e487b7160e01b600052602160045260246000fd5b8152905462010000810465ffffffffffff166020830152600160401b90046001600160801b031660409091015292915050565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146122675760405162461bcd60e51b815260206004820152601f60248201527f4f6e6c7920565246436f6f7264696e61746f722063616e2066756c66696c6c006044820152606401610a89565b6113e08282612c7b565b60008281526020819052604090206001015461228c8161265e565b6111758383612ad6565b600080516020613f1e8339815191526122ae8161265e565b6000805b848110156124775760008781526008602052604081208787848181106122e857634e487b7160e01b600052603260045260246000fd5b9050602002013560016122fb9190613d40565b8154811061231957634e487b7160e01b600052603260045260246000fd5b600091825260209091200180549091506001600160a01b03868116600160301b909204161461238a5760405162461bcd60e51b815260206004820152601e60248201527f456e74727920646964206e6f742062656c6f6e6720746f20706c6179657200006044820152606401610a89565b80546601000000000000600160d01b031916815560008787848181106123c057634e487b7160e01b600052603260045260246000fd5b90506020020135600014156123d757506000612441565b600089815260086020526040902088888581811061240557634e487b7160e01b600052603260045260246000fd5b905060200201358154811061242a57634e487b7160e01b600052603260045260246000fd5b60009182526020909120015465ffffffffffff1690505b815461245690829065ffffffffffff16613e01565b6124609085613d40565b93505050808061246f90613e5b565b9150506122b2565b50604080518281526001600160a01b038516602082015287917f2cca80c1af5abb202a642a502875436822768d733462843a7c3a902b0fad99d091016116ab565b600082815260086020526040812081906124d29084612d38565b6000858152600860205260408120805492935090918390811061250557634e487b7160e01b600052603260045260246000fd5b600091825260209091200154600160301b90046001600160a01b0316905080156125325791506108f09050565b6000825b8115801561258b5750600087815260086020526040812080548390811061256d57634e487b7160e01b600052603260045260246000fd5b600091825260209091200154600160301b90046001600160a01b0316145b156125c257806125b7576000878152600860205260409020546125b090600190613e01565b9050612536565b6125b0600182613e01565b81156126085760405162461bcd60e51b8152602060048201526015602482015274105b1b081d5cd95c9cc8189b1858dadb1a5cdd1959605a1b6044820152606401610a89565b600087815260086020526040902080548290811061263657634e487b7160e01b600052603260045260246000fd5b600091825260209091200154600160301b90046001600160a01b031694506108f09350505050565b6126688133612e29565b50565b612697604080516080810190915280600081526020016000815260006020820181905260409091015290565b6000600a83815481106126ba57634e487b7160e01b600052603260045260246000fd5b6000918252602080832086845260079091526040909220910191506001825460ff1660068111156126fb57634e487b7160e01b600052602160045260246000fd5b146127415760405162461bcd60e51b8152602060048201526016602482015275526166666c6520696e2077726f6e672073746174757360501b6044820152606401610a89565b805482546001600160801b03918216600160401b90910490911610156127a95760405162461bcd60e51b815260206004820152601760248201527f4e6f7420656e6f7567682066756e6473207261697365640000000000000000006044820152606401610a89565b81548154600160401b9091046001600160801b03908116600160801b9092041611156128175760405162461bcd60e51b815260206004820152601860248201527f446573697265642066756e6473206e6f742072616973656400000000000000006044820152606401610a89565b815460ff19166004178083556040516001600160801b03600160401b90920491909116815284907ff2be214756d2fbc1e781d10809ddef33000009d805be55356bb348134ce21c689060200160405180910390a2604080516080810190915282548390829060ff16600681111561289e57634e487b7160e01b600052602160045260246000fd5b60068111156128bd57634e487b7160e01b600052602160045260246000fd5b81528154602090910190610100900460ff1660028111156128ee57634e487b7160e01b600052602160045260246000fd5b600281111561290d57634e487b7160e01b600052602160045260246000fd5b8152905462010000810465ffffffffffff166020830152600160401b90046001600160801b0316604090910152949350505050565b6003546040516370a0823160e01b8152306004820152600091906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a082319060240160206040518083038186803b1580156129a857600080fd5b505afa1580156129bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129e0919061385b565b1015612a425760405162461bcd60e51b815260206004820152602b60248201527f4e6f7420656e6f756768204c494e4b202d2066696c6c20636f6e74726163742060448201526a1dda5d1a0819985d58d95d60aa1b6064820152608401610a89565b60006108f0600254600354612e8d565b612a5c828261209a565b6113e0576000828152602081815260408083206001600160a01b03851684529091529020805460ff19166001179055612a923390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b612ae0828261209a565b156113e0576000828152602081815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b604080516080810190915260009080828152602001836002811115612b7057634e487b7160e01b600052602160045260246000fd5b81526000602082018190526040909101819052600a8054600181810183559190925282517fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a890920180549394508493909291839160ff191690836006811115612be957634e487b7160e01b600052602160045260246000fd5b021790555060208201518154829061ff001916610100836002811115612c1f57634e487b7160e01b600052602160045260246000fd5b0217905550604082015181546060909301516001600160801b0316600160401b02600160401b600160c01b031965ffffffffffff90921662010000029190911662010000600160c01b0319909316929092179190911790555050565b6000828152600560209081526040808320815180830190925280548252600101549181018290529190612cae9084613e9c565b612cb9906001613d40565b60408051808201825285815260208082018481528651600090815260048352849020835181559051600190910155855183518881529182018590529394509092917f7c40e661b8212d0c4f60ac6e6ebed99c28680c7b3ede5b82f3b0254543f62fca910160405180910390a28251612d31908361301f565b5050505050565b8154600090612d49575060006108f0565b82546000905b80821015612dbc576000612d6383836133dc565b905084868281548110612d8657634e487b7160e01b600052603260045260246000fd5b60009182526020909120015465ffffffffffff161115612da857809150612db6565b612db3816001613d40565b92505b50612d4f565b600082118015612e0857508385612dd4600185613e01565b81548110612df257634e487b7160e01b600052603260045260246000fd5b60009182526020909120015465ffffffffffff16145b15612e2157612e18600183613e01565b925050506108f0565b5090506108f0565b612e33828261209a565b6113e057612e4b816001600160a01b031660146133fe565b612e568360206133fe565b604051602001612e67929190613abf565b60408051601f198184030181529082905262461bcd60e51b8252610a8991600401613c83565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634000aea07f000000000000000000000000000000000000000000000000000000000000000084866000604051602001612efd929190918252602082015260400190565b6040516020818303038152906040526040518463ffffffff1660e01b8152600401612f2a93929190613b34565b602060405180830381600087803b158015612f4457600080fd5b505af1158015612f58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f7c91906136ee565b50600083815260016020818152604080842054815180840189905280830186905230606082015260808082018390528351808303909101815260a09091019092528151918301919091209387905290829052612fd791613d40565b6000858152600160205260409020556130178482604080516020808201949094528082019290925280518083038201815260609092019052805191012090565b949350505050565b60006009838154811061304257634e487b7160e01b600052603260045260246000fd5b906000526020600020906005020190506000600a848154811061307557634e487b7160e01b600052603260045260246000fd5b600091825260209091200190506002815460ff1660068111156130a857634e487b7160e01b600052602160045260246000fd5b14806130d757506004815460ff1660068111156130d557634e487b7160e01b600052602160045260246000fd5b145b61311c5760405162461bcd60e51b8152602060048201526016602482015275526166666c6520696e2077726f6e672073746174757360501b6044820152606401610a89565b6004820183905561312d84846124b8565b6002830180546001600160a01b039283166001600160a01b0319909116178155825460ff1916600517835554600184015460405160009392909216918381818185875af1925050503d80600081146131a1576040519150601f19603f3d011682016040523d82523d6000602084013e6131a6565b606091505b50509050806131c75760405162461bcd60e51b8152600401610a8990613c96565b82548254600091612710916131f49165ffffffffffff1690600160401b90046001600160801b0316613db3565b6131fe9190613d79565b83546001600160801b039182169250600091613224918491600160401b90910416613e01565b60038601546040519192506000916001600160a01b039091169083908381818185875af1925050503d8060008114613278576040519150601f19603f3d011682016040523d82523d6000602084013e61327d565b606091505b505090508061329e5760405162461bcd60e51b8152600401610a8990613c96565b600b546040516000916001600160a01b03169085908381818185875af1925050503d80600081146132eb576040519150601f19603f3d011682016040523d82523d6000602084013e6132f0565b606091505b50509050806133395760405162461bcd60e51b81526020600482015260156024820152744661696c65642073656e642045746820746f204d5760581b6044820152606401610a89565b887f7378e11c2b0ec7514bbf7ba369980eedcba0bca03e116dc9e7138f7748e211d68560405161336b91815260200190565b60405180910390a26002870154865460408051600160401b9092046001600160801b03168252602082018b90526001600160a01b03909216918b917fe0b2a72a0644b093aac275024c05c7c28851a0b572557a32241d13634a0f3e08910160405180910390a3505050505050505050565b60006133eb6002848418613d9f565b6133f790848416613d40565b9392505050565b6060600061340d836002613de2565b613418906002613d40565b67ffffffffffffffff81111561343e57634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f191660200182016040528015613468576020820181803683370190505b509050600360fc1b8160008151811061349157634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a905350600f60fb1b816001815181106134ce57634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a90535060006134f2846002613de2565b6134fd906001613d40565b90505b6001811115613591576f181899199a1a9b1b9c1cb0b131b232b360811b85600f166010811061353f57634e487b7160e01b600052603260045260246000fd5b1a60f81b82828151811061356357634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a90535060049490941c9361358a81613e44565b9050613500565b5083156133f75760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610a89565b80356135eb81613f08565b919050565b8035600381106135eb57600080fd5b80356001600160801b03811681146135eb57600080fd5b803565ffffffffffff811681146135eb57600080fd5b60006020828403121561363d578081fd5b81356133f781613f08565b6000806040838503121561365a578081fd5b823561366581613f08565b946020939093013593505050565b60008060008060808587031215613688578182fd5b843561369381613f08565b93506020850135925060408501356136aa81613f08565b9396929550929360600135925050565b6000806000606084860312156136ce578283fd5b83356136d981613f08565b95602085013595506040909401359392505050565b6000602082840312156136ff578081fd5b815180151581146133f7578182fd5b60006020828403121561371f578081fd5b5035919050565b60008060408385031215613738578182fd5b82359150602083013561374a81613f08565b809150509250929050565b60008060408385031215613767578182fd5b50508035926020909101359150565b600060208284031215613787578081fd5b81356001600160e01b0319811681146133f7578182fd5b600080600080600080600060c0888a0312156137b8578283fd5b6137c1886135ff565b9650602088013595506137d6604089016135ff565b9450606088013567ffffffffffffffff808211156137f2578485fd5b818a0191508a601f830112613805578485fd5b813581811115613813578586fd5b8b6020606083028501011115613827578586fd5b60208301965080955050505061383f60808901613616565b915061384d60a089016135f0565b905092959891949750929550565b60006020828403121561386c578081fd5b5051919050565b60008060408385031215613885578182fd5b8235915060208084013567ffffffffffffffff808211156138a4578384fd5b818601915086601f8301126138b7578384fd5b8135818111156138c9576138c9613ef2565b8060051b604051601f19603f830116810181811085821117156138ee576138ee613ef2565b604052828152858101935084860182860187018b101561390c578788fd5b8795505b8386101561393557613921816135e0565b855260019590950194938601938601613910565b508096505050505050509250929050565b6000806000806060858703121561395b578182fd5b84359350602085013567ffffffffffffffff80821115613979578384fd5b818701915087601f83011261398c578384fd5b81358181111561399a578485fd5b8860208260051b85010111156139ae578485fd5b60208301955080945050505060408501356139c881613f08565b939692955090935050565b6000806000606084860312156139e7578081fd5b833592506139f760208501613616565b91506040840135613a0781613f08565b809150509250925092565b600060208284031215613a23578081fd5b6133f782613616565b6000815180845260208085019450808401835b83811015613a645781516001600160a01b031687529582019590820190600101613a3f565b509495945050505050565b60008151808452613a87816020860160208601613e18565b601f01601f19169290920160200192915050565b60038110613aab57613aab613edc565b9052565b60078110613aab57613aab613edc565b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000815260008351613af7816017850160208801613e18565b7001034b99036b4b9b9b4b733903937b6329607d1b6017918401918201528351613b28816028840160208801613e18565b01602801949350505050565b60018060a01b0384168152826020820152606060408201526000613b5b6060830184613a6f565b95945050505050565b606081526000613b776060830186613a2c565b905083602083015265ffffffffffff83166040830152949350505050565b606081526000613ba86060830186613a2c565b65ffffffffffff94851660208401529290931660409091015292915050565b602080825282518282018190526000919060409081850190868401855b82811015613c1a578151805165ffffffffffff1685528601516001600160a01b0316868501529284019290850190600101613be4565b5091979650505050505050565b82151581526040602082015260006130176040830184613a6f565b60808101613c508287613aaf565b613c5d6020830186613a9b565b65ffffffffffff841660408301526001600160801b038316606083015295945050505050565b6020815260006133f76020830184613a6f565b6020808252601490820152732330b4b632b2103a379039b2b7321022ba3432b960611b604082015260600190565b6000608082019050613cd7828451613aaf565b6020830151613ce96020840182613a9b565b5065ffffffffffff60408401511660408301526001600160801b03606084015116606083015292915050565b60006001600160801b03808316818516808303821115613d3757613d37613eb0565b01949350505050565b60008219821115613d5357613d53613eb0565b500190565b600065ffffffffffff808316818516808303821115613d3757613d37613eb0565b60006001600160801b0380841680613d9357613d93613ec6565b92169190910492915050565b600082613dae57613dae613ec6565b500490565b60006001600160801b0380831681851681830481118215151615613dd957613dd9613eb0565b02949350505050565b6000816000190483118215151615613dfc57613dfc613eb0565b500290565b600082821015613e1357613e13613eb0565b500390565b60005b83811015613e33578181015183820152602001613e1b565b83811115610cba5750506000910152565b600081613e5357613e53613eb0565b506000190190565b6000600019821415613e6f57613e6f613eb0565b5060010190565b600065ffffffffffff80831681811415613e9257613e92613eb0565b6001019392505050565b600082613eab57613eab613ec6565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b038116811461266857600080fdfe523a704056dcd17bcf83bed8b68c59416dac1119be77755efe3bde0a64e46e0ca2646970667358221220c02bb1e500344175aec911bacd64ba965d4d19bd5b66a71237debc237a37fc2564736f6c63430008040033000000000000000000000000f0d54349addcf704f77ae15b96510dea15cb7952000000000000000000000000514910771af9ca656af840dff83e8264ecf986caaa77729d3466ca35ae8d28b3bbac7cc36a5031efdc430821c02bc31a238af4450000000000000000000000000000000000000000000000000000000000000001
Deployed Bytecode
0x60806040526004361061021a5760003560e01c806353b7a59b1161012357806393a75d02116100ab578063d649214c1161006f578063d649214c1461078b578063ddba6e6b146107ab578063eb99038c14610811578063f369145514610835578063f5b541a61461085557600080fd5b806393a75d02146106c557806394985ddd146106f2578063a217fddf14610712578063babdf60b14610727578063d547741f1461076b57600080fd5b80636ecc20da116100f25780636ecc20da1461060a5780637c903fc01461061d5780637fa4cacb1461065157806381d12c581461067157806391d14854146106a557600080fd5b806353b7a59b146105355780635d4bc0ce1461056d5780635fba3171146105ca5780636371ba0d146105ea57600080fd5b8063248a9ca3116101a657806336568abe1161017557806336568abe14610478578063365e36581461049857806336734e34146104c55780633a3956c2146104e55780634239a50c1461051557600080fd5b8063248a9ca3146103b15780632a596800146103ef5780632f2ff15d14610438578063317f30591461045857600080fd5b80630b148ff0116101ed5780630b148ff01461031b5780630df716021461033d5780631e6cd3951461035d5780631fe968571461037d578063236854961461039e57600080fd5b8063013805c51461021f57806301ffc9a71461026a578063039be5581461029a578063043a1c9a146102fb575b600080fd5b34801561022b57600080fd5b5061023f61023a366004613755565b610877565b6040805165ffffffffffff90931683526001600160a01b039091166020830152015b60405180910390f35b34801561027657600080fd5b5061028a610285366004613776565b6108bf565b6040519015158152602001610261565b3480156102a657600080fd5b506102db6102b536600461370e565b6007602052600090815260409020546001600160801b0380821691600160801b90041682565b604080516001600160801b03938416815292909116602083015201610261565b34801561030757600080fd5b5061028a610316366004613648565b6108f6565b34801561032757600080fd5b5061033b6103363660046139d3565b61098f565b005b34801561034957600080fd5b5061033b61035836600461370e565b610c4b565b34801561036957600080fd5b5061028a61037836600461370e565b610cc0565b34801561038957600080fd5b5061028a61039836600461362c565b50600090565b61033b6103ac366004613755565b610deb565b3480156103bd57600080fd5b506103e16103cc36600461370e565b60009081526020819052604090206001015490565b604051908152602001610261565b3480156103fb57600080fd5b5061042361040a36600461370e565b6005602052600090815260409020805460019091015482565b60408051928352602083019190915201610261565b34801561044457600080fd5b5061033b610453366004613726565b611150565b34801561046457600080fd5b5061033b61047336600461370e565b61117a565b34801561048457600080fd5b5061033b610493366004613726565b611366565b3480156104a457600080fd5b506104b86104b336600461370e565b6113e4565b6040516102619190613bc7565b3480156104d157600080fd5b5061033b6104e0366004613873565b611472565b3480156104f157600080fd5b5061050561050036600461370e565b6116bb565b6040516102619493929190613c42565b34801561052157600080fd5b5061033b61053036600461370e565b611707565b34801561054157600080fd5b50600b54610555906001600160a01b031681565b6040516001600160a01b039091168152602001610261565b34801561057957600080fd5b5061058d61058836600461370e565b61175e565b6040805165ffffffffffff909616865260208601949094526001600160a01b0392831693850193909352166060830152608082015260a001610261565b3480156105d657600080fd5b5061033b6105e536600461370e565b6117b5565b3480156105f657600080fd5b506103e161060536600461379e565b611a54565b61033b61061836600461370e565b611f0a565b34801561062957600080fd5b506103e17fde5ee446972f4e39ab62c03aa34b2096680a875c3fdb3eb2f947cbb93341c05881565b34801561065d57600080fd5b5061033b61066c36600461362c565b61206c565b34801561067d57600080fd5b5061042361068c36600461370e565b6004602052600090815260409020805460019091015482565b3480156106b157600080fd5b5061028a6106c0366004613726565b61209a565b3480156106d157600080fd5b506106e56106e036600461370e565b6120c3565b6040516102619190613cc4565b3480156106fe57600080fd5b5061033b61070d366004613755565b6121ef565b34801561071e57600080fd5b506103e1600081565b34801561073357600080fd5b5061075d610742366004613673565b60408051602081019091526000815260019094509492505050565b604051610261929190613c27565b34801561077757600080fd5b5061033b610786366004613726565b612271565b34801561079757600080fd5b5061033b6107a6366004613946565b612296565b3480156107b757600080fd5b506107ef6107c636600461370e565b600660205260009081526040902080546001820154600290920154909165ffffffffffff169083565b6040805193845265ffffffffffff909216602084015290820152606001610261565b34801561081d57600080fd5b5061028a61082c3660046136ba565b60009392505050565b34801561084157600080fd5b50610555610850366004613755565b6124b8565b34801561086157600080fd5b506103e1600080516020613f1e83398151915281565b6008602052816000526040600020818154811061089357600080fd5b60009182526020909120015465ffffffffffff81169250600160301b90046001600160a01b0316905082565b60006001600160e01b03198216637965db0b60e01b14806108f057506301ffc9a760e01b6001600160e01b03198316145b92915050565b6000806009838154811061091a57634e487b7160e01b600052603260045260246000fd5b60009182526020918290206040805160a0810182526005909302909101805465ffffffffffff16835260018101549383019390935260028301546001600160a01b0390811691830191909152600383015481166060830181905260049093015460809092019190915285161491505092915050565b7fde5ee446972f4e39ab62c03aa34b2096680a875c3fdb3eb2f947cbb93341c0586109b98161265e565b6000600a85815481106109dc57634e487b7160e01b600052603260045260246000fd5b6000918252602090912001905060018154610100900460ff166002811115610a1457634e487b7160e01b600052602160045260246000fd5b1480610a48575060028154610100900460ff166002811115610a4657634e487b7160e01b600052602160045260246000fd5b145b610a925760405162461bcd60e51b8152602060048201526016602482015275115b9d1c9e481d1e5c19481b9bdd08185b1b1bddd95960521b60448201526064015b60405180910390fd5b60006040518060400160405280868460000160029054906101000a900465ffffffffffff16610ac19190613d58565b65ffffffffffff90811682526001600160a01b0380881660209384015260008a8152600884526040812080546001810182559082529084902085519101805494860151909216600160301b026001600160d01b03199094169083161792909217909155835491925086918491600291610b4291859162010000900416613d58565b92506101000a81548165ffffffffffff021916908365ffffffffffff1602179055506000600167ffffffffffffffff811115610b8e57634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015610bb7578160200160208202803683370190505b5090508481600081518110610bdc57634e487b7160e01b600052603260045260246000fd5b6001600160a01b0390921660209283029190910190910152825460405188917f4da4f5fab0816c65315b6f5d15f879f96b98661133d7b3787788f291367604fb91610c3a9185918b9165ffffffffffff620100009091041690613b95565b60405180910390a250505050505050565b600080516020613f1e833981519152610c638161265e565b6000610c6e8361266b565b90506000610c7a612942565b9050610cba84836040015165ffffffffffff1683604080518082018252938452602080850193845260009283526005905290209151825551600190910155565b50505050565b600080600a8381548110610ce457634e487b7160e01b600052603260045260246000fd5b60009182526020909120604080516080810190915291018054829060ff166006811115610d2157634e487b7160e01b600052602160045260246000fd5b6006811115610d4057634e487b7160e01b600052602160045260246000fd5b81528154602090910190610100900460ff166002811115610d7157634e487b7160e01b600052602160045260246000fd5b6002811115610d9057634e487b7160e01b600052602160045260246000fd5b8152905462010000810465ffffffffffff166020830152600160401b90046001600160801b03166040909101529050600181516006811115610de257634e487b7160e01b600052602160045260246000fd5b14159392505050565b6000600a8381548110610e0e57634e487b7160e01b600052603260045260246000fd5b6000918252602090912001905060018154610100900460ff166002811115610e4657634e487b7160e01b600052602160045260246000fd5b1415610e8e5760405163efeb42cf60e01b8152602060048201526016602482015275115b9d1c9e481d1e5c19481b9bdd08185b1b1bddd95960521b6044820152606401610a89565b81610ecb5760405163efeb42cf60e01b815260206004820152600c60248201526b0686f774d616e7920697320360a41b6044820152606401610a89565b60008281526006602090815260409182902082516060810184528154808252600183015465ffffffffffff1693820193909352600290910154928101929092528414610f4f5760405163efeb42cf60e01b81526020600482015260126024820152711259081b9bdd081a5b881c9859999b19525960721b6044820152606401610a89565b602081015165ffffffffffff8116610f9d5760405163efeb42cf60e01b815260206004820152601060248201526f1259081b9bdd081cdd5c1c1bdc9d195960821b6044820152606401610a89565b81604001513414610ffd5760405163efeb42cf60e01b8152602060048201526024808201527f6d73672e76616c7565206d75737420626520657175616c20746f2074686520706044820152637269636560e01b6064820152608401610a89565b8254604080518082019091526201000090910465ffffffffffff1690600090806110278585613d58565b65ffffffffffff90811682523360209283015260008a8152600880845260408220805460018101825590835291849020855192018054948601516001600160a01b0316600160301b026001600160d01b03199095169290931691909117929092179055865491925034918791906110b09084906001600160801b03600160401b90910416613d15565b92506101000a8154816001600160801b0302191690836001600160801b0316021790555082826110e09190613d58565b855467ffffffffffff000019166201000065ffffffffffff9283168102919091178088556040805192909104909216815260208101889052339189917fd746af8dc82f9bed98cea0fe0264eb1c3d2e5f7bcc77fc5efb429c79df407887910160405180910390a350505050505050565b60008281526020819052604090206001015461116b8161265e565b6111758383612a52565b505050565b600080516020613f1e8339815191526111928161265e565b6000600a83815481106111b557634e487b7160e01b600052603260045260246000fd5b600091825260209091200190506006815460ff1660068111156111e857634e487b7160e01b600052602160045260246000fd5b148061121757506003815460ff16600681111561121557634e487b7160e01b600052602160045260246000fd5b145b6112525760405162461bcd60e51b815260206004820152600c60248201526b57726f6e672073746174757360a01b6044820152606401610a89565b805460ff1916600317808255600b546040516000926001600160a01b03909216916001600160801b03600160401b90910416908381818185875af1925050503d80600081146112bd576040519150601f19603f3d011682016040523d82523d6000602084013e6112c2565b606091505b50509050806113095760405162461bcd60e51b81526020600482015260136024820152724661696c2073656e642045746820746f204d5760681b6044820152606401610a89565b8154604051600160401b9091046001600160801b0316815284907fcdef6558dae40f2699846eedf449462daab85b1224ad7f077569ba91aaa949259060200160405180910390a2508054600160401b600160c01b03191690555050565b6001600160a01b03811633146113d65760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b6064820152608401610a89565b6113e08282612ad6565b5050565b606060086000838152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b82821015611467576000848152602090819020604080518082019091529084015465ffffffffffff81168252600160301b90046001600160a01b031681830152825260019092019101611419565b505050509050919050565b600080516020613f1e83398151915261148a8161265e565b6000600a84815481106114ad57634e487b7160e01b600052603260045260246000fd5b600091825260209091200190506001815460ff1660068111156114e057634e487b7160e01b600052602160045260246000fd5b1461152d5760405162461bcd60e51b815260206004820152601960248201527f526166666c65206973206e6f7420696e206163636570746564000000000000006044820152606401610a89565b82516000805b8281101561162f57600086828151811061155d57634e487b7160e01b600052603260045260246000fd5b6020026020010151905060006040518060400160405280848860000160029054906101000a900465ffffffffffff1665ffffffffffff1661159e9190613d40565b6115a9906001613d40565b65ffffffffffff90811682526001600160a01b0380861660209384015260008d8152600884526040812080546001810182559082529084902085519101805494860151909216600160301b026001600160d01b0319909416921691909117919091179055905061161884613e76565b93505050808061162790613e5b565b915050611533565b50825461164b90829062010000900465ffffffffffff16613d58565b835467ffffffffffff000019166201000065ffffffffffff92831681029190911780865560405189937f4da4f5fab0816c65315b6f5d15f879f96b98661133d7b3787788f291367604fb936116ab938b9389939290910490911690613b64565b60405180910390a2505050505050565b600a81815481106116cb57600080fd5b60009182526020909120015460ff80821692506101008204169062010000810465ffffffffffff1690600160401b90046001600160801b031684565b60006117128261266b565b9050600061171e612942565b905061117583836040015165ffffffffffff1683604080518082018252938452602080850193845260009283526005905290209151825551600190910155565b6009818154811061176e57600080fd5b60009182526020909120600590910201805460018201546002830154600384015460049094015465ffffffffffff909316945090926001600160a01b039182169291169085565b600080516020613f1e8339815191526117cd8161265e565b6000600983815481106117f057634e487b7160e01b600052603260045260246000fd5b906000526020600020906005020190506000600a848154811061182357634e487b7160e01b600052603260045260246000fd5b600091825260209091200190506005815460ff16600681111561185657634e487b7160e01b600052602160045260246000fd5b1415801561188857506003815460ff16600681111561188557634e487b7160e01b600052602160045260246000fd5b14155b80156118b857506002815460ff1660068111156118b557634e487b7160e01b600052602160045260246000fd5b14155b80156118e857506004815460ff1660068111156118e557634e487b7160e01b600052602160045260246000fd5b14155b801561191857506006815460ff16600681111561191557634e487b7160e01b600052602160045260246000fd5b14155b6119535760405162461bcd60e51b815260206004820152600c60248201526b57726f6e672073746174757360a01b6044820152606401610a89565b6001815460ff16600681111561197957634e487b7160e01b600052602160045260246000fd5b14156119fa57600382015460018301546040516000926001600160a01b031691908381818185875af1925050503d80600081146119d2576040519150601f19603f3d011682016040523d82523d6000602084013e6119d7565b606091505b50509050806119f85760405162461bcd60e51b8152600401610a8990613c96565b505b805460ff19166006178082556040516001600160801b03600160401b90920491909116815284907fd512a34b0f0618078770fcd85d974df1ab46a7882e8b3d45aa91764f4961aed29060200160405180910390a250505050565b6000600080516020613f1e833981519152611a6e8161265e565b6113888465ffffffffffff161115611abe5760405162461bcd60e51b81526020600482015260136024820152720c6dedadad2e6e6d2dedc40e8dede40d0d2ced606b1b6044820152606401610a89565b6040805160a08101825265ffffffffffff8681168252602082018b81526000938301848152606084018581526080850186815260098054600181018255975285517f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7af6005909802978801805465ffffffffffff1916919096161790945591517f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7b0860155517f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7b1850180546001600160a01b03199081166001600160a01b039384161790915591517f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7b2860180549093169116179055517f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7b390920191909155611c0384612b3b565b600954600090611c1590600190613e01565b905086611c505760405162461bcd60e51b81526020600482015260096024820152684e6f2070726963657360b81b6044820152606401610a89565b60005b87811015611de9576000898983818110611c7d57634e487b7160e01b600052603260045260246000fd5b9050606002016020016020810190611c959190613a12565b65ffffffffffff1611611cdc5760405162461bcd60e51b815260206004820152600f60248201526e06e756d456e7472696573206973203608c1b6044820152606401610a89565b600060405180606001604052808481526020018b8b85818110611d0f57634e487b7160e01b600052603260045260246000fd5b9050606002016020016020810190611d279190613a12565b65ffffffffffff1681526020018b8b85818110611d5457634e487b7160e01b600052603260045260246000fd5b90506060020160400135815250905080600660008c8c86818110611d8857634e487b7160e01b600052603260045260246000fd5b60600291909101358252506020808201929092526040908101600020835181559183015160018301805465ffffffffffff191665ffffffffffff90921691909117905591909101516002909101555080611de181613e5b565b915050611c53565b506040805180820182526001600160801b03808c1682528d8116602080840191825260008681526007909152848120935191518316600160801b02919092161790915590518b9183917ff6f5afeb49bc62176d1efaa06a1753999cc29bf378f1004ea916f37f41d7638a9190a360408051808201825260018082523360208084019182526000868152600882529485208054938401815580865290852084519301805492516001600160a01b0316600160301b026001600160d01b031990931665ffffffffffff949094169390931791909117909155838352805491929091611ee257634e487b7160e01b600052603260045260246000fd5b600091825260209091200180546001600160d01b0319169055509a9950505050505050505050565b6000600a8281548110611f2d57634e487b7160e01b600052603260045260246000fd5b906000526020600020019050600060098381548110611f5c57634e487b7160e01b600052603260045260246000fd5b6000918252602082206005909102019150825460ff166006811115611f9157634e487b7160e01b600052602160045260246000fd5b14611fd35760405162461bcd60e51b8152602060048201526012602482015271149859999b19481b9bdd0810d4915055115160721b6044820152606401610a89565b348160010154146120195760405162461bcd60e51b815260206004820152601060248201526f141c9a5e99481b9bdd081cdd185ad95960821b6044820152606401610a89565b815460ff19166001178255600381018054336001600160a01b0319909116811790915560405184907f8bb509eedfd1c4847b0a8a2b4493cf2ebb9970dc367e477cd2a8523e212dc1db90600090a3505050565b60006120778161265e565b50600b80546001600160a01b0319166001600160a01b0392909216919091179055565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b6120ef604080516080810190915280600081526020016000815260006020820181905260409091015290565b600a828154811061211057634e487b7160e01b600052603260045260246000fd5b60009182526020909120604080516080810190915291018054829060ff16600681111561214d57634e487b7160e01b600052602160045260246000fd5b600681111561216c57634e487b7160e01b600052602160045260246000fd5b81528154602090910190610100900460ff16600281111561219d57634e487b7160e01b600052602160045260246000fd5b60028111156121bc57634e487b7160e01b600052602160045260246000fd5b8152905462010000810465ffffffffffff166020830152600160401b90046001600160801b031660409091015292915050565b336001600160a01b037f000000000000000000000000f0d54349addcf704f77ae15b96510dea15cb795216146122675760405162461bcd60e51b815260206004820152601f60248201527f4f6e6c7920565246436f6f7264696e61746f722063616e2066756c66696c6c006044820152606401610a89565b6113e08282612c7b565b60008281526020819052604090206001015461228c8161265e565b6111758383612ad6565b600080516020613f1e8339815191526122ae8161265e565b6000805b848110156124775760008781526008602052604081208787848181106122e857634e487b7160e01b600052603260045260246000fd5b9050602002013560016122fb9190613d40565b8154811061231957634e487b7160e01b600052603260045260246000fd5b600091825260209091200180549091506001600160a01b03868116600160301b909204161461238a5760405162461bcd60e51b815260206004820152601e60248201527f456e74727920646964206e6f742062656c6f6e6720746f20706c6179657200006044820152606401610a89565b80546601000000000000600160d01b031916815560008787848181106123c057634e487b7160e01b600052603260045260246000fd5b90506020020135600014156123d757506000612441565b600089815260086020526040902088888581811061240557634e487b7160e01b600052603260045260246000fd5b905060200201358154811061242a57634e487b7160e01b600052603260045260246000fd5b60009182526020909120015465ffffffffffff1690505b815461245690829065ffffffffffff16613e01565b6124609085613d40565b93505050808061246f90613e5b565b9150506122b2565b50604080518281526001600160a01b038516602082015287917f2cca80c1af5abb202a642a502875436822768d733462843a7c3a902b0fad99d091016116ab565b600082815260086020526040812081906124d29084612d38565b6000858152600860205260408120805492935090918390811061250557634e487b7160e01b600052603260045260246000fd5b600091825260209091200154600160301b90046001600160a01b0316905080156125325791506108f09050565b6000825b8115801561258b5750600087815260086020526040812080548390811061256d57634e487b7160e01b600052603260045260246000fd5b600091825260209091200154600160301b90046001600160a01b0316145b156125c257806125b7576000878152600860205260409020546125b090600190613e01565b9050612536565b6125b0600182613e01565b81156126085760405162461bcd60e51b8152602060048201526015602482015274105b1b081d5cd95c9cc8189b1858dadb1a5cdd1959605a1b6044820152606401610a89565b600087815260086020526040902080548290811061263657634e487b7160e01b600052603260045260246000fd5b600091825260209091200154600160301b90046001600160a01b031694506108f09350505050565b6126688133612e29565b50565b612697604080516080810190915280600081526020016000815260006020820181905260409091015290565b6000600a83815481106126ba57634e487b7160e01b600052603260045260246000fd5b6000918252602080832086845260079091526040909220910191506001825460ff1660068111156126fb57634e487b7160e01b600052602160045260246000fd5b146127415760405162461bcd60e51b8152602060048201526016602482015275526166666c6520696e2077726f6e672073746174757360501b6044820152606401610a89565b805482546001600160801b03918216600160401b90910490911610156127a95760405162461bcd60e51b815260206004820152601760248201527f4e6f7420656e6f7567682066756e6473207261697365640000000000000000006044820152606401610a89565b81548154600160401b9091046001600160801b03908116600160801b9092041611156128175760405162461bcd60e51b815260206004820152601860248201527f446573697265642066756e6473206e6f742072616973656400000000000000006044820152606401610a89565b815460ff19166004178083556040516001600160801b03600160401b90920491909116815284907ff2be214756d2fbc1e781d10809ddef33000009d805be55356bb348134ce21c689060200160405180910390a2604080516080810190915282548390829060ff16600681111561289e57634e487b7160e01b600052602160045260246000fd5b60068111156128bd57634e487b7160e01b600052602160045260246000fd5b81528154602090910190610100900460ff1660028111156128ee57634e487b7160e01b600052602160045260246000fd5b600281111561290d57634e487b7160e01b600052602160045260246000fd5b8152905462010000810465ffffffffffff166020830152600160401b90046001600160801b0316604090910152949350505050565b6003546040516370a0823160e01b8152306004820152600091906001600160a01b037f000000000000000000000000514910771af9ca656af840dff83e8264ecf986ca16906370a082319060240160206040518083038186803b1580156129a857600080fd5b505afa1580156129bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129e0919061385b565b1015612a425760405162461bcd60e51b815260206004820152602b60248201527f4e6f7420656e6f756768204c494e4b202d2066696c6c20636f6e74726163742060448201526a1dda5d1a0819985d58d95d60aa1b6064820152608401610a89565b60006108f0600254600354612e8d565b612a5c828261209a565b6113e0576000828152602081815260408083206001600160a01b03851684529091529020805460ff19166001179055612a923390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b612ae0828261209a565b156113e0576000828152602081815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b604080516080810190915260009080828152602001836002811115612b7057634e487b7160e01b600052602160045260246000fd5b81526000602082018190526040909101819052600a8054600181810183559190925282517fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a890920180549394508493909291839160ff191690836006811115612be957634e487b7160e01b600052602160045260246000fd5b021790555060208201518154829061ff001916610100836002811115612c1f57634e487b7160e01b600052602160045260246000fd5b0217905550604082015181546060909301516001600160801b0316600160401b02600160401b600160c01b031965ffffffffffff90921662010000029190911662010000600160c01b0319909316929092179190911790555050565b6000828152600560209081526040808320815180830190925280548252600101549181018290529190612cae9084613e9c565b612cb9906001613d40565b60408051808201825285815260208082018481528651600090815260048352849020835181559051600190910155855183518881529182018590529394509092917f7c40e661b8212d0c4f60ac6e6ebed99c28680c7b3ede5b82f3b0254543f62fca910160405180910390a28251612d31908361301f565b5050505050565b8154600090612d49575060006108f0565b82546000905b80821015612dbc576000612d6383836133dc565b905084868281548110612d8657634e487b7160e01b600052603260045260246000fd5b60009182526020909120015465ffffffffffff161115612da857809150612db6565b612db3816001613d40565b92505b50612d4f565b600082118015612e0857508385612dd4600185613e01565b81548110612df257634e487b7160e01b600052603260045260246000fd5b60009182526020909120015465ffffffffffff16145b15612e2157612e18600183613e01565b925050506108f0565b5090506108f0565b612e33828261209a565b6113e057612e4b816001600160a01b031660146133fe565b612e568360206133fe565b604051602001612e67929190613abf565b60408051601f198184030181529082905262461bcd60e51b8252610a8991600401613c83565b60007f000000000000000000000000514910771af9ca656af840dff83e8264ecf986ca6001600160a01b0316634000aea07f000000000000000000000000f0d54349addcf704f77ae15b96510dea15cb795284866000604051602001612efd929190918252602082015260400190565b6040516020818303038152906040526040518463ffffffff1660e01b8152600401612f2a93929190613b34565b602060405180830381600087803b158015612f4457600080fd5b505af1158015612f58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f7c91906136ee565b50600083815260016020818152604080842054815180840189905280830186905230606082015260808082018390528351808303909101815260a09091019092528151918301919091209387905290829052612fd791613d40565b6000858152600160205260409020556130178482604080516020808201949094528082019290925280518083038201815260609092019052805191012090565b949350505050565b60006009838154811061304257634e487b7160e01b600052603260045260246000fd5b906000526020600020906005020190506000600a848154811061307557634e487b7160e01b600052603260045260246000fd5b600091825260209091200190506002815460ff1660068111156130a857634e487b7160e01b600052602160045260246000fd5b14806130d757506004815460ff1660068111156130d557634e487b7160e01b600052602160045260246000fd5b145b61311c5760405162461bcd60e51b8152602060048201526016602482015275526166666c6520696e2077726f6e672073746174757360501b6044820152606401610a89565b6004820183905561312d84846124b8565b6002830180546001600160a01b039283166001600160a01b0319909116178155825460ff1916600517835554600184015460405160009392909216918381818185875af1925050503d80600081146131a1576040519150601f19603f3d011682016040523d82523d6000602084013e6131a6565b606091505b50509050806131c75760405162461bcd60e51b8152600401610a8990613c96565b82548254600091612710916131f49165ffffffffffff1690600160401b90046001600160801b0316613db3565b6131fe9190613d79565b83546001600160801b039182169250600091613224918491600160401b90910416613e01565b60038601546040519192506000916001600160a01b039091169083908381818185875af1925050503d8060008114613278576040519150601f19603f3d011682016040523d82523d6000602084013e61327d565b606091505b505090508061329e5760405162461bcd60e51b8152600401610a8990613c96565b600b546040516000916001600160a01b03169085908381818185875af1925050503d80600081146132eb576040519150601f19603f3d011682016040523d82523d6000602084013e6132f0565b606091505b50509050806133395760405162461bcd60e51b81526020600482015260156024820152744661696c65642073656e642045746820746f204d5760581b6044820152606401610a89565b887f7378e11c2b0ec7514bbf7ba369980eedcba0bca03e116dc9e7138f7748e211d68560405161336b91815260200190565b60405180910390a26002870154865460408051600160401b9092046001600160801b03168252602082018b90526001600160a01b03909216918b917fe0b2a72a0644b093aac275024c05c7c28851a0b572557a32241d13634a0f3e08910160405180910390a3505050505050505050565b60006133eb6002848418613d9f565b6133f790848416613d40565b9392505050565b6060600061340d836002613de2565b613418906002613d40565b67ffffffffffffffff81111561343e57634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f191660200182016040528015613468576020820181803683370190505b509050600360fc1b8160008151811061349157634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a905350600f60fb1b816001815181106134ce57634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a90535060006134f2846002613de2565b6134fd906001613d40565b90505b6001811115613591576f181899199a1a9b1b9c1cb0b131b232b360811b85600f166010811061353f57634e487b7160e01b600052603260045260246000fd5b1a60f81b82828151811061356357634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a90535060049490941c9361358a81613e44565b9050613500565b5083156133f75760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610a89565b80356135eb81613f08565b919050565b8035600381106135eb57600080fd5b80356001600160801b03811681146135eb57600080fd5b803565ffffffffffff811681146135eb57600080fd5b60006020828403121561363d578081fd5b81356133f781613f08565b6000806040838503121561365a578081fd5b823561366581613f08565b946020939093013593505050565b60008060008060808587031215613688578182fd5b843561369381613f08565b93506020850135925060408501356136aa81613f08565b9396929550929360600135925050565b6000806000606084860312156136ce578283fd5b83356136d981613f08565b95602085013595506040909401359392505050565b6000602082840312156136ff578081fd5b815180151581146133f7578182fd5b60006020828403121561371f578081fd5b5035919050565b60008060408385031215613738578182fd5b82359150602083013561374a81613f08565b809150509250929050565b60008060408385031215613767578182fd5b50508035926020909101359150565b600060208284031215613787578081fd5b81356001600160e01b0319811681146133f7578182fd5b600080600080600080600060c0888a0312156137b8578283fd5b6137c1886135ff565b9650602088013595506137d6604089016135ff565b9450606088013567ffffffffffffffff808211156137f2578485fd5b818a0191508a601f830112613805578485fd5b813581811115613813578586fd5b8b6020606083028501011115613827578586fd5b60208301965080955050505061383f60808901613616565b915061384d60a089016135f0565b905092959891949750929550565b60006020828403121561386c578081fd5b5051919050565b60008060408385031215613885578182fd5b8235915060208084013567ffffffffffffffff808211156138a4578384fd5b818601915086601f8301126138b7578384fd5b8135818111156138c9576138c9613ef2565b8060051b604051601f19603f830116810181811085821117156138ee576138ee613ef2565b604052828152858101935084860182860187018b101561390c578788fd5b8795505b8386101561393557613921816135e0565b855260019590950194938601938601613910565b508096505050505050509250929050565b6000806000806060858703121561395b578182fd5b84359350602085013567ffffffffffffffff80821115613979578384fd5b818701915087601f83011261398c578384fd5b81358181111561399a578485fd5b8860208260051b85010111156139ae578485fd5b60208301955080945050505060408501356139c881613f08565b939692955090935050565b6000806000606084860312156139e7578081fd5b833592506139f760208501613616565b91506040840135613a0781613f08565b809150509250925092565b600060208284031215613a23578081fd5b6133f782613616565b6000815180845260208085019450808401835b83811015613a645781516001600160a01b031687529582019590820190600101613a3f565b509495945050505050565b60008151808452613a87816020860160208601613e18565b601f01601f19169290920160200192915050565b60038110613aab57613aab613edc565b9052565b60078110613aab57613aab613edc565b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000815260008351613af7816017850160208801613e18565b7001034b99036b4b9b9b4b733903937b6329607d1b6017918401918201528351613b28816028840160208801613e18565b01602801949350505050565b60018060a01b0384168152826020820152606060408201526000613b5b6060830184613a6f565b95945050505050565b606081526000613b776060830186613a2c565b905083602083015265ffffffffffff83166040830152949350505050565b606081526000613ba86060830186613a2c565b65ffffffffffff94851660208401529290931660409091015292915050565b602080825282518282018190526000919060409081850190868401855b82811015613c1a578151805165ffffffffffff1685528601516001600160a01b0316868501529284019290850190600101613be4565b5091979650505050505050565b82151581526040602082015260006130176040830184613a6f565b60808101613c508287613aaf565b613c5d6020830186613a9b565b65ffffffffffff841660408301526001600160801b038316606083015295945050505050565b6020815260006133f76020830184613a6f565b6020808252601490820152732330b4b632b2103a379039b2b7321022ba3432b960611b604082015260600190565b6000608082019050613cd7828451613aaf565b6020830151613ce96020840182613a9b565b5065ffffffffffff60408401511660408301526001600160801b03606084015116606083015292915050565b60006001600160801b03808316818516808303821115613d3757613d37613eb0565b01949350505050565b60008219821115613d5357613d53613eb0565b500190565b600065ffffffffffff808316818516808303821115613d3757613d37613eb0565b60006001600160801b0380841680613d9357613d93613ec6565b92169190910492915050565b600082613dae57613dae613ec6565b500490565b60006001600160801b0380831681851681830481118215151615613dd957613dd9613eb0565b02949350505050565b6000816000190483118215151615613dfc57613dfc613eb0565b500290565b600082821015613e1357613e13613eb0565b500390565b60005b83811015613e33578181015183820152602001613e1b565b83811115610cba5750506000910152565b600081613e5357613e53613eb0565b506000190190565b6000600019821415613e6f57613e6f613eb0565b5060010190565b600065ffffffffffff80831681811415613e9257613e92613eb0565b6001019392505050565b600082613eab57613eab613ec6565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b038116811461266857600080fdfe523a704056dcd17bcf83bed8b68c59416dac1119be77755efe3bde0a64e46e0ca2646970667358221220c02bb1e500344175aec911bacd64ba965d4d19bd5b66a71237debc237a37fc2564736f6c63430008040033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000f0d54349addcf704f77ae15b96510dea15cb7952000000000000000000000000514910771af9ca656af840dff83e8264ecf986caaa77729d3466ca35ae8d28b3bbac7cc36a5031efdc430821c02bc31a238af4450000000000000000000000000000000000000000000000000000000000000001
-----Decoded View---------------
Arg [0] : _vrfCoordinator (address): 0xf0d54349aDdcf704F77AE15b96510dEA15cb7952
Arg [1] : _linkToken (address): 0x514910771AF9Ca656af840dff83E8264EcF986CA
Arg [2] : _keyHash (bytes32): 0xaa77729d3466ca35ae8d28b3bbac7cc36a5031efdc430821c02bc31a238af445
Arg [3] : _mainetFee (bool): True
-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 000000000000000000000000f0d54349addcf704f77ae15b96510dea15cb7952
Arg [1] : 000000000000000000000000514910771af9ca656af840dff83e8264ecf986ca
Arg [2] : aa77729d3466ca35ae8d28b3bbac7cc36a5031efdc430821c02bc31a238af445
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000001
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.