Source Code
Latest 25 from a total of 10,278 transactions
| Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Prospect Batch | 39327061 | 53 days ago | IN | 10 MON | 0.408 | ||||
| Prospect Batch | 39327044 | 53 days ago | IN | 28 MON | 0.408 | ||||
| Prospect Batch | 39327028 | 53 days ago | IN | 19 MON | 0.408 | ||||
| Prospect Batch | 39326802 | 53 days ago | IN | 21.1 MON | 0.408 | ||||
| Prospect Batch | 39326785 | 53 days ago | IN | 19.1 MON | 0.408 | ||||
| Prospect Batch | 39326769 | 53 days ago | IN | 27.1 MON | 0.408 | ||||
| Prospect Batch | 39326753 | 53 days ago | IN | 17.1 MON | 0.408 | ||||
| Prospect Batch | 39326737 | 53 days ago | IN | 14.1 MON | 0.408 | ||||
| Prospect Batch | 39326720 | 53 days ago | IN | 17.1 MON | 0.408 | ||||
| Set Protocol Vau... | 39280651 | 53 days ago | IN | 0 MON | 0.00522348 | ||||
| Set Protocol Vau... | 39280643 | 53 days ago | IN | 0 MON | 0.00745856 | ||||
| Claim Admin Fees | 39278954 | 53 days ago | IN | 0 MON | 0.00637919 | ||||
| Claim Mon Only | 39272581 | 53 days ago | IN | 0 MON | 0.00833015 | ||||
| Claim Mon Only | 39269782 | 53 days ago | IN | 0 MON | 0.0153 | ||||
| Claim Mon Only | 39269524 | 53 days ago | IN | 0 MON | 0.0153 | ||||
| Claim Mon Only | 39269515 | 53 days ago | IN | 0 MON | 0.0153 | ||||
| Claim Mon Only | 39269506 | 53 days ago | IN | 0 MON | 0.0153 | ||||
| Claim Mon Only | 39269497 | 53 days ago | IN | 0 MON | 0.0153 | ||||
| Claim Mon Only | 39269487 | 53 days ago | IN | 0 MON | 0.0153 | ||||
| Claim Mon Only | 39269479 | 53 days ago | IN | 0 MON | 0.0153 | ||||
| Claim Mon Only | 39269470 | 53 days ago | IN | 0 MON | 0.0153 | ||||
| Claim Mon Only | 39269461 | 53 days ago | IN | 0 MON | 0.0153 | ||||
| Claim Mon Only | 39269453 | 53 days ago | IN | 0 MON | 0.0153 | ||||
| Claim Mon Only | 39269443 | 53 days ago | IN | 0 MON | 0.0153 | ||||
| Claim Mon Only | 39269432 | 53 days ago | IN | 0 MON | 0.0153 |
Latest 25 internal transactions (View All)
Advanced mode:
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 39280643 | 53 days ago | 15,514.55114928 MON | ||||
| 39278954 | 53 days ago | 1,551.45511492 MON | ||||
| 39272581 | 53 days ago | 111.8 MON | ||||
| 39269782 | 53 days ago | 1,438.64404152 MON | ||||
| 39269524 | 53 days ago | 1,045.58428473 MON | ||||
| 39269515 | 53 days ago | 1,602.5252725 MON | ||||
| 39269506 | 53 days ago | 716.767185 MON | ||||
| 39269497 | 53 days ago | 866.4718832 MON | ||||
| 39269487 | 53 days ago | 896.38763055 MON | ||||
| 39269479 | 53 days ago | 662.17098668 MON | ||||
| 39269470 | 53 days ago | 1,620.61544673 MON | ||||
| 39269461 | 53 days ago | 1,969.10018535 MON | ||||
| 39269453 | 53 days ago | 1,501.16505493 MON | ||||
| 39269443 | 53 days ago | 789.22216003 MON | ||||
| 39269432 | 53 days ago | 1,801.28839732 MON | ||||
| 39269423 | 53 days ago | 1,697.2683383 MON | ||||
| 39269414 | 53 days ago | 756.71742133 MON | ||||
| 39269405 | 53 days ago | 1,930.75453765 MON | ||||
| 39269395 | 53 days ago | 637.50626613 MON | ||||
| 39269386 | 53 days ago | 740.51867924 MON | ||||
| 39269377 | 53 days ago | 1,765.13988287 MON | ||||
| 39269368 | 53 days ago | 1,698.12748152 MON | ||||
| 39269359 | 53 days ago | 714.54001301 MON | ||||
| 39269350 | 53 days ago | 811.04786113 MON | ||||
| 39269341 | 53 days ago | 1,825.90262457 MON |
Loading...
Loading
Contract Name:
CrystalSupply
Compiler Version
v0.8.28+commit.7893614a
Optimization Enabled:
Yes with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@pythnetwork/entropy-sdk-solidity/IEntropyV2.sol";
import "@pythnetwork/entropy-sdk-solidity/IEntropyConsumer.sol";
contract CrystalSupply is Ownable, ReentrancyGuard, IEntropyConsumer {
IERC20 public immutable crystalToken;
// Pyth Entropy V2
IEntropyV2 public immutable entropy;
// Halving mechanism constants
uint256 public constant INITIAL_REWARD = 32 ether;
uint256 public constant HALVING_INTERVAL = 3_000_000 ether;
uint256 public constant INITIAL_CIRCULATING = 105_000 ether;
uint256 public constant MAX_HALVINGS = 6;
uint256 public constant GRID_SIZE = 25;
uint256 public constant MIN_STAKE = 0.1 ether;
uint256 public constant REVENUE_FEE_BP = 1100;
uint256 public constant VAULT_FEE_BP = 1000;
uint256 public constant ADMIN_FEE_BP = 100;
uint256 public constant REFINING_FEE_BP = 1000;
uint256 public KEEPER_FEE = 0.1 ether;
uint256 public maxAutoCheckpointRounds = 100;
address public protocolVault;
address public adminWallet;
uint256 public pendingAdminFees;
uint256 public pendingVaultFees;
uint256 public currentRoundId;
uint256 public accumulatedTokenPot;
uint256 public lastRoundStartTime;
bool public isRolling;
struct Round {
uint256 monTotalOfLosingBlocks;
uint256 monTotalOnWinningBlock;
uint256 totalRoundStake;
uint8 winningBlock;
bool finalized;
bool motherlodeHit;
bool isWinnerTakeAll;
uint256 winningTicket;
uint256 monPerShare;
uint256 tokenPerShare;
uint256 winnerTakeAllTokenAmount;
uint256 finalizedAt;
uint256[25] blockTotals;
uint256[25] minerCounts;
}
mapping(uint256 => Round) public rounds;
mapping(uint256 => mapping(address => mapping(uint8 => uint256))) public userBlockDeposits;
mapping(uint256 => mapping(address => mapping(uint8 => uint256))) public userCumulativeStart;
mapping(uint256 => mapping(address => uint256)) public userKeeperFee;
event Prospect(address indexed user, uint256 roundId, uint8 blockIdx, uint256 amount);
event RoundEnded(uint256 roundId, uint8 winBlock, bool winnerTakeAll, bool motherlode);
event CheckpointedByKeeper(address indexed keeper, address indexed user, uint256 roundId, uint256 tokens, uint256 mon, uint256 keeperFee);
event Claimed(address indexed user, uint256 monAmt, uint256 tokenAmt);
event RoundStarted(uint256 indexed roundId, uint256 timestamp);
event KeeperFeeUpdated(uint256 oldFee, uint256 newFee);
event MaxAutoCheckpointRoundsUpdated(uint256 oldLimit, uint256 newLimit);
event ProtocolVaultUpdated(address indexed oldVault, address indexed newVault);
event AdminWalletUpdated(address indexed oldWallet, address indexed newWallet);
event AdminFeesClaimed(address indexed admin, uint256 amount);
event VaultFeesClaimed(address indexed vault, uint256 amount);
event RandomnessRequested(uint256 indexed roundId, uint64 sequenceNumber);
// Pyth Entropy tracking
uint64 public currentSequenceNumber;
mapping(uint64 => uint256) public sequenceToRound;
uint256 public constant MIN_ROUND_DURATION = 60;
uint256 public roundDuration = 60;
uint256 public intermissionDuration = 12; // Configurable intermission for winner reveal
uint256 public minimumParticipants = 1;
mapping(uint256 => uint256) public roundParticipantCount;
mapping(uint256 => mapping(address => bool)) public hasParticipated;
mapping(uint256 => mapping(uint8 => mapping(address => bool))) public userHasProspectedBlock;
mapping(uint256 => address[]) public roundParticipants; // Track all participants per round
uint256 public totalUnclaimedTokens;
uint256 public minerRewardsFactor;
uint256 public totalRefinedTokens;
uint256 public totalSupplyDistributed; // Tracks TAL distributed for halving calculations
mapping(address => uint256) public userUnclaimedBalance;
mapping(address => uint256) public userRewardsFactor;
mapping(address => uint256) public userRefinedCrystal;
mapping(uint256 => mapping(address => bool)) public userCreditedRound;
mapping(address => uint256) public lastCheckpointedRound;
mapping(address => uint256) public userPendingMon;
struct CheckpointRequest {
address user;
uint256 roundId;
}
CheckpointRequest[] public checkpointQueue;
mapping(address => mapping(uint256 => bool)) public inCheckpointQueue;
constructor(
address _entropy,
address _token,
address _protocolVault,
address _adminWallet
) Ownable(msg.sender) {
entropy = IEntropyV2(_entropy);
crystalToken = IERC20(_token);
protocolVault = _protocolVault;
adminWallet = _adminWallet;
lastRoundStartTime = block.timestamp;
}
function getEntropy() internal view override returns (address) {
return address(entropy);
}
function entropyCallback(
uint64 sequenceNumber,
address,
bytes32 randomNumber
) internal override {
uint256 roundId = sequenceToRound[sequenceNumber];
require(isRolling && roundId == currentRoundId, "Invalid sequence");
uint256 randomValue = uint256(randomNumber);
uint256 rwBlock = randomValue;
uint256 rwMode = uint256(keccak256(abi.encodePacked(randomValue, uint256(1))));
uint256 rwTicket = uint256(keccak256(abi.encodePacked(randomValue, uint256(2))));
_finalizeRound(rwBlock, rwMode, rwTicket);
currentSequenceNumber = 0;
}
function setRoundConfig(uint256 _duration, uint256 _minParticipants, uint256 _intermission) external onlyOwner {
require(_duration >= MIN_ROUND_DURATION, "Too short");
roundDuration = _duration;
minimumParticipants = _minParticipants;
intermissionDuration = _intermission;
}
function blockTotalStake(uint256 rId, uint8 blockIdx) external view returns (uint256) {
return rounds[rId].blockTotals[blockIdx];
}
function getUserBalances(address user) external view returns (
uint256 unclaimed,
uint256 refined,
uint256 total
) {
unclaimed = userUnclaimedBalance[user];
refined = userRefinedCrystal[user];
if (minerRewardsFactor > userRewardsFactor[user]) {
uint256 delta = minerRewardsFactor - userRewardsFactor[user];
uint256 accruedRefined = (delta * unclaimed) / 1e18;
refined += accruedRefined;
}
if (unclaimed > 0 || refined > 0) {
uint256 fee = (unclaimed * REFINING_FEE_BP) / 10000;
uint256 netUnclaimed = unclaimed - fee;
total = netUnclaimed + refined;
} else {
total = 0;
}
return (unclaimed, refined, total);
}
function getEntropyFee() public view returns (uint128) {
return entropy.getFeeV2();
}
/**
* @notice Calculate current reward per round based on halving schedule
* @return Current reward amount
*/
function getCurrentReward() public view returns (uint256) {
uint256 totalCirculating = INITIAL_CIRCULATING + totalSupplyDistributed;
uint256 halvings = totalCirculating / HALVING_INTERVAL;
// Cap at MAX_HALVINGS to prevent underflow
if (halvings > MAX_HALVINGS) {
halvings = MAX_HALVINGS;
}
// Use bitshift for efficient division by 2^halvings
return INITIAL_REWARD >> halvings;
}
/**
* @notice Calculate motherlode increment (20% of current reward)
* @return Motherlode increment amount
*/
function getMotherlodeInc() public view returns (uint256) {
return getCurrentReward() / 5; // 20% of current reward
}
function prospect(uint8 blockIdx) external payable nonReentrant {
require(block.timestamp >= lastRoundStartTime, "Round not started yet (intermission)");
uint256 rId = isRolling ? currentRoundId + 1 : currentRoundId;
bool isFirstProspect = (userKeeperFee[rId][msg.sender] == 0);
if (isFirstProspect) {
require(msg.value >= MIN_STAKE + KEEPER_FEE, "Send stake + keeper fee");
} else {
require(msg.value >= MIN_STAKE, "Min stake");
}
_prospect(msg.sender, blockIdx, msg.value, rId);
}
function prospectBatch(uint32 blockMask) external payable nonReentrant {
require(block.timestamp >= lastRoundStartTime, "Round not started yet (intermission)");
require(msg.value >= MIN_STAKE + KEEPER_FEE, "Send total stake + keeper fee");
require(blockMask > 0, "No blocks selected");
uint256 rId = isRolling ? currentRoundId + 1 : currentRoundId;
uint256 selectedCount = 0;
uint32 tempMask = blockMask;
for (uint8 i = 0; i < GRID_SIZE; i++) {
if (tempMask & 1 == 1) {
selectedCount++;
}
tempMask >>= 1;
}
require(selectedCount > 0, "No blocks selected");
uint256 totalStake = msg.value - KEEPER_FEE;
uint256 stakePerBlock = totalStake / selectedCount;
uint256 remainder = totalStake % selectedCount;
require(stakePerBlock >= MIN_STAKE, "Min per block");
tempMask = blockMask;
bool isFirst = true;
for (uint8 i = 0; i < GRID_SIZE; i++) {
if (tempMask & 1 == 1) {
if (isFirst) {
_prospect(msg.sender, i, stakePerBlock + KEEPER_FEE + remainder, rId);
isFirst = false;
} else {
_prospect(msg.sender, i, stakePerBlock, rId);
}
}
tempMask >>= 1;
}
}
function _prospect(address user, uint8 blockIdx, uint256 amount, uint256 rId) internal {
require(blockIdx < GRID_SIZE, "Invalid Block");
uint256 stakeAmount = amount;
bool isFirstProspect = (userKeeperFee[rId][user] == 0);
if (isFirstProspect) {
stakeAmount = amount - KEEPER_FEE;
userKeeperFee[rId][user] = KEEPER_FEE;
}
_prospectInternal(user, blockIdx, stakeAmount, rId);
}
function _prospectInternal(address user, uint8 blockIdx, uint256 netAmount, uint256 rId) internal {
uint256 currentTotal = rounds[rId].blockTotals[blockIdx];
if (userBlockDeposits[rId][user][blockIdx] == 0) {
userCumulativeStart[rId][user][blockIdx] = currentTotal;
}
userBlockDeposits[rId][user][blockIdx] += netAmount;
rounds[rId].blockTotals[blockIdx] += netAmount;
rounds[rId].totalRoundStake += netAmount;
if (!userHasProspectedBlock[rId][blockIdx][user]) {
userHasProspectedBlock[rId][blockIdx][user] = true;
rounds[rId].minerCounts[blockIdx]++;
}
if (!hasParticipated[rId][user]) {
hasParticipated[rId][user] = true;
roundParticipantCount[rId]++;
roundParticipants[rId].push(user); // Track participant address
if (!inCheckpointQueue[user][rId]) {
inCheckpointQueue[user][rId] = true;
checkpointQueue.push(CheckpointRequest({user: user, roundId: rId}));
}
}
emit Prospect(user, rId, blockIdx, netAmount);
}
function _updateUserRewards(address user) internal {
if (minerRewardsFactor > userRewardsFactor[user]) {
uint256 delta = minerRewardsFactor - userRewardsFactor[user];
uint256 unclaimed = userUnclaimedBalance[user];
uint256 refined = (delta * unclaimed) / 1e18;
userRefinedCrystal[user] += refined;
}
userRewardsFactor[user] = minerRewardsFactor;
}
function _creditUserReward(address user, uint256 amount) internal {
_updateUserRewards(user);
userUnclaimedBalance[user] += amount;
totalUnclaimedTokens += amount;
}
function triggerRound() external payable {
require(block.timestamp >= lastRoundStartTime + roundDuration, "Too early");
require(!isRolling, "Already rolling");
require(roundParticipantCount[currentRoundId] >= minimumParticipants, "Not enough participants");
// Get fee for Pyth Entropy V2 - keeper must pay this
uint128 fee = entropy.getFeeV2();
require(msg.value >= fee, "Insufficient entropy fee");
isRolling = true;
// Request randomness from Pyth Entropy V2 (no provider/userRandom needed)
uint64 sequenceNumber = entropy.requestV2{value: fee}();
currentSequenceNumber = sequenceNumber;
sequenceToRound[sequenceNumber] = currentRoundId;
// Refund excess MON to caller
if (msg.value > fee) {
(bool success, ) = msg.sender.call{value: msg.value - fee}("");
require(success, "Refund failed");
}
emit RandomnessRequested(currentRoundId, sequenceNumber);
}
function _finalizeRound(uint256 rwBlock, uint256 rwMode, uint256 rwTicket) internal {
Round storage r = rounds[currentRoundId];
r.winningBlock = uint8(rwBlock % GRID_SIZE);
r.motherlodeHit = ((rwBlock >> 32) % 625 == 0);
uint256 winningBlockTotal = r.blockTotals[r.winningBlock];
r.monTotalOnWinningBlock = winningBlockTotal;
uint256 roundTotal = r.totalRoundStake;
uint256 losingMon = roundTotal - winningBlockTotal;
r.monTotalOfLosingBlocks = losingMon;
if (winningBlockTotal == 0) {
uint256 adminFee = (roundTotal * ADMIN_FEE_BP) / 10000;
pendingAdminFees += adminFee;
pendingVaultFees += roundTotal - adminFee;
r.monPerShare = 0;
r.tokenPerShare = 0;
} else {
uint256 adminFee = (losingMon * ADMIN_FEE_BP) / 10000;
uint256 vaultFee = (losingMon * VAULT_FEE_BP) / 10000;
uint256 totalFees = adminFee + vaultFee;
pendingAdminFees += adminFee;
pendingVaultFees += vaultFee;
uint256 losingMonAfterFees = losingMon - totalFees;
r.monPerShare = (losingMonAfterFees * 1e18) / winningBlockTotal;
// Use dynamic reward based on halving schedule
uint256 baseReward = getCurrentReward();
uint256 motherlodeInc = getMotherlodeInc();
// Accumulate motherlode pot if not hit
if (!r.motherlodeHit) {
accumulatedTokenPot += motherlodeInc;
}
// Calculate payout
uint256 payoutToken;
if (r.motherlodeHit) {
payoutToken = accumulatedTokenPot + baseReward;
accumulatedTokenPot = 0;
} else {
payoutToken = baseReward;
}
// Track total distributed for halving calculations
totalSupplyDistributed += payoutToken;
if (rwMode % 2 == 0) {
r.isWinnerTakeAll = true;
r.winnerTakeAllTokenAmount = payoutToken;
r.winningTicket = rwTicket % winningBlockTotal;
} else {
r.isWinnerTakeAll = false;
r.tokenPerShare = (payoutToken * 1e18) / winningBlockTotal;
}
}
r.finalized = true;
r.finalizedAt = block.timestamp;
emit RoundEnded(currentRoundId, r.winningBlock, r.isWinnerTakeAll, r.motherlodeHit);
currentRoundId++;
lastRoundStartTime = block.timestamp + intermissionDuration;
isRolling = false;
emit RoundStarted(currentRoundId, lastRoundStartTime);
}
function checkpointUserAuto(address user) external nonReentrant {
uint256 startRound = lastCheckpointedRound[user] + 1;
uint256 endRound = currentRoundId;
if (endRound - startRound > maxAutoCheckpointRounds) {
endRound = startRound + maxAutoCheckpointRounds;
}
uint256 totalKeeperFee = 0;
for (uint256 rId = startRound; rId < endRound; rId++) {
Round storage r = rounds[rId];
if (!r.finalized || userCreditedRound[rId][user]) {
continue;
}
uint256 userStake = userBlockDeposits[rId][user][r.winningBlock];
if (userStake > 0) {
uint256 roundTokens = 0;
if (r.isWinnerTakeAll) {
uint256 userStart = userCumulativeStart[rId][user][r.winningBlock];
if (r.winningTicket >= userStart && r.winningTicket < userStart + userStake) {
roundTokens = r.winnerTakeAllTokenAmount;
}
} else {
roundTokens = (userStake * r.tokenPerShare) / 1e18;
}
if (roundTokens > 0) {
_creditUserReward(user, roundTokens);
}
// Calculate and track MON inline to save stack space
uint256 roundMon = userStake + (userStake * r.monPerShare) / 1e18;
userPendingMon[user] += roundMon;
userCreditedRound[rId][user] = true;
uint256 keeperFee = userKeeperFee[rId][user];
if (keeperFee > 0) {
userKeeperFee[rId][user] = 0;
totalKeeperFee += keeperFee;
emit CheckpointedByKeeper(msg.sender, user, rId, roundTokens, roundMon, keeperFee);
} else {
emit CheckpointedByKeeper(msg.sender, user, rId, roundTokens, roundMon, 0);
}
}
}
if (endRound > 0) {
lastCheckpointedRound[user] = endRound - 1;
}
if (totalKeeperFee > 0) {
payable(msg.sender).transfer(totalKeeperFee);
}
}
function checkpointUser(address user, uint256[] calldata rIds) external nonReentrant {
uint256 totalKeeperFee = 0;
for (uint i = 0; i < rIds.length; i++) {
uint256 rId = rIds[i];
require(rId < currentRoundId, "Active round");
Round storage r = rounds[rId];
require(r.finalized, "Round not finalized");
if (userCreditedRound[rId][user]) {
continue;
}
uint256 userStake = userBlockDeposits[rId][user][r.winningBlock];
if (userStake > 0) {
uint256 roundTokens = 0;
if (r.isWinnerTakeAll) {
uint256 userStart = userCumulativeStart[rId][user][r.winningBlock];
if (r.winningTicket >= userStart && r.winningTicket < userStart + userStake) {
roundTokens = r.winnerTakeAllTokenAmount;
}
} else {
roundTokens = (userStake * r.tokenPerShare) / 1e18;
}
if (roundTokens > 0) {
_creditUserReward(user, roundTokens);
}
// Calculate and track MON inline to save stack space
uint256 roundMon = userStake + (userStake * r.monPerShare) / 1e18;
userPendingMon[user] += roundMon;
userCreditedRound[rId][user] = true;
uint256 keeperFee = userKeeperFee[rId][user];
if (keeperFee > 0) {
userKeeperFee[rId][user] = 0;
totalKeeperFee += keeperFee;
emit CheckpointedByKeeper(msg.sender, user, rId, roundTokens, roundMon, keeperFee);
} else {
emit CheckpointedByKeeper(msg.sender, user, rId, roundTokens, roundMon, 0);
}
}
}
if (totalKeeperFee > 0) {
payable(msg.sender).transfer(totalKeeperFee);
}
}
function checkpointFromQueue(uint256[] calldata queueIndices) external nonReentrant {
uint256 totalKeeperFee = 0;
uint256 queueLen = checkpointQueue.length;
for (uint i = 0; i < queueIndices.length; i++) {
uint256 idx = queueIndices[i];
require(idx < queueLen, "Invalid index");
if (i > 0) {
require(queueIndices[i] < queueIndices[i - 1], "Indices must be sorted descending");
}
CheckpointRequest memory req = checkpointQueue[idx];
address user = req.user;
uint256 rId = req.roundId;
if (rId >= currentRoundId) continue;
Round storage r = rounds[rId];
if (!r.finalized) continue;
if (userCreditedRound[rId][user]) {
_removeFromQueue(idx);
queueLen--;
continue;
}
uint256 userStake = userBlockDeposits[rId][user][r.winningBlock];
if (userStake > 0) {
uint256 roundTokens = 0;
if (r.isWinnerTakeAll) {
uint256 userStart = userCumulativeStart[rId][user][r.winningBlock];
if (r.winningTicket >= userStart && r.winningTicket < userStart + userStake) {
roundTokens = r.winnerTakeAllTokenAmount;
}
} else {
roundTokens = (userStake * r.tokenPerShare) / 1e18;
}
if (roundTokens > 0) {
_creditUserReward(user, roundTokens);
}
uint256 roundMon = userStake + (userStake * r.monPerShare) / 1e18;
userPendingMon[user] += roundMon;
userCreditedRound[rId][user] = true;
uint256 keeperFee = userKeeperFee[rId][user];
if (keeperFee > 0) {
userKeeperFee[rId][user] = 0;
totalKeeperFee += keeperFee;
emit CheckpointedByKeeper(msg.sender, user, rId, roundTokens, roundMon, keeperFee);
} else {
emit CheckpointedByKeeper(msg.sender, user, rId, roundTokens, roundMon, 0);
}
}
_removeFromQueue(idx);
queueLen--;
}
if (totalKeeperFee > 0) {
payable(msg.sender).transfer(totalKeeperFee);
}
}
function _removeFromQueue(uint256 idx) internal {
uint256 lastIdx = checkpointQueue.length - 1;
CheckpointRequest memory removed = checkpointQueue[idx];
inCheckpointQueue[removed.user][removed.roundId] = false;
if (idx != lastIdx) {
checkpointQueue[idx] = checkpointQueue[lastIdx];
}
checkpointQueue.pop();
}
function claimMonOnly() external nonReentrant {
uint256 pendingMon = userPendingMon[msg.sender];
require(pendingMon > 0, "Nothing to claim");
userPendingMon[msg.sender] = 0;
(bool s, ) = payable(msg.sender).call{value: pendingMon}("");
require(s, "Transfer MON failed");
emit Claimed(msg.sender, pendingMon, 0);
}
function claim() external nonReentrant {
uint256 pendingMon = userPendingMon[msg.sender];
_updateUserRewards(msg.sender);
uint256 totalTokens = userUnclaimedBalance[msg.sender];
uint256 refined = userRefinedCrystal[msg.sender];
require(pendingMon > 0 || totalTokens > 0 || refined > 0, "Nothing to claim");
uint256 tokensToTransfer = 0;
if (totalTokens > 0 || refined > 0) {
uint256 fee = (totalTokens * REFINING_FEE_BP) / 10000;
uint256 netTokens = totalTokens - fee;
if (fee > 0 && totalUnclaimedTokens > totalTokens) {
uint256 remainingUnclaimed = totalUnclaimedTokens - totalTokens;
minerRewardsFactor += (fee * 1e18) / remainingUnclaimed;
totalRefinedTokens += fee;
}
userUnclaimedBalance[msg.sender] = 0;
userRefinedCrystal[msg.sender] = 0;
totalUnclaimedTokens -= totalTokens;
tokensToTransfer = netTokens + refined;
}
if (pendingMon > 0) {
userPendingMon[msg.sender] = 0;
(bool s, ) = payable(msg.sender).call{value: pendingMon}("");
require(s, "Transfer MON failed");
}
if (tokensToTransfer > 0) {
require(crystalToken.transfer(msg.sender, tokensToTransfer), "Transfer TOK failed");
}
emit Claimed(msg.sender, pendingMon, tokensToTransfer);
}
function setKeeperFee(uint256 _newFee) external onlyOwner {
uint256 oldFee = KEEPER_FEE;
KEEPER_FEE = _newFee;
emit KeeperFeeUpdated(oldFee, _newFee);
}
function setMaxAutoCheckpointRounds(uint256 _newLimit) external onlyOwner {
require(_newLimit > 0, "Limit must be > 0");
uint256 oldLimit = maxAutoCheckpointRounds;
maxAutoCheckpointRounds = _newLimit;
emit MaxAutoCheckpointRoundsUpdated(oldLimit, _newLimit);
}
function setProtocolVault(address _newVault) external onlyOwner {
require(_newVault != address(0), "Invalid address");
address oldVault = protocolVault;
if (pendingVaultFees > 0) {
uint256 amount = pendingVaultFees;
pendingVaultFees = 0;
(bool success, ) = oldVault.call{value: amount}("");
require(success, "Fee transfer failed");
emit VaultFeesClaimed(oldVault, amount);
}
protocolVault = _newVault;
emit ProtocolVaultUpdated(oldVault, _newVault);
}
function setAdminWallet(address _newWallet) external onlyOwner {
require(_newWallet != address(0), "Invalid address");
address oldWallet = adminWallet;
if (pendingAdminFees > 0) {
uint256 amount = pendingAdminFees;
pendingAdminFees = 0;
(bool success, ) = oldWallet.call{value: amount}("");
require(success, "Fee transfer failed");
emit AdminFeesClaimed(oldWallet, amount);
}
adminWallet = _newWallet;
emit AdminWalletUpdated(oldWallet, _newWallet);
}
function claimAdminFees() external nonReentrant {
require(msg.sender == adminWallet, "Not admin");
uint256 amount = pendingAdminFees;
require(amount > 0, "No fees to claim");
pendingAdminFees = 0;
(bool success, ) = msg.sender.call{value: amount}("");
require(success, "Transfer failed");
emit AdminFeesClaimed(msg.sender, amount);
}
function claimVaultFees() external nonReentrant {
require(msg.sender == protocolVault, "Not vault");
uint256 amount = pendingVaultFees;
require(amount > 0, "No fees to claim");
pendingVaultFees = 0;
(bool success, ) = msg.sender.call{value: amount}("");
require(success, "Transfer failed");
emit VaultFeesClaimed(msg.sender, amount);
}
function emergencyUnstick() external onlyOwner {
isRolling = false;
currentSequenceNumber = 0;
}
function getCurrentRoundGrid() external view returns (uint256[25] memory) {
return rounds[currentRoundId].blockTotals;
}
function getCurrentRoundMinerCounts() external view returns (uint256[25] memory) {
return rounds[currentRoundId].minerCounts;
}
function getUserBlockDepositsForRound(uint256 roundId, address user) external view returns (uint256[25] memory) {
uint256[25] memory deposits;
for (uint8 i = 0; i < GRID_SIZE; i++) {
deposits[i] = userBlockDeposits[roundId][user][i];
}
return deposits;
}
function getCheckpointQueueLength() external view returns (uint256) {
return checkpointQueue.length;
}
function getCheckpointQueue(uint256 offset, uint256 limit) external view returns (
CheckpointRequest[] memory requests,
uint256 total
) {
total = checkpointQueue.length;
if (offset >= total) {
return (new CheckpointRequest[](0), total);
}
uint256 end = offset + limit;
if (end > total) {
end = total;
}
uint256 count = end - offset;
requests = new CheckpointRequest[](count);
for (uint256 i = 0; i < count; i++) {
requests[i] = checkpointQueue[offset + i];
}
return (requests, total);
}
function getRoundParticipants(uint256 roundId, uint256 offset, uint256 limit) external view returns (
address[] memory participants,
uint256 total
) {
total = roundParticipants[roundId].length;
if (offset >= total) {
return (new address[](0), total);
}
uint256 end = offset + limit;
if (end > total) {
end = total;
}
uint256 count = end - offset;
participants = new address[](count);
for (uint256 i = 0; i < count; i++) {
participants[i] = roundParticipants[roundId][offset + i];
}
return (participants, total);
}
struct WinnerInfo {
address user;
uint256 stake;
uint256 monWon;
uint256 tokenWon;
}
struct RoundWinnersResult {
WinnerInfo[] winners;
uint256 totalWinners;
uint8 winningBlock;
bool motherlodeHit;
bool isWinnerTakeAll;
uint256 finalizedAt;
}
function _countWinners(uint256 roundId, uint8 winBlock) internal view returns (uint256 count) {
uint256 len = roundParticipants[roundId].length;
for (uint256 i = 0; i < len; i++) {
if (userBlockDeposits[roundId][roundParticipants[roundId][i]][winBlock] > 0) {
count++;
}
}
}
function _calculateWinnerReward(
uint256 roundId,
address user,
uint8 winBlock,
uint256 stake
) internal view returns (uint256 monWon, uint256 tokenWon) {
Round storage r = rounds[roundId];
monWon = stake + (stake * r.monPerShare) / 1e18;
if (r.isWinnerTakeAll) {
uint256 userStart = userCumulativeStart[roundId][user][winBlock];
if (r.winningTicket >= userStart && r.winningTicket < userStart + stake) {
tokenWon = r.winnerTakeAllTokenAmount;
}
} else {
tokenWon = (stake * r.tokenPerShare) / 1e18;
}
}
function getRoundWinners(uint256 roundId, uint256 offset, uint256 limit) external view returns (RoundWinnersResult memory result) {
Round storage r = rounds[roundId];
require(r.finalized, "Round not finalized");
result.winningBlock = r.winningBlock;
result.motherlodeHit = r.motherlodeHit;
result.isWinnerTakeAll = r.isWinnerTakeAll;
result.finalizedAt = r.finalizedAt;
result.totalWinners = _countWinners(roundId, r.winningBlock);
if (offset >= result.totalWinners) {
result.winners = new WinnerInfo[](0);
return result;
}
uint256 end = offset + limit;
if (end > result.totalWinners) {
end = result.totalWinners;
}
uint256 count = end - offset;
result.winners = new WinnerInfo[](count);
uint256 found = 0;
uint256 collected = 0;
uint256 len = roundParticipants[roundId].length;
for (uint256 i = 0; i < len && collected < count; i++) {
address user = roundParticipants[roundId][i];
uint256 stake = userBlockDeposits[roundId][user][r.winningBlock];
if (stake > 0) {
if (found >= offset) {
(uint256 monWon, uint256 tokenWon) = _calculateWinnerReward(roundId, user, r.winningBlock, stake);
result.winners[collected] = WinnerInfo(user, stake, monWon, tokenWon);
collected++;
}
found++;
}
}
}
struct RoundInfo {
uint256 totalStake;
uint8 winningBlock;
bool finalized;
bool motherlodeHit;
bool isWinnerTakeAll;
uint256 monPerShare;
uint256 tokenPerShare;
uint256 winnerTakeAllTokenAmount;
uint256 finalizedAt;
uint256 participantCount;
}
function getRoundData(uint256 roundId) external view returns (RoundInfo memory info) {
Round storage r = rounds[roundId];
info.totalStake = r.totalRoundStake;
info.winningBlock = r.winningBlock;
info.finalized = r.finalized;
info.motherlodeHit = r.motherlodeHit;
info.isWinnerTakeAll = r.isWinnerTakeAll;
info.monPerShare = r.monPerShare;
info.tokenPerShare = r.tokenPerShare;
info.winnerTakeAllTokenAmount = r.winnerTakeAllTokenAmount;
info.finalizedAt = r.finalizedAt;
info.participantCount = roundParticipants[roundId].length;
}
receive() external payable {}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)
pragma solidity ^0.8.20;
import {Context} from "../utils/Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* The initial owner is set to the address provided by the deployer. This can
* later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
/**
* @dev The caller account is not authorized to perform an operation.
*/
error OwnableUnauthorizedAccount(address account);
/**
* @dev The owner is not a valid owner account. (eg. `address(0)`)
*/
error OwnableInvalidOwner(address owner);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the address provided by the deployer as the initial owner.
*/
constructor(address initialOwner) {
if (initialOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(initialOwner);
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
if (owner() != _msgSender()) {
revert OwnableUnauthorizedAccount(_msgSender());
}
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
if (newOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/IERC20.sol)
pragma solidity >=0.4.16;
/**
* @dev Interface of the ERC-20 standard as defined in the ERC.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the value of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the value of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 value) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the
* allowance mechanism. `value` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 value) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (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;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/ReentrancyGuard.sol)
pragma solidity ^0.8.20;
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If EIP-1153 (transient storage) is available on the chain you're deploying at,
* consider using {ReentrancyGuardTransient} instead.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*/
abstract contract ReentrancyGuard {
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant NOT_ENTERED = 1;
uint256 private constant ENTERED = 2;
uint256 private _status;
/**
* @dev Unauthorized reentrant call.
*/
error ReentrancyGuardReentrantCall();
constructor() {
_status = NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and making it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
_nonReentrantBefore();
_;
_nonReentrantAfter();
}
function _nonReentrantBefore() private {
// On the first call to nonReentrant, _status will be NOT_ENTERED
if (_status == ENTERED) {
revert ReentrancyGuardReentrantCall();
}
// Any calls to nonReentrant after this point will fail
_status = ENTERED;
}
function _nonReentrantAfter() private {
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = NOT_ENTERED;
}
/**
* @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
* `nonReentrant` function in the call stack.
*/
function _reentrancyGuardEntered() internal view returns (bool) {
return _status == ENTERED;
}
}// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;
import "./EntropyStructs.sol";
// Deprecated -- these events are still emitted, but the lack of indexing
// makes them hard to use.
interface EntropyEvents {
event Registered(EntropyStructs.ProviderInfo provider);
event Requested(EntropyStructs.Request request);
event RequestedWithCallback(
address indexed provider,
address indexed requestor,
uint64 indexed sequenceNumber,
bytes32 userRandomNumber,
EntropyStructs.Request request
);
event Revealed(
EntropyStructs.Request request,
bytes32 userRevelation,
bytes32 providerRevelation,
bytes32 blockHash,
bytes32 randomNumber
);
event RevealedWithCallback(
EntropyStructs.Request request,
bytes32 userRandomNumber,
bytes32 providerRevelation,
bytes32 randomNumber
);
event CallbackFailed(
address indexed provider,
address indexed requestor,
uint64 indexed sequenceNumber,
bytes32 userRandomNumber,
bytes32 providerRevelation,
bytes32 randomNumber,
bytes errorCode
);
event ProviderFeeUpdated(address provider, uint128 oldFee, uint128 newFee);
event ProviderDefaultGasLimitUpdated(
address indexed provider,
uint32 oldDefaultGasLimit,
uint32 newDefaultGasLimit
);
event ProviderUriUpdated(address provider, bytes oldUri, bytes newUri);
event ProviderFeeManagerUpdated(
address provider,
address oldFeeManager,
address newFeeManager
);
event ProviderMaxNumHashesAdvanced(
address provider,
uint32 oldMaxNumHashes,
uint32 newMaxNumHashes
);
event Withdrawal(
address provider,
address recipient,
uint128 withdrawnAmount
);
}// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;
import "./EntropyStructs.sol";
/**
* @title EntropyEventsV2
* @notice Interface defining events for the Entropy V2 system, which handles random number generation
* and provider management on Ethereum.
* @dev This interface is used to emit events that track the lifecycle of random number requests,
* provider registrations, and system configurations.
*/
interface EntropyEventsV2 {
/**
* @notice Emitted when a new provider registers with the Entropy system
* @param provider The address of the registered provider
* @param extraArgs A field for extra data for forward compatibility.
*/
event Registered(address indexed provider, bytes extraArgs);
/**
* @notice Emitted when a user requests a random number from a provider
* @param provider The address of the provider handling the request
* @param caller The address of the user requesting the random number
* @param sequenceNumber A unique identifier for this request
* @param userContribution The user's contribution to the random number
* @param gasLimit The gas limit for the callback.
* @param extraArgs A field for extra data for forward compatibility.
*/
event Requested(
address indexed provider,
address indexed caller,
uint64 indexed sequenceNumber,
bytes32 userContribution,
uint32 gasLimit,
bytes extraArgs
);
/**
* @notice Emitted when a provider reveals the generated random number
* @param provider The address of the provider that generated the random number
* @param caller The address of the user who requested the random number (and who receives a callback)
* @param sequenceNumber The unique identifier of the request
* @param randomNumber The generated random number
* @param userContribution The user's contribution to the random number
* @param providerContribution The provider's contribution to the random number
* @param callbackFailed Whether the callback to the caller failed
* @param callbackReturnValue Return value from the callback. If the callback failed, this field contains
* the error code and any additional returned data. Note that "" often indicates an out-of-gas error.
* If the callback returns more than 256 bytes, only the first 256 bytes of the callback return value are included.
* @param callbackGasUsed How much gas the callback used.
* @param extraArgs A field for extra data for forward compatibility.
*/
event Revealed(
address indexed provider,
address indexed caller,
uint64 indexed sequenceNumber,
bytes32 randomNumber,
bytes32 userContribution,
bytes32 providerContribution,
bool callbackFailed,
bytes callbackReturnValue,
uint32 callbackGasUsed,
bytes extraArgs
);
/**
* @notice Emitted when a provider updates their fee
* @param provider The address of the provider updating their fee
* @param oldFee The previous fee amount
* @param newFee The new fee amount
* @param extraArgs A field for extra data for forward compatibility.
*/
event ProviderFeeUpdated(
address indexed provider,
uint128 oldFee,
uint128 newFee,
bytes extraArgs
);
/**
* @notice Emitted when a provider updates their default gas limit
* @param provider The address of the provider updating their gas limit
* @param oldDefaultGasLimit The previous default gas limit
* @param newDefaultGasLimit The new default gas limit
* @param extraArgs A field for extra data for forward compatibility.
*/
event ProviderDefaultGasLimitUpdated(
address indexed provider,
uint32 oldDefaultGasLimit,
uint32 newDefaultGasLimit,
bytes extraArgs
);
/**
* @notice Emitted when a provider updates their URI
* @param provider The address of the provider updating their URI
* @param oldUri The previous URI
* @param newUri The new URI
* @param extraArgs A field for extra data for forward compatibility.
*/
event ProviderUriUpdated(
address indexed provider,
bytes oldUri,
bytes newUri,
bytes extraArgs
);
/**
* @notice Emitted when a provider updates their fee manager address
* @param provider The address of the provider updating their fee manager
* @param oldFeeManager The previous fee manager address
* @param newFeeManager The new fee manager address
* @param extraArgs A field for extra data for forward compatibility.
*/
event ProviderFeeManagerUpdated(
address indexed provider,
address oldFeeManager,
address newFeeManager,
bytes extraArgs
);
/**
* @notice Emitted when a provider updates their maximum number of hashes that can be advanced
* @param provider The address of the provider updating their max hashes
* @param oldMaxNumHashes The previous maximum number of hashes
* @param newMaxNumHashes The new maximum number of hashes
* @param extraArgs A field for extra data for forward compatibility.
*/
event ProviderMaxNumHashesAdvanced(
address indexed provider,
uint32 oldMaxNumHashes,
uint32 newMaxNumHashes,
bytes extraArgs
);
/**
* @notice Emitted when a provider withdraws their accumulated fees
* @param provider The address of the provider withdrawing fees
* @param recipient The address receiving the withdrawn fees
* @param withdrawnAmount The amount of fees withdrawn
* @param extraArgs A field for extra data for forward compatibility.
*/
event Withdrawal(
address indexed provider,
address indexed recipient,
uint128 withdrawnAmount,
bytes extraArgs
);
}// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.0;
// This contract holds old versions of the Entropy structs that are no longer used for contract storage.
// However, they are still used in EntropyEvents to maintain the public interface of prior versions of
// the Entropy contract.
//
// See EntropyStructsV2 for the struct definitions currently in use.
contract EntropyStructs {
struct ProviderInfo {
uint128 feeInWei;
uint128 accruedFeesInWei;
// The commitment that the provider posted to the blockchain, and the sequence number
// where they committed to this. This value is not advanced after the provider commits,
// and instead is stored to help providers track where they are in the hash chain.
bytes32 originalCommitment;
uint64 originalCommitmentSequenceNumber;
// Metadata for the current commitment. Providers may optionally use this field to help
// manage rotations (i.e., to pick the sequence number from the correct hash chain).
bytes commitmentMetadata;
// Optional URI where clients can retrieve revelations for the provider.
// Client SDKs can use this field to automatically determine how to retrieve random values for each provider.
// TODO: specify the API that must be implemented at this URI
bytes uri;
// The first sequence number that is *not* included in the current commitment (i.e., an exclusive end index).
// The contract maintains the invariant that sequenceNumber <= endSequenceNumber.
// If sequenceNumber == endSequenceNumber, the provider must rotate their commitment to add additional random values.
uint64 endSequenceNumber;
// The sequence number that will be assigned to the next inbound user request.
uint64 sequenceNumber;
// The current commitment represents an index/value in the provider's hash chain.
// These values are used to verify requests for future sequence numbers. Note that
// currentCommitmentSequenceNumber < sequenceNumber.
//
// The currentCommitment advances forward through the provider's hash chain as values
// are revealed on-chain.
bytes32 currentCommitment;
uint64 currentCommitmentSequenceNumber;
// An address that is authorized to set / withdraw fees on behalf of this provider.
address feeManager;
// Maximum number of hashes to record in a request. This should be set according to the maximum gas limit
// the provider supports for callbacks.
uint32 maxNumHashes;
}
struct Request {
// Storage slot 1 //
address provider;
uint64 sequenceNumber;
// The number of hashes required to verify the provider revelation.
uint32 numHashes;
// Storage slot 2 //
// The commitment is keccak256(userCommitment, providerCommitment). Storing the hash instead of both saves 20k gas by
// eliminating 1 store.
bytes32 commitment;
// Storage slot 3 //
// The number of the block where this request was created.
// Note that we're using a uint64 such that we have an additional space for an address and other fields in
// this storage slot. Although block.number returns a uint256, 64 bits should be plenty to index all of the
// blocks ever generated.
uint64 blockNumber;
// The address that requested this random number.
address requester;
// If true, incorporate the blockhash of blockNumber into the generated random value.
bool useBlockhash;
// True if this is a request that expects a callback.
bool isRequestWithCallback;
}
}// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.0;
contract EntropyStructsV2 {
struct ProviderInfo {
uint128 feeInWei;
uint128 accruedFeesInWei;
// The commitment that the provider posted to the blockchain, and the sequence number
// where they committed to this. This value is not advanced after the provider commits,
// and instead is stored to help providers track where they are in the hash chain.
bytes32 originalCommitment;
uint64 originalCommitmentSequenceNumber;
// Metadata for the current commitment. Providers may optionally use this field to help
// manage rotations (i.e., to pick the sequence number from the correct hash chain).
bytes commitmentMetadata;
// Optional URI where clients can retrieve revelations for the provider.
// Client SDKs can use this field to automatically determine how to retrieve random values for each provider.
// TODO: specify the API that must be implemented at this URI
bytes uri;
// The first sequence number that is *not* included in the current commitment (i.e., an exclusive end index).
// The contract maintains the invariant that sequenceNumber <= endSequenceNumber.
// If sequenceNumber == endSequenceNumber, the provider must rotate their commitment to add additional random values.
uint64 endSequenceNumber;
// The sequence number that will be assigned to the next inbound user request.
uint64 sequenceNumber;
// The current commitment represents an index/value in the provider's hash chain.
// These values are used to verify requests for future sequence numbers. Note that
// currentCommitmentSequenceNumber < sequenceNumber.
//
// The currentCommitment advances forward through the provider's hash chain as values
// are revealed on-chain.
bytes32 currentCommitment;
uint64 currentCommitmentSequenceNumber;
// An address that is authorized to set / withdraw fees on behalf of this provider.
address feeManager;
// Maximum number of hashes to record in a request. This should be set according to the maximum gas limit
// the provider supports for callbacks.
uint32 maxNumHashes;
// Default gas limit to use for callbacks.
uint32 defaultGasLimit;
}
struct Request {
// Storage slot 1 //
address provider;
uint64 sequenceNumber;
// The number of hashes required to verify the provider revelation.
uint32 numHashes;
// Storage slot 2 //
// The commitment is keccak256(userCommitment, providerCommitment). Storing the hash instead of both saves 20k gas by
// eliminating 1 store.
bytes32 commitment;
// Storage slot 3 //
// The number of the block where this request was created.
// Note that we're using a uint64 such that we have an additional space for an address and other fields in
// this storage slot. Although block.number returns a uint256, 64 bits should be plenty to index all of the
// blocks ever generated.
uint64 blockNumber;
// The address that requested this random number.
address requester;
// If true, incorporate the blockhash of blockNumber into the generated random value.
bool useBlockhash;
// Status flag for requests with callbacks. See EntropyConstants for the possible values of this flag.
uint8 callbackStatus;
// The gasLimit in units of 10k gas. (i.e., 2 = 20k gas). We're using units of 10k in order to fit this
// field into the remaining 2 bytes of this storage slot. The dynamic range here is 10k - 655M, which should
// cover all real-world use cases.
uint16 gasLimit10k;
}
}// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.0;
abstract contract IEntropyConsumer {
// This method is called by Entropy to provide the random number to the consumer.
// It asserts that the msg.sender is the Entropy contract. It is not meant to be
// override by the consumer.
function _entropyCallback(
uint64 sequence,
address provider,
bytes32 randomNumber
) external {
address entropy = getEntropy();
require(entropy != address(0), "Entropy address not set");
require(msg.sender == entropy, "Only Entropy can call this function");
entropyCallback(sequence, provider, randomNumber);
}
// getEntropy returns Entropy contract address. The method is being used to check that the
// callback is indeed from Entropy contract. The consumer is expected to implement this method.
// Entropy address can be found here - https://docs.pyth.network/entropy/contract-addresses
function getEntropy() internal view virtual returns (address);
// This method is expected to be implemented by the consumer to handle the random number.
// It will be called by _entropyCallback after _entropyCallback ensures that the call is
// indeed from Entropy contract.
function entropyCallback(
uint64 sequence,
address provider,
bytes32 randomNumber
) internal virtual;
}// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.0;
import "./EntropyEvents.sol";
import "./EntropyEventsV2.sol";
import "./EntropyStructsV2.sol";
interface IEntropyV2 is EntropyEventsV2 {
/// @notice Request a random number using the default provider with default gas limit
/// @return assignedSequenceNumber A unique identifier for this request
/// @dev The address calling this function should be a contract that inherits from the IEntropyConsumer interface.
/// The `entropyCallback` method on that interface will receive a callback with the returned sequence number and
/// the generated random number.
///
/// `entropyCallback` will be run with the provider's configured default gas limit.
///
/// This method will revert unless the caller provides a sufficient fee (at least `getFeeV2()`) as msg.value.
/// Note that the fee can change over time. Callers of this method should explicitly compute `getFeeV2()`
/// prior to each invocation (as opposed to hardcoding a value). Further note that excess value is *not* refunded to the caller.
///
/// Note that this method uses an in-contract PRNG to generate the user's contribution to the random number.
/// This approach modifies the security guarantees such that a dishonest validator and provider can
/// collude to manipulate the result (as opposed to a malicious user and provider). That is, the user
/// now trusts the validator honestly draw a random number. If you wish to avoid this trust assumption,
/// call a variant of `requestV2` that accepts a `userRandomNumber` parameter.
function requestV2()
external
payable
returns (uint64 assignedSequenceNumber);
/// @notice Request a random number using the default provider with specified gas limit
/// @param gasLimit The gas limit for the callback function.
/// @return assignedSequenceNumber A unique identifier for this request
/// @dev The address calling this function should be a contract that inherits from the IEntropyConsumer interface.
/// The `entropyCallback` method on that interface will receive a callback with the returned sequence number and
/// the generated random number.
///
/// `entropyCallback` will be run with the `gasLimit` provided to this function.
/// The `gasLimit` will be rounded up to a multiple of 10k (e.g., 19000 -> 20000), and furthermore is lower bounded
/// by the provider's configured default limit.
///
/// This method will revert unless the caller provides a sufficient fee (at least `getFeeV2(gasLimit)`) as msg.value.
/// Note that the fee can change over time. Callers of this method should explicitly compute `getFeeV2(gasLimit)`
/// prior to each invocation (as opposed to hardcoding a value). Further note that excess value is *not* refunded to the caller.
///
/// Note that this method uses an in-contract PRNG to generate the user's contribution to the random number.
/// This approach modifies the security guarantees such that a dishonest validator and provider can
/// collude to manipulate the result (as opposed to a malicious user and provider). That is, the user
/// now trusts the validator honestly draw a random number. If you wish to avoid this trust assumption,
/// call a variant of `requestV2` that accepts a `userRandomNumber` parameter.
function requestV2(
uint32 gasLimit
) external payable returns (uint64 assignedSequenceNumber);
/// @notice Request a random number from a specific provider with specified gas limit
/// @param provider The address of the provider to request from
/// @param gasLimit The gas limit for the callback function
/// @return assignedSequenceNumber A unique identifier for this request
/// @dev The address calling this function should be a contract that inherits from the IEntropyConsumer interface.
/// The `entropyCallback` method on that interface will receive a callback with the returned sequence number and
/// the generated random number.
///
/// `entropyCallback` will be run with the `gasLimit` provided to this function.
/// The `gasLimit` will be rounded up to a multiple of 10k (e.g., 19000 -> 20000), and furthermore is lower bounded
/// by the provider's configured default limit.
///
/// This method will revert unless the caller provides a sufficient fee (at least `getFeeV2(provider, gasLimit)`) as msg.value.
/// Note that provider fees can change over time. Callers of this method should explicitly compute `getFeeV2(provider, gasLimit)`
/// prior to each invocation (as opposed to hardcoding a value). Further note that excess value is *not* refunded to the caller.
///
/// Note that this method uses an in-contract PRNG to generate the user's contribution to the random number.
/// This approach modifies the security guarantees such that a dishonest validator and provider can
/// collude to manipulate the result (as opposed to a malicious user and provider). That is, the user
/// now trusts the validator honestly draw a random number. If you wish to avoid this trust assumption,
/// call a variant of `requestV2` that accepts a `userRandomNumber` parameter.
function requestV2(
address provider,
uint32 gasLimit
) external payable returns (uint64 assignedSequenceNumber);
/// @notice Request a random number from a specific provider with a user-provided random number and gas limit
/// @param provider The address of the provider to request from
/// @param userRandomNumber A random number provided by the user for additional entropy
/// @param gasLimit The gas limit for the callback function. Pass 0 to get a sane default value -- see note below.
/// @return assignedSequenceNumber A unique identifier for this request
/// @dev The address calling this function should be a contract that inherits from the IEntropyConsumer interface.
/// The `entropyCallback` method on that interface will receive a callback with the returned sequence number and
/// the generated random number.
///
/// `entropyCallback` will be run with the `gasLimit` provided to this function.
/// The `gasLimit` will be rounded up to a multiple of 10k (e.g., 19000 -> 20000), and furthermore is lower bounded
/// by the provider's configured default limit.
///
/// This method will revert unless the caller provides a sufficient fee (at least `getFeeV2(provider, gasLimit)`) as msg.value.
/// Note that provider fees can change over time. Callers of this method should explicitly compute `getFeeV2(provider, gasLimit)`
/// prior to each invocation (as opposed to hardcoding a value). Further note that excess value is *not* refunded to the caller.
function requestV2(
address provider,
bytes32 userRandomNumber,
uint32 gasLimit
) external payable returns (uint64 assignedSequenceNumber);
/// @notice Get information about a specific entropy provider
/// @param provider The address of the provider to query
/// @return info The provider information including configuration, fees, and operational status
/// @dev This method returns detailed information about a provider's configuration and capabilities.
/// The returned ProviderInfo struct contains information such as the provider's fee structure and gas limits.
function getProviderInfoV2(
address provider
) external view returns (EntropyStructsV2.ProviderInfo memory info);
/// @notice Get the address of the default entropy provider
/// @return provider The address of the default provider
/// @dev This method returns the address of the provider that will be used when no specific provider is specified
/// in the requestV2 calls. The default provider can be used to get the base fee and gas limit information.
function getDefaultProvider() external view returns (address provider);
/// @notice Get information about a specific request
/// @param provider The address of the provider that handled the request
/// @param sequenceNumber The unique identifier of the request
/// @return req The request information including status, random number, and other metadata
/// @dev This method allows querying the state of a previously made request. The returned Request struct
/// contains information about whether the request was fulfilled, the generated random number (if available),
/// and other metadata about the request.
function getRequestV2(
address provider,
uint64 sequenceNumber
) external view returns (EntropyStructsV2.Request memory req);
/// @notice Get the fee charged by the default provider for the default gas limit
/// @return feeAmount The fee amount in wei
/// @dev This method returns the base fee required to make a request using the default provider with
/// the default gas limit. This fee should be passed as msg.value when calling requestV2().
/// The fee can change over time, so this method should be called before each request.
function getFeeV2() external view returns (uint128 feeAmount);
/// @notice Get the fee charged by the default provider for a specific gas limit
/// @param gasLimit The gas limit for the callback function
/// @return feeAmount The fee amount in wei
/// @dev This method returns the fee required to make a request using the default provider with
/// the specified gas limit. This fee should be passed as msg.value when calling requestV2(gasLimit).
/// The fee can change over time, so this method should be called before each request.
function getFeeV2(
uint32 gasLimit
) external view returns (uint128 feeAmount);
/// @notice Get the fee charged by a specific provider for a request with a given gas limit
/// @param provider The address of the provider to query
/// @param gasLimit The gas limit for the callback function
/// @return feeAmount The fee amount in wei
/// @dev This method returns the fee required to make a request using the specified provider with
/// the given gas limit. This fee should be passed as msg.value when calling requestV2(provider, gasLimit)
/// or requestV2(provider, userRandomNumber, gasLimit). The fee can change over time, so this method
/// should be called before each request.
function getFeeV2(
address provider,
uint32 gasLimit
) external view returns (uint128 feeAmount);
}{
"optimizer": {
"enabled": true,
"runs": 200
},
"viaIR": false,
"evmVersion": "paris",
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_entropy","type":"address"},{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_protocolVault","type":"address"},{"internalType":"address","name":"_adminWallet","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"admin","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"AdminFeesClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldWallet","type":"address"},{"indexed":true,"internalType":"address","name":"newWallet","type":"address"}],"name":"AdminWalletUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"keeper","type":"address"},{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"roundId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tokens","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"mon","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"keeperFee","type":"uint256"}],"name":"CheckpointedByKeeper","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"monAmt","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tokenAmt","type":"uint256"}],"name":"Claimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newFee","type":"uint256"}],"name":"KeeperFeeUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldLimit","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newLimit","type":"uint256"}],"name":"MaxAutoCheckpointRoundsUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"roundId","type":"uint256"},{"indexed":false,"internalType":"uint8","name":"blockIdx","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Prospect","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldVault","type":"address"},{"indexed":true,"internalType":"address","name":"newVault","type":"address"}],"name":"ProtocolVaultUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"roundId","type":"uint256"},{"indexed":false,"internalType":"uint64","name":"sequenceNumber","type":"uint64"}],"name":"RandomnessRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"roundId","type":"uint256"},{"indexed":false,"internalType":"uint8","name":"winBlock","type":"uint8"},{"indexed":false,"internalType":"bool","name":"winnerTakeAll","type":"bool"},{"indexed":false,"internalType":"bool","name":"motherlode","type":"bool"}],"name":"RoundEnded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"roundId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"RoundStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"vault","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"VaultFeesClaimed","type":"event"},{"inputs":[],"name":"ADMIN_FEE_BP","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GRID_SIZE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"HALVING_INTERVAL","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"INITIAL_CIRCULATING","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"INITIAL_REWARD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"KEEPER_FEE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_HALVINGS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_ROUND_DURATION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_STAKE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REFINING_FEE_BP","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REVENUE_FEE_BP","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"VAULT_FEE_BP","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"sequence","type":"uint64"},{"internalType":"address","name":"provider","type":"address"},{"internalType":"bytes32","name":"randomNumber","type":"bytes32"}],"name":"_entropyCallback","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"accumulatedTokenPot","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"adminWallet","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"rId","type":"uint256"},{"internalType":"uint8","name":"blockIdx","type":"uint8"}],"name":"blockTotalStake","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"queueIndices","type":"uint256[]"}],"name":"checkpointFromQueue","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"checkpointQueue","outputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"roundId","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256[]","name":"rIds","type":"uint256[]"}],"name":"checkpointUser","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"checkpointUserAuto","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimAdminFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimMonOnly","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimVaultFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"crystalToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentRoundId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentSequenceNumber","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"emergencyUnstick","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"entropy","outputs":[{"internalType":"contract IEntropyV2","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"offset","type":"uint256"},{"internalType":"uint256","name":"limit","type":"uint256"}],"name":"getCheckpointQueue","outputs":[{"components":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"roundId","type":"uint256"}],"internalType":"struct CrystalSupply.CheckpointRequest[]","name":"requests","type":"tuple[]"},{"internalType":"uint256","name":"total","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCheckpointQueueLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentRoundGrid","outputs":[{"internalType":"uint256[25]","name":"","type":"uint256[25]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentRoundMinerCounts","outputs":[{"internalType":"uint256[25]","name":"","type":"uint256[25]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getEntropyFee","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMotherlodeInc","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"roundId","type":"uint256"}],"name":"getRoundData","outputs":[{"components":[{"internalType":"uint256","name":"totalStake","type":"uint256"},{"internalType":"uint8","name":"winningBlock","type":"uint8"},{"internalType":"bool","name":"finalized","type":"bool"},{"internalType":"bool","name":"motherlodeHit","type":"bool"},{"internalType":"bool","name":"isWinnerTakeAll","type":"bool"},{"internalType":"uint256","name":"monPerShare","type":"uint256"},{"internalType":"uint256","name":"tokenPerShare","type":"uint256"},{"internalType":"uint256","name":"winnerTakeAllTokenAmount","type":"uint256"},{"internalType":"uint256","name":"finalizedAt","type":"uint256"},{"internalType":"uint256","name":"participantCount","type":"uint256"}],"internalType":"struct CrystalSupply.RoundInfo","name":"info","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"roundId","type":"uint256"},{"internalType":"uint256","name":"offset","type":"uint256"},{"internalType":"uint256","name":"limit","type":"uint256"}],"name":"getRoundParticipants","outputs":[{"internalType":"address[]","name":"participants","type":"address[]"},{"internalType":"uint256","name":"total","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"roundId","type":"uint256"},{"internalType":"uint256","name":"offset","type":"uint256"},{"internalType":"uint256","name":"limit","type":"uint256"}],"name":"getRoundWinners","outputs":[{"components":[{"components":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"stake","type":"uint256"},{"internalType":"uint256","name":"monWon","type":"uint256"},{"internalType":"uint256","name":"tokenWon","type":"uint256"}],"internalType":"struct CrystalSupply.WinnerInfo[]","name":"winners","type":"tuple[]"},{"internalType":"uint256","name":"totalWinners","type":"uint256"},{"internalType":"uint8","name":"winningBlock","type":"uint8"},{"internalType":"bool","name":"motherlodeHit","type":"bool"},{"internalType":"bool","name":"isWinnerTakeAll","type":"bool"},{"internalType":"uint256","name":"finalizedAt","type":"uint256"}],"internalType":"struct CrystalSupply.RoundWinnersResult","name":"result","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getUserBalances","outputs":[{"internalType":"uint256","name":"unclaimed","type":"uint256"},{"internalType":"uint256","name":"refined","type":"uint256"},{"internalType":"uint256","name":"total","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"roundId","type":"uint256"},{"internalType":"address","name":"user","type":"address"}],"name":"getUserBlockDepositsForRound","outputs":[{"internalType":"uint256[25]","name":"","type":"uint256[25]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"name":"hasParticipated","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"inCheckpointQueue","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"intermissionDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isRolling","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"lastCheckpointedRound","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastRoundStartTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxAutoCheckpointRounds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minerRewardsFactor","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minimumParticipants","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingAdminFees","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingVaultFees","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"blockIdx","type":"uint8"}],"name":"prospect","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint32","name":"blockMask","type":"uint32"}],"name":"prospectBatch","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"protocolVault","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"roundDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"roundParticipantCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"roundParticipants","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"rounds","outputs":[{"internalType":"uint256","name":"monTotalOfLosingBlocks","type":"uint256"},{"internalType":"uint256","name":"monTotalOnWinningBlock","type":"uint256"},{"internalType":"uint256","name":"totalRoundStake","type":"uint256"},{"internalType":"uint8","name":"winningBlock","type":"uint8"},{"internalType":"bool","name":"finalized","type":"bool"},{"internalType":"bool","name":"motherlodeHit","type":"bool"},{"internalType":"bool","name":"isWinnerTakeAll","type":"bool"},{"internalType":"uint256","name":"winningTicket","type":"uint256"},{"internalType":"uint256","name":"monPerShare","type":"uint256"},{"internalType":"uint256","name":"tokenPerShare","type":"uint256"},{"internalType":"uint256","name":"winnerTakeAllTokenAmount","type":"uint256"},{"internalType":"uint256","name":"finalizedAt","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"","type":"uint64"}],"name":"sequenceToRound","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_newWallet","type":"address"}],"name":"setAdminWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newFee","type":"uint256"}],"name":"setKeeperFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newLimit","type":"uint256"}],"name":"setMaxAutoCheckpointRounds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newVault","type":"address"}],"name":"setProtocolVault","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_duration","type":"uint256"},{"internalType":"uint256","name":"_minParticipants","type":"uint256"},{"internalType":"uint256","name":"_intermission","type":"uint256"}],"name":"setRoundConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"totalRefinedTokens","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupplyDistributed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalUnclaimedTokens","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"triggerRound","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint8","name":"","type":"uint8"}],"name":"userBlockDeposits","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"name":"userCreditedRound","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint8","name":"","type":"uint8"}],"name":"userCumulativeStart","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint8","name":"","type":"uint8"},{"internalType":"address","name":"","type":"address"}],"name":"userHasProspectedBlock","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"name":"userKeeperFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userPendingMon","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userRefinedCrystal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userRewardsFactor","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userUnclaimedBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
60c060405267016345785d8a00006002556064600355603c601255600c601355600160145534801561003057600080fd5b5060405161515e38038061515e83398101604081905261004f9161012f565b338061007557604051631e4fbdf760e01b81526000600482015260240160405180910390fd5b61007e816100c3565b50600180556001600160a01b0393841660a052918316608052600480549184166001600160a01b03199283161790556005805492909316911617905542600a55610183565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b038116811461012a57600080fd5b919050565b6000806000806080858703121561014557600080fd5b61014e85610113565b935061015c60208601610113565b925061016a60408601610113565b915061017860608601610113565b905092959194509250565b60805160a051614f936101cb600039600081816106bc0152818161115a01528181611cf20152818161294c0152612a51015260008181610e2e0152611bf10152614f936000f3fe6080604052600436106104825760003560e01c80638aec854211610255578063c9fbcfb011610144578063f0f2f6ee116100c1578063fbb098ee11610085578063fbb098ee14610f35578063fc44e4c714610f4b578063fc89aeaa14610f84578063fcfd837f14610fa4578063fd5c0cc614610fb9578063fe31a61314610fd957600080fd5b8063f0f2f6ee14610e8e578063f2fde38b14610ea1578063f7cb789a14610ec1578063fa0648cb14610ed7578063faddbdb214610ef757600080fd5b8063da1f57c811610108578063da1f57c814610df0578063dbab925314610e06578063dbf4025b14610e1c578063de26eadf14610e50578063ebca8add14610e7057600080fd5b8063c9fbcfb014610d64578063cb1c2b5c14610d79578063cb56532014610d95578063cb6b532e14610daf578063d20e43411461075657600080fd5b8063a6edbfa8116101d2578063af85bdbc11610196578063af85bdbc14610c9a578063b116944414610cb0578063b370488014610ce8578063c566482c14610d22578063c9f73df614610d4f57600080fd5b8063a6edbfa814610bcf578063aafbc82114610bef578063ab5669ad14610c2a578063abd3f61214610c3f578063ae1eac9114610c7a57600080fd5b806398dfca7f1161021957806398dfca7f14610b195780639cbe5efd14610b39578063a1b44ff814610b4f578063a34398a214610b6f578063a345bf4314610bba57600080fd5b80638aec8542146109be5780638c65c81f146109d35780638da5cb5b14610ab55780638f32b2fe14610ad357806390cc399c14610b1157600080fd5b806352a5f1f81161037157806368aa6ffc116102ee57806376c154a5116102b257806376c154a5146109265780637838c03114610953578063783fe32f146109685780637fc4eda81461097b5780638396c2b01461099057600080fd5b806368aa6ffc146108735780636920c820146108a05780636a842462146108ce578063715018a6146108e457806371e51e9e146108f957600080fd5b80636157714c116103355780636157714c146107cb57806361613897146107ed57806363a4390b1461081a57806364febe9614610847578063687ddf3b1461085d57600080fd5b806352a5f1f8146107365780635342c8bc1461075657806353fd66fd1461076c5780635a9249e61461078c5780635fd9491d146107ac57600080fd5b806336bcf7d6116103ff57806343a70146116103c357806343a701461461069457806347ce07cc146106aa57806349208981146106de5780634c5970601461070b5780634e71d92d1461072157600080fd5b806336bcf7d6146105ff57806336f1e6c01461061c57806339c5dec7146106315780633be83035146106515780633d1b760b1461067e57600080fd5b80632007641911610446578063200764191461054e5780632d971e6314610565578063317a98771461059257806335082933146105a757806336b19cd7146105c757600080fd5b8063053b37e61461048e5780630720da52146104b75780630bab460b146104e457806312a2f1f4146104f9578063170ad53c1461053857600080fd5b3661048957005b600080fd5b34801561049a57600080fd5b506104a460035481565b6040519081526020015b60405180910390f35b3480156104c357600080fd5b506104d76104d2366004614816565b610fef565b6040516104ae919061482f565b3480156104f057600080fd5b506104a46110de565b34801561050557600080fd5b50610519610514366004614816565b6110f9565b604080516001600160a01b0390931683526020830191909152016104ae565b34801561054457600080fd5b506104a460195481565b34801561055a57600080fd5b50610563611131565b005b34801561057157600080fd5b5061057a611156565b6040516001600160801b0390911681526020016104ae565b34801561059e57600080fd5b506105636111da565b3480156105b357600080fd5b506105636105c23660046148e2565b61131d565b3480156105d357600080fd5b506005546105e7906001600160a01b031681565b6040516001600160a01b0390911681526020016104ae565b34801561060b57600080fd5b506104a46801bc16d674ec80000081565b34801561062857600080fd5b506104a4600681565b34801561063d57600080fd5b5061056361064c3660046148e2565b6114bc565b34801561065d57600080fd5b5061067161066c3660046148fd565b61165b565b6040516104ae9190614929565b34801561068a57600080fd5b506104a460025481565b3480156106a057600080fd5b506104a460095481565b3480156106b657600080fd5b506105e77f000000000000000000000000000000000000000000000000000000000000000081565b3480156106ea57600080fd5b506104a46106f93660046148e2565b60216020526000908152604090205481565b34801561071757600080fd5b506104a460145481565b34801561072d57600080fd5b50610563611998565b34801561074257600080fd5b50610563610751366004614a07565b611cf0565b34801561076257600080fd5b506104a46103e881565b34801561077857600080fd5b50610563610787366004614a8a565b611ddc565b34801561079857600080fd5b506004546105e7906001600160a01b031681565b3480156107b857600080fd5b506104a46a027b46536c66c8e300000081565b3480156107d757600080fd5b506107e0612277565b6040516104ae9190614acc565b3480156107f957600080fd5b506104a4610808366004614afe565b60116020526000908152604090205481565b34801561082657600080fd5b506104a4610835366004614816565b60156020526000908152604090205481565b34801561085357600080fd5b506104a460135481565b34801561086957600080fd5b506104a4601c5481565b34801561087f57600080fd5b506104a461088e3660046148e2565b60226020526000908152604090205481565b3480156108ac57600080fd5b506108c06108bb366004614b1b565b6122c8565b6040516104ae929190614b3d565b3480156108da57600080fd5b506104a460075481565b3480156108f057600080fd5b5061056361242e565b34801561090557600080fd5b506104a46109143660046148e2565b601e6020526000908152604090205481565b34801561093257600080fd5b506104a46109413660046148e2565b601d6020526000908152604090205481565b34801561095f57600080fd5b506104a4606481565b610563610976366004614b9f565b612440565b34801561098757600080fd5b506104a4601981565b34801561099c57600080fd5b506109b06109ab3660046148fd565b6126d6565b6040516104ae929190614bc5565b3480156109ca57600080fd5b506104a4612800565b3480156109df57600080fd5b50610a586109ee366004614816565b600c6020526000908152604090208054600182015460028301546003840154600485015460058601546006870154600788015460089098015496979596949560ff80861696610100870482169662010000810483169663010000009091049092169491939192908c565b604080519c8d5260208d019b909b52998b019890985260ff90961660608a0152931515608089015291151560a0880152151560c087015260e0860152610100850152610120840152610140830152610160820152610180016104ae565b348015610ac157600080fd5b506000546001600160a01b03166105e7565b348015610adf57600080fd5b506104a4610aee366004614c19565b600e60209081526000938452604080852082529284528284209052825290205481565b610563612855565b348015610b2557600080fd5b50610563610b34366004614816565b612bf1565b348015610b4557600080fd5b506104a460085481565b348015610b5b57600080fd5b50610563610b6a366004614816565b612c3f565b348015610b7b57600080fd5b50610baa610b8a366004614c55565b601660209081526000928352604080842090915290825290205460ff1681565b60405190151581526020016104ae565b348015610bc657600080fd5b50610563612cc9565b348015610bdb57600080fd5b50610563610bea366004614c81565b612e1a565b348015610bfb57600080fd5b50610baa610c0a366004614cd4565b602460209081526000928352604080842090915290825290205460ff1681565b348015610c3657600080fd5b506104a4603c81565b348015610c4b57600080fd5b50610c5f610c5a3660046148e2565b6131ba565b604080519384526020840192909252908201526060016104ae565b348015610c8657600080fd5b506107e0610c95366004614c55565b6132a8565b348015610ca657600080fd5b506104a4601a5481565b348015610cbc57600080fd5b506104a4610ccb366004614c55565b600f60209081526000928352604080842090915290825290205481565b348015610cf457600080fd5b50601054610d099067ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020016104ae565b348015610d2e57600080fd5b506104a4610d3d3660046148e2565b601f6020526000908152604090205481565b348015610d5b57600080fd5b506107e061332a565b348015610d7057600080fd5b5061056361337a565b348015610d8557600080fd5b506104a467016345785d8a000081565b348015610da157600080fd5b50600b54610baa9060ff1681565b348015610dbb57600080fd5b50610baa610dca366004614cfe565b601760209081526000938452604080852082529284528284209052825290205460ff1681565b348015610dfc57600080fd5b506104a460065481565b348015610e1257600080fd5b506104a4601b5481565b348015610e2857600080fd5b506105e77f000000000000000000000000000000000000000000000000000000000000000081565b348015610e5c57600080fd5b506105e7610e6b366004614b1b565b6134cb565b348015610e7c57600080fd5b506104a469163c0fb846284fa0000081565b610563610e9c366004614d31565b613503565b348015610ead57600080fd5b50610563610ebc3660046148e2565b613638565b348015610ecd57600080fd5b506104a460125481565b348015610ee357600080fd5b506104a4610ef2366004614d4c565b613673565b348015610f0357600080fd5b506104a4610f12366004614c19565b600d60209081526000938452604080852082529284528284209052825290205481565b348015610f4157600080fd5b506104a461044c81565b348015610f5757600080fd5b50610baa610f66366004614c55565b60208080526000928352604080842090915290825290205460ff1681565b348015610f9057600080fd5b50610563610f9f3660046148e2565b6136a1565b348015610fb057600080fd5b506023546104a4565b348015610fc557600080fd5b50610563610fd43660046148fd565b613a1e565b348015610fe557600080fd5b506104a4600a5481565b61104e60405180610140016040528060008152602001600060ff16815260200160001515815260200160001515815260200160001515815260200160008152602001600081526020016000815260200160008152602001600081525090565b6000828152600c6020908152604080832060028101548552600381015460ff80821687860152610100808304821615158886015262010000830482161515606089015263010000009092041615156080870152600582015460a0870152600682015460c0870152600782015460e08701526008909101549085015293825260189052919091205461012082015290565b600060056110ea612800565b6110f49190614d9b565b905090565b6023818154811061110957600080fd5b6000918252602090912060029091020180546001909101546001600160a01b03909116915082565b611139613a71565b600b805460ff191690556010805467ffffffffffffffff19169055565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316638204b67a6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156111b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110f49190614daf565b6111e2613a9e565b33600090815260226020526040902054806112375760405162461bcd60e51b815260206004820152601060248201526f4e6f7468696e6720746f20636c61696d60801b60448201526064015b60405180910390fd5b336000818152602260205260408082208290555190919083908381818185875af1925050503d8060008114611288576040519150601f19603f3d011682016040523d82523d6000602084013e61128d565b606091505b50509050806112d45760405162461bcd60e51b8152602060048201526013602482015272151c985b9cd9995c881353d38819985a5b1959606a1b604482015260640161122e565b604080518381526000602082015233917f987d620f307ff6b94d58743cb7a7509f24071586a77759b77c2d4e29f75a2f9a91015b60405180910390a2505061131b60018055565b565b611325613a71565b6001600160a01b03811661136d5760405162461bcd60e51b815260206004820152600f60248201526e496e76616c6964206164647265737360881b604482015260640161122e565b6005546006546001600160a01b03909116901561146b57600680546000918290556040519091906001600160a01b0384169083908381818185875af1925050503d80600081146113d9576040519150601f19603f3d011682016040523d82523d6000602084013e6113de565b606091505b50509050806114255760405162461bcd60e51b8152602060048201526013602482015272119959481d1c985b9cd9995c8819985a5b1959606a1b604482015260640161122e565b826001600160a01b03167f6dda1c050330bbf19404606d86eb8277c7a84ee0b310a5311f255750f72e71ea8360405161146091815260200190565b60405180910390a250505b600580546001600160a01b0319166001600160a01b0384811691821790925560405190918316907fb03e0c2c1a6f3df4b388eee743d2ab30b064eb703533a6808a42b292cff9a97990600090a35050565b6114c4613a71565b6001600160a01b03811661150c5760405162461bcd60e51b815260206004820152600f60248201526e496e76616c6964206164647265737360881b604482015260640161122e565b6004546007546001600160a01b03909116901561160a57600780546000918290556040519091906001600160a01b0384169083908381818185875af1925050503d8060008114611578576040519150601f19603f3d011682016040523d82523d6000602084013e61157d565b606091505b50509050806115c45760405162461bcd60e51b8152602060048201526013602482015272119959481d1c985b9cd9995c8819985a5b1959606a1b604482015260640161122e565b826001600160a01b03167fe1b962d6a17421db47dc42910fbf9205832ca07f240e024fbc819c44540d8812836040516115ff91815260200190565b60405180910390a250505b600480546001600160a01b0319166001600160a01b0384811691821790925560405190918316907f6d0ea9c8b710f5c47c6869e683ae5d091320fac973498fc2b9ff84140dc9838390600090a35050565b6040805160c081018252606080825260006020830181905292820183905281018290526080810182905260a08101919091526000848152600c602052604090206003810154610100900460ff166116ea5760405162461bcd60e51b8152602060048201526013602482015272149bdd5b99081b9bdd08199a5b985b1a5e9959606a1b604482015260640161122e565b600381015460ff8082166040850181905262010000830482161515606086015263010000009092041615156080840152600882015460a084015261172f908690613ac8565b6020830181905284106117a2576040805160008082526020820190925290611799565b611786604051806080016040528060006001600160a01b031681526020016000815260200160008152602001600081525090565b8152602001906001900390816117525790505b50825250611991565b60006117ae8486614dee565b905082602001518111156117c3575060208201515b60006117cf8683614e01565b90508067ffffffffffffffff8111156117ea576117ea614dd8565b60405190808252806020026020018201604052801561184f57816020015b61183c604051806080016040528060006001600160a01b031681526020016000815260200160008152602001600081525090565b8152602001906001900390816118085790505b5084526000878152601860205260408120548190815b818110801561187357508483105b156119895760008b815260186020526040812080548390811061189857611898614e14565b60009182526020808320909101548e8352600d825260408084206001600160a01b0390921680855291835280842060038d015460ff1685529092529120549091508015611974578b8610611966576000806119068f858d60030160009054906101000a900460ff1686613b65565b915091506040518060800160405280856001600160a01b03168152602001848152602001838152602001828152508c60000151888151811061194a5761194a614e14565b6020026020010181905250868061196090614e2a565b97505050505b8561197081614e2a565b9650505b5050808061198190614e2a565b915050611865565b505050505050505b9392505050565b6119a0613a9e565b33600081815260226020526040902054906119ba90613c4b565b336000908152601d6020908152604080832054601f90925290912054821515806119e45750600082115b806119ef5750600081115b611a2e5760405162461bcd60e51b815260206004820152601060248201526f4e6f7468696e6720746f20636c61696d60801b604482015260640161122e565b600080831180611a3e5750600082115b15611b2a576000612710611a546103e886614e43565b611a5e9190614d9b565b90506000611a6c8286614e01565b9050600082118015611a7f575084601954115b15611ae457600085601954611a949190614e01565b905080611aa984670de0b6b3a7640000614e43565b611ab39190614d9b565b601a6000828254611ac49190614dee565b9250508190555082601b6000828254611add9190614dee565b9091555050505b336000908152601d60209081526040808320839055601f909152812081905560198054879290611b15908490614e01565b90915550611b2590508482614dee565b925050505b8315611bcf57336000818152602260205260408082208290555190919086908381818185875af1925050503d8060008114611b81576040519150601f19603f3d011682016040523d82523d6000602084013e611b86565b606091505b5050905080611bcd5760405162461bcd60e51b8152602060048201526013602482015272151c985b9cd9995c881353d38819985a5b1959606a1b604482015260640161122e565b505b8015611ca85760405163a9059cbb60e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb906044016020604051808303816000875af1158015611c42573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c669190614e5a565b611ca85760405162461bcd60e51b8152602060048201526013602482015272151c985b9cd9995c881513d2c819985a5b1959606a1b604482015260640161122e565b604080518581526020810183905233917f987d620f307ff6b94d58743cb7a7509f24071586a77759b77c2d4e29f75a2f9a910160405180910390a25050505061131b60018055565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b038116611d675760405162461bcd60e51b815260206004820152601760248201527f456e74726f70792061646472657373206e6f7420736574000000000000000000604482015260640161122e565b336001600160a01b03821614611dcb5760405162461bcd60e51b815260206004820152602360248201527f4f6e6c7920456e74726f70792063616e2063616c6c20746869732066756e637460448201526234b7b760e91b606482015260840161122e565b611dd6848484613d21565b50505050565b611de4613a9e565b602354600090815b83811015612232576000858583818110611e0857611e08614e14565b905060200201359050828110611e505760405162461bcd60e51b815260206004820152600d60248201526c092dcecc2d8d2c840d2dcc8caf609b1b604482015260640161122e565b8115611ee9578585611e63600185614e01565b818110611e7257611e72614e14565b90506020020135868684818110611e8b57611e8b614e14565b9050602002013510611ee95760405162461bcd60e51b815260206004820152602160248201527f496e6469636573206d75737420626520736f727465642064657363656e64696e6044820152606760f81b606482015260840161122e565b600060238281548110611efe57611efe614e14565b60009182526020918290206040805180820190915260029092020180546001600160a01b031680835260019091015492820183905260085491935091908110611f4a575050505061222a565b6000818152600c602052604090206003810154610100900460ff16611f7357505050505061222a565b6000828152602080805260408083206001600160a01b038716845290915290205460ff1615611fbc57611fa585613e17565b86611faf81614e7c565b975050505050505061222a565b6000828152600d602090815260408083206001600160a01b03871684528252808320600385015460ff168452909152902054801561220d5760038201546000906301000000900460ff1615612070576000848152600e602090815260408083206001600160a01b03891684528252808320600387015460ff1684529091529020546004840154811180159061205d57506120568382614dee565b8460040154105b1561206a57836007015491505b50612096565b670de0b6b3a76400008360060154836120899190614e43565b6120939190614d9b565b90505b80156120a6576120a68582613f46565b6000670de0b6b3a76400008460050154846120c19190614e43565b6120cb9190614d9b565b6120d59084614dee565b6001600160a01b038716600090815260226020526040812080549293508392909190612102908490614dee565b90915550506000858152602080805260408083206001600160a01b038a16808552908352818420805460ff19166001179055888452600f835281842090845290915290205480156121c5576000868152600f602090815260408083206001600160a01b038b16845290915281205561217a818d614dee565b604080518881526020810186905290810184905260608101839052909c506001600160a01b038816903390600080516020614f3e8339815191529060800160405180910390a3612209565b6040805187815260208101859052908101839052600060608201526001600160a01b038816903390600080516020614f3e8339815191529060800160405180910390a35b5050505b61221686613e17565b8761222081614e7c565b9850505050505050505b600101611dec565b50811561226857604051339083156108fc029084906000818181858888f19350505050158015612266573d6000803e3d6000fd5b505b505061227360018055565b5050565b61227f6147f7565b6008546000908152600c6020526040908190208151610320810190925260220160198282826020028201915b8154815260200190600101908083116122ab575050505050905090565b60235460609080841061231a576040805160008082526020820190925290612312565b60408051808201909152600080825260208201528152602001906001900390816122eb5790505b509150612427565b60006123268486614dee565b9050818111156123335750805b600061233f8683614e01565b90508067ffffffffffffffff81111561235a5761235a614dd8565b60405190808252806020026020018201604052801561239f57816020015b60408051808201909152600080825260208201528152602001906001900390816123785790505b50935060005b818110156124235760236123b98289614dee565b815481106123c9576123c9614e14565b60009182526020918290206040805180820190915260029092020180546001600160a01b031682526001015491810191909152855186908390811061241057612410614e14565b60209081029190910101526001016123a5565b5050505b9250929050565b612436613a71565b61131b6000613f99565b612448613a9e565b600a5442101561246a5760405162461bcd60e51b815260040161122e90614e93565b60025461247f9067016345785d8a0000614dee565b3410156124ce5760405162461bcd60e51b815260206004820152601d60248201527f53656e6420746f74616c207374616b65202b206b656570657220666565000000604482015260640161122e565b60008163ffffffff16116125195760405162461bcd60e51b8152602060048201526012602482015271139bc8189b1bd8dadcc81cd95b1958dd195960721b604482015260640161122e565b600b5460009060ff1661252e5760085461253c565b60085461253c906001614dee565b9050600082815b60198160ff1610156125885760018083169003612568578261256481614e2a565b9350505b60018263ffffffff16901c9150808061258090614ed7565b915050612543565b50600082116125ce5760405162461bcd60e51b8152602060048201526012602482015271139bc8189b1bd8dadcc81cd95b1958dd195960721b604482015260640161122e565b6000600254346125de9190614e01565b905060006125ec8483614d9b565b905060006125fa8584614ef6565b905067016345785d8a00008210156126445760405162461bcd60e51b815260206004820152600d60248201526c4d696e2070657220626c6f636b60981b604482015260640161122e565b869350600160005b60198160ff1610156126c257600180871690036126a25781156126965761268d3382856002548861267d9190614dee565b6126879190614dee565b8b613fe9565b600091506126a2565b6126a23382868b613fe9565b60018663ffffffff16901c955080806126ba90614ed7565b91505061264c565b50505050505050506126d360018055565b50565b6000838152601860205260409020546060908084106127055760408051600081526020810190915291506127f8565b60006127118486614dee565b90508181111561271e5750805b600061272a8683614e01565b90508067ffffffffffffffff81111561274557612745614dd8565b60405190808252806020026020018201604052801561276e578160200160208202803683370190505b50935060005b818110156127f45760008881526018602052604090206127948289614dee565b815481106127a4576127a4614e14565b9060005260206000200160009054906101000a90046001600160a01b03168582815181106127d4576127d4614e14565b6001600160a01b0390921660209283029190910190910152600101612774565b5050505b935093915050565b600080601c5469163c0fb846284fa0000061281b9190614dee565b905060006128346a027b46536c66c8e300000083614d9b565b90506006811115612843575060065b6801bc16d674ec800000901c92915050565b601254600a546128659190614dee565b4210156128a05760405162461bcd60e51b8152602060048201526009602482015268546f6f206561726c7960b81b604482015260640161122e565b600b5460ff16156128e55760405162461bcd60e51b815260206004820152600f60248201526e416c726561647920726f6c6c696e6760881b604482015260640161122e565b60145460085460009081526015602052604090205410156129485760405162461bcd60e51b815260206004820152601760248201527f4e6f7420656e6f756768207061727469636970616e7473000000000000000000604482015260640161122e565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316638204b67a6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156129a8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129cc9190614daf565b9050806001600160801b0316341015612a275760405162461bcd60e51b815260206004820152601860248201527f496e73756666696369656e7420656e74726f7079206665650000000000000000604482015260640161122e565b600b805460ff1916600117905560408051637b43155d60e01b815290516000916001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691637b43155d916001600160801b038616916004808301926020929190829003018185885af1158015612aa8573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190612acd9190614f0a565b6010805467ffffffffffffffff191667ffffffffffffffff83169081179091556008546000918252601160205260409091205590506001600160801b038216341115612bad57600033612b296001600160801b03851634614e01565b604051600081818185875af1925050503d8060008114612b65576040519150601f19603f3d011682016040523d82523d6000602084013e612b6a565b606091505b5050905080612bab5760405162461bcd60e51b815260206004820152600d60248201526c1499599d5b990819985a5b1959609a1b604482015260640161122e565b505b60085460405167ffffffffffffffff831681527fb9560bd3e25a95a3fcca6c0f21c6e8d9d07165bb54ae84dd553e21bbd94ce2629060200160405180910390a25050565b612bf9613a71565b600280549082905560408051828152602081018490527fe22b4203e51a04604258271faf98bf06a6f25e13004a7bce95940d2a2adbae8c91015b60405180910390a15050565b612c47613a71565b60008111612c8b5760405162461bcd60e51b815260206004820152601160248201527004c696d6974206d757374206265203e203607c1b604482015260640161122e565b600380549082905560408051828152602081018490527fd0497f09900611069b215093d3f3a5087f9719137e3a3fc9f716995a4be91f3b9101612c33565b612cd1613a9e565b6005546001600160a01b03163314612d175760405162461bcd60e51b81526020600482015260096024820152682737ba1030b236b4b760b91b604482015260640161122e565b60065480612d5a5760405162461bcd60e51b815260206004820152601060248201526f4e6f206665657320746f20636c61696d60801b604482015260640161122e565b60006006819055604051339083908381818185875af1925050503d8060008114612da0576040519150601f19603f3d011682016040523d82523d6000602084013e612da5565b606091505b5050905080612de85760405162461bcd60e51b815260206004820152600f60248201526e151c985b9cd9995c8819985a5b1959608a1b604482015260640161122e565b60405182815233907f6dda1c050330bbf19404606d86eb8277c7a84ee0b310a5311f255750f72e71ea90602001611308565b612e22613a9e565b6000805b82811015613175576000848483818110612e4257612e42614e14565b9050602002013590506008548110612e8b5760405162461bcd60e51b815260206004820152600c60248201526b1058dd1a5d99481c9bdd5b9960a21b604482015260640161122e565b6000818152600c602052604090206003810154610100900460ff16612ee85760405162461bcd60e51b8152602060048201526013602482015272149bdd5b99081b9bdd08199a5b985b1a5e9959606a1b604482015260640161122e565b6000828152602080805260408083206001600160a01b038b16845290915290205460ff1615612f1857505061316d565b6000828152600d602090815260408083206001600160a01b038b1684528252808320600385015460ff16845290915290205480156131695760038201546000906301000000900460ff1615612fcc576000848152600e602090815260408083206001600160a01b038d1684528252808320600387015460ff16845290915290205460048401548111801590612fb95750612fb28382614dee565b8460040154105b15612fc657836007015491505b50612ff2565b670de0b6b3a7640000836006015483612fe59190614e43565b612fef9190614d9b565b90505b8015613002576130028982613f46565b6000670de0b6b3a764000084600501548461301d9190614e43565b6130279190614d9b565b6130319084614dee565b6001600160a01b038b1660009081526022602052604081208054929350839290919061305e908490614dee565b90915550506000858152602080805260408083206001600160a01b038e16808552908352818420805460ff19166001179055888452600f83528184209084529091529020548015613121576000868152600f602090815260408083206001600160a01b038f1684529091528120556130d68189614dee565b6040805188815260208101869052908101849052606081018390529098506001600160a01b038c16903390600080516020614f3e8339815191529060800160405180910390a3613165565b6040805187815260208101859052908101839052600060608201526001600160a01b038c16903390600080516020614f3e8339815191529060800160405180910390a35b5050505b5050505b600101612e26565b5080156131ab57604051339082156108fc029083906000818181858888f193505050501580156131a9573d6000803e3d6000fd5b505b506131b560018055565b505050565b6001600160a01b0381166000908152601d6020908152604080832054601f835281842054601e90935290832054601a54919391111561324b576001600160a01b0384166000908152601e6020526040812054601a546132199190614e01565b90506000670de0b6b3a76400006132308684614e43565b61323a9190614d9b565b90506132468185614dee565b935050505b600083118061325a5750600082115b1561329d5760006127106132706103e886614e43565b61327a9190614d9b565b905060006132888286614e01565b90506132948482614dee565b925050506132a1565b5060005b9193909250565b6132b06147f7565b6132b86147f7565b60005b60198160ff161015613320576000858152600d602090815260408083206001600160a01b0388168452825280832060ff85168085529252909120549083906019811061330957613309614e14565b60200201528061331881614ed7565b9150506132bb565b5090505b92915050565b6133326147f7565b6008546000908152600c6020526040908190208151610320810190925260090160198282826020028201918154815260200190600101908083116122ab575050505050905090565b613382613a9e565b6004546001600160a01b031633146133c85760405162461bcd60e51b8152602060048201526009602482015268139bdd081d985d5b1d60ba1b604482015260640161122e565b6007548061340b5760405162461bcd60e51b815260206004820152601060248201526f4e6f206665657320746f20636c61696d60801b604482015260640161122e565b60006007819055604051339083908381818185875af1925050503d8060008114613451576040519150601f19603f3d011682016040523d82523d6000602084013e613456565b606091505b50509050806134995760405162461bcd60e51b815260206004820152600f60248201526e151c985b9cd9995c8819985a5b1959608a1b604482015260640161122e565b60405182815233907fe1b962d6a17421db47dc42910fbf9205832ca07f240e024fbc819c44540d881290602001611308565b601860205281600052604060002081815481106134e757600080fd5b6000918252602090912001546001600160a01b03169150829050565b61350b613a9e565b600a5442101561352d5760405162461bcd60e51b815260040161122e90614e93565b600b5460009060ff1661354257600854613550565b600854613550906001614dee565b6000818152600f602090815260408083203384529091529020549091501580156135dd576002546135899067016345785d8a0000614dee565b3410156135d85760405162461bcd60e51b815260206004820152601760248201527f53656e64207374616b65202b206b656570657220666565000000000000000000604482015260640161122e565b613621565b67016345785d8a00003410156136215760405162461bcd60e51b81526020600482015260096024820152684d696e207374616b6560b81b604482015260640161122e565b61362d33843485613fe9565b50506126d360018055565b613640613a71565b6001600160a01b03811661366a57604051631e4fbdf760e01b81526000600482015260240161122e565b6126d381613f99565b6000828152600c6020526040812060090160ff83166019811061369857613698614e14565b01549392505050565b6136a9613a9e565b6001600160a01b0381166000908152602160205260408120546136cd906001614dee565b600854600354919250906136e18383614e01565b11156136f7576003546136f49083614dee565b90505b6000825b828110156139b1576000818152600c602052604090206003810154610100900460ff16158061374a57506000828152602080805260408083206001600160a01b038a16845290915290205460ff165b1561375557506139a9565b6000828152600d602090815260408083206001600160a01b038a1684528252808320600385015460ff16845290915290205480156139a65760038201546000906301000000900460ff1615613809576000848152600e602090815260408083206001600160a01b038c1684528252808320600387015460ff168452909152902054600484015481118015906137f657506137ef8382614dee565b8460040154105b1561380357836007015491505b5061382f565b670de0b6b3a76400008360060154836138229190614e43565b61382c9190614d9b565b90505b801561383f5761383f8882613f46565b6000670de0b6b3a764000084600501548461385a9190614e43565b6138649190614d9b565b61386e9084614dee565b6001600160a01b038a1660009081526022602052604081208054929350839290919061389b908490614dee565b90915550506000858152602080805260408083206001600160a01b038d16808552908352818420805460ff19166001179055888452600f8352818420908452909152902054801561395e576000868152600f602090815260408083206001600160a01b038e1684529091528120556139138188614dee565b6040805188815260208101869052908101849052606081018390529097506001600160a01b038b16903390600080516020614f3e8339815191529060800160405180910390a36139a2565b6040805187815260208101859052908101839052600060608201526001600160a01b038b16903390600080516020614f3e8339815191529060800160405180910390a35b5050505b50505b6001016136fb565b5081156139dd576139c3600183614e01565b6001600160a01b0385166000908152602160205260409020555b8015613a1257604051339082156108fc029083906000818181858888f19350505050158015613a10573d6000803e3d6000fd5b505b5050506126d360018055565b613a26613a71565b603c831015613a635760405162461bcd60e51b8152602060048201526009602482015268151bdbc81cda1bdc9d60ba1b604482015260640161122e565b601292909255601455601355565b6000546001600160a01b0316331461131b5760405163118cdaa760e01b815233600482015260240161122e565b600260015403613ac157604051633ee5aeb560e01b815260040160405180910390fd5b6002600155565b600082815260186020526040812054815b81811015613b5d576000858152600d6020908152604080832060189092528220805483919085908110613b0e57613b0e614e14565b60009182526020808320909101546001600160a01b03168352828101939093526040918201812060ff891682529092529020541115613b555782613b5181614e2a565b9350505b600101613ad9565b505092915050565b6000848152600c602052604081206005810154829190670de0b6b3a764000090613b8f9086614e43565b613b999190614d9b565b613ba39085614dee565b60038201549093506301000000900460ff1615613c1b576000878152600e602090815260408083206001600160a01b038a168452825280832060ff8916845290915290205460048201548111801590613c085750613c018582614dee565b8260040154105b15613c1557816007015492505b50613c41565b670de0b6b3a7640000816006015485613c349190614e43565b613c3e9190614d9b565b91505b5094509492505050565b6001600160a01b0381166000908152601e6020526040902054601a541115613d02576001600160a01b0381166000908152601e6020526040812054601a54613c939190614e01565b6001600160a01b0383166000908152601d6020526040812054919250670de0b6b3a7640000613cc28385614e43565b613ccc9190614d9b565b6001600160a01b0385166000908152601f6020526040812080549293508392909190613cf9908490614dee565b90915550505050505b601a546001600160a01b039091166000908152601e6020526040902055565b67ffffffffffffffff8316600090815260116020526040902054600b5460ff168015613d4e575060085481145b613d8d5760405162461bcd60e51b815260206004820152601060248201526f496e76616c69642073657175656e636560801b604482015260640161122e565b60405182908190600090613db1908390600190602001918252602082015260400190565b60408051601f19818403018152828252805160209182012081840187905260028484015282518085038401815260609094019092528251920191909120909150613dfc8383836140a2565b50506010805467ffffffffffffffff19169055505050505050565b602354600090613e2990600190614e01565b9050600060238381548110613e4057613e40614e14565b60009182526020808320604080518082018252600290940290910180546001600160a01b03168085526001909101548484019081529085526024835281852090518552909152909120805460ff191690559050828214613f075760238281548110613ead57613ead614e14565b906000526020600020906002020160238481548110613ece57613ece614e14565b60009182526020909120825460029092020180546001600160a01b0319166001600160a01b039092169190911781556001918201549101555b6023805480613f1857613f18614f27565b60008281526020812060026000199093019283020180546001600160a01b0319168155600101559055505050565b613f4f82613c4b565b6001600160a01b0382166000908152601d602052604081208054839290613f77908490614dee565b925050819055508060196000828254613f909190614dee565b90915550505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60198360ff161061402c5760405162461bcd60e51b815260206004820152600d60248201526c496e76616c696420426c6f636b60981b604482015260640161122e565b6000818152600f602090815260408083206001600160a01b0388168452909152902054829015801561408e576002546140659085614e01565b6002546000858152600f602090815260408083206001600160a01b038c16845290915290205591505b61409a8686848661444f565b505050505050565b6008546000908152600c602052604090206140be601985614ef6565b60038201805460ff191660ff929092169190911790556140e4610271602086901c614ef6565b60038201805462ff000019811692156201000002928317909155600091600984019160ff9081169116176019811061411e5761411e614e14565b0154600183018190556002830154909150600061413b8383614e01565b808555905060008390036141b1576000612710614159606485614e43565b6141639190614d9b565b905080600660008282546141779190614dee565b9091555061418790508184614e01565b600760008282546141989190614dee565b9091555050600060058601819055600686015550614363565b60006127106141c1606484614e43565b6141cb9190614d9b565b905060006127106141de6103e885614e43565b6141e89190614d9b565b905060006141f68284614dee565b9050826006600082825461420a9190614dee565b9250508190555081600760008282546142239190614dee565b90915550600090506142358286614e01565b90508661424a82670de0b6b3a7640000614e43565b6142549190614d9b565b60058901556000614263612800565b9050600061426f6110de565b60038b015490915062010000900460ff1661429c5780600960008282546142969190614dee565b90915550505b60038a015460009062010000900460ff16156142cc57826009546142c09190614dee565b600060095590506142cf565b50815b80601c60008282546142e19190614dee565b909155506142f2905060028e614ef6565b6000036143295760038b01805463ff0000001916630100000017905560078b0181905561431f8a8d614ef6565b60048c015561435b565b60038b01805463ff000000191690558961434b82670de0b6b3a7640000614e43565b6143559190614d9b565b60068c01555b505050505050505b60038401805461010061ff00198216179182905542600880880191909155546040805191825260ff92831660208301526301000000840483161515908201526201000090920416151560608201527f73b6989256872bd8853751760a7960291ec2e04e1d8191bd624381f27fca9f8e9060800160405180910390a1600880549060006143ee83614e2a565b90915550506013546144009042614dee565b600a819055600b805460ff19169055600854604051918252907f278844837bcf8364a705384bf3a2812901f54155bae86dea81dd52aa5b9ec0e39060200160405180910390a250505050505050565b6000818152600c6020526040812060090160ff85166019811061447457614474614e14565b01546000838152600d602090815260408083206001600160a01b038a168452825280832060ff89168452909152812054919250036144dd576000828152600e602090815260408083206001600160a01b0389168452825280832060ff8816845290915290208190555b6000828152600d602090815260408083206001600160a01b0389168452825280832060ff881684529091528120805485929061451a908490614dee565b90915550506000828152600c60205260409020839060090160ff86166019811061454657614546614e14565b0160008282546145569190614dee565b90915550506000828152600c60205260408120600201805485929061457c908490614dee565b9091555050600082815260176020908152604080832060ff80891685529083528184206001600160a01b038a168552909252909120541661462557600082815260176020908152604080832060ff88168085529083528184206001600160a01b038a1685528352818420805460ff19166001179055858452600c909252909120602201906019811061461057614610614e14565b01805490600061461f83614e2a565b91905055505b60008281526016602090815260408083206001600160a01b038916845290915290205460ff166147a25760008281526016602090815260408083206001600160a01b03891684528252808320805460ff191660011790558483526015909152812080549161469283614e2a565b9091555050600082815260186020908152604080832080546001810182559084528284200180546001600160a01b0319166001600160a01b038a1690811790915583526024825280832085845290915290205460ff166147a2576001600160a01b03858116600081815260246020908152604080832087845282528083208054600160ff1990911681179091558151808301909252938152908101868152602380549485018155909252517fd57b2b5166478fd4318d2acc6cc2c704584312bdd8781b32d5d06abda57f4230600290930292830180546001600160a01b031916919094161790925590517fd57b2b5166478fd4318d2acc6cc2c704584312bdd8781b32d5d06abda57f4231909101555b6040805183815260ff861660208201529081018490526001600160a01b038616907f60c16227b368ec1b75014bc56837d084cbaf0b6989beb0cced9d343d9b5a94679060600160405180910390a25050505050565b6040518061032001604052806019906020820280368337509192915050565b60006020828403121561482857600080fd5b5035919050565b8151815260208083015161014083019161484d9084018260ff169052565b506040830151614861604084018215159052565b506060830151614875606084018215159052565b506080830151614889608084018215159052565b5060a083015160a083015260c083015160c083015260e083015160e083015261010083015161010083015261012083015161012083015292915050565b80356001600160a01b03811681146148dd57600080fd5b919050565b6000602082840312156148f457600080fd5b611991826148c6565b60008060006060848603121561491257600080fd5b505081359360208301359350604090920135919050565b6020808252825160c083830152805160e08401819052600092919091019082906101008501905b8083101561499c57835160018060a01b03815116835260208101516020840152604081015160408401526060810151606084015250608082019150602084019350600183019250614950565b5060208601516040860152604086015192506149bd606086018460ff169052565b606086015180151560808701529250608086015180151560a0870152925060a086015160c086015280935050505092915050565b67ffffffffffffffff811681146126d357600080fd5b600080600060608486031215614a1c57600080fd5b8335614a27816149f1565b9250614a35602085016148c6565b9150604084013590509250925092565b60008083601f840112614a5757600080fd5b50813567ffffffffffffffff811115614a6f57600080fd5b6020830191508360208260051b850101111561242757600080fd5b60008060208385031215614a9d57600080fd5b823567ffffffffffffffff811115614ab457600080fd5b614ac085828601614a45565b90969095509350505050565b6103208101818360005b6019811015614af5578151835260209283019290910190600101614ad6565b50505092915050565b600060208284031215614b1057600080fd5b8135611991816149f1565b60008060408385031215614b2e57600080fd5b50508035926020909101359150565b6040808252835190820181905260009060208501906060840190835b81811015614b8c57835180516001600160a01b031684526020908101518185015290930192604090920191600101614b59565b5050602093909301939093525092915050565b600060208284031215614bb157600080fd5b813563ffffffff8116811461199157600080fd5b6040808252835190820181905260009060208501906060840190835b81811015614b8c5783516001600160a01b0316835260209384019390920191600101614be1565b803560ff811681146148dd57600080fd5b600080600060608486031215614c2e57600080fd5b83359250614c3e602085016148c6565b9150614c4c60408501614c08565b90509250925092565b60008060408385031215614c6857600080fd5b82359150614c78602084016148c6565b90509250929050565b600080600060408486031215614c9657600080fd5b614c9f846148c6565b9250602084013567ffffffffffffffff811115614cbb57600080fd5b614cc786828701614a45565b9497909650939450505050565b60008060408385031215614ce757600080fd5b614cf0836148c6565b946020939093013593505050565b600080600060608486031215614d1357600080fd5b83359250614d2360208501614c08565b9150614c4c604085016148c6565b600060208284031215614d4357600080fd5b61199182614c08565b60008060408385031215614d5f57600080fd5b82359150614c7860208401614c08565b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600082614daa57614daa614d6f565b500490565b600060208284031215614dc157600080fd5b81516001600160801b038116811461199157600080fd5b634e487b7160e01b600052604160045260246000fd5b8082018082111561332457613324614d85565b8181038181111561332457613324614d85565b634e487b7160e01b600052603260045260246000fd5b600060018201614e3c57614e3c614d85565b5060010190565b808202811582820484141761332457613324614d85565b600060208284031215614e6c57600080fd5b8151801515811461199157600080fd5b600081614e8b57614e8b614d85565b506000190190565b60208082526024908201527f526f756e64206e6f742073746172746564207965742028696e7465726d697373604082015263696f6e2960e01b606082015260800190565b600060ff821660ff8103614eed57614eed614d85565b60010192915050565b600082614f0557614f05614d6f565b500690565b600060208284031215614f1c57600080fd5b8151611991816149f1565b634e487b7160e01b600052603160045260246000fdfe07f32f6f4c1b7fe2a67cebec7f6546a6324a14e661023fa65d8dd4e6605183a2a264697066735822122084fd1ca0ad41a672fa65085d0cb27f203b2f08017c9fac58f993355b2f5e4d7764736f6c634300081c0033000000000000000000000000d458261e832415cfd3bae5e416fdf3230ce6f1340000000000000000000000000b4de26631b54b0aa272d0e9b1e46fb723db4a1100000000000000000000000099662e7cc1970de202e97d5b2b70215d5370b1f400000000000000000000000099662e7cc1970de202e97d5b2b70215d5370b1f4
Deployed Bytecode
0x6080604052600436106104825760003560e01c80638aec854211610255578063c9fbcfb011610144578063f0f2f6ee116100c1578063fbb098ee11610085578063fbb098ee14610f35578063fc44e4c714610f4b578063fc89aeaa14610f84578063fcfd837f14610fa4578063fd5c0cc614610fb9578063fe31a61314610fd957600080fd5b8063f0f2f6ee14610e8e578063f2fde38b14610ea1578063f7cb789a14610ec1578063fa0648cb14610ed7578063faddbdb214610ef757600080fd5b8063da1f57c811610108578063da1f57c814610df0578063dbab925314610e06578063dbf4025b14610e1c578063de26eadf14610e50578063ebca8add14610e7057600080fd5b8063c9fbcfb014610d64578063cb1c2b5c14610d79578063cb56532014610d95578063cb6b532e14610daf578063d20e43411461075657600080fd5b8063a6edbfa8116101d2578063af85bdbc11610196578063af85bdbc14610c9a578063b116944414610cb0578063b370488014610ce8578063c566482c14610d22578063c9f73df614610d4f57600080fd5b8063a6edbfa814610bcf578063aafbc82114610bef578063ab5669ad14610c2a578063abd3f61214610c3f578063ae1eac9114610c7a57600080fd5b806398dfca7f1161021957806398dfca7f14610b195780639cbe5efd14610b39578063a1b44ff814610b4f578063a34398a214610b6f578063a345bf4314610bba57600080fd5b80638aec8542146109be5780638c65c81f146109d35780638da5cb5b14610ab55780638f32b2fe14610ad357806390cc399c14610b1157600080fd5b806352a5f1f81161037157806368aa6ffc116102ee57806376c154a5116102b257806376c154a5146109265780637838c03114610953578063783fe32f146109685780637fc4eda81461097b5780638396c2b01461099057600080fd5b806368aa6ffc146108735780636920c820146108a05780636a842462146108ce578063715018a6146108e457806371e51e9e146108f957600080fd5b80636157714c116103355780636157714c146107cb57806361613897146107ed57806363a4390b1461081a57806364febe9614610847578063687ddf3b1461085d57600080fd5b806352a5f1f8146107365780635342c8bc1461075657806353fd66fd1461076c5780635a9249e61461078c5780635fd9491d146107ac57600080fd5b806336bcf7d6116103ff57806343a70146116103c357806343a701461461069457806347ce07cc146106aa57806349208981146106de5780634c5970601461070b5780634e71d92d1461072157600080fd5b806336bcf7d6146105ff57806336f1e6c01461061c57806339c5dec7146106315780633be83035146106515780633d1b760b1461067e57600080fd5b80632007641911610446578063200764191461054e5780632d971e6314610565578063317a98771461059257806335082933146105a757806336b19cd7146105c757600080fd5b8063053b37e61461048e5780630720da52146104b75780630bab460b146104e457806312a2f1f4146104f9578063170ad53c1461053857600080fd5b3661048957005b600080fd5b34801561049a57600080fd5b506104a460035481565b6040519081526020015b60405180910390f35b3480156104c357600080fd5b506104d76104d2366004614816565b610fef565b6040516104ae919061482f565b3480156104f057600080fd5b506104a46110de565b34801561050557600080fd5b50610519610514366004614816565b6110f9565b604080516001600160a01b0390931683526020830191909152016104ae565b34801561054457600080fd5b506104a460195481565b34801561055a57600080fd5b50610563611131565b005b34801561057157600080fd5b5061057a611156565b6040516001600160801b0390911681526020016104ae565b34801561059e57600080fd5b506105636111da565b3480156105b357600080fd5b506105636105c23660046148e2565b61131d565b3480156105d357600080fd5b506005546105e7906001600160a01b031681565b6040516001600160a01b0390911681526020016104ae565b34801561060b57600080fd5b506104a46801bc16d674ec80000081565b34801561062857600080fd5b506104a4600681565b34801561063d57600080fd5b5061056361064c3660046148e2565b6114bc565b34801561065d57600080fd5b5061067161066c3660046148fd565b61165b565b6040516104ae9190614929565b34801561068a57600080fd5b506104a460025481565b3480156106a057600080fd5b506104a460095481565b3480156106b657600080fd5b506105e77f000000000000000000000000d458261e832415cfd3bae5e416fdf3230ce6f13481565b3480156106ea57600080fd5b506104a46106f93660046148e2565b60216020526000908152604090205481565b34801561071757600080fd5b506104a460145481565b34801561072d57600080fd5b50610563611998565b34801561074257600080fd5b50610563610751366004614a07565b611cf0565b34801561076257600080fd5b506104a46103e881565b34801561077857600080fd5b50610563610787366004614a8a565b611ddc565b34801561079857600080fd5b506004546105e7906001600160a01b031681565b3480156107b857600080fd5b506104a46a027b46536c66c8e300000081565b3480156107d757600080fd5b506107e0612277565b6040516104ae9190614acc565b3480156107f957600080fd5b506104a4610808366004614afe565b60116020526000908152604090205481565b34801561082657600080fd5b506104a4610835366004614816565b60156020526000908152604090205481565b34801561085357600080fd5b506104a460135481565b34801561086957600080fd5b506104a4601c5481565b34801561087f57600080fd5b506104a461088e3660046148e2565b60226020526000908152604090205481565b3480156108ac57600080fd5b506108c06108bb366004614b1b565b6122c8565b6040516104ae929190614b3d565b3480156108da57600080fd5b506104a460075481565b3480156108f057600080fd5b5061056361242e565b34801561090557600080fd5b506104a46109143660046148e2565b601e6020526000908152604090205481565b34801561093257600080fd5b506104a46109413660046148e2565b601d6020526000908152604090205481565b34801561095f57600080fd5b506104a4606481565b610563610976366004614b9f565b612440565b34801561098757600080fd5b506104a4601981565b34801561099c57600080fd5b506109b06109ab3660046148fd565b6126d6565b6040516104ae929190614bc5565b3480156109ca57600080fd5b506104a4612800565b3480156109df57600080fd5b50610a586109ee366004614816565b600c6020526000908152604090208054600182015460028301546003840154600485015460058601546006870154600788015460089098015496979596949560ff80861696610100870482169662010000810483169663010000009091049092169491939192908c565b604080519c8d5260208d019b909b52998b019890985260ff90961660608a0152931515608089015291151560a0880152151560c087015260e0860152610100850152610120840152610140830152610160820152610180016104ae565b348015610ac157600080fd5b506000546001600160a01b03166105e7565b348015610adf57600080fd5b506104a4610aee366004614c19565b600e60209081526000938452604080852082529284528284209052825290205481565b610563612855565b348015610b2557600080fd5b50610563610b34366004614816565b612bf1565b348015610b4557600080fd5b506104a460085481565b348015610b5b57600080fd5b50610563610b6a366004614816565b612c3f565b348015610b7b57600080fd5b50610baa610b8a366004614c55565b601660209081526000928352604080842090915290825290205460ff1681565b60405190151581526020016104ae565b348015610bc657600080fd5b50610563612cc9565b348015610bdb57600080fd5b50610563610bea366004614c81565b612e1a565b348015610bfb57600080fd5b50610baa610c0a366004614cd4565b602460209081526000928352604080842090915290825290205460ff1681565b348015610c3657600080fd5b506104a4603c81565b348015610c4b57600080fd5b50610c5f610c5a3660046148e2565b6131ba565b604080519384526020840192909252908201526060016104ae565b348015610c8657600080fd5b506107e0610c95366004614c55565b6132a8565b348015610ca657600080fd5b506104a4601a5481565b348015610cbc57600080fd5b506104a4610ccb366004614c55565b600f60209081526000928352604080842090915290825290205481565b348015610cf457600080fd5b50601054610d099067ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020016104ae565b348015610d2e57600080fd5b506104a4610d3d3660046148e2565b601f6020526000908152604090205481565b348015610d5b57600080fd5b506107e061332a565b348015610d7057600080fd5b5061056361337a565b348015610d8557600080fd5b506104a467016345785d8a000081565b348015610da157600080fd5b50600b54610baa9060ff1681565b348015610dbb57600080fd5b50610baa610dca366004614cfe565b601760209081526000938452604080852082529284528284209052825290205460ff1681565b348015610dfc57600080fd5b506104a460065481565b348015610e1257600080fd5b506104a4601b5481565b348015610e2857600080fd5b506105e77f0000000000000000000000000b4de26631b54b0aa272d0e9b1e46fb723db4a1181565b348015610e5c57600080fd5b506105e7610e6b366004614b1b565b6134cb565b348015610e7c57600080fd5b506104a469163c0fb846284fa0000081565b610563610e9c366004614d31565b613503565b348015610ead57600080fd5b50610563610ebc3660046148e2565b613638565b348015610ecd57600080fd5b506104a460125481565b348015610ee357600080fd5b506104a4610ef2366004614d4c565b613673565b348015610f0357600080fd5b506104a4610f12366004614c19565b600d60209081526000938452604080852082529284528284209052825290205481565b348015610f4157600080fd5b506104a461044c81565b348015610f5757600080fd5b50610baa610f66366004614c55565b60208080526000928352604080842090915290825290205460ff1681565b348015610f9057600080fd5b50610563610f9f3660046148e2565b6136a1565b348015610fb057600080fd5b506023546104a4565b348015610fc557600080fd5b50610563610fd43660046148fd565b613a1e565b348015610fe557600080fd5b506104a4600a5481565b61104e60405180610140016040528060008152602001600060ff16815260200160001515815260200160001515815260200160001515815260200160008152602001600081526020016000815260200160008152602001600081525090565b6000828152600c6020908152604080832060028101548552600381015460ff80821687860152610100808304821615158886015262010000830482161515606089015263010000009092041615156080870152600582015460a0870152600682015460c0870152600782015460e08701526008909101549085015293825260189052919091205461012082015290565b600060056110ea612800565b6110f49190614d9b565b905090565b6023818154811061110957600080fd5b6000918252602090912060029091020180546001909101546001600160a01b03909116915082565b611139613a71565b600b805460ff191690556010805467ffffffffffffffff19169055565b60007f000000000000000000000000d458261e832415cfd3bae5e416fdf3230ce6f1346001600160a01b0316638204b67a6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156111b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110f49190614daf565b6111e2613a9e565b33600090815260226020526040902054806112375760405162461bcd60e51b815260206004820152601060248201526f4e6f7468696e6720746f20636c61696d60801b60448201526064015b60405180910390fd5b336000818152602260205260408082208290555190919083908381818185875af1925050503d8060008114611288576040519150601f19603f3d011682016040523d82523d6000602084013e61128d565b606091505b50509050806112d45760405162461bcd60e51b8152602060048201526013602482015272151c985b9cd9995c881353d38819985a5b1959606a1b604482015260640161122e565b604080518381526000602082015233917f987d620f307ff6b94d58743cb7a7509f24071586a77759b77c2d4e29f75a2f9a91015b60405180910390a2505061131b60018055565b565b611325613a71565b6001600160a01b03811661136d5760405162461bcd60e51b815260206004820152600f60248201526e496e76616c6964206164647265737360881b604482015260640161122e565b6005546006546001600160a01b03909116901561146b57600680546000918290556040519091906001600160a01b0384169083908381818185875af1925050503d80600081146113d9576040519150601f19603f3d011682016040523d82523d6000602084013e6113de565b606091505b50509050806114255760405162461bcd60e51b8152602060048201526013602482015272119959481d1c985b9cd9995c8819985a5b1959606a1b604482015260640161122e565b826001600160a01b03167f6dda1c050330bbf19404606d86eb8277c7a84ee0b310a5311f255750f72e71ea8360405161146091815260200190565b60405180910390a250505b600580546001600160a01b0319166001600160a01b0384811691821790925560405190918316907fb03e0c2c1a6f3df4b388eee743d2ab30b064eb703533a6808a42b292cff9a97990600090a35050565b6114c4613a71565b6001600160a01b03811661150c5760405162461bcd60e51b815260206004820152600f60248201526e496e76616c6964206164647265737360881b604482015260640161122e565b6004546007546001600160a01b03909116901561160a57600780546000918290556040519091906001600160a01b0384169083908381818185875af1925050503d8060008114611578576040519150601f19603f3d011682016040523d82523d6000602084013e61157d565b606091505b50509050806115c45760405162461bcd60e51b8152602060048201526013602482015272119959481d1c985b9cd9995c8819985a5b1959606a1b604482015260640161122e565b826001600160a01b03167fe1b962d6a17421db47dc42910fbf9205832ca07f240e024fbc819c44540d8812836040516115ff91815260200190565b60405180910390a250505b600480546001600160a01b0319166001600160a01b0384811691821790925560405190918316907f6d0ea9c8b710f5c47c6869e683ae5d091320fac973498fc2b9ff84140dc9838390600090a35050565b6040805160c081018252606080825260006020830181905292820183905281018290526080810182905260a08101919091526000848152600c602052604090206003810154610100900460ff166116ea5760405162461bcd60e51b8152602060048201526013602482015272149bdd5b99081b9bdd08199a5b985b1a5e9959606a1b604482015260640161122e565b600381015460ff8082166040850181905262010000830482161515606086015263010000009092041615156080840152600882015460a084015261172f908690613ac8565b6020830181905284106117a2576040805160008082526020820190925290611799565b611786604051806080016040528060006001600160a01b031681526020016000815260200160008152602001600081525090565b8152602001906001900390816117525790505b50825250611991565b60006117ae8486614dee565b905082602001518111156117c3575060208201515b60006117cf8683614e01565b90508067ffffffffffffffff8111156117ea576117ea614dd8565b60405190808252806020026020018201604052801561184f57816020015b61183c604051806080016040528060006001600160a01b031681526020016000815260200160008152602001600081525090565b8152602001906001900390816118085790505b5084526000878152601860205260408120548190815b818110801561187357508483105b156119895760008b815260186020526040812080548390811061189857611898614e14565b60009182526020808320909101548e8352600d825260408084206001600160a01b0390921680855291835280842060038d015460ff1685529092529120549091508015611974578b8610611966576000806119068f858d60030160009054906101000a900460ff1686613b65565b915091506040518060800160405280856001600160a01b03168152602001848152602001838152602001828152508c60000151888151811061194a5761194a614e14565b6020026020010181905250868061196090614e2a565b97505050505b8561197081614e2a565b9650505b5050808061198190614e2a565b915050611865565b505050505050505b9392505050565b6119a0613a9e565b33600081815260226020526040902054906119ba90613c4b565b336000908152601d6020908152604080832054601f90925290912054821515806119e45750600082115b806119ef5750600081115b611a2e5760405162461bcd60e51b815260206004820152601060248201526f4e6f7468696e6720746f20636c61696d60801b604482015260640161122e565b600080831180611a3e5750600082115b15611b2a576000612710611a546103e886614e43565b611a5e9190614d9b565b90506000611a6c8286614e01565b9050600082118015611a7f575084601954115b15611ae457600085601954611a949190614e01565b905080611aa984670de0b6b3a7640000614e43565b611ab39190614d9b565b601a6000828254611ac49190614dee565b9250508190555082601b6000828254611add9190614dee565b9091555050505b336000908152601d60209081526040808320839055601f909152812081905560198054879290611b15908490614e01565b90915550611b2590508482614dee565b925050505b8315611bcf57336000818152602260205260408082208290555190919086908381818185875af1925050503d8060008114611b81576040519150601f19603f3d011682016040523d82523d6000602084013e611b86565b606091505b5050905080611bcd5760405162461bcd60e51b8152602060048201526013602482015272151c985b9cd9995c881353d38819985a5b1959606a1b604482015260640161122e565b505b8015611ca85760405163a9059cbb60e01b8152336004820152602481018290527f0000000000000000000000000b4de26631b54b0aa272d0e9b1e46fb723db4a116001600160a01b03169063a9059cbb906044016020604051808303816000875af1158015611c42573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c669190614e5a565b611ca85760405162461bcd60e51b8152602060048201526013602482015272151c985b9cd9995c881513d2c819985a5b1959606a1b604482015260640161122e565b604080518581526020810183905233917f987d620f307ff6b94d58743cb7a7509f24071586a77759b77c2d4e29f75a2f9a910160405180910390a25050505061131b60018055565b7f000000000000000000000000d458261e832415cfd3bae5e416fdf3230ce6f1346001600160a01b038116611d675760405162461bcd60e51b815260206004820152601760248201527f456e74726f70792061646472657373206e6f7420736574000000000000000000604482015260640161122e565b336001600160a01b03821614611dcb5760405162461bcd60e51b815260206004820152602360248201527f4f6e6c7920456e74726f70792063616e2063616c6c20746869732066756e637460448201526234b7b760e91b606482015260840161122e565b611dd6848484613d21565b50505050565b611de4613a9e565b602354600090815b83811015612232576000858583818110611e0857611e08614e14565b905060200201359050828110611e505760405162461bcd60e51b815260206004820152600d60248201526c092dcecc2d8d2c840d2dcc8caf609b1b604482015260640161122e565b8115611ee9578585611e63600185614e01565b818110611e7257611e72614e14565b90506020020135868684818110611e8b57611e8b614e14565b9050602002013510611ee95760405162461bcd60e51b815260206004820152602160248201527f496e6469636573206d75737420626520736f727465642064657363656e64696e6044820152606760f81b606482015260840161122e565b600060238281548110611efe57611efe614e14565b60009182526020918290206040805180820190915260029092020180546001600160a01b031680835260019091015492820183905260085491935091908110611f4a575050505061222a565b6000818152600c602052604090206003810154610100900460ff16611f7357505050505061222a565b6000828152602080805260408083206001600160a01b038716845290915290205460ff1615611fbc57611fa585613e17565b86611faf81614e7c565b975050505050505061222a565b6000828152600d602090815260408083206001600160a01b03871684528252808320600385015460ff168452909152902054801561220d5760038201546000906301000000900460ff1615612070576000848152600e602090815260408083206001600160a01b03891684528252808320600387015460ff1684529091529020546004840154811180159061205d57506120568382614dee565b8460040154105b1561206a57836007015491505b50612096565b670de0b6b3a76400008360060154836120899190614e43565b6120939190614d9b565b90505b80156120a6576120a68582613f46565b6000670de0b6b3a76400008460050154846120c19190614e43565b6120cb9190614d9b565b6120d59084614dee565b6001600160a01b038716600090815260226020526040812080549293508392909190612102908490614dee565b90915550506000858152602080805260408083206001600160a01b038a16808552908352818420805460ff19166001179055888452600f835281842090845290915290205480156121c5576000868152600f602090815260408083206001600160a01b038b16845290915281205561217a818d614dee565b604080518881526020810186905290810184905260608101839052909c506001600160a01b038816903390600080516020614f3e8339815191529060800160405180910390a3612209565b6040805187815260208101859052908101839052600060608201526001600160a01b038816903390600080516020614f3e8339815191529060800160405180910390a35b5050505b61221686613e17565b8761222081614e7c565b9850505050505050505b600101611dec565b50811561226857604051339083156108fc029084906000818181858888f19350505050158015612266573d6000803e3d6000fd5b505b505061227360018055565b5050565b61227f6147f7565b6008546000908152600c6020526040908190208151610320810190925260220160198282826020028201915b8154815260200190600101908083116122ab575050505050905090565b60235460609080841061231a576040805160008082526020820190925290612312565b60408051808201909152600080825260208201528152602001906001900390816122eb5790505b509150612427565b60006123268486614dee565b9050818111156123335750805b600061233f8683614e01565b90508067ffffffffffffffff81111561235a5761235a614dd8565b60405190808252806020026020018201604052801561239f57816020015b60408051808201909152600080825260208201528152602001906001900390816123785790505b50935060005b818110156124235760236123b98289614dee565b815481106123c9576123c9614e14565b60009182526020918290206040805180820190915260029092020180546001600160a01b031682526001015491810191909152855186908390811061241057612410614e14565b60209081029190910101526001016123a5565b5050505b9250929050565b612436613a71565b61131b6000613f99565b612448613a9e565b600a5442101561246a5760405162461bcd60e51b815260040161122e90614e93565b60025461247f9067016345785d8a0000614dee565b3410156124ce5760405162461bcd60e51b815260206004820152601d60248201527f53656e6420746f74616c207374616b65202b206b656570657220666565000000604482015260640161122e565b60008163ffffffff16116125195760405162461bcd60e51b8152602060048201526012602482015271139bc8189b1bd8dadcc81cd95b1958dd195960721b604482015260640161122e565b600b5460009060ff1661252e5760085461253c565b60085461253c906001614dee565b9050600082815b60198160ff1610156125885760018083169003612568578261256481614e2a565b9350505b60018263ffffffff16901c9150808061258090614ed7565b915050612543565b50600082116125ce5760405162461bcd60e51b8152602060048201526012602482015271139bc8189b1bd8dadcc81cd95b1958dd195960721b604482015260640161122e565b6000600254346125de9190614e01565b905060006125ec8483614d9b565b905060006125fa8584614ef6565b905067016345785d8a00008210156126445760405162461bcd60e51b815260206004820152600d60248201526c4d696e2070657220626c6f636b60981b604482015260640161122e565b869350600160005b60198160ff1610156126c257600180871690036126a25781156126965761268d3382856002548861267d9190614dee565b6126879190614dee565b8b613fe9565b600091506126a2565b6126a23382868b613fe9565b60018663ffffffff16901c955080806126ba90614ed7565b91505061264c565b50505050505050506126d360018055565b50565b6000838152601860205260409020546060908084106127055760408051600081526020810190915291506127f8565b60006127118486614dee565b90508181111561271e5750805b600061272a8683614e01565b90508067ffffffffffffffff81111561274557612745614dd8565b60405190808252806020026020018201604052801561276e578160200160208202803683370190505b50935060005b818110156127f45760008881526018602052604090206127948289614dee565b815481106127a4576127a4614e14565b9060005260206000200160009054906101000a90046001600160a01b03168582815181106127d4576127d4614e14565b6001600160a01b0390921660209283029190910190910152600101612774565b5050505b935093915050565b600080601c5469163c0fb846284fa0000061281b9190614dee565b905060006128346a027b46536c66c8e300000083614d9b565b90506006811115612843575060065b6801bc16d674ec800000901c92915050565b601254600a546128659190614dee565b4210156128a05760405162461bcd60e51b8152602060048201526009602482015268546f6f206561726c7960b81b604482015260640161122e565b600b5460ff16156128e55760405162461bcd60e51b815260206004820152600f60248201526e416c726561647920726f6c6c696e6760881b604482015260640161122e565b60145460085460009081526015602052604090205410156129485760405162461bcd60e51b815260206004820152601760248201527f4e6f7420656e6f756768207061727469636970616e7473000000000000000000604482015260640161122e565b60007f000000000000000000000000d458261e832415cfd3bae5e416fdf3230ce6f1346001600160a01b0316638204b67a6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156129a8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129cc9190614daf565b9050806001600160801b0316341015612a275760405162461bcd60e51b815260206004820152601860248201527f496e73756666696369656e7420656e74726f7079206665650000000000000000604482015260640161122e565b600b805460ff1916600117905560408051637b43155d60e01b815290516000916001600160a01b037f000000000000000000000000d458261e832415cfd3bae5e416fdf3230ce6f1341691637b43155d916001600160801b038616916004808301926020929190829003018185885af1158015612aa8573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190612acd9190614f0a565b6010805467ffffffffffffffff191667ffffffffffffffff83169081179091556008546000918252601160205260409091205590506001600160801b038216341115612bad57600033612b296001600160801b03851634614e01565b604051600081818185875af1925050503d8060008114612b65576040519150601f19603f3d011682016040523d82523d6000602084013e612b6a565b606091505b5050905080612bab5760405162461bcd60e51b815260206004820152600d60248201526c1499599d5b990819985a5b1959609a1b604482015260640161122e565b505b60085460405167ffffffffffffffff831681527fb9560bd3e25a95a3fcca6c0f21c6e8d9d07165bb54ae84dd553e21bbd94ce2629060200160405180910390a25050565b612bf9613a71565b600280549082905560408051828152602081018490527fe22b4203e51a04604258271faf98bf06a6f25e13004a7bce95940d2a2adbae8c91015b60405180910390a15050565b612c47613a71565b60008111612c8b5760405162461bcd60e51b815260206004820152601160248201527004c696d6974206d757374206265203e203607c1b604482015260640161122e565b600380549082905560408051828152602081018490527fd0497f09900611069b215093d3f3a5087f9719137e3a3fc9f716995a4be91f3b9101612c33565b612cd1613a9e565b6005546001600160a01b03163314612d175760405162461bcd60e51b81526020600482015260096024820152682737ba1030b236b4b760b91b604482015260640161122e565b60065480612d5a5760405162461bcd60e51b815260206004820152601060248201526f4e6f206665657320746f20636c61696d60801b604482015260640161122e565b60006006819055604051339083908381818185875af1925050503d8060008114612da0576040519150601f19603f3d011682016040523d82523d6000602084013e612da5565b606091505b5050905080612de85760405162461bcd60e51b815260206004820152600f60248201526e151c985b9cd9995c8819985a5b1959608a1b604482015260640161122e565b60405182815233907f6dda1c050330bbf19404606d86eb8277c7a84ee0b310a5311f255750f72e71ea90602001611308565b612e22613a9e565b6000805b82811015613175576000848483818110612e4257612e42614e14565b9050602002013590506008548110612e8b5760405162461bcd60e51b815260206004820152600c60248201526b1058dd1a5d99481c9bdd5b9960a21b604482015260640161122e565b6000818152600c602052604090206003810154610100900460ff16612ee85760405162461bcd60e51b8152602060048201526013602482015272149bdd5b99081b9bdd08199a5b985b1a5e9959606a1b604482015260640161122e565b6000828152602080805260408083206001600160a01b038b16845290915290205460ff1615612f1857505061316d565b6000828152600d602090815260408083206001600160a01b038b1684528252808320600385015460ff16845290915290205480156131695760038201546000906301000000900460ff1615612fcc576000848152600e602090815260408083206001600160a01b038d1684528252808320600387015460ff16845290915290205460048401548111801590612fb95750612fb28382614dee565b8460040154105b15612fc657836007015491505b50612ff2565b670de0b6b3a7640000836006015483612fe59190614e43565b612fef9190614d9b565b90505b8015613002576130028982613f46565b6000670de0b6b3a764000084600501548461301d9190614e43565b6130279190614d9b565b6130319084614dee565b6001600160a01b038b1660009081526022602052604081208054929350839290919061305e908490614dee565b90915550506000858152602080805260408083206001600160a01b038e16808552908352818420805460ff19166001179055888452600f83528184209084529091529020548015613121576000868152600f602090815260408083206001600160a01b038f1684529091528120556130d68189614dee565b6040805188815260208101869052908101849052606081018390529098506001600160a01b038c16903390600080516020614f3e8339815191529060800160405180910390a3613165565b6040805187815260208101859052908101839052600060608201526001600160a01b038c16903390600080516020614f3e8339815191529060800160405180910390a35b5050505b5050505b600101612e26565b5080156131ab57604051339082156108fc029083906000818181858888f193505050501580156131a9573d6000803e3d6000fd5b505b506131b560018055565b505050565b6001600160a01b0381166000908152601d6020908152604080832054601f835281842054601e90935290832054601a54919391111561324b576001600160a01b0384166000908152601e6020526040812054601a546132199190614e01565b90506000670de0b6b3a76400006132308684614e43565b61323a9190614d9b565b90506132468185614dee565b935050505b600083118061325a5750600082115b1561329d5760006127106132706103e886614e43565b61327a9190614d9b565b905060006132888286614e01565b90506132948482614dee565b925050506132a1565b5060005b9193909250565b6132b06147f7565b6132b86147f7565b60005b60198160ff161015613320576000858152600d602090815260408083206001600160a01b0388168452825280832060ff85168085529252909120549083906019811061330957613309614e14565b60200201528061331881614ed7565b9150506132bb565b5090505b92915050565b6133326147f7565b6008546000908152600c6020526040908190208151610320810190925260090160198282826020028201918154815260200190600101908083116122ab575050505050905090565b613382613a9e565b6004546001600160a01b031633146133c85760405162461bcd60e51b8152602060048201526009602482015268139bdd081d985d5b1d60ba1b604482015260640161122e565b6007548061340b5760405162461bcd60e51b815260206004820152601060248201526f4e6f206665657320746f20636c61696d60801b604482015260640161122e565b60006007819055604051339083908381818185875af1925050503d8060008114613451576040519150601f19603f3d011682016040523d82523d6000602084013e613456565b606091505b50509050806134995760405162461bcd60e51b815260206004820152600f60248201526e151c985b9cd9995c8819985a5b1959608a1b604482015260640161122e565b60405182815233907fe1b962d6a17421db47dc42910fbf9205832ca07f240e024fbc819c44540d881290602001611308565b601860205281600052604060002081815481106134e757600080fd5b6000918252602090912001546001600160a01b03169150829050565b61350b613a9e565b600a5442101561352d5760405162461bcd60e51b815260040161122e90614e93565b600b5460009060ff1661354257600854613550565b600854613550906001614dee565b6000818152600f602090815260408083203384529091529020549091501580156135dd576002546135899067016345785d8a0000614dee565b3410156135d85760405162461bcd60e51b815260206004820152601760248201527f53656e64207374616b65202b206b656570657220666565000000000000000000604482015260640161122e565b613621565b67016345785d8a00003410156136215760405162461bcd60e51b81526020600482015260096024820152684d696e207374616b6560b81b604482015260640161122e565b61362d33843485613fe9565b50506126d360018055565b613640613a71565b6001600160a01b03811661366a57604051631e4fbdf760e01b81526000600482015260240161122e565b6126d381613f99565b6000828152600c6020526040812060090160ff83166019811061369857613698614e14565b01549392505050565b6136a9613a9e565b6001600160a01b0381166000908152602160205260408120546136cd906001614dee565b600854600354919250906136e18383614e01565b11156136f7576003546136f49083614dee565b90505b6000825b828110156139b1576000818152600c602052604090206003810154610100900460ff16158061374a57506000828152602080805260408083206001600160a01b038a16845290915290205460ff165b1561375557506139a9565b6000828152600d602090815260408083206001600160a01b038a1684528252808320600385015460ff16845290915290205480156139a65760038201546000906301000000900460ff1615613809576000848152600e602090815260408083206001600160a01b038c1684528252808320600387015460ff168452909152902054600484015481118015906137f657506137ef8382614dee565b8460040154105b1561380357836007015491505b5061382f565b670de0b6b3a76400008360060154836138229190614e43565b61382c9190614d9b565b90505b801561383f5761383f8882613f46565b6000670de0b6b3a764000084600501548461385a9190614e43565b6138649190614d9b565b61386e9084614dee565b6001600160a01b038a1660009081526022602052604081208054929350839290919061389b908490614dee565b90915550506000858152602080805260408083206001600160a01b038d16808552908352818420805460ff19166001179055888452600f8352818420908452909152902054801561395e576000868152600f602090815260408083206001600160a01b038e1684529091528120556139138188614dee565b6040805188815260208101869052908101849052606081018390529097506001600160a01b038b16903390600080516020614f3e8339815191529060800160405180910390a36139a2565b6040805187815260208101859052908101839052600060608201526001600160a01b038b16903390600080516020614f3e8339815191529060800160405180910390a35b5050505b50505b6001016136fb565b5081156139dd576139c3600183614e01565b6001600160a01b0385166000908152602160205260409020555b8015613a1257604051339082156108fc029083906000818181858888f19350505050158015613a10573d6000803e3d6000fd5b505b5050506126d360018055565b613a26613a71565b603c831015613a635760405162461bcd60e51b8152602060048201526009602482015268151bdbc81cda1bdc9d60ba1b604482015260640161122e565b601292909255601455601355565b6000546001600160a01b0316331461131b5760405163118cdaa760e01b815233600482015260240161122e565b600260015403613ac157604051633ee5aeb560e01b815260040160405180910390fd5b6002600155565b600082815260186020526040812054815b81811015613b5d576000858152600d6020908152604080832060189092528220805483919085908110613b0e57613b0e614e14565b60009182526020808320909101546001600160a01b03168352828101939093526040918201812060ff891682529092529020541115613b555782613b5181614e2a565b9350505b600101613ad9565b505092915050565b6000848152600c602052604081206005810154829190670de0b6b3a764000090613b8f9086614e43565b613b999190614d9b565b613ba39085614dee565b60038201549093506301000000900460ff1615613c1b576000878152600e602090815260408083206001600160a01b038a168452825280832060ff8916845290915290205460048201548111801590613c085750613c018582614dee565b8260040154105b15613c1557816007015492505b50613c41565b670de0b6b3a7640000816006015485613c349190614e43565b613c3e9190614d9b565b91505b5094509492505050565b6001600160a01b0381166000908152601e6020526040902054601a541115613d02576001600160a01b0381166000908152601e6020526040812054601a54613c939190614e01565b6001600160a01b0383166000908152601d6020526040812054919250670de0b6b3a7640000613cc28385614e43565b613ccc9190614d9b565b6001600160a01b0385166000908152601f6020526040812080549293508392909190613cf9908490614dee565b90915550505050505b601a546001600160a01b039091166000908152601e6020526040902055565b67ffffffffffffffff8316600090815260116020526040902054600b5460ff168015613d4e575060085481145b613d8d5760405162461bcd60e51b815260206004820152601060248201526f496e76616c69642073657175656e636560801b604482015260640161122e565b60405182908190600090613db1908390600190602001918252602082015260400190565b60408051601f19818403018152828252805160209182012081840187905260028484015282518085038401815260609094019092528251920191909120909150613dfc8383836140a2565b50506010805467ffffffffffffffff19169055505050505050565b602354600090613e2990600190614e01565b9050600060238381548110613e4057613e40614e14565b60009182526020808320604080518082018252600290940290910180546001600160a01b03168085526001909101548484019081529085526024835281852090518552909152909120805460ff191690559050828214613f075760238281548110613ead57613ead614e14565b906000526020600020906002020160238481548110613ece57613ece614e14565b60009182526020909120825460029092020180546001600160a01b0319166001600160a01b039092169190911781556001918201549101555b6023805480613f1857613f18614f27565b60008281526020812060026000199093019283020180546001600160a01b0319168155600101559055505050565b613f4f82613c4b565b6001600160a01b0382166000908152601d602052604081208054839290613f77908490614dee565b925050819055508060196000828254613f909190614dee565b90915550505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60198360ff161061402c5760405162461bcd60e51b815260206004820152600d60248201526c496e76616c696420426c6f636b60981b604482015260640161122e565b6000818152600f602090815260408083206001600160a01b0388168452909152902054829015801561408e576002546140659085614e01565b6002546000858152600f602090815260408083206001600160a01b038c16845290915290205591505b61409a8686848661444f565b505050505050565b6008546000908152600c602052604090206140be601985614ef6565b60038201805460ff191660ff929092169190911790556140e4610271602086901c614ef6565b60038201805462ff000019811692156201000002928317909155600091600984019160ff9081169116176019811061411e5761411e614e14565b0154600183018190556002830154909150600061413b8383614e01565b808555905060008390036141b1576000612710614159606485614e43565b6141639190614d9b565b905080600660008282546141779190614dee565b9091555061418790508184614e01565b600760008282546141989190614dee565b9091555050600060058601819055600686015550614363565b60006127106141c1606484614e43565b6141cb9190614d9b565b905060006127106141de6103e885614e43565b6141e89190614d9b565b905060006141f68284614dee565b9050826006600082825461420a9190614dee565b9250508190555081600760008282546142239190614dee565b90915550600090506142358286614e01565b90508661424a82670de0b6b3a7640000614e43565b6142549190614d9b565b60058901556000614263612800565b9050600061426f6110de565b60038b015490915062010000900460ff1661429c5780600960008282546142969190614dee565b90915550505b60038a015460009062010000900460ff16156142cc57826009546142c09190614dee565b600060095590506142cf565b50815b80601c60008282546142e19190614dee565b909155506142f2905060028e614ef6565b6000036143295760038b01805463ff0000001916630100000017905560078b0181905561431f8a8d614ef6565b60048c015561435b565b60038b01805463ff000000191690558961434b82670de0b6b3a7640000614e43565b6143559190614d9b565b60068c01555b505050505050505b60038401805461010061ff00198216179182905542600880880191909155546040805191825260ff92831660208301526301000000840483161515908201526201000090920416151560608201527f73b6989256872bd8853751760a7960291ec2e04e1d8191bd624381f27fca9f8e9060800160405180910390a1600880549060006143ee83614e2a565b90915550506013546144009042614dee565b600a819055600b805460ff19169055600854604051918252907f278844837bcf8364a705384bf3a2812901f54155bae86dea81dd52aa5b9ec0e39060200160405180910390a250505050505050565b6000818152600c6020526040812060090160ff85166019811061447457614474614e14565b01546000838152600d602090815260408083206001600160a01b038a168452825280832060ff89168452909152812054919250036144dd576000828152600e602090815260408083206001600160a01b0389168452825280832060ff8816845290915290208190555b6000828152600d602090815260408083206001600160a01b0389168452825280832060ff881684529091528120805485929061451a908490614dee565b90915550506000828152600c60205260409020839060090160ff86166019811061454657614546614e14565b0160008282546145569190614dee565b90915550506000828152600c60205260408120600201805485929061457c908490614dee565b9091555050600082815260176020908152604080832060ff80891685529083528184206001600160a01b038a168552909252909120541661462557600082815260176020908152604080832060ff88168085529083528184206001600160a01b038a1685528352818420805460ff19166001179055858452600c909252909120602201906019811061461057614610614e14565b01805490600061461f83614e2a565b91905055505b60008281526016602090815260408083206001600160a01b038916845290915290205460ff166147a25760008281526016602090815260408083206001600160a01b03891684528252808320805460ff191660011790558483526015909152812080549161469283614e2a565b9091555050600082815260186020908152604080832080546001810182559084528284200180546001600160a01b0319166001600160a01b038a1690811790915583526024825280832085845290915290205460ff166147a2576001600160a01b03858116600081815260246020908152604080832087845282528083208054600160ff1990911681179091558151808301909252938152908101868152602380549485018155909252517fd57b2b5166478fd4318d2acc6cc2c704584312bdd8781b32d5d06abda57f4230600290930292830180546001600160a01b031916919094161790925590517fd57b2b5166478fd4318d2acc6cc2c704584312bdd8781b32d5d06abda57f4231909101555b6040805183815260ff861660208201529081018490526001600160a01b038616907f60c16227b368ec1b75014bc56837d084cbaf0b6989beb0cced9d343d9b5a94679060600160405180910390a25050505050565b6040518061032001604052806019906020820280368337509192915050565b60006020828403121561482857600080fd5b5035919050565b8151815260208083015161014083019161484d9084018260ff169052565b506040830151614861604084018215159052565b506060830151614875606084018215159052565b506080830151614889608084018215159052565b5060a083015160a083015260c083015160c083015260e083015160e083015261010083015161010083015261012083015161012083015292915050565b80356001600160a01b03811681146148dd57600080fd5b919050565b6000602082840312156148f457600080fd5b611991826148c6565b60008060006060848603121561491257600080fd5b505081359360208301359350604090920135919050565b6020808252825160c083830152805160e08401819052600092919091019082906101008501905b8083101561499c57835160018060a01b03815116835260208101516020840152604081015160408401526060810151606084015250608082019150602084019350600183019250614950565b5060208601516040860152604086015192506149bd606086018460ff169052565b606086015180151560808701529250608086015180151560a0870152925060a086015160c086015280935050505092915050565b67ffffffffffffffff811681146126d357600080fd5b600080600060608486031215614a1c57600080fd5b8335614a27816149f1565b9250614a35602085016148c6565b9150604084013590509250925092565b60008083601f840112614a5757600080fd5b50813567ffffffffffffffff811115614a6f57600080fd5b6020830191508360208260051b850101111561242757600080fd5b60008060208385031215614a9d57600080fd5b823567ffffffffffffffff811115614ab457600080fd5b614ac085828601614a45565b90969095509350505050565b6103208101818360005b6019811015614af5578151835260209283019290910190600101614ad6565b50505092915050565b600060208284031215614b1057600080fd5b8135611991816149f1565b60008060408385031215614b2e57600080fd5b50508035926020909101359150565b6040808252835190820181905260009060208501906060840190835b81811015614b8c57835180516001600160a01b031684526020908101518185015290930192604090920191600101614b59565b5050602093909301939093525092915050565b600060208284031215614bb157600080fd5b813563ffffffff8116811461199157600080fd5b6040808252835190820181905260009060208501906060840190835b81811015614b8c5783516001600160a01b0316835260209384019390920191600101614be1565b803560ff811681146148dd57600080fd5b600080600060608486031215614c2e57600080fd5b83359250614c3e602085016148c6565b9150614c4c60408501614c08565b90509250925092565b60008060408385031215614c6857600080fd5b82359150614c78602084016148c6565b90509250929050565b600080600060408486031215614c9657600080fd5b614c9f846148c6565b9250602084013567ffffffffffffffff811115614cbb57600080fd5b614cc786828701614a45565b9497909650939450505050565b60008060408385031215614ce757600080fd5b614cf0836148c6565b946020939093013593505050565b600080600060608486031215614d1357600080fd5b83359250614d2360208501614c08565b9150614c4c604085016148c6565b600060208284031215614d4357600080fd5b61199182614c08565b60008060408385031215614d5f57600080fd5b82359150614c7860208401614c08565b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600082614daa57614daa614d6f565b500490565b600060208284031215614dc157600080fd5b81516001600160801b038116811461199157600080fd5b634e487b7160e01b600052604160045260246000fd5b8082018082111561332457613324614d85565b8181038181111561332457613324614d85565b634e487b7160e01b600052603260045260246000fd5b600060018201614e3c57614e3c614d85565b5060010190565b808202811582820484141761332457613324614d85565b600060208284031215614e6c57600080fd5b8151801515811461199157600080fd5b600081614e8b57614e8b614d85565b506000190190565b60208082526024908201527f526f756e64206e6f742073746172746564207965742028696e7465726d697373604082015263696f6e2960e01b606082015260800190565b600060ff821660ff8103614eed57614eed614d85565b60010192915050565b600082614f0557614f05614d6f565b500690565b600060208284031215614f1c57600080fd5b8151611991816149f1565b634e487b7160e01b600052603160045260246000fdfe07f32f6f4c1b7fe2a67cebec7f6546a6324a14e661023fa65d8dd4e6605183a2a264697066735822122084fd1ca0ad41a672fa65085d0cb27f203b2f08017c9fac58f993355b2f5e4d7764736f6c634300081c0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000d458261e832415cfd3bae5e416fdf3230ce6f1340000000000000000000000000b4de26631b54b0aa272d0e9b1e46fb723db4a1100000000000000000000000099662e7cc1970de202e97d5b2b70215d5370b1f400000000000000000000000099662e7cc1970de202e97d5b2b70215d5370b1f4
-----Decoded View---------------
Arg [0] : _entropy (address): 0xD458261E832415CFd3BAE5E416FdF3230ce6F134
Arg [1] : _token (address): 0x0b4DE26631B54b0AA272D0e9b1e46fB723dB4a11
Arg [2] : _protocolVault (address): 0x99662E7CC1970DE202e97D5B2b70215D5370B1f4
Arg [3] : _adminWallet (address): 0x99662E7CC1970DE202e97D5B2b70215D5370B1f4
-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 000000000000000000000000d458261e832415cfd3bae5e416fdf3230ce6f134
Arg [1] : 0000000000000000000000000b4de26631b54b0aa272d0e9b1e46fb723db4a11
Arg [2] : 00000000000000000000000099662e7cc1970de202e97d5b2b70215d5370b1f4
Arg [3] : 00000000000000000000000099662e7cc1970de202e97d5b2b70215d5370b1f4
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$7.56
Net Worth in MON
Token Allocations
MON
100.00%
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|---|---|---|---|---|
| MONAD | 100.00% | $0.018921 | 399.6 | $7.56 |
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.