Feature Tip: Add private address tag to any address under My Name Tag !
Overview
ETH Balance
1.48752 ETH
Eth Value
$4,979.94 (@ $3,347.81/ETH)Token Holdings
More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 4,076 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Refund | 19608958 | 228 days ago | IN | 0 ETH | 0.00107819 | ||||
Claim Prizes | 19166110 | 291 days ago | IN | 0 ETH | 0.00163649 | ||||
Claim Prizes | 19059573 | 306 days ago | IN | 0 ETH | 0.0008426 | ||||
Enter | 19038556 | 309 days ago | IN | 0 ETH | 0.00281658 | ||||
Claim Prizes | 19033527 | 309 days ago | IN | 0 ETH | 0.00182502 | ||||
Enter | 19033243 | 309 days ago | IN | 0.03 ETH | 0.0009272 | ||||
Enter | 19033240 | 309 days ago | IN | 0.03 ETH | 0.00092938 | ||||
Enter | 19033238 | 309 days ago | IN | 0.03 ETH | 0.00098399 | ||||
Claim Prizes | 19030884 | 310 days ago | IN | 0 ETH | 0.00173021 | ||||
Claim Prizes | 19030524 | 310 days ago | IN | 0 ETH | 0.00278943 | ||||
Claim Prizes | 19030368 | 310 days ago | IN | 0 ETH | 0.00229531 | ||||
Reveal | 19030366 | 310 days ago | IN | 0 ETH | 0.00561919 | ||||
Enter | 19030354 | 310 days ago | IN | 0 ETH | 0.00670361 | ||||
Enter | 19028366 | 310 days ago | IN | 0 ETH | 0.00427602 | ||||
Enter | 19015293 | 312 days ago | IN | 0 ETH | 0.00216116 | ||||
Claim Prizes | 19014819 | 312 days ago | IN | 0 ETH | 0.00125444 | ||||
Enter | 19014479 | 312 days ago | IN | 0 ETH | 0.00280239 | ||||
Claim Prizes | 19014399 | 312 days ago | IN | 0 ETH | 0.0022732 | ||||
Reveal | 19014351 | 312 days ago | IN | 0 ETH | 0.00472756 | ||||
Enter | 19014344 | 312 days ago | IN | 0 ETH | 0.00610845 | ||||
Enter | 19014324 | 312 days ago | IN | 0 ETH | 0.003486 | ||||
Enter | 19013144 | 312 days ago | IN | 0 ETH | 0.00276062 | ||||
Claim Prizes | 19012520 | 312 days ago | IN | 0 ETH | 0.00196675 | ||||
Claim Prizes | 19009964 | 313 days ago | IN | 0 ETH | 0.00110239 | ||||
Reveal | 19009939 | 313 days ago | IN | 0 ETH | 0.00276316 |
Latest 25 internal transactions (View All)
Advanced mode:
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
18978982 | 317 days ago | 0.0000195 ETH | ||||
18977486 | 317 days ago | 1 ETH | ||||
18972964 | 318 days ago | 1 ETH | ||||
18962701 | 319 days ago | 0.25 ETH | ||||
18789614 | 343 days ago | 1.19 ETH | ||||
18772307 | 346 days ago | 2 ETH | ||||
18760805 | 347 days ago | 1.19 ETH | ||||
18752577 | 349 days ago | 0.2975 ETH | ||||
18752574 | 349 days ago | 0.2975 ETH | ||||
18752569 | 349 days ago | 0.2975 ETH | ||||
18749557 | 349 days ago | 0.2975 ETH | ||||
18749286 | 349 days ago | 0.595 ETH | ||||
18749207 | 349 days ago | 0.0125 ETH | ||||
18742733 | 350 days ago | 0.19 ETH | ||||
18742730 | 350 days ago | 1.19 ETH | ||||
18742723 | 350 days ago | 0.05 ETH | ||||
18741454 | 350 days ago | 0.2975 ETH | ||||
18740158 | 350 days ago | 0.2975 ETH | ||||
18739757 | 350 days ago | 0.2975 ETH | ||||
18739752 | 350 days ago | 0.2975 ETH | ||||
18739748 | 350 days ago | 0.0125 ETH | ||||
18731034 | 352 days ago | 2.95 ETH | ||||
18728105 | 352 days ago | 2.95 ETH | ||||
18727844 | 352 days ago | 0.1 ETH | ||||
18710940 | 354 days ago | 0.2975 ETH |
Loading...
Loading
Contract Name:
PokeTheBear
Compiler Version
v0.8.20+commit.a1b79de6
Optimization Enabled:
Yes with 888888 runs
Other Settings:
london EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity 0.8.20; import {LowLevelWETH} from "@looksrare/contracts-libs/contracts/lowLevelCallers/LowLevelWETH.sol"; import {LowLevelERC20Transfer} from "@looksrare/contracts-libs/contracts/lowLevelCallers/LowLevelERC20Transfer.sol"; import {PackableReentrancyGuard} from "@looksrare/contracts-libs/contracts/PackableReentrancyGuard.sol"; import {Pausable} from "@looksrare/contracts-libs/contracts/Pausable.sol"; import {ITransferManager} from "@looksrare/contracts-transfer-manager/contracts/interfaces/ITransferManager.sol"; import {AccessControl} from "@openzeppelin/contracts/access/AccessControl.sol"; import {VRFCoordinatorV2Interface} from "@chainlink/contracts/src/v0.8/interfaces/VRFCoordinatorV2Interface.sol"; import {VRFConsumerBaseV2} from "@chainlink/contracts/src/v0.8/VRFConsumerBaseV2.sol"; import {IPokeTheBear} from "./interfaces/IPokeTheBear.sol"; // ∩___∩ // |ノ ヽ // / ● ● | クマ──!! // | (_●_) ミ // 彡、 |∪| 、`\ // / __ ヽノ /´> ) // (___) / (_/ // | / // | /\ \ // | / ) ) // ∪ ( \ // \_) /** * @title Poke The Bear, a bear might maul you to death if you poke it. * @author LooksRare protocol team (👀,💎) */ contract PokeTheBear is IPokeTheBear, AccessControl, Pausable, PackableReentrancyGuard, LowLevelERC20Transfer, LowLevelWETH, VRFConsumerBaseV2 { /** * @notice Operators are allowed to commit rounds */ bytes32 private constant OPERATOR_ROLE = keccak256("OPERATOR_ROLE"); /** * @notice 100% in basis points. */ uint256 private constant ONE_HUNDRED_PERCENT_IN_BASIS_POINTS = 10_000; /** * @notice The maximum number of players per round. */ uint256 private constant MAXIMUM_NUMBER_OF_PLAYERS_PER_ROUND = 32; /** * @notice The minimum duration for a round. */ uint40 private constant MINIMUM_ROUND_DURATION = 1 minutes; /** * @notice The maximum duration for a round. */ uint40 private constant MAXIMUM_ROUND_DURATION = 1 hours; /** * @notice Wrapped native token address. (WETH for most chains) */ address private immutable WRAPPED_NATIVE_TOKEN; /** * @notice The key hash of the Chainlink VRF. */ bytes32 private immutable KEY_HASH; /** * @notice The subscription ID of the Chainlink VRF. */ uint64 private immutable SUBSCRIPTION_ID; /** * @notice The Chainlink VRF coordinator. */ VRFCoordinatorV2Interface private immutable VRF_COORDINATOR; /** * @notice The transfer manager to handle ERC-20 deposits. */ ITransferManager private immutable TRANSFER_MANAGER; mapping(uint256 requestId => RandomnessRequest) public randomnessRequests; mapping(uint256 caveId => mapping(uint256 => Round)) private rounds; /** * @notice Player participations in each round. * @dev 65,536 x 256 = 16,777,216 rounds, which is enough for 5 minutes rounds for 159 years. */ mapping(address playerAddress => mapping(uint256 caveId => uint256[65536] roundIds)) private playerParticipations; mapping(uint256 caveId => Cave) public caves; /** * @notice The address of the protocol fee recipient. */ address public protocolFeeRecipient; /** * @notice The next cave ID. */ uint256 public nextCaveId = 1; /** * @param _owner The owner of the contract. * @param _protocolFeeRecipient The address of the protocol fee recipient. * @param wrappedNativeToken The wrapped native token address. * @param _transferManager The transfer manager to handle ERC-20 deposits. * @param keyHash The key hash of the Chainlink VRF. * @param vrfCoordinator The Chainlink VRF coordinator. * @param subscriptionId The subscription ID of the Chainlink VRF. */ constructor( address _owner, address _operator, address _protocolFeeRecipient, address wrappedNativeToken, address _transferManager, bytes32 keyHash, address vrfCoordinator, uint64 subscriptionId ) VRFConsumerBaseV2(vrfCoordinator) { _grantRole(DEFAULT_ADMIN_ROLE, _owner); _grantRole(OPERATOR_ROLE, _operator); WRAPPED_NATIVE_TOKEN = wrappedNativeToken; KEY_HASH = keyHash; VRF_COORDINATOR = VRFCoordinatorV2Interface(vrfCoordinator); SUBSCRIPTION_ID = subscriptionId; TRANSFER_MANAGER = ITransferManager(_transferManager); _updateProtocolFeeRecipient(_protocolFeeRecipient); } /** * @inheritdoc IPokeTheBear */ function addCave( uint256 enterAmount, address enterCurrency, uint8 playersPerRound, uint40 roundDuration, uint16 protocolFeeBp ) external returns (uint256 caveId) { _validateIsOwner(); if (playersPerRound < 2) { revert InsufficientNumberOfPlayers(); } if (playersPerRound > MAXIMUM_NUMBER_OF_PLAYERS_PER_ROUND) { revert ExceedsMaximumNumberOfPlayersPerRound(); } if (protocolFeeBp > 2_500) { revert ProtocolFeeBasisPointsTooHigh(); } unchecked { if ( (enterAmount - ((enterAmount * protocolFeeBp) / ONE_HUNDRED_PERCENT_IN_BASIS_POINTS)) % (playersPerRound - 1) != 0 ) { revert IndivisibleEnterAmount(); } } if (roundDuration < MINIMUM_ROUND_DURATION || roundDuration > MAXIMUM_ROUND_DURATION) { revert InvalidRoundDuration(); } caveId = nextCaveId; caves[caveId].enterAmount = enterAmount; caves[caveId].enterCurrency = enterCurrency; caves[caveId].playersPerRound = playersPerRound; caves[caveId].roundDuration = roundDuration; caves[caveId].protocolFeeBp = protocolFeeBp; caves[caveId].isActive = true; _open({caveId: caveId, roundId: 1}); unchecked { ++nextCaveId; } emit CaveAdded(caveId, enterAmount, enterCurrency, roundDuration, playersPerRound, protocolFeeBp); } /** * @inheritdoc IPokeTheBear */ function removeCave(uint256 caveId) external { _validateIsOwner(); Cave storage cave = caves[caveId]; if (cave.roundsCount < cave.lastCommittedRoundId) { revert RoundsIncomplete(); } caves[caveId].isActive = false; emit CaveRemoved(caveId); } /** * @inheritdoc IPokeTheBear */ function commit(CommitmentCalldata[] calldata commitments) external { _validateIsOperator(); uint256 commitmentsLength = commitments.length; for (uint256 i; i < commitmentsLength; ) { uint256 caveId = commitments[i].caveId; Cave storage cave = caves[caveId]; if (!cave.isActive) { revert InactiveCave(); } uint256 startingRoundId = cave.lastCommittedRoundId + 1; bytes32[] calldata perCaveCommitments = commitments[i].commitments; uint256 perCaveCommitmentsLength = perCaveCommitments.length; for (uint256 j; j < perCaveCommitmentsLength; ) { uint256 roundId = startingRoundId + j; bytes32 commitment = perCaveCommitments[j]; if (commitment == bytes32(0)) { revert InvalidCommitment(caveId, roundId); } rounds[caveId][roundId].commitment = commitment; unchecked { ++j; } } cave.lastCommittedRoundId = uint40(startingRoundId + perCaveCommitmentsLength - 1); unchecked { ++i; } } emit CommitmentsSubmitted(commitments); } /** * @inheritdoc IPokeTheBear */ function updateProtocolFeeRecipient(address _protocolFeeRecipient) external { _validateIsOwner(); _updateProtocolFeeRecipient(_protocolFeeRecipient); } /** * @inheritdoc IPokeTheBear * @notice As rounds to enter are in numerical order and cannot be skipped, entering multiple rounds can revert when a round in between is already filled. Resolve by sending multiple transactions of consecutive rounds if such issue exists. Fee on transfer tokens will not be supported. * @dev Players can still deposit into the round past the cutoff time. Only when other players start withdrawing * or deposit into the next round, the current round will be cancelled and no longer accept deposits. */ function enter( uint256 caveId, uint256 startingRoundId, uint256 numberOfRounds ) external payable nonReentrant whenNotPaused { Cave storage cave = caves[caveId]; address enterCurrency = cave.enterCurrency; uint256 enterAmount = cave.enterAmount * numberOfRounds; if (enterCurrency == address(0)) { if (msg.value != enterAmount) { revert InvalidEnterAmount(); } } else { if (msg.value != 0) { revert InvalidEnterCurrency(); } TRANSFER_MANAGER.transferERC20(enterCurrency, msg.sender, address(this), enterAmount); } _enter(caveId, startingRoundId, numberOfRounds); } /** * @inheritdoc IPokeTheBear * @dev Player index starts from 1 as the array has a fixed length of 32 and * 0 is used to indicate an empty slot. */ function reveal(uint256 requestId, uint256 playerIndices, bytes32 salt) external whenNotPaused { RandomnessRequest storage randomnessRequest = randomnessRequests[requestId]; uint256 caveId = randomnessRequest.caveId; uint256 roundId = randomnessRequest.roundId; Round storage round = rounds[caveId][roundId]; if (round.status != RoundStatus.Drawn) { revert InvalidRoundStatus(); } if (keccak256(abi.encodePacked(playerIndices, salt)) != round.commitment) { revert HashedPlayerIndicesDoesNotMatchCommitment(); } uint256 numberOfPlayers = round.players.length; uint256 losingIndex = (randomnessRequest.randomWord % numberOfPlayers) + 1; // Check numbers are nonrepeating and within the range uint256 playerIndicesBitmap; for (uint256 i; i < numberOfPlayers; ) { uint8 playerIndex = uint8(playerIndices >> (i * 8)); // Player index starts from 1 if (playerIndex == 0 || playerIndex > numberOfPlayers) { revert InvalidPlayerIndex(caveId, roundId); } uint256 bitmask = 1 << playerIndex; if (playerIndicesBitmap & bitmask != 0) { revert RepeatingPlayerIndex(); } playerIndicesBitmap |= bitmask; round.playerIndices[i] = playerIndex; if (playerIndex == losingIndex) { round.players[i].isLoser = true; } unchecked { ++i; } } round.salt = salt; round.status = RoundStatus.Revealed; emit RoundStatusUpdated(caveId, roundId, RoundStatus.Revealed); Cave storage cave = caves[caveId]; _transferTokens( protocolFeeRecipient, cave.enterCurrency, (cave.enterAmount * cave.protocolFeeBp) / ONE_HUNDRED_PERCENT_IN_BASIS_POINTS ); _open(caveId, _unsafeAdd(roundId, 1)); } /** * @inheritdoc IPokeTheBear */ function refund(WithdrawalCalldata[] calldata refundCalldataArray) external nonReentrant whenNotPaused { TransferAccumulator memory transferAccumulator; uint256 refundCount = refundCalldataArray.length; Withdrawal[] memory withdrawalEventData = new Withdrawal[](refundCount); for (uint256 i; i < refundCount; ) { WithdrawalCalldata calldata refundCalldata = refundCalldataArray[i]; uint256 caveId = refundCalldata.caveId; Cave storage cave = caves[caveId]; uint256 roundsCount = refundCalldata.playerDetails.length; Withdrawal memory withdrawal = withdrawalEventData[i]; withdrawal.caveId = caveId; withdrawal.roundIds = new uint256[](roundsCount); for (uint256 j; j < roundsCount; ) { PlayerWithdrawalCalldata calldata playerDetails = refundCalldata.playerDetails[j]; uint256 roundId = playerDetails.roundId; Round storage round = rounds[caveId][roundId]; RoundStatus roundStatus = round.status; uint256 currentNumberOfPlayers = round.players.length; { if (roundStatus < RoundStatus.Revealed) { if (!_cancellable(round, roundStatus, cave.playersPerRound, currentNumberOfPlayers)) { revert InvalidRoundStatus(); } _cancel(caveId, roundId); } uint256 playerIndex = playerDetails.playerIndex; if (playerIndex >= currentNumberOfPlayers) { revert InvalidPlayerIndex(caveId, roundId); } Player storage player = round.players[playerIndex]; _validatePlayerCanWithdraw(caveId, roundId, player); player.withdrawn = true; } withdrawal.roundIds[j] = roundId; unchecked { ++j; } } _accumulateOrTransferTokenOut(cave.enterAmount * roundsCount, cave.enterCurrency, transferAccumulator); unchecked { ++i; } } if (transferAccumulator.amount != 0) { _transferTokens(msg.sender, transferAccumulator.tokenAddress, transferAccumulator.amount); } emit DepositsRefunded(withdrawalEventData, msg.sender); } /** * @inheritdoc IPokeTheBear * @dev If a player chooses to rollover his prizes, only the principal is rolled over. The profit is * always sent back to the player. */ function rollover(RolloverCalldata[] calldata rolloverCalldataArray) external payable nonReentrant whenNotPaused { TransferAccumulator memory entryAccumulator; TransferAccumulator memory prizeAccumulator; Rollover[] memory rolloverEventData = new Rollover[](rolloverCalldataArray.length); uint256 msgValueLeft = msg.value; for (uint256 i; i < rolloverCalldataArray.length; ) { RolloverCalldata calldata rolloverCalldata = rolloverCalldataArray[i]; uint256 roundsCount = rolloverCalldata.playerDetails.length; if (roundsCount == 0) { revert InvalidPlayerDetails(); } uint256 caveId = rolloverCalldata.caveId; Cave storage cave = caves[caveId]; uint256 numberOfExtraRoundsToEnter = rolloverCalldata.numberOfExtraRoundsToEnter; address enterCurrency = cave.enterCurrency; // Enter extra rounds if (numberOfExtraRoundsToEnter != 0) { if (enterCurrency == address(0)) { msgValueLeft -= cave.enterAmount * numberOfExtraRoundsToEnter; } else { if (enterCurrency == entryAccumulator.tokenAddress) { entryAccumulator.amount += cave.enterAmount * numberOfExtraRoundsToEnter; } else { if (entryAccumulator.amount != 0) { TRANSFER_MANAGER.transferERC20( entryAccumulator.tokenAddress, msg.sender, address(this), entryAccumulator.amount ); } entryAccumulator.tokenAddress = enterCurrency; entryAccumulator.amount = cave.enterAmount * numberOfExtraRoundsToEnter; } } } Rollover memory rolloverEvent = rolloverEventData[i]; rolloverEvent.caveId = caveId; rolloverEvent.rolledOverRoundIds = new uint256[](roundsCount); uint256 prizeAmount; for (uint256 j; j < roundsCount; ) { PlayerWithdrawalCalldata calldata playerDetails = rolloverCalldata.playerDetails[j]; RoundStatus roundStatus = _handleRolloverRound(playerDetails, caveId, cave.playersPerRound); if (roundStatus == RoundStatus.Revealed) { prizeAmount += _prizeAmount(cave); } rolloverEvent.rolledOverRoundIds[j] = playerDetails.roundId; unchecked { ++j; } } uint256 startingRoundId = rolloverCalldata.startingRoundId; rolloverEvent.rollingOverToRoundIdStart = startingRoundId; _enter({ caveId: caveId, startingRoundId: startingRoundId, numberOfRounds: roundsCount + numberOfExtraRoundsToEnter }); if (prizeAmount != 0) { _accumulateOrTransferTokenOut(prizeAmount, enterCurrency, prizeAccumulator); } unchecked { ++i; } } if (msgValueLeft != 0) { revert InvalidEnterAmount(); } if (entryAccumulator.amount != 0) { TRANSFER_MANAGER.transferERC20( entryAccumulator.tokenAddress, msg.sender, address(this), entryAccumulator.amount ); } if (prizeAccumulator.amount != 0) { _transferTokens(msg.sender, prizeAccumulator.tokenAddress, prizeAccumulator.amount); } emit DepositsRolledOver(rolloverEventData, msg.sender); } /** * @inheritdoc IPokeTheBear */ function claimPrizes(WithdrawalCalldata[] calldata claimPrizeCalldataArray) external nonReentrant whenNotPaused { TransferAccumulator memory transferAccumulator; uint256 claimPrizeCount = claimPrizeCalldataArray.length; Withdrawal[] memory withdrawalEventData = new Withdrawal[](claimPrizeCount); for (uint256 i; i < claimPrizeCount; ) { WithdrawalCalldata calldata claimPrizeCalldata = claimPrizeCalldataArray[i]; uint256 caveId = claimPrizeCalldata.caveId; Cave storage cave = caves[caveId]; uint256 roundAmount = cave.enterAmount + _prizeAmount(cave); PlayerWithdrawalCalldata[] calldata playerDetailsArray = claimPrizeCalldata.playerDetails; uint256 roundsCount = playerDetailsArray.length; Withdrawal memory withdrawal = withdrawalEventData[i]; withdrawal.caveId = caveId; withdrawal.roundIds = new uint256[](roundsCount); for (uint256 j; j < roundsCount; ) { PlayerWithdrawalCalldata calldata playerDetails = playerDetailsArray[j]; uint256 roundId = playerDetails.roundId; Round storage round = rounds[caveId][roundId]; if (round.status != RoundStatus.Revealed) { revert InvalidRoundStatus(); } Player storage player = round.players[playerDetails.playerIndex]; _validatePlayerCanWithdraw(caveId, roundId, player); player.withdrawn = true; withdrawal.roundIds[j] = roundId; unchecked { ++j; } } _accumulateOrTransferTokenOut(roundAmount * roundsCount, cave.enterCurrency, transferAccumulator); unchecked { ++i; } } if (transferAccumulator.amount != 0) { _transferTokens(msg.sender, transferAccumulator.tokenAddress, transferAccumulator.amount); } emit PrizesClaimed(withdrawalEventData, msg.sender); } /** * @inheritdoc IPokeTheBear */ function cancel(uint256 caveId) external nonReentrant { Cave storage cave = caves[caveId]; uint40 roundsCount = cave.roundsCount; Round storage round = rounds[caveId][roundsCount]; if (!_cancellable(round, round.status, cave.playersPerRound, round.players.length)) { revert NotCancellable(); } _cancel(caveId, roundsCount); } /** * @inheritdoc IPokeTheBear */ function cancel(uint256 caveId, uint256 numberOfRounds) external nonReentrant whenPaused { _validateIsOwner(); Cave storage cave = caves[caveId]; uint256 startingRoundId = cave.roundsCount; uint256 lastRoundId = startingRoundId + numberOfRounds - 1; if (numberOfRounds == 0 || lastRoundId > cave.lastCommittedRoundId) { revert NotCancellable(); } for (uint256 roundId = startingRoundId; roundId <= lastRoundId; ) { rounds[caveId][roundId].status = RoundStatus.Cancelled; unchecked { ++roundId; } } cave.roundsCount = uint40(lastRoundId); emit RoundsCancelled(caveId, startingRoundId, numberOfRounds); } function getRound( uint256 caveId, uint256 roundId ) external view returns ( RoundStatus status, uint40 cutoffTime, uint40 drawnAt, bytes32 commitment, bytes32 salt, uint8[32] memory playerIndices, Player[] memory players ) { Round memory round = rounds[caveId][roundId]; return ( round.status, round.cutoffTime, round.drawnAt, round.commitment, round.salt, round.playerIndices, round.players ); } /** * @dev Checks if the round is cancellable. A round is cancellable if its status is Cancelled, * its status is Open but it has passed its cutoff time, its status is Drawing but Chainlink VRF * callback did not happen on time, or its status is Drawn but the result was not revealed. * @param caveId The ID of the cave. * @param roundId The ID of the round. */ function cancellable(uint256 caveId, uint256 roundId) external view returns (bool) { Round storage round = rounds[caveId][roundId]; return _cancellable(round, round.status, caves[caveId].playersPerRound, round.players.length); } /** * @inheritdoc IPokeTheBear */ function togglePaused() external { _validateIsOwner(); paused() ? _unpause() : _pause(); } /** * @inheritdoc IPokeTheBear */ function isPlayerInRound(uint256 caveId, uint256 roundId, address player) public view returns (bool) { uint256 bucket = roundId >> 8; uint256 slot = 1 << (roundId & 0xff); return playerParticipations[player][caveId][bucket] & slot != 0; } /** * @param requestId The ID of the request * @param randomWords The random words returned by Chainlink */ function fulfillRandomWords(uint256 requestId, uint256[] memory randomWords) internal override { if (randomnessRequests[requestId].exists) { uint256 caveId = randomnessRequests[requestId].caveId; uint256 roundId = randomnessRequests[requestId].roundId; Round storage round = rounds[caveId][roundId]; if (round.status == RoundStatus.Drawing) { round.status = RoundStatus.Drawn; randomnessRequests[requestId].randomWord = randomWords[0]; emit RoundStatusUpdated(caveId, roundId, RoundStatus.Drawn); } } } /** * @dev This function is used to enter rounds, charging is done outside of this function. * @param caveId The ID of the cave. * @param startingRoundId The ID of the starting round. * @param numberOfRounds The number of rounds to enter. */ function _enter(uint256 caveId, uint256 startingRoundId, uint256 numberOfRounds) private { if (startingRoundId == 0 || numberOfRounds == 0) { revert InvalidRoundParameters(); } Cave storage cave = caves[caveId]; if (!cave.isActive) { revert InactiveCave(); } uint256 endingRoundIdPlusOne = startingRoundId + numberOfRounds; if (_unsafeSubtract(endingRoundIdPlusOne, 1) > cave.lastCommittedRoundId) { revert CommitmentNotAvailable(); } Round storage startingRound = rounds[caveId][startingRoundId]; // We just need to check the first round's status. If the first round is open, // subsequent rounds will not be drawn/cancelled as well. RoundStatus startingRoundStatus = startingRound.status; if (startingRoundStatus > RoundStatus.Open) { revert RoundCannotBeEntered(caveId, startingRoundId); } uint8 playersPerRound = cave.playersPerRound; if (startingRoundStatus == RoundStatus.None) { if (startingRoundId > 1) { uint256 lastRoundId = _unsafeSubtract(startingRoundId, 1); Round storage lastRound = rounds[caveId][lastRoundId]; if (_cancellable(lastRound, lastRound.status, playersPerRound, lastRound.players.length)) { _cancel(caveId, lastRoundId); // The current round is now open (_cancel calls _open), we can manually change startingRoundStatus without touching the storage. startingRoundStatus = RoundStatus.Open; } } } for (uint256 roundId = startingRoundId; roundId < endingRoundIdPlusOne; ) { if (isPlayerInRound(caveId, roundId, msg.sender)) { revert PlayerAlreadyParticipated(caveId, roundId, msg.sender); } // Starting round already exists from outside the loop so we can reuse it for gas efficiency. Round storage round = roundId == startingRoundId ? startingRound : rounds[caveId][roundId]; uint256 newNumberOfPlayers = _unsafeAdd(round.players.length, 1); // This is not be a problem for the current open round, but this // can be a problem for future rounds. if (newNumberOfPlayers > playersPerRound) { revert RoundCannotBeEntered(caveId, roundId); } round.players.push(Player({addr: msg.sender, isLoser: false, withdrawn: false})); _markPlayerInRound(caveId, roundId, msg.sender); // Start countdown only for the current round and only if it is the first player. if (roundId == startingRoundId) { if (startingRoundStatus == RoundStatus.Open) { if (round.cutoffTime == 0) { round.cutoffTime = uint40(block.timestamp) + cave.roundDuration; } if (newNumberOfPlayers == playersPerRound) { _draw(caveId, roundId); } } } unchecked { ++roundId; } } emit RoundsEntered(caveId, startingRoundId, numberOfRounds, msg.sender); } /** * @param caveId The ID of the cave. * @param roundId The ID of the round to draw. */ function _draw(uint256 caveId, uint256 roundId) private { rounds[caveId][roundId].status = RoundStatus.Drawing; rounds[caveId][roundId].drawnAt = uint40(block.timestamp); uint256 requestId = VRF_COORDINATOR.requestRandomWords({ keyHash: KEY_HASH, subId: SUBSCRIPTION_ID, minimumRequestConfirmations: uint16(3), callbackGasLimit: uint32(500_000), numWords: uint32(1) }); if (randomnessRequests[requestId].exists) { revert RandomnessRequestAlreadyExists(); } randomnessRequests[requestId].exists = true; randomnessRequests[requestId].caveId = uint40(caveId); randomnessRequests[requestId].roundId = uint40(roundId); emit RandomnessRequested(caveId, roundId, requestId); emit RoundStatusUpdated(caveId, roundId, RoundStatus.Drawing); } /** * @dev This function cancels the current round and opens the next round. * @param caveId The ID of the cave. * @param roundId The ID of the round to cancel. */ function _cancel(uint256 caveId, uint256 roundId) private { rounds[caveId][roundId].status = RoundStatus.Cancelled; emit RoundStatusUpdated(caveId, roundId, RoundStatus.Cancelled); _open(caveId, _unsafeAdd(roundId, 1)); } /** * @dev This function opens a new round. * If the new round is already fully filled, it will be drawn immediately. * If the round is partially filled, the countdown starts. * @param caveId The ID of the cave. * @param roundId The ID of the round to open. */ function _open(uint256 caveId, uint256 roundId) private { Round storage round = rounds[caveId][roundId]; uint256 playersCount = round.players.length; Cave storage cave = caves[caveId]; if (playersCount == cave.playersPerRound) { _draw(caveId, roundId); } else { round.status = RoundStatus.Open; cave.roundsCount = uint40(roundId); emit RoundStatusUpdated(caveId, roundId, RoundStatus.Open); if (playersCount != 0) { round.cutoffTime = uint40(block.timestamp) + cave.roundDuration; } } } /** * @param playerDetails Information about the player to rollover. * @param caveId The ID of the cave. * @param playersPerRound The number of required players. */ function _handleRolloverRound( PlayerWithdrawalCalldata calldata playerDetails, uint256 caveId, uint8 playersPerRound ) private returns (RoundStatus roundStatus) { uint256 roundId = playerDetails.roundId; uint256 playerIndex = playerDetails.playerIndex; Round storage round = rounds[caveId][roundId]; roundStatus = round.status; uint256 currentNumberOfPlayers = round.players.length; if (roundStatus < RoundStatus.Revealed) { if (!_cancellable(round, roundStatus, playersPerRound, currentNumberOfPlayers)) { revert InvalidRoundStatus(); } _cancel(caveId, roundId); } if (playerIndex >= currentNumberOfPlayers) { revert InvalidPlayerIndex(caveId, roundId); } Player storage player = round.players[playerIndex]; _validatePlayerCanWithdraw(caveId, roundId, player); player.withdrawn = true; } /** * @param recipient The recipient of the transfer. * @param currency The transfer currency. * @param amount The transfer amount. */ function _transferTokens(address recipient, address currency, uint256 amount) private { if (currency == address(0)) { _transferETHAndWrapIfFailWithGasLimit(WRAPPED_NATIVE_TOKEN, recipient, amount, gasleft()); } else { _executeERC20DirectTransfer(currency, recipient, amount); } } /** * @param tokenAmount The amount of tokens to accumulate. * @param tokenAddress The token address to accumulate. * @param transferAccumulator The transfer accumulator state so far. */ function _accumulateOrTransferTokenOut( uint256 tokenAmount, address tokenAddress, TransferAccumulator memory transferAccumulator ) private { if (tokenAddress == transferAccumulator.tokenAddress) { transferAccumulator.amount += tokenAmount; } else { if (transferAccumulator.amount != 0) { _transferTokens(msg.sender, transferAccumulator.tokenAddress, transferAccumulator.amount); } transferAccumulator.tokenAddress = tokenAddress; transferAccumulator.amount = tokenAmount; } } /** * @notice Marks a player as participated in a round. * @dev A round starts with the ID 1 and the bitmap starts with the index 0, therefore we need to subtract 1. * @param caveId The ID of the cave. * @param roundId The ID of the round. * @param player The address of the player. */ function _markPlayerInRound(uint256 caveId, uint256 roundId, address player) private { uint256 bucket = roundId >> 8; uint256 slot = 1 << (roundId & 0xff); playerParticipations[player][caveId][bucket] |= slot; } /** * @notice Checks if the round data fulfills an expired open round. * @param roundStatus The status of the round. * @param cutoffTime The cutoff time of the round. * @param currentNumberOfPlayers The current number of players in the round. * @param playersPerRound The maximum number of players in a round. */ function _isExpiredOpenRound( RoundStatus roundStatus, uint40 cutoffTime, uint256 currentNumberOfPlayers, uint8 playersPerRound ) private view returns (bool) { return roundStatus == RoundStatus.Open && cutoffTime != 0 && block.timestamp >= cutoffTime && currentNumberOfPlayers < playersPerRound; } /** * @notice Checks if the round is pending VRF or commitment reveal for too long. We tolerate a delay of up to 1 day. * @param roundStatus The status of the round. * @param round The round to check. */ function _pendingVRFOrRevealForTooLong(RoundStatus roundStatus, Round storage round) private view returns (bool) { return (roundStatus == RoundStatus.Drawing || roundStatus == RoundStatus.Drawn) && block.timestamp >= round.drawnAt + 1 days; } /** * @dev player.isLoser is a check for claimPrize only, but it is also useful to act as an invariant for refund. * @param caveId The ID of the cave. * @param roundId The ID of the round. * @param player The player. */ function _validatePlayerCanWithdraw(uint256 caveId, uint256 roundId, Player storage player) private view { if (player.isLoser || player.withdrawn || player.addr != msg.sender) { revert IneligibleToWithdraw(caveId, roundId); } } /** * @dev Checks if the round is cancellable. A round is cancellable if its status is Cancelled, * its status is Open but it has passed its cutoff time, its status is Drawing but Chainlink VRF * callback did not happen on time, or its status is Drawn but the result was not revealed. * @param round The round to check. * @param roundStatus The status of the round. * @param playersPerRound The maximum number of players in the round. * @param currentNumberOfPlayers The current number of players in the round. */ function _cancellable( Round storage round, RoundStatus roundStatus, uint8 playersPerRound, uint256 currentNumberOfPlayers ) private view returns (bool) { return _isExpiredOpenRound(roundStatus, round.cutoffTime, currentNumberOfPlayers, playersPerRound) || _pendingVRFOrRevealForTooLong(roundStatus, round); } /** * @param _protocolFeeRecipient The new protocol fee recipient address */ function _updateProtocolFeeRecipient(address _protocolFeeRecipient) internal { if (_protocolFeeRecipient == address(0)) { revert InvalidValue(); } protocolFeeRecipient = _protocolFeeRecipient; emit ProtocolFeeRecipientUpdated(_protocolFeeRecipient); } /** * @notice Calculates the prize amount. * @param cave The cave to calculate the prize amount. */ function _prizeAmount(Cave storage cave) private view returns (uint256) { return (cave.enterAmount * (_unsafeSubtract(ONE_HUNDRED_PERCENT_IN_BASIS_POINTS, cave.protocolFeeBp))) / ONE_HUNDRED_PERCENT_IN_BASIS_POINTS / _unsafeSubtract(cave.playersPerRound, 1); } /** * Unsafe math functions. */ function _unsafeAdd(uint256 a, uint256 b) private pure returns (uint256) { unchecked { return a + b; } } function _unsafeSubtract(uint256 a, uint256 b) private pure returns (uint256) { unchecked { return a - b; } } function _validateIsOwner() private view { if (!hasRole(DEFAULT_ADMIN_ROLE, msg.sender)) { revert NotOwner(); } } function _validateIsOperator() private view { if (!hasRole(OPERATOR_ROLE, msg.sender)) { revert NotOperator(); } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.17; // Interfaces import {IWETH} from "../interfaces/generic/IWETH.sol"; /** * @title LowLevelWETH * @notice This contract contains a function to transfer ETH with an option to wrap to WETH. * If the ETH transfer fails within a gas limit, the amount in ETH is wrapped to WETH and then transferred. * @author LooksRare protocol team (👀,💎) */ contract LowLevelWETH { /** * @notice It transfers ETH to a recipient with a specified gas limit. * If the original transfers fails, it wraps to WETH and transfers the WETH to recipient. * @param _WETH WETH address * @param _to Recipient address * @param _amount Amount to transfer * @param _gasLimit Gas limit to perform the ETH transfer */ function _transferETHAndWrapIfFailWithGasLimit( address _WETH, address _to, uint256 _amount, uint256 _gasLimit ) internal { bool status; assembly { status := call(_gasLimit, _to, _amount, 0, 0, 0, 0) } if (!status) { IWETH(_WETH).deposit{value: _amount}(); IWETH(_WETH).transfer(_to, _amount); } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.17; // Interfaces import {IERC20} from "../interfaces/generic/IERC20.sol"; // Errors import {ERC20TransferFail, ERC20TransferFromFail} from "../errors/LowLevelErrors.sol"; import {NotAContract} from "../errors/GenericErrors.sol"; /** * @title LowLevelERC20Transfer * @notice This contract contains low-level calls to transfer ERC20 tokens. * @author LooksRare protocol team (👀,💎) */ contract LowLevelERC20Transfer { /** * @notice Execute ERC20 transferFrom * @param currency Currency address * @param from Sender address * @param to Recipient address * @param amount Amount to transfer */ function _executeERC20TransferFrom(address currency, address from, address to, uint256 amount) internal { if (currency.code.length == 0) { revert NotAContract(); } (bool status, bytes memory data) = currency.call(abi.encodeCall(IERC20.transferFrom, (from, to, amount))); if (!status) { revert ERC20TransferFromFail(); } if (data.length > 0) { if (!abi.decode(data, (bool))) { revert ERC20TransferFromFail(); } } } /** * @notice Execute ERC20 (direct) transfer * @param currency Currency address * @param to Recipient address * @param amount Amount to transfer */ function _executeERC20DirectTransfer(address currency, address to, uint256 amount) internal { if (currency.code.length == 0) { revert NotAContract(); } (bool status, bytes memory data) = currency.call(abi.encodeCall(IERC20.transfer, (to, amount))); if (!status) { revert ERC20TransferFail(); } if (data.length > 0) { if (!abi.decode(data, (bool))) { revert ERC20TransferFail(); } } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.17; // Interfaces import {IReentrancyGuard} from "./interfaces/IReentrancyGuard.sol"; /** * @title PackableReentrancyGuard * @notice This contract protects against reentrancy attacks. * It is adjusted from OpenZeppelin. * The only difference between this contract and ReentrancyGuard * is that _status is uint8 instead of uint256 so that it can be * packed with other contracts' storage variables. * @author LooksRare protocol team (👀,💎) */ abstract contract PackableReentrancyGuard is IReentrancyGuard { uint8 private _status; /** * @notice Modifier to wrap functions to prevent reentrancy calls. */ modifier nonReentrant() { if (_status == 2) { revert ReentrancyFail(); } _status = 2; _; _status = 1; } constructor() { _status = 1; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.17; /** * @title Pausable * @notice This contract makes it possible to pause the contract. * It is adjusted from OpenZeppelin. * @author LooksRare protocol team (👀,💎) */ abstract contract Pausable { /** * @dev Emitted when the pause is triggered by `account`. */ event Paused(address account); /** * @dev Emitted when the pause is lifted by `account`. */ event Unpaused(address account); error IsPaused(); error NotPaused(); bool private _paused; /** * @dev Modifier to make a function callable only when the contract is not paused. * * Requirements: * * - The contract must not be paused. */ modifier whenNotPaused() { _requireNotPaused(); _; } /** * @dev Modifier to make a function callable only when the contract is paused. * * Requirements: * * - The contract must be paused. */ modifier whenPaused() { _requirePaused(); _; } /** * @dev Returns true if the contract is paused, and false otherwise. */ function paused() public view virtual returns (bool) { return _paused; } /** * @dev Throws if the contract is paused. */ function _requireNotPaused() internal view virtual { if (paused()) { revert IsPaused(); } } /** * @dev Throws if the contract is not paused. */ function _requirePaused() internal view virtual { if (!paused()) { revert NotPaused(); } } /** * @dev Triggers stopped state. * * Requirements: * * - The contract must not be paused. */ function _pause() internal virtual whenNotPaused { _paused = true; emit Paused(msg.sender); } /** * @dev Returns to normal state. * * Requirements: * * - The contract must be paused. */ function _unpause() internal virtual whenPaused { _paused = false; emit Unpaused(msg.sender); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.20; // Enums import {TokenType} from "../enums/TokenType.sol"; /** * @title ITransferManager * @author LooksRare protocol team (👀,💎) */ interface ITransferManager { /** * @notice This struct is only used for transferBatchItemsAcrossCollections. * @param tokenAddress Token address * @param tokenType 0 for ERC721, 1 for ERC1155 * @param itemIds Array of item ids to transfer * @param amounts Array of amounts to transfer */ struct BatchTransferItem { address tokenAddress; TokenType tokenType; uint256[] itemIds; uint256[] amounts; } /** * @notice It is emitted if operators' approvals to transfer NFTs are granted by a user. * @param user Address of the user * @param operators Array of operator addresses */ event ApprovalsGranted(address user, address[] operators); /** * @notice It is emitted if operators' approvals to transfer NFTs are revoked by a user. * @param user Address of the user * @param operators Array of operator addresses */ event ApprovalsRemoved(address user, address[] operators); /** * @notice It is emitted if a new operator is added to the global allowlist. * @param operator Operator address */ event OperatorAllowed(address operator); /** * @notice It is emitted if an operator is removed from the global allowlist. * @param operator Operator address */ event OperatorRemoved(address operator); /** * @notice It is returned if the operator to approve has already been approved by the user. */ error OperatorAlreadyApprovedByUser(); /** * @notice It is returned if the operator to revoke has not been previously approved by the user. */ error OperatorNotApprovedByUser(); /** * @notice It is returned if the transfer caller is already allowed by the owner. * @dev This error can only be returned for owner operations. */ error OperatorAlreadyAllowed(); /** * @notice It is returned if the operator to approve is not in the global allowlist defined by the owner. * @dev This error can be returned if the user tries to grant approval to an operator address not in the * allowlist or if the owner tries to remove the operator from the global allowlist. */ error OperatorNotAllowed(); /** * @notice It is returned if the transfer caller is invalid. * For a transfer called to be valid, the operator must be in the global allowlist and * approved by the 'from' user. */ error TransferCallerInvalid(); /** * @notice This function transfers ERC20 tokens. * @param tokenAddress Token address * @param from Sender address * @param to Recipient address * @param amount amount */ function transferERC20( address tokenAddress, address from, address to, uint256 amount ) external; /** * @notice This function transfers a single item for a single ERC721 collection. * @param tokenAddress Token address * @param from Sender address * @param to Recipient address * @param itemId Item ID */ function transferItemERC721( address tokenAddress, address from, address to, uint256 itemId ) external; /** * @notice This function transfers items for a single ERC721 collection. * @param tokenAddress Token address * @param from Sender address * @param to Recipient address * @param itemIds Array of itemIds * @param amounts Array of amounts */ function transferItemsERC721( address tokenAddress, address from, address to, uint256[] calldata itemIds, uint256[] calldata amounts ) external; /** * @notice This function transfers a single item for a single ERC1155 collection. * @param tokenAddress Token address * @param from Sender address * @param to Recipient address * @param itemId Item ID * @param amount Amount */ function transferItemERC1155( address tokenAddress, address from, address to, uint256 itemId, uint256 amount ) external; /** * @notice This function transfers items for a single ERC1155 collection. * @param tokenAddress Token address * @param from Sender address * @param to Recipient address * @param itemIds Array of itemIds * @param amounts Array of amounts * @dev It does not allow batch transferring if from = msg.sender since native function should be used. */ function transferItemsERC1155( address tokenAddress, address from, address to, uint256[] calldata itemIds, uint256[] calldata amounts ) external; /** * @notice This function transfers items across an array of tokens that can be ERC20, ERC721 and ERC1155. * @param items Array of BatchTransferItem * @param from Sender address * @param to Recipient address */ function transferBatchItemsAcrossCollections( BatchTransferItem[] calldata items, address from, address to ) external; /** * @notice This function allows a user to grant approvals for an array of operators. * Users cannot grant approvals if the operator is not allowed by this contract's owner. * @param operators Array of operator addresses * @dev Each operator address must be globally allowed to be approved. */ function grantApprovals(address[] calldata operators) external; /** * @notice This function allows a user to revoke existing approvals for an array of operators. * @param operators Array of operator addresses * @dev Each operator address must be approved at the user level to be revoked. */ function revokeApprovals(address[] calldata operators) external; /** * @notice This function allows an operator to be added for the shared transfer system. * Once the operator is allowed, users can grant NFT approvals to this operator. * @param operator Operator address to allow * @dev Only callable by owner. */ function allowOperator(address operator) external; /** * @notice This function allows the user to remove an operator for the shared transfer system. * @param operator Operator address to remove * @dev Only callable by owner. */ function removeOperator(address operator) external; /** * @notice This returns whether the user has approved the operator address. * The first address is the user and the second address is the operator. */ function hasUserApprovedOperator(address user, address operator) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol) pragma solidity ^0.8.20; import {IAccessControl} from "./IAccessControl.sol"; import {Context} from "../utils/Context.sol"; import {ERC165} from "../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: * * ```solidity * 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}: * * ```solidity * 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. We recommend using {AccessControlDefaultAdminRules} * to enforce additional security measures for this role. */ abstract contract AccessControl is Context, IAccessControl, ERC165 { struct RoleData { mapping(address account => bool) hasRole; bytes32 adminRole; } mapping(bytes32 role => RoleData) private _roles; bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; /** * @dev Modifier that checks that an account has a specific role. Reverts * with an {AccessControlUnauthorizedAccount} error including the required role. */ 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 returns (bool) { return _roles[role].hasRole[account]; } /** * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()` * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier. */ function _checkRole(bytes32 role) internal view virtual { _checkRole(role, _msgSender()); } /** * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account` * is missing `role`. */ function _checkRole(bytes32 role, address account) internal view virtual { if (!hasRole(role, account)) { revert AccessControlUnauthorizedAccount(account, role); } } /** * @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 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 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 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 `callerConfirmation`. * * May emit a {RoleRevoked} event. */ function renounceRole(bytes32 role, address callerConfirmation) public virtual { if (callerConfirmation != _msgSender()) { revert AccessControlBadConfirmation(); } _revokeRole(role, callerConfirmation); } /** * @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 Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted. * * Internal function without access restriction. * * May emit a {RoleGranted} event. */ function _grantRole(bytes32 role, address account) internal virtual returns (bool) { if (!hasRole(role, account)) { _roles[role].hasRole[account] = true; emit RoleGranted(role, account, _msgSender()); return true; } else { return false; } } /** * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked. * * Internal function without access restriction. * * May emit a {RoleRevoked} event. */ function _revokeRole(bytes32 role, address account) internal virtual returns (bool) { if (hasRole(role, account)) { _roles[role].hasRole[account] = false; emit RoleRevoked(role, account, _msgSender()); return true; } else { return false; } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface VRFCoordinatorV2Interface { /** * @notice Get configuration relevant for making requests * @return minimumRequestConfirmations global min for request confirmations * @return maxGasLimit global max for request gas limit * @return s_provingKeyHashes list of registered key hashes */ function getRequestConfig() external view returns ( uint16, uint32, bytes32[] memory ); /** * @notice Request a set of random words. * @param keyHash - Corresponds to a particular oracle job which uses * that key for generating the VRF proof. Different keyHash's have different gas price * ceilings, so you can select a specific one to bound your maximum per request cost. * @param subId - The ID of the VRF subscription. Must be funded * with the minimum subscription balance required for the selected keyHash. * @param minimumRequestConfirmations - How many blocks you'd like the * oracle to wait before responding to the request. See SECURITY CONSIDERATIONS * for why you may want to request more. The acceptable range is * [minimumRequestBlockConfirmations, 200]. * @param callbackGasLimit - How much gas you'd like to receive in your * fulfillRandomWords callback. Note that gasleft() inside fulfillRandomWords * may be slightly less than this amount because of gas used calling the function * (argument decoding etc.), so you may need to request slightly more than you expect * to have inside fulfillRandomWords. The acceptable range is * [0, maxGasLimit] * @param numWords - The number of uint256 random values you'd like to receive * in your fulfillRandomWords callback. Note these numbers are expanded in a * secure way by the VRFCoordinator from a single random value supplied by the oracle. * @return requestId - A unique identifier of the request. Can be used to match * a request to a response in fulfillRandomWords. */ function requestRandomWords( bytes32 keyHash, uint64 subId, uint16 minimumRequestConfirmations, uint32 callbackGasLimit, uint32 numWords ) external returns (uint256 requestId); /** * @notice Create a VRF subscription. * @return subId - A unique subscription id. * @dev You can manage the consumer set dynamically with addConsumer/removeConsumer. * @dev Note to fund the subscription, use transferAndCall. For example * @dev LINKTOKEN.transferAndCall( * @dev address(COORDINATOR), * @dev amount, * @dev abi.encode(subId)); */ function createSubscription() external returns (uint64 subId); /** * @notice Get a VRF subscription. * @param subId - ID of the subscription * @return balance - LINK balance of the subscription in juels. * @return reqCount - number of requests for this subscription, determines fee tier. * @return owner - owner of the subscription. * @return consumers - list of consumer address which are able to use this subscription. */ function getSubscription(uint64 subId) external view returns ( uint96 balance, uint64 reqCount, address owner, address[] memory consumers ); /** * @notice Request subscription owner transfer. * @param subId - ID of the subscription * @param newOwner - proposed new owner of the subscription */ function requestSubscriptionOwnerTransfer(uint64 subId, address newOwner) external; /** * @notice Request subscription owner transfer. * @param subId - ID of the subscription * @dev will revert if original owner of subId has * not requested that msg.sender become the new owner. */ function acceptSubscriptionOwnerTransfer(uint64 subId) external; /** * @notice Add a consumer to a VRF subscription. * @param subId - ID of the subscription * @param consumer - New consumer which can use the subscription */ function addConsumer(uint64 subId, address consumer) external; /** * @notice Remove a consumer from a VRF subscription. * @param subId - ID of the subscription * @param consumer - Consumer to remove from the subscription */ function removeConsumer(uint64 subId, address consumer) external; /** * @notice Cancel a subscription * @param subId - ID of the subscription * @param to - Where to send the remaining LINK to */ function cancelSubscription(uint64 subId, address to) external; /* * @notice Check to see if there exists a request commitment consumers * for all consumers and keyhashes for a given sub. * @param subId - ID of the subscription * @return true if there exists at least one unfulfilled request for the subscription, false * otherwise. */ function pendingRequestExists(uint64 subId) external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /** **************************************************************************** * @notice Interface for contracts using VRF randomness * ***************************************************************************** * @dev PURPOSE * * @dev Reggie the Random Oracle (not his real job) wants to provide randomness * @dev to Vera the verifier in such a way that Vera can be sure he's not * @dev making his output up to suit himself. Reggie provides Vera a public key * @dev to which he knows the secret key. Each time Vera provides a seed to * @dev Reggie, he gives back a value which is computed completely * @dev deterministically from the seed and the secret key. * * @dev Reggie provides a proof by which Vera can verify that the output was * @dev correctly computed once Reggie tells it to her, but without that proof, * @dev the output is indistinguishable to her from a uniform random sample * @dev from the output space. * * @dev The purpose of this contract is to make it easy for unrelated contracts * @dev to talk to Vera the verifier about the work Reggie is doing, to provide * @dev simple access to a verifiable source of randomness. It ensures 2 things: * @dev 1. The fulfillment came from the VRFCoordinator * @dev 2. The consumer contract implements fulfillRandomWords. * ***************************************************************************** * @dev USAGE * * @dev Calling contracts must inherit from VRFConsumerBase, and can * @dev initialize VRFConsumerBase's attributes in their constructor as * @dev shown: * * @dev contract VRFConsumer { * @dev constructor(<other arguments>, address _vrfCoordinator, address _link) * @dev VRFConsumerBase(_vrfCoordinator) public { * @dev <initialization with other arguments goes here> * @dev } * @dev } * * @dev The oracle will have given you an ID for the VRF keypair they have * @dev committed to (let's call it keyHash). Create subscription, fund it * @dev and your consumer contract as a consumer of it (see VRFCoordinatorInterface * @dev subscription management functions). * @dev Call requestRandomWords(keyHash, subId, minimumRequestConfirmations, * @dev callbackGasLimit, numWords), * @dev see (VRFCoordinatorInterface for a description of the arguments). * * @dev Once the VRFCoordinator has received and validated the oracle's response * @dev to your request, it will call your contract's fulfillRandomWords method. * * @dev The randomness argument to fulfillRandomWords is a set of random words * @dev generated from your requestId and the blockHash of the request. * * @dev If your contract could have concurrent requests open, you can use the * @dev requestId returned from requestRandomWords to track which response is associated * @dev with which randomness request. * @dev See "SECURITY CONSIDERATIONS" for principles to keep in mind, * @dev if your contract could have multiple requests in flight simultaneously. * * @dev Colliding `requestId`s are cryptographically impossible as long as seeds * @dev differ. * * ***************************************************************************** * @dev SECURITY CONSIDERATIONS * * @dev A method with the ability to call your fulfillRandomness method directly * @dev could spoof a VRF response with any random value, so it's critical that * @dev it cannot be directly called by anything other than this base contract * @dev (specifically, by the VRFConsumerBase.rawFulfillRandomness method). * * @dev For your users to trust that your contract's random behavior is free * @dev from malicious interference, it's best if you can write it so that all * @dev behaviors implied by a VRF response are executed *during* your * @dev fulfillRandomness method. If your contract must store the response (or * @dev anything derived from it) and use it later, you must ensure that any * @dev user-significant behavior which depends on that stored value cannot be * @dev manipulated by a subsequent VRF request. * * @dev Similarly, both miners and the VRF oracle itself have some influence * @dev over the order in which VRF responses appear on the blockchain, so if * @dev your contract could have multiple VRF requests in flight simultaneously, * @dev you must ensure that the order in which the VRF responses arrive cannot * @dev be used to manipulate your contract's user-significant behavior. * * @dev Since the block hash of the block which contains the requestRandomness * @dev call is mixed into the input to the VRF *last*, a sufficiently powerful * @dev miner could, in principle, fork the blockchain to evict the block * @dev containing the request, forcing the request to be included in a * @dev different block with a different hash, and therefore a different input * @dev to the VRF. However, such an attack would incur a substantial economic * @dev cost. This cost scales with the number of blocks the VRF oracle waits * @dev until it calls responds to a request. It is for this reason that * @dev that you can signal to an oracle you'd like them to wait longer before * @dev responding to the request (however this is not enforced in the contract * @dev and so remains effective only in the case of unmodified oracle software). */ abstract contract VRFConsumerBaseV2 { error OnlyCoordinatorCanFulfill(address have, address want); address private immutable vrfCoordinator; /** * @param _vrfCoordinator address of VRFCoordinator contract */ constructor(address _vrfCoordinator) { vrfCoordinator = _vrfCoordinator; } /** * @notice fulfillRandomness handles the VRF response. Your contract must * @notice implement it. See "SECURITY CONSIDERATIONS" above for important * @notice principles to keep in mind when implementing your fulfillRandomness * @notice method. * * @dev VRFConsumerBaseV2 expects its subcontracts to have a method with this * @dev signature, and will call it once it has verified the proof * @dev associated with the randomness. (It is triggered via a call to * @dev rawFulfillRandomness, below.) * * @param requestId The Id initially returned by requestRandomness * @param randomWords the VRF output expanded to the requested number of words */ function fulfillRandomWords(uint256 requestId, uint256[] memory randomWords) internal virtual; // rawFulfillRandomness is called by VRFCoordinator when it receives a valid VRF // proof. rawFulfillRandomness then calls fulfillRandomness, after validating // the origin of the call function rawFulfillRandomWords(uint256 requestId, uint256[] memory randomWords) external { if (msg.sender != vrfCoordinator) { revert OnlyCoordinatorCanFulfill(msg.sender, vrfCoordinator); } fulfillRandomWords(requestId, randomWords); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.20; interface IPokeTheBear { /** * @notice The status of a round. * None: The round hasn't started yet. * Open: The round is open for players to enter. * Drawing: The round is being drawn using Chainlink VRF. * Drawn: The round has been drawn. Chainlink VRF has returned a random number. * Revealed: The loser has been revealed. * Cancelled: The round has been cancelled. */ enum RoundStatus { None, Open, Drawing, Drawn, Revealed, Cancelled } /** * @notice A player in a round. * @param addr The address of the player. * @param isLoser Whether the player is the loser. * @param withdrawn Whether the player has withdrawn the prize or the original deposit. */ struct Player { address addr; bool isLoser; bool withdrawn; } /** * @notice A round of Poke The Bear. * @param status The status of the round. * @param cutoffTime The cutoff time to start or cancel the round if there aren't enough players. * @param drawnAt The timestamp when the round was drawn. * @param commitment The commitment of the shuffled player indices. * @param salt The salt used to generate the commitment. * @param playerIndices The player indices. * @param players The players. */ struct Round { RoundStatus status; uint40 cutoffTime; uint40 drawnAt; bytes32 commitment; bytes32 salt; uint8[32] playerIndices; Player[] players; } /** * @param exists Whether the request exists. * @param caveId The id of the cave. * @param roundId The id of the round. * @param randomWord The random words returned by Chainlink VRF. * If randomWord == 0, then the request is still pending. */ struct RandomnessRequest { bool exists; uint40 caveId; uint40 roundId; uint256 randomWord; } /** * @notice A cave of Poke The Bear. * @param enterAmount The amount to enter the cave with. * @param enterCurrency The currency to enter the cave with. * @param roundsCount The number of rounds in the cave. * @param lastCommittedRoundId The last committed round ID. * @param roundDuration The duration of a round. * @param playersPerRound The maximum number of players in a round. * @param protocolFeeBp The protocol fee in basis points. */ struct Cave { uint256 enterAmount; address enterCurrency; uint40 roundsCount; uint40 lastCommittedRoundId; uint40 roundDuration; uint8 playersPerRound; uint16 protocolFeeBp; bool isActive; } /** * @notice The calldata for commitments. * @param caveId The cave ID of the commitments. * @param commitments The commitments. The pre-image of the commitment is the shuffled player indices. */ struct CommitmentCalldata { uint256 caveId; bytes32[] commitments; } /** * @notice The calldata for a withdrawal/claim/rollover. * @param caveId The cave ID of the withdrawal/claim/rollover. * @param playerDetails The player's details in the rounds' players array. */ struct WithdrawalCalldata { uint256 caveId; PlayerWithdrawalCalldata[] playerDetails; } /** * @notice The calldata for a withdrawal/claim/rollover. * @param caveId The cave ID of the withdrawal/claim/rollover. * @param startingRoundId The starting round ID to enter. * @param numberOfExtraRoundsToEnter The number of extra rounds to enter, in addition to rollover rounds. * @param playerDetails The player's details in the rounds' players array. */ struct RolloverCalldata { uint256 caveId; uint256 startingRoundId; uint256 numberOfExtraRoundsToEnter; PlayerWithdrawalCalldata[] playerDetails; } /** * @notice The calldata for a single player withdrawal/claim/rollover. * @param roundId The round ID of the withdrawal/claim/rollover. * @param playerIndex The player index of the withdrawal/claim/rollover. */ struct PlayerWithdrawalCalldata { uint256 roundId; uint256 playerIndex; } /** * @notice The withdrawal/claim/rollover. * @param caveId The cave ID of the withdrawal/claim/rollover. * @param roundIds The round IDs to withdraw/claim/rollover. */ struct Withdrawal { uint256 caveId; uint256[] roundIds; } /** * @notice The rollover for event emission. * @param caveId The cave ID of the rollover. * @param rolledOverRoundIds The rolled over round IDs. * @param rollingOverToRoundIdStart The starting round ID to roll into */ struct Rollover { uint256 caveId; uint256[] rolledOverRoundIds; uint256 rollingOverToRoundIdStart; } /** * @notice This is used to accumulate the amount of tokens to be transferred. * @param tokenAddress The address of the token. * @param amount The amount of tokens accumulated. */ struct TransferAccumulator { address tokenAddress; uint256 amount; } event CommitmentsSubmitted(CommitmentCalldata[] commitments); event DepositsRolledOver(Rollover[] rollovers, address player); event DepositsRefunded(Withdrawal[] deposits, address player); event PrizesClaimed(Withdrawal[] prizes, address player); event ProtocolFeeRecipientUpdated(address protocolFeeRecipient); event RoundStatusUpdated(uint256 caveId, uint256 roundId, RoundStatus status); event RoundsCancelled(uint256 caveId, uint256 startingRoundId, uint256 numberOfRounds); event RoundsEntered(uint256 caveId, uint256 startingRoundId, uint256 numberOfRounds, address player); event RandomnessRequested(uint256 caveId, uint256 roundId, uint256 requestId); event CaveAdded( uint256 caveId, uint256 enterAmount, address enterCurrency, uint40 roundDuration, uint8 playersPerRound, uint16 protocolFeeBp ); event CaveRemoved(uint256 caveId); error CommitmentNotAvailable(); error ExceedsMaximumNumberOfPlayersPerRound(); error HashedPlayerIndicesDoesNotMatchCommitment(); error InactiveCave(); error IndivisibleEnterAmount(); error IneligibleToWithdraw(uint256 caveId, uint256 roundId); error InvalidEnterAmount(); error InsufficientNumberOfPlayers(); error InvalidCommitment(uint256 caveId, uint256 roundId); error InvalidPlayerDetails(); error InvalidPlayerIndex(uint256 caveId, uint256 roundId); error InvalidRoundDuration(); error InvalidRoundParameters(); error InvalidRoundStatus(); error InvalidEnterCurrency(); error InvalidValue(); error NotOperator(); error NotOwner(); error NotCancellable(); error PlayerAlreadyParticipated(uint256 caveId, uint256 roundId, address player); error ProtocolFeeBasisPointsTooHigh(); error RepeatingPlayerIndex(); error RandomnessRequestAlreadyExists(); error RoundCannotBeEntered(uint256 caveId, uint256 roundId); error RoundsIncomplete(); /** * @notice Add a new cave. Only callable by the contract owner. * @param enterAmount The amount to enter the cave with. * @param enterCurrency The currency to enter the cave with. * @param playersPerRound The maximum number of players in a round. * @param roundDuration The duration of a round. * @param protocolFeeBp The protocol fee in basis points. Max 25%. */ function addCave( uint256 enterAmount, address enterCurrency, uint8 playersPerRound, uint40 roundDuration, uint16 protocolFeeBp ) external returns (uint256 caveId); /** * @notice Remove a cave. Only callable by the contract owner. * @param caveId The cave ID to remove. */ function removeCave(uint256 caveId) external; /** * @dev Update the protocol fee recipient. Only callable by the contract owner. * @param _protocolFeeRecipient The address of the protocol fee recipient */ function updateProtocolFeeRecipient(address _protocolFeeRecipient) external; /** * @notice Enter the current round of a cave. * @param caveId The cave ID of the round to enter. * @param startingRoundId The starting round ID to enter. * @param numberOfRounds The number of rounds to enter, starting from the starting round ID. */ function enter(uint256 caveId, uint256 startingRoundId, uint256 numberOfRounds) external payable; /** * @notice Commit the player indices for multiple rounds. * @param commitments The array of commitments. */ function commit(CommitmentCalldata[] calldata commitments) external; /** * @notice Reveal the result of a round. * @param requestId The Chainlink VRF request ID. * @param playerIndices The indices of the players. * @param salt The salt used to concatenate with the playerIndices to generate the commitment. */ function reveal(uint256 requestId, uint256 playerIndices, bytes32 salt) external; /** * @notice Get a refund for cancelled rounds. * @param refundCalldataArray The array of refund calldata. */ function refund(WithdrawalCalldata[] calldata refundCalldataArray) external; /** * @notice Rollover cancelled rounds' deposits to the current round + upcoming rounds. * @param rolloverCalldataArray The array of rollover calldata. */ function rollover(RolloverCalldata[] calldata rolloverCalldataArray) external payable; /** * @notice Claim prizes for multiple rounds. * @param claimPrizeCalldataArray The array of claim prize calldata. */ function claimPrizes(WithdrawalCalldata[] calldata claimPrizeCalldataArray) external; /** * @notice Cancel the latest round when the round is expired. * @param caveId The cave ID of the round to cancel. */ function cancel(uint256 caveId) external; /** * @notice Allow the contract owner to cancel the current and future rounds if the contract is paused. * @param caveId The cave ID of the rounds to cancel. * @param numberOfRounds The number of rounds to cancel.. */ function cancel(uint256 caveId, uint256 numberOfRounds) external; /** * @notice Get a round of a given cave. * @param caveId The cave ID. * @param roundId The round ID. */ function getRound( uint256 caveId, uint256 roundId ) external view returns ( RoundStatus status, uint40 cutoffTime, uint40 drawnAt, bytes32 commitment, bytes32 salt, uint8[32] memory playerIndices, Player[] memory players ); /** * @notice Check if the player is in a specific round. * @param caveId The cave ID. * @param roundId The round ID. * @return The player's address. */ function isPlayerInRound(uint256 caveId, uint256 roundId, address player) external view returns (bool); /** * @notice This function allows the owner to pause/unpause the contract. */ function togglePaused() external; }
// SPDX-License-Identifier: MIT pragma solidity >=0.5.0; interface IWETH { function deposit() external payable; function transfer(address dst, uint256 wad) external returns (bool); function withdraw(uint256 wad) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.17; interface IERC20 { event Transfer(address indexed from, address indexed to, uint256 value); event Approval(address indexed owner, address indexed spender, uint256 value); function totalSupply() external view returns (uint256); function balanceOf(address account) external view returns (uint256); function transfer(address to, uint256 amount) external returns (bool); function allowance(address owner, address spender) external view returns (uint256); function approve(address spender, uint256 amount) external returns (bool); function transferFrom(address from, address to, uint256 amount) external returns (bool); function decimals() external view returns (uint8); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.17; /** * @notice It is emitted if the ETH transfer fails. */ error ETHTransferFail(); /** * @notice It is emitted if the ERC20 approval fails. */ error ERC20ApprovalFail(); /** * @notice It is emitted if the ERC20 transfer fails. */ error ERC20TransferFail(); /** * @notice It is emitted if the ERC20 transferFrom fails. */ error ERC20TransferFromFail(); /** * @notice It is emitted if the ERC721 transferFrom fails. */ error ERC721TransferFromFail(); /** * @notice It is emitted if the ERC1155 safeTransferFrom fails. */ error ERC1155SafeTransferFromFail(); /** * @notice It is emitted if the ERC1155 safeBatchTransferFrom fails. */ error ERC1155SafeBatchTransferFromFail();
// SPDX-License-Identifier: MIT pragma solidity ^0.8.17; /** * @notice It is emitted if the call recipient is not a contract. */ error NotAContract();
// SPDX-License-Identifier: MIT pragma solidity ^0.8.17; /** * @title IReentrancyGuard * @author LooksRare protocol team (👀,💎) */ interface IReentrancyGuard { /** * @notice This is returned when there is a reentrant call. */ error ReentrancyFail(); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.20; enum TokenType { ERC20, ERC721, ERC1155 }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol) pragma solidity ^0.8.20; /** * @dev External interface of AccessControl declared to support ERC165 detection. */ interface IAccessControl { /** * @dev The `account` is missing a role. */ error AccessControlUnauthorizedAccount(address account, bytes32 neededRole); /** * @dev The caller of a function is not the expected one. * * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}. */ error AccessControlBadConfirmation(); /** * @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. */ 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 `callerConfirmation`. */ function renounceRole(bytes32 role, address callerConfirmation) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/Context.sol) pragma solidity ^0.8.20; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol) pragma solidity ^0.8.20; import {IERC165} from "./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); * } * ``` */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
{ "remappings": [ "@chainlink/=node_modules/@chainlink/", "@ensdomains/=node_modules/@ensdomains/", "@eth-optimism/=node_modules/@eth-optimism/", "@looksrare/=node_modules/@looksrare/", "@openzeppelin/=node_modules/@openzeppelin/", "ds-test/=lib/forge-std/lib/ds-test/src/", "eth-gas-reporter/=node_modules/eth-gas-reporter/", "forge-std/=lib/forge-std/src/", "hardhat/=node_modules/hardhat/" ], "optimizer": { "enabled": true, "runs": 888888 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "london", "viaIR": true, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_operator","type":"address"},{"internalType":"address","name":"_protocolFeeRecipient","type":"address"},{"internalType":"address","name":"wrappedNativeToken","type":"address"},{"internalType":"address","name":"_transferManager","type":"address"},{"internalType":"bytes32","name":"keyHash","type":"bytes32"},{"internalType":"address","name":"vrfCoordinator","type":"address"},{"internalType":"uint64","name":"subscriptionId","type":"uint64"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AccessControlBadConfirmation","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"neededRole","type":"bytes32"}],"name":"AccessControlUnauthorizedAccount","type":"error"},{"inputs":[],"name":"CommitmentNotAvailable","type":"error"},{"inputs":[],"name":"ERC20TransferFail","type":"error"},{"inputs":[],"name":"ExceedsMaximumNumberOfPlayersPerRound","type":"error"},{"inputs":[],"name":"HashedPlayerIndicesDoesNotMatchCommitment","type":"error"},{"inputs":[],"name":"InactiveCave","type":"error"},{"inputs":[],"name":"IndivisibleEnterAmount","type":"error"},{"inputs":[{"internalType":"uint256","name":"caveId","type":"uint256"},{"internalType":"uint256","name":"roundId","type":"uint256"}],"name":"IneligibleToWithdraw","type":"error"},{"inputs":[],"name":"InsufficientNumberOfPlayers","type":"error"},{"inputs":[{"internalType":"uint256","name":"caveId","type":"uint256"},{"internalType":"uint256","name":"roundId","type":"uint256"}],"name":"InvalidCommitment","type":"error"},{"inputs":[],"name":"InvalidEnterAmount","type":"error"},{"inputs":[],"name":"InvalidEnterCurrency","type":"error"},{"inputs":[],"name":"InvalidPlayerDetails","type":"error"},{"inputs":[{"internalType":"uint256","name":"caveId","type":"uint256"},{"internalType":"uint256","name":"roundId","type":"uint256"}],"name":"InvalidPlayerIndex","type":"error"},{"inputs":[],"name":"InvalidRoundDuration","type":"error"},{"inputs":[],"name":"InvalidRoundParameters","type":"error"},{"inputs":[],"name":"InvalidRoundStatus","type":"error"},{"inputs":[],"name":"InvalidValue","type":"error"},{"inputs":[],"name":"IsPaused","type":"error"},{"inputs":[],"name":"NotAContract","type":"error"},{"inputs":[],"name":"NotCancellable","type":"error"},{"inputs":[],"name":"NotOperator","type":"error"},{"inputs":[],"name":"NotOwner","type":"error"},{"inputs":[],"name":"NotPaused","type":"error"},{"inputs":[{"internalType":"address","name":"have","type":"address"},{"internalType":"address","name":"want","type":"address"}],"name":"OnlyCoordinatorCanFulfill","type":"error"},{"inputs":[{"internalType":"uint256","name":"caveId","type":"uint256"},{"internalType":"uint256","name":"roundId","type":"uint256"},{"internalType":"address","name":"player","type":"address"}],"name":"PlayerAlreadyParticipated","type":"error"},{"inputs":[],"name":"ProtocolFeeBasisPointsTooHigh","type":"error"},{"inputs":[],"name":"RandomnessRequestAlreadyExists","type":"error"},{"inputs":[],"name":"ReentrancyFail","type":"error"},{"inputs":[],"name":"RepeatingPlayerIndex","type":"error"},{"inputs":[{"internalType":"uint256","name":"caveId","type":"uint256"},{"internalType":"uint256","name":"roundId","type":"uint256"}],"name":"RoundCannotBeEntered","type":"error"},{"inputs":[],"name":"RoundsIncomplete","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"caveId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"enterAmount","type":"uint256"},{"indexed":false,"internalType":"address","name":"enterCurrency","type":"address"},{"indexed":false,"internalType":"uint40","name":"roundDuration","type":"uint40"},{"indexed":false,"internalType":"uint8","name":"playersPerRound","type":"uint8"},{"indexed":false,"internalType":"uint16","name":"protocolFeeBp","type":"uint16"}],"name":"CaveAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"caveId","type":"uint256"}],"name":"CaveRemoved","type":"event"},{"anonymous":false,"inputs":[{"components":[{"internalType":"uint256","name":"caveId","type":"uint256"},{"internalType":"bytes32[]","name":"commitments","type":"bytes32[]"}],"indexed":false,"internalType":"struct IPokeTheBear.CommitmentCalldata[]","name":"commitments","type":"tuple[]"}],"name":"CommitmentsSubmitted","type":"event"},{"anonymous":false,"inputs":[{"components":[{"internalType":"uint256","name":"caveId","type":"uint256"},{"internalType":"uint256[]","name":"roundIds","type":"uint256[]"}],"indexed":false,"internalType":"struct IPokeTheBear.Withdrawal[]","name":"deposits","type":"tuple[]"},{"indexed":false,"internalType":"address","name":"player","type":"address"}],"name":"DepositsRefunded","type":"event"},{"anonymous":false,"inputs":[{"components":[{"internalType":"uint256","name":"caveId","type":"uint256"},{"internalType":"uint256[]","name":"rolledOverRoundIds","type":"uint256[]"},{"internalType":"uint256","name":"rollingOverToRoundIdStart","type":"uint256"}],"indexed":false,"internalType":"struct IPokeTheBear.Rollover[]","name":"rollovers","type":"tuple[]"},{"indexed":false,"internalType":"address","name":"player","type":"address"}],"name":"DepositsRolledOver","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"components":[{"internalType":"uint256","name":"caveId","type":"uint256"},{"internalType":"uint256[]","name":"roundIds","type":"uint256[]"}],"indexed":false,"internalType":"struct IPokeTheBear.Withdrawal[]","name":"prizes","type":"tuple[]"},{"indexed":false,"internalType":"address","name":"player","type":"address"}],"name":"PrizesClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"protocolFeeRecipient","type":"address"}],"name":"ProtocolFeeRecipientUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"caveId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"roundId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"requestId","type":"uint256"}],"name":"RandomnessRequested","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":false,"internalType":"uint256","name":"caveId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"roundId","type":"uint256"},{"indexed":false,"internalType":"enum IPokeTheBear.RoundStatus","name":"status","type":"uint8"}],"name":"RoundStatusUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"caveId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"startingRoundId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"numberOfRounds","type":"uint256"}],"name":"RoundsCancelled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"caveId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"startingRoundId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"numberOfRounds","type":"uint256"},{"indexed":false,"internalType":"address","name":"player","type":"address"}],"name":"RoundsEntered","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"enterAmount","type":"uint256"},{"internalType":"address","name":"enterCurrency","type":"address"},{"internalType":"uint8","name":"playersPerRound","type":"uint8"},{"internalType":"uint40","name":"roundDuration","type":"uint40"},{"internalType":"uint16","name":"protocolFeeBp","type":"uint16"}],"name":"addCave","outputs":[{"internalType":"uint256","name":"caveId","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"caveId","type":"uint256"},{"internalType":"uint256","name":"numberOfRounds","type":"uint256"}],"name":"cancel","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"caveId","type":"uint256"}],"name":"cancel","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"caveId","type":"uint256"},{"internalType":"uint256","name":"roundId","type":"uint256"}],"name":"cancellable","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"caveId","type":"uint256"}],"name":"caves","outputs":[{"internalType":"uint256","name":"enterAmount","type":"uint256"},{"internalType":"address","name":"enterCurrency","type":"address"},{"internalType":"uint40","name":"roundsCount","type":"uint40"},{"internalType":"uint40","name":"lastCommittedRoundId","type":"uint40"},{"internalType":"uint40","name":"roundDuration","type":"uint40"},{"internalType":"uint8","name":"playersPerRound","type":"uint8"},{"internalType":"uint16","name":"protocolFeeBp","type":"uint16"},{"internalType":"bool","name":"isActive","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"caveId","type":"uint256"},{"components":[{"internalType":"uint256","name":"roundId","type":"uint256"},{"internalType":"uint256","name":"playerIndex","type":"uint256"}],"internalType":"struct IPokeTheBear.PlayerWithdrawalCalldata[]","name":"playerDetails","type":"tuple[]"}],"internalType":"struct IPokeTheBear.WithdrawalCalldata[]","name":"claimPrizeCalldataArray","type":"tuple[]"}],"name":"claimPrizes","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"caveId","type":"uint256"},{"internalType":"bytes32[]","name":"commitments","type":"bytes32[]"}],"internalType":"struct IPokeTheBear.CommitmentCalldata[]","name":"commitments","type":"tuple[]"}],"name":"commit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"caveId","type":"uint256"},{"internalType":"uint256","name":"startingRoundId","type":"uint256"},{"internalType":"uint256","name":"numberOfRounds","type":"uint256"}],"name":"enter","outputs":[],"stateMutability":"payable","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":"caveId","type":"uint256"},{"internalType":"uint256","name":"roundId","type":"uint256"}],"name":"getRound","outputs":[{"internalType":"enum IPokeTheBear.RoundStatus","name":"status","type":"uint8"},{"internalType":"uint40","name":"cutoffTime","type":"uint40"},{"internalType":"uint40","name":"drawnAt","type":"uint40"},{"internalType":"bytes32","name":"commitment","type":"bytes32"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"uint8[32]","name":"playerIndices","type":"uint8[32]"},{"components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"bool","name":"isLoser","type":"bool"},{"internalType":"bool","name":"withdrawn","type":"bool"}],"internalType":"struct IPokeTheBear.Player[]","name":"players","type":"tuple[]"}],"stateMutability":"view","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":"uint256","name":"caveId","type":"uint256"},{"internalType":"uint256","name":"roundId","type":"uint256"},{"internalType":"address","name":"player","type":"address"}],"name":"isPlayerInRound","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nextCaveId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"protocolFeeRecipient","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"requestId","type":"uint256"}],"name":"randomnessRequests","outputs":[{"internalType":"bool","name":"exists","type":"bool"},{"internalType":"uint40","name":"caveId","type":"uint40"},{"internalType":"uint40","name":"roundId","type":"uint40"},{"internalType":"uint256","name":"randomWord","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"requestId","type":"uint256"},{"internalType":"uint256[]","name":"randomWords","type":"uint256[]"}],"name":"rawFulfillRandomWords","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"caveId","type":"uint256"},{"components":[{"internalType":"uint256","name":"roundId","type":"uint256"},{"internalType":"uint256","name":"playerIndex","type":"uint256"}],"internalType":"struct IPokeTheBear.PlayerWithdrawalCalldata[]","name":"playerDetails","type":"tuple[]"}],"internalType":"struct IPokeTheBear.WithdrawalCalldata[]","name":"refundCalldataArray","type":"tuple[]"}],"name":"refund","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"caveId","type":"uint256"}],"name":"removeCave","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"callerConfirmation","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"requestId","type":"uint256"},{"internalType":"uint256","name":"playerIndices","type":"uint256"},{"internalType":"bytes32","name":"salt","type":"bytes32"}],"name":"reveal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"caveId","type":"uint256"},{"internalType":"uint256","name":"startingRoundId","type":"uint256"},{"internalType":"uint256","name":"numberOfExtraRoundsToEnter","type":"uint256"},{"components":[{"internalType":"uint256","name":"roundId","type":"uint256"},{"internalType":"uint256","name":"playerIndex","type":"uint256"}],"internalType":"struct IPokeTheBear.PlayerWithdrawalCalldata[]","name":"playerDetails","type":"tuple[]"}],"internalType":"struct IPokeTheBear.RolloverCalldata[]","name":"rolloverCalldataArray","type":"tuple[]"}],"name":"rollover","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":[],"name":"togglePaused","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_protocolFeeRecipient","type":"address"}],"name":"updateProtocolFeeRecipient","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
61014034620001bb576001600160401b036200508238819003601f8101601f1916840183811185821017620001c05784928291604052833961010093849181010312620001bb576200005181620001d6565b916200006060208301620001d6565b906200006f60408401620001d6565b916200007e60608501620001d6565b6200008c60808601620001d6565b9560a08601519260e0620000a360c08901620001d6565b9701519485168503620001bb57620000d5620000dc928a61ff00196001541617600155886080526001600755620001eb565b506200026b565b5060a05260c0526001600160a01b03928316855260e05291811661012090815291168015620001a957600680546001600160a01b031916821790556040519081527fc1b5345cce283376356748dc57f2dfa7120431d016fc7ca9ba641bc65f91411d90602090a160405190614d5492836200030e843960805183614743015260a051836142d4015260c0518381816139c50152613ccb015260e0518381816139eb0152613cf1015251828181613a3b0152613d40015251818181611b5b01528181611eb301526120be0152f35b604051632a9ffab760e21b8152600490fd5b600080fd5b634e487b7160e01b600052604160045260246000fd5b51906001600160a01b0382168203620001bb57565b6001600160a01b031660008181527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604081205490919060ff166200026757818052816020526040822081835260205260408220600160ff198254161790553391600080516020620050628339815191528180a4600190565b5090565b6001600160a01b031660008181527fee57cd81e84075558e8fcc182a1f4393f91fc97f963a136e66b7f949a62f319f60205260408120549091907f97667070c54ef182b0f5858b034beac1b6f3089aa2d3188bb1e8929f4fa9b9299060ff166200030857808352826020526040832082845260205260408320600160ff1982541617905560008051602062005062833981519152339380a4600190565b50509056fe6080604052600436101561001257600080fd5b60003560e01c8062efa895146101d657806301ffc9a7146101d15780631df47f80146101cc5780631fe543e3146101c7578063248a9ca3146101c2578063286eca7f146101bd5780632f2ff15d146101b857806331c58858146101b357806336566f06146101ae57806336568abe146101a957806339ec68a3146101a45780633ca6915f1461019f57806340e58ee51461019a57806344ce2671146101955780635c975abb146101905780635cb6dfff1461018b57806361d49ea81461018657806364df049e146101815780636be5361e1461017c57806378c3a5dd1461017757806391d1485414610172578063962626e81461016d578063a217fddf14610168578063bc20805714610163578063d547741f1461015e578063d7eb82a714610159578063fad8269f146101545763faf7d65e1461014f57600080fd5b6124bb565b612264565b6121fa565b61219d565b611fc8565b611f8e565b611a48565b6119ca565b6118ff565b61166d565b61161b565b61126f565b6111f9565b6111b8565b611143565b611021565b610e2b565b610c5b565b610abc565b6109bf565b610983565b61091b565b610813565b6107c6565b61071c565b61051c565b61043a565b346104355760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104355760043560243590600190600260ff835460081c161461040b5761024f6102007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff6001541617600155565b610257614904565b61025f614666565b81610274826000526005602052604060002090565b01805464ffffffffff90818160a01c16946102976102928888612a59565b612a76565b918388159182156103fc575b50506103d257855b8281111561037557505082547fffffffffffffff0000000000ffffffffffffffffffffffffffffffffffffffff16911660a01b78ffffffffff0000000000000000000000000000000000000000161790557fddd9a1ac1ae0095c1389781239f4f4280ebfb649201b0556f78e77fa289e91839261033f90604051938493846040919493926060820195825260208201520152565b0390a16103736101007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff6001541617600155565b005b806103cc6103a184936103928a6000526003602052604060002090565b90600052602052604060002090565b60057fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00825416179055565b016102ab565b60046040517f67909b15000000000000000000000000000000000000000000000000000000008152fd5b60c81c168311905083386102a3565b60046040517f1bbee726000000000000000000000000000000000000000000000000000000008152fd5b600080fd5b346104355760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610435576004357fffffffff00000000000000000000000000000000000000000000000000000000811680910361043557807f7965db0b00000000000000000000000000000000000000000000000000000000602092149081156104cf575b506040519015158152f35b7f01ffc9a700000000000000000000000000000000000000000000000000000000915014386104c4565b6024359073ffffffffffffffffffffffffffffffffffffffff8216820361043557565b346104355760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104355760043573ffffffffffffffffffffffffffffffffffffffff811680910361043557610574614666565b80156105d1576020817fc1b5345cce283376356748dc57f2dfa7120431d016fc7ca9ba641bc65f91411d927fffffffffffffffffffffffff00000000000000000000000000000000000000006006541617600655604051908152a1005b60046040517faa7feadc000000000000000000000000000000000000000000000000000000008152fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60e0810190811067ffffffffffffffff82111761064657604052565b6105fb565b67ffffffffffffffff811161064657604052565b6040810190811067ffffffffffffffff82111761064657604052565b6060810190811067ffffffffffffffff82111761064657604052565b610400810190811067ffffffffffffffff82111761064657604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761064657604052565b604051906107028261067b565b565b67ffffffffffffffff81116106465760051b60200190565b346104355760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104355760243567ffffffffffffffff811161043557366023820112156104355780600401359061077782610704565b9061078560405192836106b4565b82825260209260248484019160051b8301019136831161043557602401905b8282106107b7576103738460043561472c565b813581529084019084016107a4565b346104355760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104355760043560005260006020526020600160406000200154604051908152f35b346104355760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104355760043561084d614666565b80600052600560205260016040600020015464ffffffffff808260c81c169160a01c16106108f1576108ec816108dc60026108b37f3b1b1a7c6b021e524cac489566ae6d22e8dde1b38bcc164bb70490fa21daf97c956000526005602052604060002090565b017fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff8154169055565b6040519081529081906020820190565b0390a1005b60046040517ff9250d0c000000000000000000000000000000000000000000000000000000008152fd5b346104355760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610435576103736004356109586104f9565b90806000526000602052610973600160406000200154614ae6565b614b60565b600091031261043557565b346104355760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610435576020600754604051908152f35b346104355760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610435576109f6614666565b60015460ff811615610a5f5750610a0b614904565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00600154166001557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa6020604051338152a1005b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00600191610a8b6148ce565b16176001557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586020604051338152a1005b346104355760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261043557610af36104f9565b3373ffffffffffffffffffffffffffffffffffffffff821603610b1c5761037390600435614c43565b60046040517f6697b232000000000000000000000000000000000000000000000000000000008152fd5b60061115610b5057565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b906006821015610b505752565b9193959490946104c091610ba38484810198610b7f565b64ffffffffff806020971687860152604095168585015260609788850152608084015260a083016000905b868210610c42575050506104a08201528551938490526104e001948201936000915b848310610c005750505050505090565b8551805173ffffffffffffffffffffffffffffffffffffffff168852808501511515888601528101511515878201529581019594830194600190920191610bf0565b825160ff16815291860191600191909101908601610bce565b34610435576040807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610435576104008151610c9981610697565b369037600090600435825260036020528082206024358352602052808220815191610cc38361062a565b81549260ff84166006811015610d935790610d8f929181526020810193610d1464ffffffffff610cff818960081c16889064ffffffffff169052565b8484019760301c16879064ffffffffff169052565b60018101546060830190815260028201549060808401918252610d7c610d70610d526004610d446003880161302e565b9660a0890197885201613300565b9560c081019687525198610d658a610b46565b5164ffffffffff1690565b985164ffffffffff1690565b9051915192519351945197889788610b8c565b0390f35b6024867f4e487b710000000000000000000000000000000000000000000000000000000081526021600452fd5b9060207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8301126104355760043567ffffffffffffffff9283821161043557806023830112156104355781600401359384116104355760248460051b83010111610435576024019190565b3461043557610e3936610dc0565b610e416146c9565b60005b818110610e7d57507f1f0def5d5179f4d53a0dafd78f3ae044c7cbf799630739fd50674bbec8c356b8916108ec60405192839283612ab0565b610e8881838561294f565b3590610e9e826000526005602052604060002090565b91610eb8610eb4600285015460ff9060401c1690565b1590565b610ff757600180930190610eea610ee0610edb845464ffffffffff9060c81c1690565b6129c3565b64ffffffffff1690565b610f02610ef885888a61294f565b60208101906129f7565b9260005b848110610f7857505050610ee0610292610f729493610f2493612a59565b7fffff0000000000ffffffffffffffffffffffffffffffffffffffffffffffffff7dffffffffff0000000000000000000000000000000000000000000000000083549260c81b169116179055565b01610e44565b610f828185612a59565b610f8d828786612a66565b35908115610fb9579089610fb1819493610392876000526003602052604060002090565b015501610f06565b6040517f795bfe85000000000000000000000000000000000000000000000000000000008152600481018590526024810191909152604490fd5b0390fd5b60046040517fe7d1a70d000000000000000000000000000000000000000000000000000000008152fd5b346104355760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261043557600435600260ff60015460081c161461040b576110946102007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff6001541617600155565b8060005260056020526040600020611105610eb464ffffffffff600184015460a01c169260036020526110dc8460406000209064ffffffffff16600052602052604060002090565b906110f960026110ed845460ff1690565b92015460281c60ff1690565b90600483015492614558565b6103d25761111291613e95565b6103736101007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff6001541617600155565b346104355760a07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104355761117a6104f9565b6044359060ff821682036104355760643564ffffffffff81168103610435576084359061ffff8216820361043557610d8f936108dc9360043561256d565b346104355760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261043557602060ff600154166040519015158152f35b346104355760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261043557600435600052600260205260806040600020600181549101546040519160ff81161515835264ffffffffff90818160081c16602085015260301c1660408301526060820152f35b346104355760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610435576024356044356112ac6148ce565b6004906112c482356000526002602052604060002090565b9081549264ffffffffff808560081c169460301c16916112f283610392876000526003602052604060002090565b906003611300835460ff1690565b61130981610b46565b036115f25760408051602081018981528183018490529194919061135881606081015b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081018352826106b4565b5190209560019687850154036115ca578661138461137f848701938454938491015461255e565b612a4b565b90600386016000805b838110611499576103738d8d8d7ff7ab5a65307ab9788b10eab6a0e173842698dc9772bc3e58eaac1d6e0315b0598e6113f18f8f600282015560047fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00825416179055565b518481526020810183905260046040820152606090a161149261141e846000526005602052604060002090565b60065473ffffffffffffffffffffffffffffffffffffffff169061148c61148461145e8784015473ffffffffffffffffffffffffffffffffffffffff1690565b9261147e6114776002835493015461ffff9060301c1690565b61ffff1690565b90612c09565b612710900490565b916142ad565b0190614061565b6114ad8e6114a683612bf3565b1c60ff1690565b9160ff831690811580156115c1575b61157f578d821b908181166115575717928d929187916114f9906114e08589612c28565b90919060ff8084549260031b9316831b921b1916179055565b14611505575b0161138d565b6115526115128289612c41565b50740100000000000000000000000000000000000000007fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff825416179055565b6114ff565b898d517f8ce0d24b000000000000000000000000000000000000000000000000000000008152fd5b8e89610ff38f8f519384937fa06986c7000000000000000000000000000000000000000000000000000000008552840160209093929193604081019481520152565b508582116114bc565b5083517fb06ec8f9000000000000000000000000000000000000000000000000000000008152fd5b826040517fc38434ab000000000000000000000000000000000000000000000000000000008152fd5b346104355760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261043557602073ffffffffffffffffffffffffffffffffffffffff60065416604051908152f35b346104355761167b36610dc0565b906001600260ff825460081c161461040b576116be6102007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff6001541617600155565b6116c66148ce565b6116ce612c59565b916116d884612c72565b9360005b818110611752577f151b7b4fba4f2f307fc85d2e1759f3691da9606509751f0f40fccf193e418e4d61033f8787602081015180611724575b5050604051918291339083612df8565b61174561174b925173ffffffffffffffffffffffffffffffffffffffff1690565b336142ad565b8380611714565b80856117608693858761294f565b82813591611778836000526005602052604060002090565b928b61178e855461178887614612565b90612a59565b926117a96117a160209283810190612cf0565b969093612d51565b51838152816117b787612d65565b910190815260005b868110611806575050505050856117de6118009594936117fa93612c09565b92015473ffffffffffffffffffffffffffffffffffffffff1690565b906143ef565b016116dc565b839597999a508681939597995061181d9294612db4565b80359061183882610392896000526003602052604060002090565b90611844825460ff1690565b9061184e82610b46565b60048092036118d6578f9493926118b9928861186d9301359101612c41565b5061187981848b6144cb565b75010000000000000000000000000000000000000000007fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff825416179055565b6118c4828551612d51565b520193918b98979593918d97956117bf565b506040517fc38434ab000000000000000000000000000000000000000000000000000000008152fd5b346104355760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104355760043560009081526005602090815260409182902080546001820154600290920154845191825273ffffffffffffffffffffffffffffffffffffffff83169382019390935264ffffffffff60a083811c82168387015260c89390931c811660608301528316608082015260ff602884901c81169282019290925261ffff603084901c1660c08201529190921c909116151560e082015261010090f35b346104355760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261043557602060ff611a3c611a086104f9565b6004356000526000845260406000209073ffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b54166040519015158152f35b611a5136610dc0565b600260ff60015460081c161461040b57611a926102007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff6001541617600155565b611a9a6148ce565b611aa2612c59565b611aaa612c59565b91611ab481612ea7565b93349160005b818110611c8657505050611c5c57602081015180611b3e575b50507f1e473be843779c10566d945a4adf38c5fa2f3585a52fc906f1d9e502cf3798879181602061033f93015180611b16575b5050604051918291339083612f6b565b611745611b37925173ffffffffffffffffffffffffffffffffffffffff1690565b3880611b06565b611b9673ffffffffffffffffffffffffffffffffffffffff9492947f000000000000000000000000000000000000000000000000000000000000000016945173ffffffffffffffffffffffffffffffffffffffff1690565b90843b15610435576040517fda3e8ce400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9290921660048301523360248301523060448301526064820152926000908490608490829084905af1918215611c57577f1e473be843779c10566d945a4adf38c5fa2f3585a52fc906f1d9e502cf3798879361033f93611c3e575b5091819350611ad3565b80611c4b611c519261064b565b80610978565b38611c34565b612c1c565b60046040517f87b71f66000000000000000000000000000000000000000000000000000000008152fd5b611c91818385612f2b565b611c9e6060820182612cf0565b80915015611f6457611cbb82356000526005602052604060002090565b91611cdd600184015473ffffffffffffffffffffffffffffffffffffffff1690565b916040820135611ded575b91849392611cf88b93968d612d51565b5186358152611d0682612d65565b6020820152600094855b838110611d62575050956040611d3b611d429360019960208501359384910152604084013590612a59565b91356134df565b82611d51575b50505001611aba565b611d5a926143ef565b388781611d48565b909192939596979450611d8281611d7c6060880188612cf0565b90612db4565b6004611da1611d99600286015460ff9060281c1690565b8835846141b2565b611daa81610b46565b14611dd3575b9060019135611dc3826020870151612d51565b5201908c94979695939291611d10565b9690611de460019261178885614612565b97909150611db0565b9673ffffffffffffffffffffffffffffffffffffffff8381169081611e2d575050611e2790611e2160408401358654612c09565b90612aa3565b96611ce8565b8a5192999273ffffffffffffffffffffffffffffffffffffffff169181831603611e78575050611e6260408301358554612c09565b611e7160208b01918251612a59565b9052611ce8565b60208b019182519182611eb1575b50505073ffffffffffffffffffffffffffffffffffffffff84168a52611e7160408401358654612c09565b7f00000000000000000000000000000000000000000000000000000000000000001691823b15610435576040517fda3e8ce400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9290921660048301523360248301523060448301526064820152906000908290608490829084905af18015611c5757611f51575b8080611e86565b80611c4b611f5e9261064b565b38611f4a565b60046040517fc7017d52000000000000000000000000000000000000000000000000000000008152fd5b346104355760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261043557602060405160008152f35b60607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261043557600435604435600260ff60015460081c161461040b576120396102007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff6001541617600155565b6120416148ce565b612055826000526005602052604060002090565b6120818261207a600184015473ffffffffffffffffffffffffffffffffffffffff1690565b9254612c09565b9073ffffffffffffffffffffffffffffffffffffffff8082166120b45750503403611c5c57611112915b602435906134df565b93919334612173577f00000000000000000000000000000000000000000000000000000000000000001693843b15610435576040517fda3e8ce400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9290921660048301523360248301523060448301526064820152926000908490608490829084905af1928315611c575761111293612160575b506120ab565b80611c4b61216d9261064b565b3861215a565b60046040517fe2a8f8a0000000000000000000000000000000000000000000000000000000008152fd5b346104355760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610435576103736004356121da6104f9565b908060005260006020526121f5600160406000200154614ae6565b614c43565b346104355760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104355760443573ffffffffffffffffffffffffffffffffffffffff811681036104355761225a6020916024356004356133a6565b6040519015158152f35b346104355761227236610dc0565b6001600260ff825460081c161461040b576122b46102007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff6001541617600155565b6122bc6148ce565b6122c4612c59565b926122ce83612c72565b9260005b818110612319577fd53f2bb6fed83c8a1662fd984e0882cef7bc2c6dd8d4d8d482ca931945efd61961033f8688602081015180611724575050604051918291339083612df8565b80866123278693858761294f565b8781359161233f836000526005602052604060002090565b9260208083019161235c886123548587612cf0565b979050612d51565b51918183528061236b87612d65565b930192835260005b86811061239a57505050505050906117fa856117de61239495948454612c09565b016122d2565b8597999a5084969850611d7c8193956123b4939597612cf0565b8035906123cf82610392876000526003602052604060002090565b906123db825460ff1690565b908b8660049283860194855496816123f38993610b46565b86811061247f575b5050500135938410159050612444575061241b8f94939261242792612c41565b506118798184896144cb565b612432828751612d51565b5201918b98979593918e979593612373565b604080517fa06986c7000000000000000000000000000000000000000000000000000000008152918201888152602081018690528291010390fd5b6124a0945061249a6002610eb49597015460ff9060281c1690565b91614558565b6118d65786906124b0868a613e95565b908d918538806123fb565b346104355760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261043557602061225a60043560009080825260038452604082206024358352845260ff6002604080852094838654169481526005885220015460281c1690600483015492614558565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b8115612568570690565b61252f565b90919493929461257b614666565b60ff8116600281106128f6576020106128cc5761ffff84166109c481116128a2576125d49061271060ff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff85011691850204840361255e565b6128785764ffffffffff8616603c811090811561286c575b50612842577f44ab42484886e3b9dfa09fe03c00b19e3386faaa7313d5de2b4bcd7d1453dd799361283d9160075497846126308a6000526005602052604060002090565b5561268c86600161264b8c6000526005602052604060002090565b019073ffffffffffffffffffffffffffffffffffffffff167fffffffffffffffffffffffff0000000000000000000000000000000000000000825416179055565b6126de8260026126a68c6000526005602052604060002090565b01907fffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffff65ff000000000083549260281b169116179055565b61272a8160026126f88c6000526005602052604060002090565b019064ffffffffff167fffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000825416179055565b61277e8360026127448c6000526005602052604060002090565b01907fffffffffffffffffffffffffffffffffffffffffffffffff0000ffffffffffff67ffff00000000000083549260301b169116179055565b6127cb60026127978b6000526005602052604060002090565b01680100000000000000007fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff825416179055565b6127d489613f21565b6127e86127e360075460010190565b600755565b6040519586958a879464ffffffffff60a09573ffffffffffffffffffffffffffffffffffffffff61ffff9660ff959b9a9660c08b019c8b5260208b015216604089015216606087015216608085015216910152565b0390a1565b60046040517f06201c01000000000000000000000000000000000000000000000000000000008152fd5b610e10915011386125ec565b60046040517f490bbdd0000000000000000000000000000000000000000000000000000000008152fd5b60046040517f36d36c7c000000000000000000000000000000000000000000000000000000008152fd5b60046040517fbaa3711d000000000000000000000000000000000000000000000000000000008152fd5b60046040517fe8a119d4000000000000000000000000000000000000000000000000000000008152fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b919081101561298f5760051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc181360301821215610435570190565b612920565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b90600164ffffffffff809316019182116129d957565b612994565b91909164ffffffffff808094169116019182116129d957565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610435570180359067ffffffffffffffff821161043557602001918160051b3603831361043557565b90600182018092116129d957565b919082018092116129d957565b919081101561298f5760051b0190565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82019182116129d957565b919082039182116129d957565b916020908082850183865252604091828501946005958484881b83010196866000935b868510612ae65750505050505050505090565b9091929394959697987fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc082820301855289357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc18436030181121561043557830180358252878101357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe182360301811215610435570187813591019167ffffffffffffffff82116104355781861b918236038413610435577f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff908c8b840152808d8401521161043557600192828a939284936060938483013701019b01950195019397969594929190612ad3565b908160031b91808304600814901517156129d957565b818102929181159184041417156129d957565b6040513d6000823e3d90fd5b919091602083101561298f57601f908360051c01921690565b805482101561298f5760005260206000200190600090565b60405190612c668261065f565b60006020838281520152565b90612c7c82610704565b6040612c8a815192836106b4565b8382527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0612cb88395610704565b0191600091825b848110612ccd575050505050565b6020908251612cdb8161065f565b85815282606081830152828601015201612cbf565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610435570180359067ffffffffffffffff821161043557602001918160061b3603831361043557565b80511561298f5760200190565b805182101561298f5760209160051b010190565b90612d6f82610704565b612d7c60405191826106b4565b8281527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0612daa8294610704565b0190602036910137565b919081101561298f5760061b0190565b90815180825260208080930193019160005b828110612de4575050505090565b835185529381019392810192600101612dd6565b909291926040808301908084528251809252606084019160608160051b860101916020809501936000915b86848410612e4e57505050505073ffffffffffffffffffffffffffffffffffffffff91509416910152565b80612e97877fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa08c6001969798999a0301875285838b518051845201519181858201520190612dc4565b9701930193019194939290612e23565b90612eb182610704565b604090612ec0825191826106b4565b8381527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0612eee8295610704565b0191600091825b848110612f03575050505050565b6020908351612f118161067b565b858152826060818301528686830152828501015201612ef5565b919081101561298f5760051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8181360301821215610435570190565b9192909260409384840194808552815180965260609586860191878260051b880101926020809501986000925b848410612fc85750505050506107029394955094019073ffffffffffffffffffffffffffffffffffffffff169052565b90919293948680827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa08d600195030187528d5190815181528580613017858501518a878601528a850190612dc4565b9301519101529c0194019401929994939190612f98565b6040805160009390929190835b602080601f880110156132f0576104006020926132e46001936132d98954916132b26131176132628c613212896131c260ff9761307c838a8d1660ff169052565b61308f8184018a8d60081c1660ff169052565b6130a28584018a8d60101c1660ff169052565b888b6102006060956130bd878201858560181c1660ff169052565b6130d26080958585888501921c1660ff169052565b61317860a0976130eb898401878760281c1660ff169052565b61312860c09b6131048d8601898960301c1660ff169052565b60e09e8f8601898960381c1660ff169052565b87876101008701921c1660ff169052565b61313d6101208401878760481c1660ff169052565b6131526101408401878760501c1660ff169052565b6131676101608401878760581c1660ff169052565b85856101808501921c1660ff169052565b61318d6101a08201858560681c1660ff169052565b6131a26101c08201858560701c1660ff169052565b6131b76101e08201858560781c1660ff169052565b01921c1660ff169052565b6131d76102208c01888b60881c1660ff169052565b6131ec6102408c01888b60901c1660ff169052565b6132016102608c01888b60981c1660ff169052565b86896102808d01921c1660ff169052565b6132276102a08a01868960a81c1660ff169052565b61323c6102c08a01868960b01c1660ff169052565b6132516102e08a01868960b81c1660ff169052565b84876103008b01921c1660ff169052565b6132776103208801848760c81c1660ff169052565b61328c6103408801848760d01c1660ff169052565b6132a16103608801848760d81c1660ff169052565b82856103808901921c1660ff169052565b6132c76103a08601828560e81c1660ff169052565b6103c08501908360f01c1660ff169052565b60f81c6103e0830152565b0194019501949261303b565b5050929350505061070282610697565b90815461330c81610704565b9260409361331c855191826106b4565b828152809460208092019260005281600020906000935b85851061334257505050505050565b600184819284516133528161067b565b865473ffffffffffffffffffffffffffffffffffffffff8116825260ff90818160a01c1615158584015260a81c16151586820152815201930194019391613333565b6201000082101561298f570190600090565b73ffffffffffffffffffffffffffffffffffffffff60ff9316600052600460205260406000209060005260205260016133e68260081c6040600020613394565b93905492161b9160031b1c16151590565b8054680100000000000000008110156106465761341991600182018155612c41565b9190916134b05780518254602083015160409093015173ffffffffffffffffffffffffffffffffffffffff9092167fffffffffffffffffffff000000000000000000000000000000000000000000009091161791151560a01b74ff0000000000000000000000000000000000000000169190911790151560a81b75ff00000000000000000000000000000000000000000016179055565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600060045260246000fd5b929190801580156138d2575b6138a857613503846000526005602052604060002090565b936002850194855460409660ff82891c161561387f576135238686612a59565b9161353e610ee060018096015464ffffffffff9060c81c1690565b917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff92838501116138565761358187610392886000526003602052604060002090565b9161358d835460ff1690565b9061359782610b46565b86821161381e5760281c60ff16936135ae82610b46565b81156137cb575b50875b85811061360f575050985194855250505050602081019190915260408101919091523360608201529091507f9a711314e8e01b50116aefb9d50edc1a6b06e39986010af70d18671666586d0e90806080810161283d565b61361a33828a6133a6565b61378c57808914801561376f57845b6004918282018a815401938985116137295750918f916136648c9695938b9560006136526106f5565b338152928160208501528301526133f7565b61366f33868f61444f565b61367d575b505050016135b8565b61368686610b46565b8486036136745764ffffffffff90816136a8825464ffffffffff9060081c1690565b16156136ce575b5050146136bf575b853880613674565b6136c9818a613c62565b6136b7565b6136ec613722926136e48a5464ffffffffff1690565b9042166129de565b7fffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000ff65ffffffffff0083549260081b169116179055565b38806136af565b9350505050610ff389928e519384937fca10b936000000000000000000000000000000000000000000000000000000008552840160209093929193604081019481520152565b613787826103928b6000526003602052604060002090565b613629565b8b517f190f2750000000000000000000000000000000000000000000000000000000008152600481018990526024810191909152336044820152606490fd5b868911156135b55788016138076137f0826103928b6000526003602052604060002090565b866137fc825460ff1690565b600483015492614558565b156135b557613817915087613e95565b84386135b5565b8b517fca10b93600000000000000000000000000000000000000000000000000000000815260048101899052602481018a9052604490fd5b60048a517f5ee0d7b4000000000000000000000000000000000000000000000000000000008152fd5b600488517fe7d1a70d000000000000000000000000000000000000000000000000000000008152fd5b60046040517f558947cf000000000000000000000000000000000000000000000000000000008152fd5b5081156134eb565b90816020910312610435575190565b61393e613913613903836000526003602052604060002090565b6001600052602052604060002090565b60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00825416179055565b64ffffffffff61399d814216613961613903856000526003602052604060002090565b907fffffffffffffffffffffffffffffffffffffffffff0000000000ffffffffffff6affffffffff00000000000083549260301b169116179055565b6040517f5d3b1d300000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060048201527f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff166024820152600360448201526207a1206064820152600160848201529160208360a48160007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff165af1928315611c5757600093613c32575b50613aa0613a99846000526002602052604060002090565b5460ff1690565b613c08577f34e010a4ef37e7b53b3d02e76e84b745a250daa244a2768dabaf7c0c1947963e613be784613b8061283d95613b33613b087ff7ab5a65307ab9788b10eab6a0e173842698dc9772bc3e58eaac1d6e0315b059996000526002602052604060002090565b60017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00825416179055565b8516613b49836000526002602052604060002090565b907fffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000ff65ffffffffff0083549260081b169116179055565b613bc8613b97826000526002602052604060002090565b66010000000000007fffffffffffffffffffffffffffffffffffffffffff0000000000ffffffffffff825416179055565b6040805185815260016020820152908101919091529081906060820190565b0390a160408051918252600160208301526002908201529081906060820190565b60046040517ff9012132000000000000000000000000000000000000000000000000000000008152fd5b613c5491935060203d8111613c5b575b613c4c81836106b4565b8101906138da565b9138613a81565b503d613c42565b90613c7e61391382610392856000526003602052604060002090565b64ffffffffff91613ca383421661396184610392856000526003602052604060002090565b6040517f5d3b1d300000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060048201527f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff166024820152600360448201526207a12060648201526001608482015260208160a48160007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff165af1908115611c5757600091613e77575b50613d9e613a99826000526002602052604060002090565b613c0857613e5281613e337ff7ab5a65307ab9788b10eab6a0e173842698dc9772bc3e58eaac1d6e0315b05996613e03613b087f34e010a4ef37e7b53b3d02e76e84b745a250daa244a2768dabaf7c0c1947963e966000526002602052604060002090565b613e1d818716613b49856000526002602052604060002090565b8616613961836000526002602052604060002090565b6040519182918686846040919493926060820195825260208201520152565b0390a161283d6040519283928360409060029294936060820195825260208201520152565b613e8f915060203d8111613c5b57613c4c81836106b4565b38613d86565b600161070292826000526003602052604060002081600052602052613ee3604060002060057fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00825416179055565b7ff7ab5a65307ab9788b10eab6a0e173842698dc9772bc3e58eaac1d6e0315b059606060405185815283602082015260056040820152a10190614061565b80600052600360205260406000206001600052602052604060002090600482015491613f57826000526005602052604060002090565b6002810180549094919060281c60ff168203613f7a5750505061070291506138e9565b8293614016600161403493613fd67ff7ab5a65307ab9788b10eab6a0e173842698dc9772bc3e58eaac1d6e0315b059969760017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00825416179055565b01740100000000000000000000000000000000000000007fffffffffffffff0000000000ffffffffffffffffffffffffffffffffffffffff825416179055565b60408051918252600160208301819052908201529081906060820190565b0390a161403f575050565b6136ec614054610702935464ffffffffff1690565b64ffffffffff42166129de565b90816000526003602052604060002081600052602052604060002091600483015492614097826000526005602052604060002090565b9360028501906140b56140af835460ff9060281c1690565b60ff1690565b81036140c8575050506107029250613c62565b91937ff7ab5a65307ab9788b10eab6a0e173842698dc9772bc3e58eaac1d6e0315b059919361411c8660017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00825416179055565b600190960180547fffffffffffffff0000000000ffffffffffffffffffffffffffffffffffffffff1660a083901b78ffffffffff00000000000000000000000000000000000000001617905564ffffffffff956141916040519283928360409060019294936060820195825260208201520152565b0390a161419d57505050565b54610702926136ec9164ffffffffff166136e4565b90929192602082359201356141d1826000526003602052604060002090565b83600052602052604060002060ff815416956004820191825480926141f58a610b46565b8960048110614262575b50505050821015614225579161421c611879926107029594612c41565b509283916144cb565b50506040517fa06986c700000000000000000000000000000000000000000000000000000000815260048101919091526024810191909152604490fd5b61426b93614558565b156142835761427a8585613e95565b388181896141ff565b60046040517fc38434ab000000000000000000000000000000000000000000000000000000008152fd5b919073ffffffffffffffffffffffffffffffffffffffff81166142f8575090610702915a917f00000000000000000000000000000000000000000000000000000000000000006149b1565b803b156143c5576040517fa9059cbb000000000000000000000000000000000000000000000000000000006020820190815273ffffffffffffffffffffffffffffffffffffffff9094166024820152604481019290925260009283928390614363816064810161132c565b51925af161436f61493b565b901561439b57805180614380575050565b81602080610eb4936143959501019101614999565b61439b57565b60046040517ff1568f95000000000000000000000000000000000000000000000000000000008152fd5b60046040517f09ee12d5000000000000000000000000000000000000000000000000000000008152fd5b9173ffffffffffffffffffffffffffffffffffffffff80825116921682811460001461442a5750602091500180519182018092116129d95752565b90602081019283518061443e575b50505252565b61444891336142ad565b3880614438565b909173ffffffffffffffffffffffffffffffffffffffff16600052600460205260406000209060005260205261448c8160081c6040600020613394565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600160ff849594549360031b94161b82841c17831b921b1916179055565b90915460ff8160a01c16908115614549575b8115614528575b506144ed575050565b6040517f7f7f26da00000000000000000000000000000000000000000000000000000000815260048101919091526024810191909152604490fd5b73ffffffffffffffffffffffffffffffffffffffff163314159050386144e4565b905060ff8160a81c16906144dd565b929091925464ffffffffff91828260081c16946006851015610b5057600185149586614608575b866145fd575b50856145f0575b5050831561459b575b50505090565b600283149350909183156145da575b50826145bb575b5050388080614595565b90915060301c811662015180018181116129d9571642101538806145b1565b60039193506145e881610b46565b1491386145aa565b60ff16119350388061458c565b421015955038614585565b801515965061457f565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60ff60028354930154926146546127109161ffff8660301c16830390612c09565b049260281c1601908115612568570490565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff161561469f57565b60046040517f30cd7471000000000000000000000000000000000000000000000000000000008152fd5b3360009081527fee57cd81e84075558e8fcc182a1f4393f91fc97f963a136e66b7f949a62f319f602052604090205460ff161561470257565b60046040517f7c214f04000000000000000000000000000000000000000000000000000000008152fd5b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016803303614897575080600052600260205260406000205460ff811661478757505050565b64ffffffffff9060081c166147ba610ee06147ac846000526002602052604060002090565b5460301c64ffffffffff1690565b916147d383610392846000526003602052604060002090565b60026147e0825460ff1690565b6147e981610b46565b146147f6575b5050505050565b6148666148547ff7ab5a65307ab9788b10eab6a0e173842698dc9772bc3e58eaac1d6e0315b0599661484f60019460037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00825416179055565b612d44565b51926000526002602052604060002090565b015561488a6040519283928360409060039294936060820195825260208201520152565b0390a138808080806147ef565b604490604051907f1cf993f40000000000000000000000000000000000000000000000000000000082523360048301526024820152fd5b60ff600154166148da57565b60046040517f1309a563000000000000000000000000000000000000000000000000000000008152fd5b60ff600154161561491157565b60046040517f6cd60201000000000000000000000000000000000000000000000000000000008152fd5b3d15614994573d9067ffffffffffffffff8211610646576040519161498860207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601846106b4565b82523d6000602084013e565b606090565b90816020910312610435575180151581036104355790565b6149c682849395600080809781948294f11590565b6149d1575b50505050565b73ffffffffffffffffffffffffffffffffffffffff16803b15614ae257604051937fd0e30db0000000000000000000000000000000000000000000000000000000008552838560048186865af1938415611c5757614a8a95602095614acf575b506040518096819582947fa9059cbb000000000000000000000000000000000000000000000000000000008452600484016020909392919373ffffffffffffffffffffffffffffffffffffffff60408201951681520152565b03925af18015611c5757614aa1575b8080806149cb565b614ac19060203d8111614ac8575b614ab981836106b4565b810190614999565b5038614a99565b503d614aaf565b80611c4b614adc9261064b565b38614a31565b8280fd5b80600052600060205260ff614b1f3360406000209073ffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b541615614b295750565b604490604051907fe2517d3f0000000000000000000000000000000000000000000000000000000082523360048301526024820152fd5b6000908082528160205260ff614b9984604085209073ffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b5416614c3d5780825281602052614bd383604084209073ffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b60017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008254161790557f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d73ffffffffffffffffffffffffffffffffffffffff3394169280a4600190565b50905090565b6000908082528160205260ff614c7c84604085209073ffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b541615614c3d5780825281602052614cb783604084209073ffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0081541690557ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b73ffffffffffffffffffffffffffffffffffffffff3394169280a460019056fea2646970667358221220a125cb17f3508dc82892b7bcfc8e7235a8793e3b5b448661287891a1a590f48364736f6c634300081400332f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d000000000000000000000000b5a9e5a319c7fda551a30be592c77394bf935c6f000000000000000000000000842ca39dfd984d4349ce8d8c95577e2bf42f4db0000000000000000000000000c8c57e4c73c71f72ca0a7e043e5d2d144f98ef13000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc200000000000000000000000000000000000ea4af05656c17b90f4d64add29e1d8af398995b04c28e9951adb9721ef74c74f93e6a478f39e7e0777be13527e7ef000000000000000000000000271682deb8c4e0901d1a1550ad2e64d568e6990900000000000000000000000000000000000000000000000000000000000002de
Deployed Bytecode
0x6080604052600436101561001257600080fd5b60003560e01c8062efa895146101d657806301ffc9a7146101d15780631df47f80146101cc5780631fe543e3146101c7578063248a9ca3146101c2578063286eca7f146101bd5780632f2ff15d146101b857806331c58858146101b357806336566f06146101ae57806336568abe146101a957806339ec68a3146101a45780633ca6915f1461019f57806340e58ee51461019a57806344ce2671146101955780635c975abb146101905780635cb6dfff1461018b57806361d49ea81461018657806364df049e146101815780636be5361e1461017c57806378c3a5dd1461017757806391d1485414610172578063962626e81461016d578063a217fddf14610168578063bc20805714610163578063d547741f1461015e578063d7eb82a714610159578063fad8269f146101545763faf7d65e1461014f57600080fd5b6124bb565b612264565b6121fa565b61219d565b611fc8565b611f8e565b611a48565b6119ca565b6118ff565b61166d565b61161b565b61126f565b6111f9565b6111b8565b611143565b611021565b610e2b565b610c5b565b610abc565b6109bf565b610983565b61091b565b610813565b6107c6565b61071c565b61051c565b61043a565b346104355760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104355760043560243590600190600260ff835460081c161461040b5761024f6102007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff6001541617600155565b610257614904565b61025f614666565b81610274826000526005602052604060002090565b01805464ffffffffff90818160a01c16946102976102928888612a59565b612a76565b918388159182156103fc575b50506103d257855b8281111561037557505082547fffffffffffffff0000000000ffffffffffffffffffffffffffffffffffffffff16911660a01b78ffffffffff0000000000000000000000000000000000000000161790557fddd9a1ac1ae0095c1389781239f4f4280ebfb649201b0556f78e77fa289e91839261033f90604051938493846040919493926060820195825260208201520152565b0390a16103736101007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff6001541617600155565b005b806103cc6103a184936103928a6000526003602052604060002090565b90600052602052604060002090565b60057fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00825416179055565b016102ab565b60046040517f67909b15000000000000000000000000000000000000000000000000000000008152fd5b60c81c168311905083386102a3565b60046040517f1bbee726000000000000000000000000000000000000000000000000000000008152fd5b600080fd5b346104355760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610435576004357fffffffff00000000000000000000000000000000000000000000000000000000811680910361043557807f7965db0b00000000000000000000000000000000000000000000000000000000602092149081156104cf575b506040519015158152f35b7f01ffc9a700000000000000000000000000000000000000000000000000000000915014386104c4565b6024359073ffffffffffffffffffffffffffffffffffffffff8216820361043557565b346104355760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104355760043573ffffffffffffffffffffffffffffffffffffffff811680910361043557610574614666565b80156105d1576020817fc1b5345cce283376356748dc57f2dfa7120431d016fc7ca9ba641bc65f91411d927fffffffffffffffffffffffff00000000000000000000000000000000000000006006541617600655604051908152a1005b60046040517faa7feadc000000000000000000000000000000000000000000000000000000008152fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60e0810190811067ffffffffffffffff82111761064657604052565b6105fb565b67ffffffffffffffff811161064657604052565b6040810190811067ffffffffffffffff82111761064657604052565b6060810190811067ffffffffffffffff82111761064657604052565b610400810190811067ffffffffffffffff82111761064657604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761064657604052565b604051906107028261067b565b565b67ffffffffffffffff81116106465760051b60200190565b346104355760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104355760243567ffffffffffffffff811161043557366023820112156104355780600401359061077782610704565b9061078560405192836106b4565b82825260209260248484019160051b8301019136831161043557602401905b8282106107b7576103738460043561472c565b813581529084019084016107a4565b346104355760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104355760043560005260006020526020600160406000200154604051908152f35b346104355760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104355760043561084d614666565b80600052600560205260016040600020015464ffffffffff808260c81c169160a01c16106108f1576108ec816108dc60026108b37f3b1b1a7c6b021e524cac489566ae6d22e8dde1b38bcc164bb70490fa21daf97c956000526005602052604060002090565b017fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff8154169055565b6040519081529081906020820190565b0390a1005b60046040517ff9250d0c000000000000000000000000000000000000000000000000000000008152fd5b346104355760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610435576103736004356109586104f9565b90806000526000602052610973600160406000200154614ae6565b614b60565b600091031261043557565b346104355760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610435576020600754604051908152f35b346104355760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610435576109f6614666565b60015460ff811615610a5f5750610a0b614904565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00600154166001557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa6020604051338152a1005b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00600191610a8b6148ce565b16176001557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586020604051338152a1005b346104355760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261043557610af36104f9565b3373ffffffffffffffffffffffffffffffffffffffff821603610b1c5761037390600435614c43565b60046040517f6697b232000000000000000000000000000000000000000000000000000000008152fd5b60061115610b5057565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b906006821015610b505752565b9193959490946104c091610ba38484810198610b7f565b64ffffffffff806020971687860152604095168585015260609788850152608084015260a083016000905b868210610c42575050506104a08201528551938490526104e001948201936000915b848310610c005750505050505090565b8551805173ffffffffffffffffffffffffffffffffffffffff168852808501511515888601528101511515878201529581019594830194600190920191610bf0565b825160ff16815291860191600191909101908601610bce565b34610435576040807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610435576104008151610c9981610697565b369037600090600435825260036020528082206024358352602052808220815191610cc38361062a565b81549260ff84166006811015610d935790610d8f929181526020810193610d1464ffffffffff610cff818960081c16889064ffffffffff169052565b8484019760301c16879064ffffffffff169052565b60018101546060830190815260028201549060808401918252610d7c610d70610d526004610d446003880161302e565b9660a0890197885201613300565b9560c081019687525198610d658a610b46565b5164ffffffffff1690565b985164ffffffffff1690565b9051915192519351945197889788610b8c565b0390f35b6024867f4e487b710000000000000000000000000000000000000000000000000000000081526021600452fd5b9060207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8301126104355760043567ffffffffffffffff9283821161043557806023830112156104355781600401359384116104355760248460051b83010111610435576024019190565b3461043557610e3936610dc0565b610e416146c9565b60005b818110610e7d57507f1f0def5d5179f4d53a0dafd78f3ae044c7cbf799630739fd50674bbec8c356b8916108ec60405192839283612ab0565b610e8881838561294f565b3590610e9e826000526005602052604060002090565b91610eb8610eb4600285015460ff9060401c1690565b1590565b610ff757600180930190610eea610ee0610edb845464ffffffffff9060c81c1690565b6129c3565b64ffffffffff1690565b610f02610ef885888a61294f565b60208101906129f7565b9260005b848110610f7857505050610ee0610292610f729493610f2493612a59565b7fffff0000000000ffffffffffffffffffffffffffffffffffffffffffffffffff7dffffffffff0000000000000000000000000000000000000000000000000083549260c81b169116179055565b01610e44565b610f828185612a59565b610f8d828786612a66565b35908115610fb9579089610fb1819493610392876000526003602052604060002090565b015501610f06565b6040517f795bfe85000000000000000000000000000000000000000000000000000000008152600481018590526024810191909152604490fd5b0390fd5b60046040517fe7d1a70d000000000000000000000000000000000000000000000000000000008152fd5b346104355760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261043557600435600260ff60015460081c161461040b576110946102007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff6001541617600155565b8060005260056020526040600020611105610eb464ffffffffff600184015460a01c169260036020526110dc8460406000209064ffffffffff16600052602052604060002090565b906110f960026110ed845460ff1690565b92015460281c60ff1690565b90600483015492614558565b6103d25761111291613e95565b6103736101007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff6001541617600155565b346104355760a07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104355761117a6104f9565b6044359060ff821682036104355760643564ffffffffff81168103610435576084359061ffff8216820361043557610d8f936108dc9360043561256d565b346104355760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261043557602060ff600154166040519015158152f35b346104355760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261043557600435600052600260205260806040600020600181549101546040519160ff81161515835264ffffffffff90818160081c16602085015260301c1660408301526060820152f35b346104355760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610435576024356044356112ac6148ce565b6004906112c482356000526002602052604060002090565b9081549264ffffffffff808560081c169460301c16916112f283610392876000526003602052604060002090565b906003611300835460ff1690565b61130981610b46565b036115f25760408051602081018981528183018490529194919061135881606081015b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081018352826106b4565b5190209560019687850154036115ca578661138461137f848701938454938491015461255e565b612a4b565b90600386016000805b838110611499576103738d8d8d7ff7ab5a65307ab9788b10eab6a0e173842698dc9772bc3e58eaac1d6e0315b0598e6113f18f8f600282015560047fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00825416179055565b518481526020810183905260046040820152606090a161149261141e846000526005602052604060002090565b60065473ffffffffffffffffffffffffffffffffffffffff169061148c61148461145e8784015473ffffffffffffffffffffffffffffffffffffffff1690565b9261147e6114776002835493015461ffff9060301c1690565b61ffff1690565b90612c09565b612710900490565b916142ad565b0190614061565b6114ad8e6114a683612bf3565b1c60ff1690565b9160ff831690811580156115c1575b61157f578d821b908181166115575717928d929187916114f9906114e08589612c28565b90919060ff8084549260031b9316831b921b1916179055565b14611505575b0161138d565b6115526115128289612c41565b50740100000000000000000000000000000000000000007fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff825416179055565b6114ff565b898d517f8ce0d24b000000000000000000000000000000000000000000000000000000008152fd5b8e89610ff38f8f519384937fa06986c7000000000000000000000000000000000000000000000000000000008552840160209093929193604081019481520152565b508582116114bc565b5083517fb06ec8f9000000000000000000000000000000000000000000000000000000008152fd5b826040517fc38434ab000000000000000000000000000000000000000000000000000000008152fd5b346104355760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261043557602073ffffffffffffffffffffffffffffffffffffffff60065416604051908152f35b346104355761167b36610dc0565b906001600260ff825460081c161461040b576116be6102007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff6001541617600155565b6116c66148ce565b6116ce612c59565b916116d884612c72565b9360005b818110611752577f151b7b4fba4f2f307fc85d2e1759f3691da9606509751f0f40fccf193e418e4d61033f8787602081015180611724575b5050604051918291339083612df8565b61174561174b925173ffffffffffffffffffffffffffffffffffffffff1690565b336142ad565b8380611714565b80856117608693858761294f565b82813591611778836000526005602052604060002090565b928b61178e855461178887614612565b90612a59565b926117a96117a160209283810190612cf0565b969093612d51565b51838152816117b787612d65565b910190815260005b868110611806575050505050856117de6118009594936117fa93612c09565b92015473ffffffffffffffffffffffffffffffffffffffff1690565b906143ef565b016116dc565b839597999a508681939597995061181d9294612db4565b80359061183882610392896000526003602052604060002090565b90611844825460ff1690565b9061184e82610b46565b60048092036118d6578f9493926118b9928861186d9301359101612c41565b5061187981848b6144cb565b75010000000000000000000000000000000000000000007fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff825416179055565b6118c4828551612d51565b520193918b98979593918d97956117bf565b506040517fc38434ab000000000000000000000000000000000000000000000000000000008152fd5b346104355760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104355760043560009081526005602090815260409182902080546001820154600290920154845191825273ffffffffffffffffffffffffffffffffffffffff83169382019390935264ffffffffff60a083811c82168387015260c89390931c811660608301528316608082015260ff602884901c81169282019290925261ffff603084901c1660c08201529190921c909116151560e082015261010090f35b346104355760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261043557602060ff611a3c611a086104f9565b6004356000526000845260406000209073ffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b54166040519015158152f35b611a5136610dc0565b600260ff60015460081c161461040b57611a926102007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff6001541617600155565b611a9a6148ce565b611aa2612c59565b611aaa612c59565b91611ab481612ea7565b93349160005b818110611c8657505050611c5c57602081015180611b3e575b50507f1e473be843779c10566d945a4adf38c5fa2f3585a52fc906f1d9e502cf3798879181602061033f93015180611b16575b5050604051918291339083612f6b565b611745611b37925173ffffffffffffffffffffffffffffffffffffffff1690565b3880611b06565b611b9673ffffffffffffffffffffffffffffffffffffffff9492947f00000000000000000000000000000000000ea4af05656c17b90f4d64add29e1d16945173ffffffffffffffffffffffffffffffffffffffff1690565b90843b15610435576040517fda3e8ce400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9290921660048301523360248301523060448301526064820152926000908490608490829084905af1918215611c57577f1e473be843779c10566d945a4adf38c5fa2f3585a52fc906f1d9e502cf3798879361033f93611c3e575b5091819350611ad3565b80611c4b611c519261064b565b80610978565b38611c34565b612c1c565b60046040517f87b71f66000000000000000000000000000000000000000000000000000000008152fd5b611c91818385612f2b565b611c9e6060820182612cf0565b80915015611f6457611cbb82356000526005602052604060002090565b91611cdd600184015473ffffffffffffffffffffffffffffffffffffffff1690565b916040820135611ded575b91849392611cf88b93968d612d51565b5186358152611d0682612d65565b6020820152600094855b838110611d62575050956040611d3b611d429360019960208501359384910152604084013590612a59565b91356134df565b82611d51575b50505001611aba565b611d5a926143ef565b388781611d48565b909192939596979450611d8281611d7c6060880188612cf0565b90612db4565b6004611da1611d99600286015460ff9060281c1690565b8835846141b2565b611daa81610b46565b14611dd3575b9060019135611dc3826020870151612d51565b5201908c94979695939291611d10565b9690611de460019261178885614612565b97909150611db0565b9673ffffffffffffffffffffffffffffffffffffffff8381169081611e2d575050611e2790611e2160408401358654612c09565b90612aa3565b96611ce8565b8a5192999273ffffffffffffffffffffffffffffffffffffffff169181831603611e78575050611e6260408301358554612c09565b611e7160208b01918251612a59565b9052611ce8565b60208b019182519182611eb1575b50505073ffffffffffffffffffffffffffffffffffffffff84168a52611e7160408401358654612c09565b7f00000000000000000000000000000000000ea4af05656c17b90f4d64add29e1d1691823b15610435576040517fda3e8ce400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9290921660048301523360248301523060448301526064820152906000908290608490829084905af18015611c5757611f51575b8080611e86565b80611c4b611f5e9261064b565b38611f4a565b60046040517fc7017d52000000000000000000000000000000000000000000000000000000008152fd5b346104355760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261043557602060405160008152f35b60607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261043557600435604435600260ff60015460081c161461040b576120396102007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff6001541617600155565b6120416148ce565b612055826000526005602052604060002090565b6120818261207a600184015473ffffffffffffffffffffffffffffffffffffffff1690565b9254612c09565b9073ffffffffffffffffffffffffffffffffffffffff8082166120b45750503403611c5c57611112915b602435906134df565b93919334612173577f00000000000000000000000000000000000ea4af05656c17b90f4d64add29e1d1693843b15610435576040517fda3e8ce400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9290921660048301523360248301523060448301526064820152926000908490608490829084905af1928315611c575761111293612160575b506120ab565b80611c4b61216d9261064b565b3861215a565b60046040517fe2a8f8a0000000000000000000000000000000000000000000000000000000008152fd5b346104355760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610435576103736004356121da6104f9565b908060005260006020526121f5600160406000200154614ae6565b614c43565b346104355760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104355760443573ffffffffffffffffffffffffffffffffffffffff811681036104355761225a6020916024356004356133a6565b6040519015158152f35b346104355761227236610dc0565b6001600260ff825460081c161461040b576122b46102007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff6001541617600155565b6122bc6148ce565b6122c4612c59565b926122ce83612c72565b9260005b818110612319577fd53f2bb6fed83c8a1662fd984e0882cef7bc2c6dd8d4d8d482ca931945efd61961033f8688602081015180611724575050604051918291339083612df8565b80866123278693858761294f565b8781359161233f836000526005602052604060002090565b9260208083019161235c886123548587612cf0565b979050612d51565b51918183528061236b87612d65565b930192835260005b86811061239a57505050505050906117fa856117de61239495948454612c09565b016122d2565b8597999a5084969850611d7c8193956123b4939597612cf0565b8035906123cf82610392876000526003602052604060002090565b906123db825460ff1690565b908b8660049283860194855496816123f38993610b46565b86811061247f575b5050500135938410159050612444575061241b8f94939261242792612c41565b506118798184896144cb565b612432828751612d51565b5201918b98979593918e979593612373565b604080517fa06986c7000000000000000000000000000000000000000000000000000000008152918201888152602081018690528291010390fd5b6124a0945061249a6002610eb49597015460ff9060281c1690565b91614558565b6118d65786906124b0868a613e95565b908d918538806123fb565b346104355760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261043557602061225a60043560009080825260038452604082206024358352845260ff6002604080852094838654169481526005885220015460281c1690600483015492614558565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b8115612568570690565b61252f565b90919493929461257b614666565b60ff8116600281106128f6576020106128cc5761ffff84166109c481116128a2576125d49061271060ff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff85011691850204840361255e565b6128785764ffffffffff8616603c811090811561286c575b50612842577f44ab42484886e3b9dfa09fe03c00b19e3386faaa7313d5de2b4bcd7d1453dd799361283d9160075497846126308a6000526005602052604060002090565b5561268c86600161264b8c6000526005602052604060002090565b019073ffffffffffffffffffffffffffffffffffffffff167fffffffffffffffffffffffff0000000000000000000000000000000000000000825416179055565b6126de8260026126a68c6000526005602052604060002090565b01907fffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffff65ff000000000083549260281b169116179055565b61272a8160026126f88c6000526005602052604060002090565b019064ffffffffff167fffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000825416179055565b61277e8360026127448c6000526005602052604060002090565b01907fffffffffffffffffffffffffffffffffffffffffffffffff0000ffffffffffff67ffff00000000000083549260301b169116179055565b6127cb60026127978b6000526005602052604060002090565b01680100000000000000007fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff825416179055565b6127d489613f21565b6127e86127e360075460010190565b600755565b6040519586958a879464ffffffffff60a09573ffffffffffffffffffffffffffffffffffffffff61ffff9660ff959b9a9660c08b019c8b5260208b015216604089015216606087015216608085015216910152565b0390a1565b60046040517f06201c01000000000000000000000000000000000000000000000000000000008152fd5b610e10915011386125ec565b60046040517f490bbdd0000000000000000000000000000000000000000000000000000000008152fd5b60046040517f36d36c7c000000000000000000000000000000000000000000000000000000008152fd5b60046040517fbaa3711d000000000000000000000000000000000000000000000000000000008152fd5b60046040517fe8a119d4000000000000000000000000000000000000000000000000000000008152fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b919081101561298f5760051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc181360301821215610435570190565b612920565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b90600164ffffffffff809316019182116129d957565b612994565b91909164ffffffffff808094169116019182116129d957565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610435570180359067ffffffffffffffff821161043557602001918160051b3603831361043557565b90600182018092116129d957565b919082018092116129d957565b919081101561298f5760051b0190565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82019182116129d957565b919082039182116129d957565b916020908082850183865252604091828501946005958484881b83010196866000935b868510612ae65750505050505050505090565b9091929394959697987fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc082820301855289357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc18436030181121561043557830180358252878101357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe182360301811215610435570187813591019167ffffffffffffffff82116104355781861b918236038413610435577f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff908c8b840152808d8401521161043557600192828a939284936060938483013701019b01950195019397969594929190612ad3565b908160031b91808304600814901517156129d957565b818102929181159184041417156129d957565b6040513d6000823e3d90fd5b919091602083101561298f57601f908360051c01921690565b805482101561298f5760005260206000200190600090565b60405190612c668261065f565b60006020838281520152565b90612c7c82610704565b6040612c8a815192836106b4565b8382527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0612cb88395610704565b0191600091825b848110612ccd575050505050565b6020908251612cdb8161065f565b85815282606081830152828601015201612cbf565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610435570180359067ffffffffffffffff821161043557602001918160061b3603831361043557565b80511561298f5760200190565b805182101561298f5760209160051b010190565b90612d6f82610704565b612d7c60405191826106b4565b8281527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0612daa8294610704565b0190602036910137565b919081101561298f5760061b0190565b90815180825260208080930193019160005b828110612de4575050505090565b835185529381019392810192600101612dd6565b909291926040808301908084528251809252606084019160608160051b860101916020809501936000915b86848410612e4e57505050505073ffffffffffffffffffffffffffffffffffffffff91509416910152565b80612e97877fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa08c6001969798999a0301875285838b518051845201519181858201520190612dc4565b9701930193019194939290612e23565b90612eb182610704565b604090612ec0825191826106b4565b8381527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0612eee8295610704565b0191600091825b848110612f03575050505050565b6020908351612f118161067b565b858152826060818301528686830152828501015201612ef5565b919081101561298f5760051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8181360301821215610435570190565b9192909260409384840194808552815180965260609586860191878260051b880101926020809501986000925b848410612fc85750505050506107029394955094019073ffffffffffffffffffffffffffffffffffffffff169052565b90919293948680827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa08d600195030187528d5190815181528580613017858501518a878601528a850190612dc4565b9301519101529c0194019401929994939190612f98565b6040805160009390929190835b602080601f880110156132f0576104006020926132e46001936132d98954916132b26131176132628c613212896131c260ff9761307c838a8d1660ff169052565b61308f8184018a8d60081c1660ff169052565b6130a28584018a8d60101c1660ff169052565b888b6102006060956130bd878201858560181c1660ff169052565b6130d26080958585888501921c1660ff169052565b61317860a0976130eb898401878760281c1660ff169052565b61312860c09b6131048d8601898960301c1660ff169052565b60e09e8f8601898960381c1660ff169052565b87876101008701921c1660ff169052565b61313d6101208401878760481c1660ff169052565b6131526101408401878760501c1660ff169052565b6131676101608401878760581c1660ff169052565b85856101808501921c1660ff169052565b61318d6101a08201858560681c1660ff169052565b6131a26101c08201858560701c1660ff169052565b6131b76101e08201858560781c1660ff169052565b01921c1660ff169052565b6131d76102208c01888b60881c1660ff169052565b6131ec6102408c01888b60901c1660ff169052565b6132016102608c01888b60981c1660ff169052565b86896102808d01921c1660ff169052565b6132276102a08a01868960a81c1660ff169052565b61323c6102c08a01868960b01c1660ff169052565b6132516102e08a01868960b81c1660ff169052565b84876103008b01921c1660ff169052565b6132776103208801848760c81c1660ff169052565b61328c6103408801848760d01c1660ff169052565b6132a16103608801848760d81c1660ff169052565b82856103808901921c1660ff169052565b6132c76103a08601828560e81c1660ff169052565b6103c08501908360f01c1660ff169052565b60f81c6103e0830152565b0194019501949261303b565b5050929350505061070282610697565b90815461330c81610704565b9260409361331c855191826106b4565b828152809460208092019260005281600020906000935b85851061334257505050505050565b600184819284516133528161067b565b865473ffffffffffffffffffffffffffffffffffffffff8116825260ff90818160a01c1615158584015260a81c16151586820152815201930194019391613333565b6201000082101561298f570190600090565b73ffffffffffffffffffffffffffffffffffffffff60ff9316600052600460205260406000209060005260205260016133e68260081c6040600020613394565b93905492161b9160031b1c16151590565b8054680100000000000000008110156106465761341991600182018155612c41565b9190916134b05780518254602083015160409093015173ffffffffffffffffffffffffffffffffffffffff9092167fffffffffffffffffffff000000000000000000000000000000000000000000009091161791151560a01b74ff0000000000000000000000000000000000000000169190911790151560a81b75ff00000000000000000000000000000000000000000016179055565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600060045260246000fd5b929190801580156138d2575b6138a857613503846000526005602052604060002090565b936002850194855460409660ff82891c161561387f576135238686612a59565b9161353e610ee060018096015464ffffffffff9060c81c1690565b917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff92838501116138565761358187610392886000526003602052604060002090565b9161358d835460ff1690565b9061359782610b46565b86821161381e5760281c60ff16936135ae82610b46565b81156137cb575b50875b85811061360f575050985194855250505050602081019190915260408101919091523360608201529091507f9a711314e8e01b50116aefb9d50edc1a6b06e39986010af70d18671666586d0e90806080810161283d565b61361a33828a6133a6565b61378c57808914801561376f57845b6004918282018a815401938985116137295750918f916136648c9695938b9560006136526106f5565b338152928160208501528301526133f7565b61366f33868f61444f565b61367d575b505050016135b8565b61368686610b46565b8486036136745764ffffffffff90816136a8825464ffffffffff9060081c1690565b16156136ce575b5050146136bf575b853880613674565b6136c9818a613c62565b6136b7565b6136ec613722926136e48a5464ffffffffff1690565b9042166129de565b7fffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000ff65ffffffffff0083549260081b169116179055565b38806136af565b9350505050610ff389928e519384937fca10b936000000000000000000000000000000000000000000000000000000008552840160209093929193604081019481520152565b613787826103928b6000526003602052604060002090565b613629565b8b517f190f2750000000000000000000000000000000000000000000000000000000008152600481018990526024810191909152336044820152606490fd5b868911156135b55788016138076137f0826103928b6000526003602052604060002090565b866137fc825460ff1690565b600483015492614558565b156135b557613817915087613e95565b84386135b5565b8b517fca10b93600000000000000000000000000000000000000000000000000000000815260048101899052602481018a9052604490fd5b60048a517f5ee0d7b4000000000000000000000000000000000000000000000000000000008152fd5b600488517fe7d1a70d000000000000000000000000000000000000000000000000000000008152fd5b60046040517f558947cf000000000000000000000000000000000000000000000000000000008152fd5b5081156134eb565b90816020910312610435575190565b61393e613913613903836000526003602052604060002090565b6001600052602052604060002090565b60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00825416179055565b64ffffffffff61399d814216613961613903856000526003602052604060002090565b907fffffffffffffffffffffffffffffffffffffffffff0000000000ffffffffffff6affffffffff00000000000083549260301b169116179055565b6040517f5d3b1d300000000000000000000000000000000000000000000000000000000081527f8af398995b04c28e9951adb9721ef74c74f93e6a478f39e7e0777be13527e7ef60048201527f00000000000000000000000000000000000000000000000000000000000002de67ffffffffffffffff166024820152600360448201526207a1206064820152600160848201529160208360a48160007f000000000000000000000000271682deb8c4e0901d1a1550ad2e64d568e6990973ffffffffffffffffffffffffffffffffffffffff165af1928315611c5757600093613c32575b50613aa0613a99846000526002602052604060002090565b5460ff1690565b613c08577f34e010a4ef37e7b53b3d02e76e84b745a250daa244a2768dabaf7c0c1947963e613be784613b8061283d95613b33613b087ff7ab5a65307ab9788b10eab6a0e173842698dc9772bc3e58eaac1d6e0315b059996000526002602052604060002090565b60017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00825416179055565b8516613b49836000526002602052604060002090565b907fffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000ff65ffffffffff0083549260081b169116179055565b613bc8613b97826000526002602052604060002090565b66010000000000007fffffffffffffffffffffffffffffffffffffffffff0000000000ffffffffffff825416179055565b6040805185815260016020820152908101919091529081906060820190565b0390a160408051918252600160208301526002908201529081906060820190565b60046040517ff9012132000000000000000000000000000000000000000000000000000000008152fd5b613c5491935060203d8111613c5b575b613c4c81836106b4565b8101906138da565b9138613a81565b503d613c42565b90613c7e61391382610392856000526003602052604060002090565b64ffffffffff91613ca383421661396184610392856000526003602052604060002090565b6040517f5d3b1d300000000000000000000000000000000000000000000000000000000081527f8af398995b04c28e9951adb9721ef74c74f93e6a478f39e7e0777be13527e7ef60048201527f00000000000000000000000000000000000000000000000000000000000002de67ffffffffffffffff166024820152600360448201526207a12060648201526001608482015260208160a48160007f000000000000000000000000271682deb8c4e0901d1a1550ad2e64d568e6990973ffffffffffffffffffffffffffffffffffffffff165af1908115611c5757600091613e77575b50613d9e613a99826000526002602052604060002090565b613c0857613e5281613e337ff7ab5a65307ab9788b10eab6a0e173842698dc9772bc3e58eaac1d6e0315b05996613e03613b087f34e010a4ef37e7b53b3d02e76e84b745a250daa244a2768dabaf7c0c1947963e966000526002602052604060002090565b613e1d818716613b49856000526002602052604060002090565b8616613961836000526002602052604060002090565b6040519182918686846040919493926060820195825260208201520152565b0390a161283d6040519283928360409060029294936060820195825260208201520152565b613e8f915060203d8111613c5b57613c4c81836106b4565b38613d86565b600161070292826000526003602052604060002081600052602052613ee3604060002060057fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00825416179055565b7ff7ab5a65307ab9788b10eab6a0e173842698dc9772bc3e58eaac1d6e0315b059606060405185815283602082015260056040820152a10190614061565b80600052600360205260406000206001600052602052604060002090600482015491613f57826000526005602052604060002090565b6002810180549094919060281c60ff168203613f7a5750505061070291506138e9565b8293614016600161403493613fd67ff7ab5a65307ab9788b10eab6a0e173842698dc9772bc3e58eaac1d6e0315b059969760017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00825416179055565b01740100000000000000000000000000000000000000007fffffffffffffff0000000000ffffffffffffffffffffffffffffffffffffffff825416179055565b60408051918252600160208301819052908201529081906060820190565b0390a161403f575050565b6136ec614054610702935464ffffffffff1690565b64ffffffffff42166129de565b90816000526003602052604060002081600052602052604060002091600483015492614097826000526005602052604060002090565b9360028501906140b56140af835460ff9060281c1690565b60ff1690565b81036140c8575050506107029250613c62565b91937ff7ab5a65307ab9788b10eab6a0e173842698dc9772bc3e58eaac1d6e0315b059919361411c8660017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00825416179055565b600190960180547fffffffffffffff0000000000ffffffffffffffffffffffffffffffffffffffff1660a083901b78ffffffffff00000000000000000000000000000000000000001617905564ffffffffff956141916040519283928360409060019294936060820195825260208201520152565b0390a161419d57505050565b54610702926136ec9164ffffffffff166136e4565b90929192602082359201356141d1826000526003602052604060002090565b83600052602052604060002060ff815416956004820191825480926141f58a610b46565b8960048110614262575b50505050821015614225579161421c611879926107029594612c41565b509283916144cb565b50506040517fa06986c700000000000000000000000000000000000000000000000000000000815260048101919091526024810191909152604490fd5b61426b93614558565b156142835761427a8585613e95565b388181896141ff565b60046040517fc38434ab000000000000000000000000000000000000000000000000000000008152fd5b919073ffffffffffffffffffffffffffffffffffffffff81166142f8575090610702915a917f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc26149b1565b803b156143c5576040517fa9059cbb000000000000000000000000000000000000000000000000000000006020820190815273ffffffffffffffffffffffffffffffffffffffff9094166024820152604481019290925260009283928390614363816064810161132c565b51925af161436f61493b565b901561439b57805180614380575050565b81602080610eb4936143959501019101614999565b61439b57565b60046040517ff1568f95000000000000000000000000000000000000000000000000000000008152fd5b60046040517f09ee12d5000000000000000000000000000000000000000000000000000000008152fd5b9173ffffffffffffffffffffffffffffffffffffffff80825116921682811460001461442a5750602091500180519182018092116129d95752565b90602081019283518061443e575b50505252565b61444891336142ad565b3880614438565b909173ffffffffffffffffffffffffffffffffffffffff16600052600460205260406000209060005260205261448c8160081c6040600020613394565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600160ff849594549360031b94161b82841c17831b921b1916179055565b90915460ff8160a01c16908115614549575b8115614528575b506144ed575050565b6040517f7f7f26da00000000000000000000000000000000000000000000000000000000815260048101919091526024810191909152604490fd5b73ffffffffffffffffffffffffffffffffffffffff163314159050386144e4565b905060ff8160a81c16906144dd565b929091925464ffffffffff91828260081c16946006851015610b5057600185149586614608575b866145fd575b50856145f0575b5050831561459b575b50505090565b600283149350909183156145da575b50826145bb575b5050388080614595565b90915060301c811662015180018181116129d9571642101538806145b1565b60039193506145e881610b46565b1491386145aa565b60ff16119350388061458c565b421015955038614585565b801515965061457f565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60ff60028354930154926146546127109161ffff8660301c16830390612c09565b049260281c1601908115612568570490565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff161561469f57565b60046040517f30cd7471000000000000000000000000000000000000000000000000000000008152fd5b3360009081527fee57cd81e84075558e8fcc182a1f4393f91fc97f963a136e66b7f949a62f319f602052604090205460ff161561470257565b60046040517f7c214f04000000000000000000000000000000000000000000000000000000008152fd5b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000271682deb8c4e0901d1a1550ad2e64d568e6990916803303614897575080600052600260205260406000205460ff811661478757505050565b64ffffffffff9060081c166147ba610ee06147ac846000526002602052604060002090565b5460301c64ffffffffff1690565b916147d383610392846000526003602052604060002090565b60026147e0825460ff1690565b6147e981610b46565b146147f6575b5050505050565b6148666148547ff7ab5a65307ab9788b10eab6a0e173842698dc9772bc3e58eaac1d6e0315b0599661484f60019460037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00825416179055565b612d44565b51926000526002602052604060002090565b015561488a6040519283928360409060039294936060820195825260208201520152565b0390a138808080806147ef565b604490604051907f1cf993f40000000000000000000000000000000000000000000000000000000082523360048301526024820152fd5b60ff600154166148da57565b60046040517f1309a563000000000000000000000000000000000000000000000000000000008152fd5b60ff600154161561491157565b60046040517f6cd60201000000000000000000000000000000000000000000000000000000008152fd5b3d15614994573d9067ffffffffffffffff8211610646576040519161498860207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601846106b4565b82523d6000602084013e565b606090565b90816020910312610435575180151581036104355790565b6149c682849395600080809781948294f11590565b6149d1575b50505050565b73ffffffffffffffffffffffffffffffffffffffff16803b15614ae257604051937fd0e30db0000000000000000000000000000000000000000000000000000000008552838560048186865af1938415611c5757614a8a95602095614acf575b506040518096819582947fa9059cbb000000000000000000000000000000000000000000000000000000008452600484016020909392919373ffffffffffffffffffffffffffffffffffffffff60408201951681520152565b03925af18015611c5757614aa1575b8080806149cb565b614ac19060203d8111614ac8575b614ab981836106b4565b810190614999565b5038614a99565b503d614aaf565b80611c4b614adc9261064b565b38614a31565b8280fd5b80600052600060205260ff614b1f3360406000209073ffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b541615614b295750565b604490604051907fe2517d3f0000000000000000000000000000000000000000000000000000000082523360048301526024820152fd5b6000908082528160205260ff614b9984604085209073ffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b5416614c3d5780825281602052614bd383604084209073ffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b60017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008254161790557f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d73ffffffffffffffffffffffffffffffffffffffff3394169280a4600190565b50905090565b6000908082528160205260ff614c7c84604085209073ffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b541615614c3d5780825281602052614cb783604084209073ffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0081541690557ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b73ffffffffffffffffffffffffffffffffffffffff3394169280a460019056fea2646970667358221220a125cb17f3508dc82892b7bcfc8e7235a8793e3b5b448661287891a1a590f48364736f6c63430008140033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000b5a9e5a319c7fda551a30be592c77394bf935c6f000000000000000000000000842ca39dfd984d4349ce8d8c95577e2bf42f4db0000000000000000000000000c8c57e4c73c71f72ca0a7e043e5d2d144f98ef13000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc200000000000000000000000000000000000ea4af05656c17b90f4d64add29e1d8af398995b04c28e9951adb9721ef74c74f93e6a478f39e7e0777be13527e7ef000000000000000000000000271682deb8c4e0901d1a1550ad2e64d568e6990900000000000000000000000000000000000000000000000000000000000002de
-----Decoded View---------------
Arg [0] : _owner (address): 0xB5a9e5a319c7fDa551a30BE592c77394bF935c6f
Arg [1] : _operator (address): 0x842cA39Dfd984d4349Ce8D8c95577E2Bf42f4dB0
Arg [2] : _protocolFeeRecipient (address): 0xC8C57e4C73c71f72cA0a7e043E5D2D144F98ef13
Arg [3] : wrappedNativeToken (address): 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2
Arg [4] : _transferManager (address): 0x00000000000ea4af05656C17b90f4d64AdD29e1d
Arg [5] : keyHash (bytes32): 0x8af398995b04c28e9951adb9721ef74c74f93e6a478f39e7e0777be13527e7ef
Arg [6] : vrfCoordinator (address): 0x271682DEB8C4E0901D1a1550aD2e64D568E69909
Arg [7] : subscriptionId (uint64): 734
-----Encoded View---------------
8 Constructor Arguments found :
Arg [0] : 000000000000000000000000b5a9e5a319c7fda551a30be592c77394bf935c6f
Arg [1] : 000000000000000000000000842ca39dfd984d4349ce8d8c95577e2bf42f4db0
Arg [2] : 000000000000000000000000c8c57e4c73c71f72ca0a7e043e5d2d144f98ef13
Arg [3] : 000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2
Arg [4] : 00000000000000000000000000000000000ea4af05656c17b90f4d64add29e1d
Arg [5] : 8af398995b04c28e9951adb9721ef74c74f93e6a478f39e7e0777be13527e7ef
Arg [6] : 000000000000000000000000271682deb8c4e0901d1a1550ad2e64d568e69909
Arg [7] : 00000000000000000000000000000000000000000000000000000000000002de
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.