Overview
ETH Balance
ETH Value
$0.00Latest 25 from a total of 38 transactions
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Set Placeholder | 401996679 | 74 days ago | IN | 0 ETH | 0.00000075 | ||||
| Settle Game | 401995783 | 74 days ago | IN | 0 ETH | 0.00001917 | ||||
| Show Chapters | 401993836 | 74 days ago | IN | 0 ETH | 0.00000166 | ||||
| Set State | 401993616 | 74 days ago | IN | 0 ETH | 0.0000012 | ||||
| Set Credits Cont... | 401993570 | 74 days ago | IN | 0 ETH | 0.00000072 | ||||
| Set Auditor Cont... | 401993568 | 74 days ago | IN | 0 ETH | 0.00000073 | ||||
| Set Max Extract | 401993565 | 74 days ago | IN | 0 ETH | 0.00000079 | ||||
| Set Credits Cont... | 401993476 | 74 days ago | IN | 0 ETH | 0.0000008 | ||||
| Set Auditor Cont... | 401993474 | 74 days ago | IN | 0 ETH | 0.00000079 | ||||
| Set Max Extract | 401993472 | 74 days ago | IN | 0 ETH | 0.00000085 | ||||
| Buy In | 401993361 | 74 days ago | IN | 0.00001 ETH | 0.00000223 | ||||
| Set Credits Cont... | 401993281 | 74 days ago | IN | 0 ETH | 0.00000079 | ||||
| Set Auditor Cont... | 401993279 | 74 days ago | IN | 0 ETH | 0.0000008 | ||||
| Set Max Extract | 401993277 | 74 days ago | IN | 0 ETH | 0.00000086 | ||||
| Buy In | 401993268 | 74 days ago | IN | 0.00001 ETH | 0.0000022 | ||||
| Set Credits Cont... | 401993222 | 74 days ago | IN | 0 ETH | 0.0000008 | ||||
| Set Auditor Cont... | 401993216 | 74 days ago | IN | 0 ETH | 0.00000078 | ||||
| Set Max Extract | 401993210 | 74 days ago | IN | 0 ETH | 0.00000083 | ||||
| Buy In | 401993171 | 74 days ago | IN | 0.00001 ETH | 0.00000196 | ||||
| Buy In | 401993068 | 74 days ago | IN | 0.00001 ETH | 0.000001 | ||||
| Buy In | 401992740 | 74 days ago | IN | 0.00001 ETH | 0.00000079 | ||||
| Buy In | 401992593 | 74 days ago | IN | 0.00001 ETH | 0.00000079 | ||||
| Buy In | 401992222 | 74 days ago | IN | 0.00001 ETH | 0.00000079 | ||||
| Buy In | 401992129 | 74 days ago | IN | 0.00001 ETH | 0.00000081 | ||||
| Buy In | 401992033 | 74 days ago | IN | 0.00001 ETH | 0.00000079 |
Latest 25 internal transactions (View All)
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 401995783 | 74 days ago | 0.00001 ETH | ||||
| 401995783 | 74 days ago | 0.00001 ETH | ||||
| 401995783 | 74 days ago | 0.00001 ETH | ||||
| 401995783 | 74 days ago | 0.00001 ETH | ||||
| 401995783 | 74 days ago | 0.00001 ETH | ||||
| 401995783 | 74 days ago | 0.00001 ETH | ||||
| 401995783 | 74 days ago | 0.00001 ETH | ||||
| 401995783 | 74 days ago | 0.00001 ETH | ||||
| 401995783 | 74 days ago | 0.00001 ETH | ||||
| 401995783 | 74 days ago | 0.00001 ETH | ||||
| 401995783 | 74 days ago | 0.00001 ETH | ||||
| 401995783 | 74 days ago | 0.00001 ETH | ||||
| 401995783 | 74 days ago | 0.00001 ETH | ||||
| 401988519 | 74 days ago | 0.00001 ETH | ||||
| 401988516 | 74 days ago | 0.00001 ETH | ||||
| 401988516 | 74 days ago | 0.00001 ETH | ||||
| 401988516 | 74 days ago | 0.00001 ETH | ||||
| 401988516 | 74 days ago | 0.00001 ETH | ||||
| 401988516 | 74 days ago | 0.00001 ETH | ||||
| 401988516 | 74 days ago | 0.00001 ETH | ||||
| 401988516 | 74 days ago | 0.00001 ETH | ||||
| 401988516 | 74 days ago | 0.00001 ETH | ||||
| 401988516 | 74 days ago | 0.00001 ETH | ||||
| 401988516 | 74 days ago | 0.00001 ETH | ||||
| 401988516 | 74 days ago | 0.00001 ETH |
Cross-Chain Transactions
Contract Source Code (Solidity Standard Json-Input format)
//SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;
/*
'##::::'##::::'###::::'##::::'##::::'########:'##::::'##:'########:'########:::::'###:::::'######::'########:
###::'###:::'## ##:::. ##::'##::::: ##.....::. ##::'##::... ##..:: ##.... ##:::'## ##:::'##... ##:... ##..::
####'####::'##:. ##:::. ##'##:::::: ##::::::::. ##'##:::::: ##:::: ##:::: ##::'##:. ##:: ##:::..::::: ##::::
## ### ##:'##:::. ##:::. ###::::::: ######:::::. ###::::::: ##:::: ########::'##:::. ##: ##:::::::::: ##::::
##. #: ##: #########::: ## ##:::::: ##...:::::: ## ##:::::: ##:::: ##.. ##::: #########: ##:::::::::: ##::::
##:.:: ##: ##.... ##:: ##:. ##::::: ##:::::::: ##:. ##::::: ##:::: ##::. ##:: ##.... ##: ##::: ##:::: ##::::
##:::: ##: ##:::: ##: ##:::. ##:::: ########: ##:::. ##:::: ##:::: ##:::. ##: ##:::: ##:. ######::::: ##::::
..:::::..::..:::::..::..:::::..:::::........::..:::::..:::::..:::::..:::::..::..:::::..:::......::::::..:::::
.................................
..####....####...##...##..######.
.##......##..##..###.###..##.....
.##.###..######..##.#.##..####...
.##..##..##..##..##...##..##.....
..####...##..##..##...##..######.
................................. */
import "./Universe.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
// WETH interface for safe ETH transfers
interface IWETH {
function deposit() external payable;
function transfer(address to, uint256 value) external returns (bool);
function balanceOf(address) external view returns (uint256);
}
// MaxExtract interface for credential verification
interface IMaxExtract {
function getActiveSectors() external view returns (uint256[] memory);
function sectors(uint256 sectorId) external view returns (address);
function sectorToOwner(uint256 sectorId) external view returns (address);
function playerToSector(address player) external view returns (uint256);
function getStakedBalance(address pilot) external view returns (uint256);
}
/**
* Game Contract - Manages game sessions and player participation
* Controls visible chapters, game state, and player buy-ins
* @author Max Extract Protocol
*/
contract Game {
// Game configuration - hardcoded values
uint256 public constant BUY_IN_PRICE = 0.00001 ether;
uint256 public immutable gameEndTime = block.timestamp + 75 minutes;
// WETH contract address (Ethereum mainnet - update for other networks)
address public constant WETH_ADDRESS = 0x82aF49447D8a07e3bd95BD0d56f35241523fBab1;
// Reference to the Universe contract
Universe public immutable universe;
// Reference to the MaxExtract contract for credential verification
IMaxExtract public maxExtract;
// Reference to the Auditor contract
address public auditorContract;
// Reference to the MaxExtract contract address for authorization checks
address public maxExtractContract;
// Reference to the Credits ERC20 token contract
IERC20 public creditsContract;
// Maintenance mode placeholder message
string public placeholder;
// Game states
enum GameState {
Open, // 0 - Players can buy in
Active, // 1 - Game is active, no more buy-ins allowed
Settled // 2 - Game has been settled, winners determined
}
// Game state variables
GameState public state;
uint8[] public visibleChapters;
address[] public players;
address[] public pilots;
// Game end and settlement variables
address[] public gameWinners; // Array of winner addresses after settlement
uint256 public winningScore; // The winning score after settlement
// Player tracking
mapping(address => bool) public isPlayerMapping;
// Pilot tracking (use isPilot() function to exclude dead pilots)
mapping(address => bool) public isPilotMapping;
// Player scores mapping
mapping(address => uint256) public scores;
// Pilot death tracking
mapping(address => bool) public deadPilots;
// Track which pilots have minted credentials from which players (one per pilot per player)
mapping(address => mapping(address => bool)) public pilotPlayerCredentialMinted;
// Track the base type for each sector (1-6, where 1 is default/starter)
// Base types represent different station tiers/visuals
mapping(uint256 => uint8) public sectorBaseType;
// Events
event ChaptersUpdated(uint8[] newVisibleChapters);
event GameStateChanged(GameState newState);
event PlayerBoughtIn(address indexed player, uint256 amount);
event PotPaidOut(address[] recipients, uint256[] percentages, uint256 totalAmount);
event PilotAdded(address indexed pilot);
event PilotsAdded(address[] pilots);
event TipGiven(address indexed pilot, address indexed player, uint256 amount);
event PilotDied(address indexed pilot, address indexed killer, address indexed playerPenalized, uint256 scorePenalty, uint256 ethForwarded);
event GameSettled(address[] winners, uint256 winningScore, uint256 totalPayout, uint256 payoutPerWinner);
event CredentialMinted(address indexed pilot, address indexed player, address indexed credentialContract);
event PointsDeducted(address indexed player, uint256 amount, uint256 newScore);
event StationUpgraded(uint256 indexed sectorId, address indexed player, address indexed pilotCaller, uint8 newBaseType);
event StationBaseTypeSet(uint256 indexed sectorId, uint8 newBaseType, address indexed setBy);
event PlaceholderUpdated(string newPlaceholder);
// Errors
error OnlyGod();
error OnlyPilot();
error GameNotOpen();
error InsufficientPayment();
error PlayerAlreadyJoined();
error PilotAlreadyAdded();
error InvalidArrayLengths();
error InvalidPercentages();
error PayoutFailed();
error PilotAlreadyDead();
error NotAPlayer();
error GameNotEnded();
error GameAlreadySettled();
error NotACredential();
error CredentialNotRegistered();
error MaxExtractNotSet();
error PilotAlreadyMintedFromPlayer();
error OnlyAuditor();
error InsufficientPoints();
error NotARegistry();
error InsufficientCreditsForUpgrade();
error NotAFuelContract();
error StationMaxLevel();
error InvalidBaseType();
error OnlyMaxExtract();
modifier onlyGod() {
if (msg.sender != universe.GOD()) revert OnlyGod();
_;
}
modifier onlyPilot() {
if (!isPilot(msg.sender)) revert OnlyPilot();
_;
}
modifier gameOpen() {
if (state != GameState.Open) revert GameNotOpen();
_;
}
/**
* Get a module address from a registry contract
* @param registryAddress The registry contract address
* @param moduleName The name of the module to look up
* @return moduleAddress The address of the module, or address(0) if not found
*/
function _getModule(
address registryAddress,
string memory moduleName
) private view returns (address moduleAddress) {
(bool success, bytes memory data) = registryAddress.staticcall(
abi.encodeWithSignature("modules(string)", moduleName)
);
if (!success || data.length < 32) {
return address(0);
}
moduleAddress = abi.decode(data, (address));
}
constructor(address _universe) {
universe = Universe(_universe);
state = GameState.Open;
}
/**
* Set which chapters are visible to players
* Only callable by the God address
* @param _chapters Array of chapter numbers to make visible
*/
function showChapters(uint8[] calldata _chapters) external onlyGod {
visibleChapters = _chapters;
emit ChaptersUpdated(_chapters);
}
/**
* Change the game state
* Only callable by the God address
* @param _newState The new game state
*/
function setState(GameState _newState) external onlyGod {
state = _newState;
emit GameStateChanged(_newState);
}
/**
* Add a pilot address
* Only callable by the God address
* @param _pilot Address to add as a pilot
*/
function addPilot(address _pilot) external onlyGod {
// Check if pilot is already added
if (isPilot(_pilot)) revert PilotAlreadyAdded();
pilots.push(_pilot);
isPilotMapping[_pilot] = true; // Add to mapping for O(1) lookups
emit PilotAdded(_pilot);
}
/**
* Add multiple pilot addresses in batch and fund them with ETH
* Only callable by the God address
* @param _pilots Array of addresses to add as pilots
*/
function addPilots(address[] calldata _pilots) external payable onlyGod {
require(_pilots.length > 0, "No pilots provided");
uint256 newPilotsCount = 0;
// First pass: count new pilots and add them
for (uint256 i = 0; i < _pilots.length; i++) {
if (!isPilot(_pilots[i])) {
pilots.push(_pilots[i]);
isPilotMapping[_pilots[i]] = true;
newPilotsCount++;
}
}
// If ETH was sent and we have new pilots, distribute it equally
if (msg.value > 0 && newPilotsCount > 0) {
uint256 ethPerPilot = msg.value / newPilotsCount;
uint256 remainder = msg.value % newPilotsCount;
// Second pass: fund the new pilots
for (uint256 i = 0; i < _pilots.length; i++) {
// Check if this pilot was just added (appears exactly once in pilots array)
bool wasJustAdded = false;
uint256 pilotCount = 0;
for (uint256 j = 0; j < pilots.length; j++) {
if (pilots[j] == _pilots[i]) {
pilotCount++;
if (pilotCount == 1) {
wasJustAdded = true;
} else {
wasJustAdded = false;
break;
}
}
}
if (wasJustAdded && ethPerPilot > 0) {
uint256 amountToSend = ethPerPilot;
if (remainder > 0) {
amountToSend += remainder;
remainder = 0;
}
(bool success, ) = payable(_pilots[i]).call{value: amountToSend}("");
require(success, "ETH transfer failed");
}
}
}
emit PilotsAdded(_pilots);
}
/**
* Fund existing pilots with ETH in batch - smart top-up system
* Only callable by the God address
* Checks each pilot's balance and only sends enough to reach the minimum
* Refunds any unused ETH back to GOD
* @param _pilots Array of pilot addresses to fund
* @param minBalancePerPilot Minimum balance each pilot should have
*/
function fundPilots(address[] calldata _pilots, uint256 minBalancePerPilot) external payable onlyGod {
require(_pilots.length > 0, "No pilots provided");
require(minBalancePerPilot > 0, "Invalid minimum balance");
uint256 totalSent = 0;
// Loop through each pilot and top up if needed
for (uint256 i = 0; i < _pilots.length; i++) {
uint256 currentBalance = _pilots[i].balance;
// Only send if below minimum
if (currentBalance < minBalancePerPilot) {
uint256 amountNeeded = minBalancePerPilot - currentBalance;
(bool success, ) = payable(_pilots[i]).call{value: amountNeeded}("");
require(success, "ETH transfer failed");
totalSent += amountNeeded;
}
}
// Refund any unused ETH back to GOD
uint256 remaining = msg.value - totalSent;
if (remaining > 0) {
(bool refundSuccess, ) = payable(msg.sender).call{value: remaining}("");
require(refundSuccess, "Refund failed");
}
}
/**
* Buy into the game by paying the buy-in price
* Only available when game state is Open
* Players can only buy in once
*/
function buyIn() external payable gameOpen {
if (msg.value < BUY_IN_PRICE) revert InsufficientPayment();
// Check if player has already joined
if (isPlayerMapping[msg.sender]) revert PlayerAlreadyJoined();
players.push(msg.sender);
isPlayerMapping[msg.sender] = true;
// Players start with 0 points
scores[msg.sender] = 0;
emit PlayerBoughtIn(msg.sender, msg.value);
// Refund excess payment
if (msg.value > BUY_IN_PRICE) {
payable(msg.sender).transfer(msg.value - BUY_IN_PRICE);
}
}
/**
* Get all visible chapters
* @return Array of visible chapter numbers
*/
function getVisibleChapters() external view returns (uint8[] memory) {
return visibleChapters;
}
/**
* Get all players who have bought in
* @return Array of player addresses
*/
function getPlayers() external view returns (address[] memory) {
return players;
}
/**
* Get the number of players who have bought in
* @return Number of players
*/
function getPlayerCount() external view returns (uint256) {
return players.length;
}
/**
* Check if a specific address is a player
* @param _player Address to check
* @return True if the address is a player
*/
function isPlayer(address _player) external view returns (bool) {
return isPlayerMapping[_player];
}
/**
* Check if a specific address is a pilot (excludes dead pilots)
* @param _pilot Address to check
* @return True if the address is a pilot and not dead
*/
function isPilot(address _pilot) public view returns (bool) {
if (deadPilots[_pilot]) {
return false;
}
return isPilotMapping[_pilot];
}
/**
* Check if a pilot is dead
* @param _pilot Address to check
* @return True if the pilot is dead
*/
function isPilotDead(address _pilot) external view returns (bool) {
return deadPilots[_pilot];
}
/**
* Get all pilots
* @return Array of pilot addresses
*/
function getPilots() external view returns (address[] memory) {
return pilots;
}
/**
* Get the number of pilots
* @return Number of pilots
*/
function getPilotCount() external view returns (uint256) {
return pilots.length;
}
/**
* Get all pilots with their ETH balances and death status
* @return pilotAddresses Array of pilot addresses
* @return ethBalances Array of ETH balances (in wei)
* @return isDead Array of death status for each pilot
*/
function getAllPilotsAndBalances() external view returns (
address[] memory pilotAddresses,
uint256[] memory ethBalances,
bool[] memory isDead
) {
uint256 pilotCount = pilots.length;
pilotAddresses = new address[](pilotCount);
ethBalances = new uint256[](pilotCount);
isDead = new bool[](pilotCount);
for (uint256 i = 0; i < pilotCount; i++) {
address pilot = pilots[i];
pilotAddresses[i] = pilot;
ethBalances[i] = pilot.balance;
isDead[i] = deadPilots[pilot];
}
return (pilotAddresses, ethBalances, isDead);
}
/**
* Dead man's switch - called when a pilot is killed
* Marks the pilot as dead and penalizes the player with 10 points
* Only callable by pilots
* @param _killer Address of the pilot who killed this pilot
* @param _playerToPenalize Address of the player to penalize (sector owner)
*/
function deadMansSwitch(address _killer, address _playerToPenalize) external {
// Use isPilotMapping directly to allow edge case calls
if (!isPilotMapping[msg.sender]) revert OnlyPilot();
// Check if pilot is already dead
if (deadPilots[msg.sender]) revert PilotAlreadyDead();
// Check if the player to penalize is actually a player
if (!isPlayerMapping[_playerToPenalize]) revert NotAPlayer();
// Mark pilot as dead
deadPilots[msg.sender] = true;
// Apply 10-point penalty to player
uint256 currentScore = scores[_playerToPenalize];
uint256 penalty = currentScore >= 10 ? 10 : currentScore;
scores[_playerToPenalize] = currentScore - penalty;
emit PilotDied(msg.sender, _killer, _playerToPenalize, penalty, 0);
}
/**
* Dead man's slash - called when a pilot is killed and player has audited stake module
* Marks the pilot as dead and slashes the killer via stake contract
* Only callable by pilots
* @param _killer Address of the pilot who killed this pilot
* @param _playerToPenalize Address of the player (sector owner) - used to find stake contract
*/
function deadMansSlash(address _killer, address _playerToPenalize) external {
// Use isPilotMapping directly to allow edge case calls
if (!isPilotMapping[msg.sender]) revert OnlyPilot();
// Check if pilot is already dead
if (deadPilots[msg.sender]) revert PilotAlreadyDead();
// Check if the player to penalize is actually a player
if (!isPlayerMapping[_playerToPenalize]) revert NotAPlayer();
// Mark pilot as dead
deadPilots[msg.sender] = true;
// Get player's sector
uint256 sectorId = maxExtract.playerToSector(_playerToPenalize);
require(sectorId != 0, "Player has no sector");
// Get registry
address registry = maxExtract.sectors(sectorId);
require(registry != address(0), "No registry");
// Get stake module
address stakeContract = _getModule(registry, "stake");
require(stakeContract != address(0), "No stake module");
// Verify audited for chapter 4
require(auditorContract != address(0), "Auditor not set");
(bool success, bytes memory data) = auditorContract.staticcall(
abi.encodeWithSignature("isAudited(address)", stakeContract)
);
require(success && data.length >= 32, "Audit check failed");
uint8 auditStatus = abi.decode(data, (uint8));
require(auditStatus == 4, "Not audited for chapter 4");
// Get killer's staked balance BEFORE slash
uint256 balanceBefore = maxExtract.getStakedBalance(_killer);
require(balanceBefore >= 10_000 * 10**18, "Killer has insufficient stake");
// Call slash on stake contract
(bool slashSuccess, ) = stakeContract.call(
abi.encodeWithSignature("slash(address)", _killer)
);
require(slashSuccess, "Slash call failed");
// VERIFY the slash actually burned the stake
uint256 balanceAfter = maxExtract.getStakedBalance(_killer);
require(balanceAfter == 0, "Slash did not burn stake - malicious stake contract");
require(balanceBefore - balanceAfter >= 10_000 * 10**18, "Slash did not burn full stake amount");
// Emit PilotDied with 0 penalty (slashing verified successful)
emit PilotDied(msg.sender, _killer, _playerToPenalize, 0, 0);
}
/**
* Tip a player with a score increase
* Only callable by pilots
* @param _player Address of the player to tip
* @param _tipAmount Amount to add to the player's score
*/
function tipPlayer(address _player, uint256 _tipAmount) external onlyPilot {
scores[_player] += _tipAmount;
emit TipGiven(msg.sender, _player, _tipAmount);
}
/**
* Get a player's current score
* @param _player Address of the player
* @return The player's current score
*/
function getPlayerScore(address _player) external view returns (uint256) {
return scores[_player];
}
/**
* Get the current game state information
* @return _state Current game state
* @return _playerCount Number of players
* @return _buyInPrice Current buy-in price
*/
function getGameInfo() external view returns (
GameState _state,
uint256 _playerCount,
uint256 _buyInPrice
) {
return (state, players.length, BUY_IN_PRICE);
}
/**
* Pay out the pot to multiple recipients with specified percentages
* Only callable by the God address
* @param recipients Array of addresses to receive payouts
* @param percentages Array of percentages (in basis points, e.g., 333 = 3.33%)
*/
function payoutPot(address[] calldata recipients, uint256[] calldata percentages) external onlyGod {
// Validate input arrays
if (recipients.length == 0 || recipients.length != percentages.length) {
revert InvalidArrayLengths();
}
// Validate percentages sum to 1000 (100.0%)
uint256 totalPercentage = 0;
for (uint256 i = 0; i < percentages.length; i++) {
totalPercentage += percentages[i];
}
if (totalPercentage != 1000) {
revert InvalidPercentages();
}
uint256 totalBalance = address(this).balance;
if (totalBalance == 0) return; // Nothing to pay out
// Pay out to each recipient
for (uint256 i = 0; i < recipients.length; i++) {
if (recipients[i] == address(0)) continue; // Skip zero addresses
uint256 amount = (totalBalance * percentages[i]) / 1000;
if (amount > 0) {
(bool success, ) = payable(recipients[i]).call{value: amount}("");
if (!success) revert PayoutFailed();
}
}
emit PotPaidOut(recipients, percentages, totalBalance);
}
/**
* Withdraw remaining contract balance to God address
* Only callable by the God address
*/
function withdraw() external onlyGod {
payable(universe.GOD()).transfer(address(this).balance);
}
/**
* Get contract balance
* @return Contract balance in wei
*/
function getBalance() external view returns (uint256) {
return address(this).balance;
}
/**
* Settle the game by finding the highest scoring player(s) and paying out the pot
* Can be called by anyone after the game end time has passed
* Splits the pot equally among all players with the highest score
*/
function settleGame() external {
// Check if game has ended
if (block.timestamp < gameEndTime) revert GameNotEnded();
// Check if game has already been settled
if (state == GameState.Settled) revert GameAlreadySettled();
// If no players, nothing to settle
if (players.length == 0) {
state = GameState.Settled;
return;
}
// Find the highest score
uint256 highestScore = 0;
for (uint256 i = 0; i < players.length; i++) {
uint256 playerScore = scores[players[i]];
if (playerScore > highestScore) {
highestScore = playerScore;
}
}
// Find all players with the highest score
address[] memory winners = new address[](players.length);
uint256 winnerCount = 0;
for (uint256 i = 0; i < players.length; i++) {
if (scores[players[i]] == highestScore) {
winners[winnerCount] = players[i];
winnerCount++;
}
}
// Resize winners array to actual winner count
gameWinners = new address[](winnerCount);
for (uint256 i = 0; i < winnerCount; i++) {
gameWinners[i] = winners[i];
}
// Set winning score and mark as settled
winningScore = highestScore;
state = GameState.Settled;
// Calculate and distribute payout
uint256 totalPayout = address(this).balance;
uint256 payoutPerWinner = 0;
if (totalPayout > 0 && winnerCount > 0) {
payoutPerWinner = totalPayout / winnerCount;
// Pay each winner
for (uint256 i = 0; i < winnerCount; i++) {
(bool success, ) = payable(gameWinners[i]).call{value: payoutPerWinner}("");
if (!success) revert PayoutFailed();
}
}
emit GameSettled(gameWinners, winningScore, totalPayout, payoutPerWinner);
}
/**
* Get the game winners (only available after settlement)
* @return Array of winner addresses
*/
function getGameWinners() external view returns (address[] memory) {
return gameWinners;
}
/**
* Check if the game can be settled (time has passed and not already settled)
* @return True if current time is past game end time and game is not settled
*/
function canGameSettle() external view returns (bool) {
return block.timestamp >= gameEndTime && state != GameState.Settled;
}
/**
* Get time remaining until game ends
* @return Seconds remaining (0 if game has ended)
*/
function getTimeRemaining() external view returns (uint256) {
if (block.timestamp >= gameEndTime) {
return 0;
}
return gameEndTime - block.timestamp;
}
/**
* Set the MaxExtract contract address
* Only callable by the God address
* @param _maxExtract Address of the MaxExtract contract
*/
function setMaxExtract(address _maxExtract) external onlyGod {
require(_maxExtract != address(0), "Invalid address");
maxExtract = IMaxExtract(_maxExtract);
maxExtractContract = _maxExtract;
}
/**
* Check if a pilot has access to a specific sector
* Checks if the pilot owns a credential NFT from that sector's credential contract
* @param _pilot The pilot address to check
* @param _sectorId The sector ID to check access for
* @return True if the pilot has a credential (balance > 0)
*/
function canPilotAccessSector(address _pilot, uint256 _sectorId) external view returns (bool) {
if (address(maxExtract) == address(0)) return false;
// Get the registry for this sector
address registryAddress = maxExtract.sectors(_sectorId);
if (registryAddress == address(0)) return false;
// Get the credential contract from the registry
address credentialContract = _getModule(registryAddress, "credential");
if (credentialContract == address(0)) return false;
// Check the pilot's balance in the credential contract (ERC721 balanceOf)
(bool balanceSuccess, bytes memory balanceData) = credentialContract.staticcall(
abi.encodeWithSignature("balanceOf(address)", _pilot)
);
if (!balanceSuccess || balanceData.length < 32) return false;
uint256 balance = abi.decode(balanceData, (uint256));
return balance > 0;
}
/**
* Called by a credential contract when a pilot mints a credential
* Derives the player address from the sector owner
* Awards 2 points to the player if verification succeeds
* Only callable by registered credential contracts through pilot transactions
* Each pilot can only mint one credential per player (prevents point farming)
* @param _sectorId The sector ID that the credential belongs to
*/
function pilotMintSectorCredential(uint256 _sectorId) external {
if (address(maxExtract) == address(0)) revert MaxExtractNotSet();
// tx.origin must be a pilot
if (!isPilot(tx.origin)) revert OnlyPilot();
// Get the registry for this sector
address registryAddress = maxExtract.sectors(_sectorId);
if (registryAddress == address(0)) revert NotARegistry();
// Get the registered credential contract from the registry
address registeredCredential = _getModule(registryAddress, "credential");
if (registeredCredential == address(0)) revert CredentialNotRegistered();
// Verify that msg.sender (the credential contract) matches the registered credential
if (registeredCredential != msg.sender) revert CredentialNotRegistered();
// Get the player who owns this sector
address player = maxExtract.sectorToOwner(_sectorId);
if (player == address(0)) revert NotAPlayer();
// Check if this pilot has already minted a credential from this player
if (pilotPlayerCredentialMinted[tx.origin][player]) revert PilotAlreadyMintedFromPlayer();
// Mark that this pilot has minted from this player
pilotPlayerCredentialMinted[tx.origin][player] = true;
// All checks passed - award 2 points to the player
scores[player] += 2;
emit CredentialMinted(tx.origin, player, msg.sender);
}
/**
* Called by a fuel contract when a pilot triggers the station upgrade
* Verifies the fuel contract has 49,500 credits and transfers them to the game
* Awards 50 points to the player upon successful upgrade
* Only callable by registered fuel contracts through pilot transactions
* @param _sectorId The sector ID that is being upgraded
*/
function upgradeStation(uint256 _sectorId) external {
if (address(maxExtract) == address(0)) revert MaxExtractNotSet();
// tx.origin must be a pilot (the one calling upgrade on the fuel contract)
if (!isPilot(tx.origin)) revert OnlyPilot();
// Get the registry for this sector
address registryAddress = maxExtract.sectors(_sectorId);
if (registryAddress == address(0)) revert NotARegistry();
// Get the registered sale contract from the registry
address fuelContract = _getModule(registryAddress, "sale");
if (fuelContract == address(0)) revert NotAFuelContract();
// Verify that msg.sender (the sale contract) matches the registered sale contract
if (fuelContract != msg.sender) revert NotAFuelContract();
// Get the player who owns this sector
address player = maxExtract.sectorToOwner(_sectorId);
if (player == address(0)) revert NotAPlayer();
// Get current base type (defaults to 1 if never upgraded)
uint8 currentBaseType = sectorBaseType[_sectorId];
if (currentBaseType == 0) currentBaseType = 1; // First time, start at base1
// Check if station is already at max level
if (currentBaseType >= 6) revert StationMaxLevel();
// Verify the fuel contract has at least 49,500 credits
uint256 upgradeAmount = 49_500 * 10**18;
if (creditsContract.balanceOf(fuelContract) < upgradeAmount) {
revert InsufficientCreditsForUpgrade();
}
// Transfer 49,500 credits from fuel contract to Game contract (requires prior approval)
creditsContract.transferFrom(fuelContract, address(this), upgradeAmount);
// Award 10 points to the player for upgrading their station
scores[player] += 10;
// Upgrade station to next level
uint8 newBaseType = currentBaseType + 1;
sectorBaseType[_sectorId] = newBaseType;
emit StationUpgraded(_sectorId, player, tx.origin, newBaseType);
}
/**
* Get the base type for a sector
* Returns the base type (1-6) for rendering the correct station image
* @param _sectorId The sector ID to query
* @return baseType The base type (1-6), defaults to 1 if never upgraded
*/
function getSectorBaseType(uint256 _sectorId) external view returns (uint8) {
uint8 baseType = sectorBaseType[_sectorId];
return baseType == 0 ? 1 : baseType; // Default to base1 if not set
}
/**
* Set the base type for a sector (God only - for testing/admin)
* Allows the God account to manually set any sector's base type
* @param _sectorId The sector ID to set
* @param _baseType The base type to set (1-6)
*/
function setSectorBaseType(uint256 _sectorId, uint8 _baseType) external onlyGod {
if (_baseType < 1 || _baseType > 6) revert InvalidBaseType();
sectorBaseType[_sectorId] = _baseType;
emit StationBaseTypeSet(_sectorId, _baseType, msg.sender);
}
/**
* Deduct points from a player's score
* Only callable by the Auditor contract
* Used when players request contract audits or other point-deducting actions
* @param _player The player address to deduct points from
* @param _amount The number of points to deduct
*/
function deductPoints(address _player, uint256 _amount) external {
if (msg.sender != auditorContract) revert OnlyAuditor();
// Check if the player exists
bool isValidPlayer = false;
for (uint256 i = 0; i < players.length; i++) {
if (players[i] == _player) {
isValidPlayer = true;
break;
}
}
if (!isValidPlayer) revert NotAPlayer();
// Check if player has enough points
uint256 currentScore = scores[_player];
if (currentScore < _amount) revert InsufficientPoints();
// Deduct points
scores[_player] = currentScore - _amount;
emit PointsDeducted(_player, _amount, scores[_player]);
}
/**
* Award broadcast points to a player
* Only callable by the MaxExtract contract
* Called when a player broadcasts their sector for the first time
* @param _player The player address to award points to
*/
function awardBroadcastPoints(address _player) external {
if (msg.sender != maxExtractContract) revert OnlyMaxExtract();
// Check if the player exists
bool isValidPlayer = false;
for (uint256 i = 0; i < players.length; i++) {
if (players[i] == _player) {
isValidPlayer = true;
break;
}
}
if (!isValidPlayer) revert NotAPlayer();
// Award 5 points
scores[_player] += 5;
}
/**
* Set the Auditor contract address
* Only callable by the God address
* @param _auditor Address of the Auditor contract
*/
function setAuditorContract(address _auditor) external onlyGod {
require(_auditor != address(0), "Invalid address");
auditorContract = _auditor;
}
/**
* Set the Credits ERC20 token contract address
* Only callable by the God address
* @param _credits Address of the Credits token contract
*/
function setCreditsContract(address _credits) external onlyGod {
require(_credits != address(0), "Invalid address");
creditsContract = IERC20(_credits);
}
/**
* Get all pilots with their CREDITS token balances in one call
* @return pilotAddresses Array of pilot addresses
* @return creditsBalances Array of CREDITS balances (in wei, 18 decimals)
*/
function getAllPilotsWithCredits() external view returns (
address[] memory pilotAddresses,
uint256[] memory creditsBalances
) {
uint256 pilotCount = pilots.length;
pilotAddresses = new address[](pilotCount);
creditsBalances = new uint256[](pilotCount);
for (uint256 i = 0; i < pilotCount; i++) {
address pilot = pilots[i];
pilotAddresses[i] = pilot;
// Get CREDITS balance if contract is set, otherwise return 0
if (address(creditsContract) != address(0)) {
creditsBalances[i] = creditsContract.balanceOf(pilot);
} else {
creditsBalances[i] = 0;
}
}
return (pilotAddresses, creditsBalances);
}
/**
* Set the placeholder message for maintenance mode
* Only callable by the God address
* When set to a non-empty string, the frontend will display maintenance mode
* @param _placeholder The placeholder message to display (empty string to disable maintenance mode)
*/
function setPlaceholder(string calldata _placeholder) external onlyGod {
placeholder = _placeholder;
emit PlaceholderUpdated(_placeholder);
}
/**
* Accept direct ETH transfers to sweeten the pot
* Anyone can contribute to increase the winner's prize pool
*/
receive() external payable {
// ETH is automatically added to contract balance
// Will be distributed to winners in settleGame()
}
}//SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;
/*
'##::::'##::::'###::::'##::::'##::::'########:'##::::'##:'########:'########:::::'###:::::'######::'########:
###::'###:::'## ##:::. ##::'##::::: ##.....::. ##::'##::... ##..:: ##.... ##:::'## ##:::'##... ##:... ##..::
####'####::'##:. ##:::. ##'##:::::: ##::::::::. ##'##:::::: ##:::: ##:::: ##::'##:. ##:: ##:::..::::: ##::::
## ### ##:'##:::. ##:::. ###::::::: ######:::::. ###::::::: ##:::: ########::'##:::. ##: ##:::::::::: ##::::
##. #: ##: #########::: ## ##:::::: ##...:::::: ## ##:::::: ##:::: ##.. ##::: #########: ##:::::::::: ##::::
##:.:: ##: ##.... ##:: ##:. ##::::: ##:::::::: ##:. ##::::: ##:::: ##::. ##:: ##.... ##: ##::: ##:::: ##::::
##:::: ##: ##:::: ##: ##:::. ##:::: ########: ##:::. ##:::: ##:::: ##:::. ##: ##:::: ##:. ######::::: ##::::
..:::::..::..:::::..::..:::::..:::::........::..:::::..:::::..:::::..:::::..::..:::::..:::......::::::..:::::
................................................................
.##..##..##..##..######..##..##..######..#####....####...######.
.##..##..###.##....##....##..##..##......##..##..##......##.....
.##..##..##.###....##....##..##..####....#####....####...####...
.##..##..##..##....##.....####...##......##..##......##..##.....
..####...##..##..######....##....######..##..##...####...######.
................................................................
*/
/**
* Universe Contract - Manages the game world state
* Handles asteroid lifecycle, ship tracking, mining actions, and verification
* Uses commit-reveal scheme for secure entropy generation
* @author Max Extract Protocol
*/
contract Universe {
// The god address - only this address can set the universe entropy
address public constant GOD = 0x0647603E7711D9686BdB9fDB1fe0b04162b73dD7;
//address public constant GOD = 0x43D9B634006B4fCe2523a710990a397AC3d18D7a;
//address public immutable GOD;
/**
* DEV FUNCTION COMMENT OUT to set entropy directly (bypasses commit-reveal)
* Only available to GOD for easier testing/development
*/
/*
function setEntropyDirect(bytes32 _entropy) external onlyGod entropyNotSet {
entropy = _entropy;
entropySet = true;
emit EntropyRevealed(_entropy, bytes32(0), 0);
}*/
// The universe entropy - immutable once set via commit-reveal
bytes32 public entropy;
bool public entropySet;
// Commit-reveal state
bytes32 public commitmentHash;
uint256 public commitBlock;
bool public commitmentMade;
// Rolling commit-reveal state for ongoing entropy generation
bytes32 public rollingEntropy;
bytes32 public lastCommit;
uint256 public roundNumber;
// Events
event CommitmentMade(bytes32 indexed commitmentHash, uint256 indexed blockNumber);
event EntropyRevealed(bytes32 indexed entropy, bytes32 reveal, uint256 commitBlockHash);
event RollingCommitReveal(uint256 indexed roundNumber, bytes32 indexed newCommit, bytes32 reveal, bytes32 newRollingEntropy);
// Errors
error OnlyGod();
error EntropyAlreadySet();
error NoCommitmentMade();
error BlockhashUnavailable();
error InvalidReveal();
error CommitmentAlreadyMade();
modifier onlyGod() {
if (msg.sender != GOD) revert OnlyGod();
_;
}
modifier entropyNotSet() {
if (entropySet) revert EntropyAlreadySet();
_;
}
constructor() {
}
/**
* Step 1: God commits to a secret random number
* @param _commitmentHash keccak256(randomNumber) - commitment to secret random number
*/
function commit(bytes32 _commitmentHash) external onlyGod entropyNotSet {
if (commitmentMade) revert CommitmentAlreadyMade();
commitmentHash = _commitmentHash;
commitBlock = block.number;
commitmentMade = true;
emit CommitmentMade(_commitmentHash, block.number);
}
/**
* Step 2: God reveals the random number to generate entropy
* Must be called in a subsequent block to ensure commit block hash is available
* @param randomNumber The secret random number that was committed to
*/
function reveal(uint256 randomNumber) external onlyGod entropyNotSet {
if (!commitmentMade) revert NoCommitmentMade();
// Get the commit block hash for additional entropy
bytes32 commitBlockHash = blockhash(commitBlock);
if (commitBlockHash == 0) revert BlockhashUnavailable();
// Verify the reveal matches the commitment
bytes32 expectedCommitment = keccak256(abi.encodePacked(randomNumber));
if (expectedCommitment != commitmentHash) revert InvalidReveal();
// Generate final entropy by combining random number with commit block hash
entropy = keccak256(abi.encodePacked(randomNumber, commitBlockHash));
entropySet = true;
emit EntropyRevealed(entropy, bytes32(randomNumber), uint256(commitBlockHash));
}
/**
* Get the current universe entropy
* @return The entropy bytes32, or 0x0 if not set yet
*/
function getEntropy() external view returns (bytes32) {
return entropy;
}
/**
* Check if entropy has been set
* @return True if entropy is available
*/
function isEntropySet() external view returns (bool) {
return entropySet;
}
/**
* Get commit-reveal state for frontend
* @return _commitmentMade Whether a commitment has been made
* @return _commitBlock The block number of the commitment
* @return _entropySet Whether entropy has been revealed
*/
function getCommitRevealState() external view returns (
bool _commitmentMade,
uint256 _commitBlock,
bool _entropySet
) {
return (commitmentMade, commitBlock, entropySet);
}
/**
* Rolling commit-reveal function for ongoing entropy generation
* Commits to next round while revealing current round in same transaction
* @param nextCommit Commitment hash for the next round (keccak256(randomNumber))
* @param revealNumber The random number being revealed for current round (0x0 for round 0)
*/
function rollingCommitReveal(bytes32 nextCommit, uint256 revealNumber) external onlyGod {
// For round 0, allow reveal to be 0 and initialize rolling entropy
if (roundNumber == 0) {
// For the first round, we accept any reveal (including 0) and initialize rolling entropy
// Use a combination of reveal and block hash for initial entropy
bytes32 currentBlockHash = blockhash(block.number - 1);
rollingEntropy = keccak256(abi.encodePacked(revealNumber, currentBlockHash));
lastCommit = nextCommit;
roundNumber = 1;
emit RollingCommitReveal(0, nextCommit, bytes32(revealNumber), rollingEntropy);
return;
}
// For subsequent rounds, verify the reveal matches the last commit
bytes32 expectedCommit = keccak256(abi.encodePacked(revealNumber));
if (expectedCommit != lastCommit) revert InvalidReveal();
// Get the block hash from when the last commit was made
// Note: We use the current block hash as the source of additional entropy
bytes32 blockHash = blockhash(block.number - 1);
// Generate new rolling entropy by combining reveal with block hash
rollingEntropy = keccak256(abi.encodePacked(revealNumber, blockHash, rollingEntropy));
// Store the new commit for next round
lastCommit = nextCommit;
roundNumber++;
emit RollingCommitReveal(roundNumber - 1, nextCommit, bytes32(revealNumber), rollingEntropy);
}
/**
* Get the current rolling entropy and round information
* @return _rollingEntropy Current rolling entropy
* @return _roundNumber Current round number
* @return _lastCommit Last commitment hash
*/
function getRollingState() external view returns (
bytes32 _rollingEntropy,
uint256 _roundNumber,
bytes32 _lastCommit
) {
return (rollingEntropy, roundNumber, lastCommit);
}
/**
* Get the main commitment hash for display purposes
* @return The current commitment hash
*/
function getCommitmentHash() external view returns (bytes32) {
return commitmentHash;
}
}// 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);
}{
"remappings": [
"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
"ds-test/=lib/solidity-bytes-utils/lib/forge-std/lib/ds-test/src/",
"erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
"forge-std/=lib/forge-std/src/",
"halmos-cheatcodes/=lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/",
"openzeppelin-contracts/=lib/openzeppelin-contracts/",
"solidity-bytes-utils/=lib/solidity-bytes-utils/contracts/"
],
"optimizer": {
"enabled": true,
"runs": 200
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "ipfs",
"appendCBOR": true
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "cancun",
"viaIR": false
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_universe","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"CredentialNotRegistered","type":"error"},{"inputs":[],"name":"GameAlreadySettled","type":"error"},{"inputs":[],"name":"GameNotEnded","type":"error"},{"inputs":[],"name":"GameNotOpen","type":"error"},{"inputs":[],"name":"InsufficientCreditsForUpgrade","type":"error"},{"inputs":[],"name":"InsufficientPayment","type":"error"},{"inputs":[],"name":"InsufficientPoints","type":"error"},{"inputs":[],"name":"InvalidArrayLengths","type":"error"},{"inputs":[],"name":"InvalidBaseType","type":"error"},{"inputs":[],"name":"InvalidPercentages","type":"error"},{"inputs":[],"name":"MaxExtractNotSet","type":"error"},{"inputs":[],"name":"NotACredential","type":"error"},{"inputs":[],"name":"NotAFuelContract","type":"error"},{"inputs":[],"name":"NotAPlayer","type":"error"},{"inputs":[],"name":"NotARegistry","type":"error"},{"inputs":[],"name":"OnlyAuditor","type":"error"},{"inputs":[],"name":"OnlyGod","type":"error"},{"inputs":[],"name":"OnlyMaxExtract","type":"error"},{"inputs":[],"name":"OnlyPilot","type":"error"},{"inputs":[],"name":"PayoutFailed","type":"error"},{"inputs":[],"name":"PilotAlreadyAdded","type":"error"},{"inputs":[],"name":"PilotAlreadyDead","type":"error"},{"inputs":[],"name":"PilotAlreadyMintedFromPlayer","type":"error"},{"inputs":[],"name":"PlayerAlreadyJoined","type":"error"},{"inputs":[],"name":"StationMaxLevel","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8[]","name":"newVisibleChapters","type":"uint8[]"}],"name":"ChaptersUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pilot","type":"address"},{"indexed":true,"internalType":"address","name":"player","type":"address"},{"indexed":true,"internalType":"address","name":"credentialContract","type":"address"}],"name":"CredentialMinted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"winners","type":"address[]"},{"indexed":false,"internalType":"uint256","name":"winningScore","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalPayout","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"payoutPerWinner","type":"uint256"}],"name":"GameSettled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"enum Game.GameState","name":"newState","type":"uint8"}],"name":"GameStateChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pilot","type":"address"}],"name":"PilotAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pilot","type":"address"},{"indexed":true,"internalType":"address","name":"killer","type":"address"},{"indexed":true,"internalType":"address","name":"playerPenalized","type":"address"},{"indexed":false,"internalType":"uint256","name":"scorePenalty","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"ethForwarded","type":"uint256"}],"name":"PilotDied","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"pilots","type":"address[]"}],"name":"PilotsAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"newPlaceholder","type":"string"}],"name":"PlaceholderUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"player","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"PlayerBoughtIn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"player","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newScore","type":"uint256"}],"name":"PointsDeducted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"recipients","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"percentages","type":"uint256[]"},{"indexed":false,"internalType":"uint256","name":"totalAmount","type":"uint256"}],"name":"PotPaidOut","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"sectorId","type":"uint256"},{"indexed":false,"internalType":"uint8","name":"newBaseType","type":"uint8"},{"indexed":true,"internalType":"address","name":"setBy","type":"address"}],"name":"StationBaseTypeSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"sectorId","type":"uint256"},{"indexed":true,"internalType":"address","name":"player","type":"address"},{"indexed":true,"internalType":"address","name":"pilotCaller","type":"address"},{"indexed":false,"internalType":"uint8","name":"newBaseType","type":"uint8"}],"name":"StationUpgraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pilot","type":"address"},{"indexed":true,"internalType":"address","name":"player","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"TipGiven","type":"event"},{"inputs":[],"name":"BUY_IN_PRICE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WETH_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_pilot","type":"address"}],"name":"addPilot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_pilots","type":"address[]"}],"name":"addPilots","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"auditorContract","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_player","type":"address"}],"name":"awardBroadcastPoints","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"buyIn","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"canGameSettle","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_pilot","type":"address"},{"internalType":"uint256","name":"_sectorId","type":"uint256"}],"name":"canPilotAccessSector","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"creditsContract","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_killer","type":"address"},{"internalType":"address","name":"_playerToPenalize","type":"address"}],"name":"deadMansSlash","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_killer","type":"address"},{"internalType":"address","name":"_playerToPenalize","type":"address"}],"name":"deadMansSwitch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"deadPilots","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_player","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"deductPoints","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_pilots","type":"address[]"},{"internalType":"uint256","name":"minBalancePerPilot","type":"uint256"}],"name":"fundPilots","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"gameEndTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"gameWinners","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllPilotsAndBalances","outputs":[{"internalType":"address[]","name":"pilotAddresses","type":"address[]"},{"internalType":"uint256[]","name":"ethBalances","type":"uint256[]"},{"internalType":"bool[]","name":"isDead","type":"bool[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllPilotsWithCredits","outputs":[{"internalType":"address[]","name":"pilotAddresses","type":"address[]"},{"internalType":"uint256[]","name":"creditsBalances","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getGameInfo","outputs":[{"internalType":"enum Game.GameState","name":"_state","type":"uint8"},{"internalType":"uint256","name":"_playerCount","type":"uint256"},{"internalType":"uint256","name":"_buyInPrice","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getGameWinners","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPilotCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPilots","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPlayerCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_player","type":"address"}],"name":"getPlayerScore","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPlayers","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_sectorId","type":"uint256"}],"name":"getSectorBaseType","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTimeRemaining","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getVisibleChapters","outputs":[{"internalType":"uint8[]","name":"","type":"uint8[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_pilot","type":"address"}],"name":"isPilot","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_pilot","type":"address"}],"name":"isPilotDead","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isPilotMapping","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_player","type":"address"}],"name":"isPlayer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isPlayerMapping","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxExtract","outputs":[{"internalType":"contract IMaxExtract","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxExtractContract","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"recipients","type":"address[]"},{"internalType":"uint256[]","name":"percentages","type":"uint256[]"}],"name":"payoutPot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_sectorId","type":"uint256"}],"name":"pilotMintSectorCredential","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"pilotPlayerCredentialMinted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"pilots","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"placeholder","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"players","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"scores","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"sectorBaseType","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_auditor","type":"address"}],"name":"setAuditorContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_credits","type":"address"}],"name":"setCreditsContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_maxExtract","type":"address"}],"name":"setMaxExtract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_placeholder","type":"string"}],"name":"setPlaceholder","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_sectorId","type":"uint256"},{"internalType":"uint8","name":"_baseType","type":"uint8"}],"name":"setSectorBaseType","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"enum Game.GameState","name":"_newState","type":"uint8"}],"name":"setState","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"settleGame","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8[]","name":"_chapters","type":"uint8[]"}],"name":"showChapters","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"state","outputs":[{"internalType":"enum Game.GameState","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_player","type":"address"},{"internalType":"uint256","name":"_tipAmount","type":"uint256"}],"name":"tipPlayer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"universe","outputs":[{"internalType":"contract Universe","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_sectorId","type":"uint256"}],"name":"upgradeStation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"visibleChapters","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"winningScore","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
60c060405261001042611194610058565b60805234801561001e575f80fd5b50604051614b52380380614b5283398101604081905261003d9161007d565b6001600160a01b031660a0526005805460ff191690556100aa565b8082018082111561007757634e487b7160e01b5f52601160045260245ffd5b92915050565b5f6020828403121561008d575f80fd5b81516001600160a01b03811681146100a3575f80fd5b9392505050565b60805160a051614a106101425f395f818161063701528181610dc501528181610e7601528181610f2e01528181611357015281816116270152818161178d01528181611a3a01528181611fd2015281816128630152818161302e0152818161394301528181613d360152613e3501525f818161055e01528181611b45015281816129bb0152818161333a015261336a0152614a105ff3fe60806040526004361061038a575f3560e01c80637fd6b2e7116101d3578063b7a17c4c116100fd578063ded72d1f1161009d578063e83267451161006d578063e832674514610b06578063f4e8b45014610b19578063f71d96cb14610b38578063fe74379114610b57575f80fd5b8063ded72d1f14610a66578063e085c53914610a94578063e19ddff314610ac8578063e5b42e9214610ae7575f80fd5b8063c7a77e2f116100d8578063c7a77e2f146109fe578063d529251d14610a11578063dac6270d14610a30578063dbb838a914610a44575f80fd5b8063b7a17c4c146109ab578063c19d93fb146109c4578063c2e52206146109ea575f80fd5b8063938a864511610173578063b2652ec411610143578063b2652ec41461092c578063b329be371461094b578063b33ac8aa1461095f578063b38321a21461097d575f80fd5b8063938a8645146108ae5780639e75143c146108cd578063a83b589c146108ee578063af331b651461090d575f80fd5b80638aa0cb6c116101ae5780638aa0cb6c146108485780638b5b9ccc146108675780638bb98fd91461087b5780639129ce391461088f575f80fd5b80637fd6b2e7146107d157806388aafa60146107f057806388f4e6eb14610829575f80fd5b8063516f4f30116102b45780637350f431116102545780637776282011610224578063777628201461075157806379390faa146107655780637bdd449c146107845780637df3c497146107a3575f80fd5b80637350f431146106ba5780637488ad24146106e8578063755b77b31461070757806376dd110f14610726575f80fd5b8063554c1b1f1161028f578063554c1b1f1461062657806356de96db1461065957806356df26be14610678578063620274061461069b575f80fd5b8063516f4f30146105d257806353aab43414610609578063546216f114610611575f80fd5b806318edd1781161032a57806344d9bc5f116102fa57806344d9bc5f1461054d57806348bb35a2146105805780634ded2e8e1461059f5780634ffac413146105be575f80fd5b806318edd178146104c6578063241e5622146104e75780632f5a90a6146105085780633ccfd60b14610539575f80fd5b806309c95e101161036557806309c95e101461041957806312065fe01461046057806316c44e6f1461047c5780631746bd1b1461049b575f80fd5b8063040141e5146103955780630642bc41146103d9578063093119f7146103f8575f80fd5b3661039157005b5f80fd5b3480156103a0575f80fd5b506103bc7382af49447d8a07e3bd95bd0d56f35241523fbab181565b6040516001600160a01b0390911681526020015b60405180910390f35b3480156103e4575f80fd5b506003546103bc906001600160a01b031681565b348015610403575f80fd5b5061041761041236600461411a565b610b76565b005b348015610424575f80fd5b50610450610433366004614151565b6001600160a01b03165f908152600b602052604090205460ff1690565b60405190151581526020016103d0565b34801561046b575f80fd5b50475b6040519081526020016103d0565b348015610487575f80fd5b506001546103bc906001600160a01b031681565b3480156104a6575f80fd5b506005546007546040516103d09260ff1691906509184e72a000906141a0565b3480156104d1575f80fd5b506104da610cc0565b6040516103d091906141bf565b3480156104f2575f80fd5b506104fb610d33565b6040516103d09190614247565b348015610513575f80fd5b50610527610522366004614259565b610d92565b60405160ff90911681526020016103d0565b348015610544575f80fd5b50610417610dc3565b348015610558575f80fd5b5061046e7f000000000000000000000000000000000000000000000000000000000000000081565b34801561058b575f80fd5b5061041761059a3660046142b7565b610f2c565b3480156105aa575f80fd5b506104506105b93660046142f5565b611027565b3480156105c9575f80fd5b5060085461046e565b3480156105dd575f80fd5b506104506105ec366004614151565b6001600160a01b03165f908152600e602052604090205460ff1690565b6104176111e1565b34801561061c575f80fd5b5061046e600a5481565b348015610631575f80fd5b506103bc7f000000000000000000000000000000000000000000000000000000000000000081565b348015610664575f80fd5b5061041761067336600461431f565b611355565b348015610683575f80fd5b5061068c611463565b6040516103d09392919061436d565b3480156106a6575f80fd5b506104176106b5366004614151565b611625565b3480156106c5575f80fd5b506104506106d4366004614151565b600c6020525f908152604090205460ff1681565b3480156106f3575f80fd5b506104176107023660046143d8565b61178b565b348015610712575f80fd5b50610417610721366004614151565b611a38565b348015610731575f80fd5b5061046e610740366004614151565b600d6020525f908152604090205481565b34801561075c575f80fd5b50610417611b43565b348015610770575f80fd5b5061041761077f3660046142f5565b611f11565b34801561078f575f80fd5b506103bc61079e366004614259565b611fa8565b3480156107ae575f80fd5b506104506107bd366004614151565b600b6020525f908152604090205460ff1681565b3480156107dc575f80fd5b506104176107eb366004614450565b611fd0565b3480156107fb575f80fd5b5061045061080a36600461411a565b600f60209081525f928352604080842090915290825290205460ff1681565b348015610834575f80fd5b5061041761084336600461411a565b612106565b348015610853575f80fd5b50610417610862366004614151565b612861565b348015610872575f80fd5b506104fb61295a565b348015610886575f80fd5b506104506129b8565b34801561089a575f80fd5b506104176108a9366004614259565b612a05565b3480156108b9575f80fd5b506104176108c8366004614151565b612cc5565b3480156108d8575f80fd5b506108e1612d94565b6040516103d09190614473565b3480156108f9575f80fd5b506104176109083660046142f5565b612e20565b348015610918575f80fd5b50610527610927366004614259565b612f62565b348015610937575f80fd5b50610450610946366004614151565b612f89565b348015610956575f80fd5b506104fb612fce565b34801561096a575f80fd5b505f546103bc906001600160a01b031681565b348015610988575f80fd5b50610450610997366004614151565b600e6020525f908152604090205460ff1681565b3480156109b6575f80fd5b5061046e6509184e72a00081565b3480156109cf575f80fd5b506005546109dd9060ff1681565b6040516103d091906144a8565b3480156109f5575f80fd5b5060075461046e565b610417610a0c3660046144b6565b61302c565b348015610a1c575f80fd5b506002546103bc906001600160a01b031681565b348015610a3b575f80fd5b5061046e613337565b348015610a4f575f80fd5b50610a5861338e565b6040516103d09291906144fd565b348015610a71575f80fd5b50610527610a80366004614259565b60106020525f908152604090205460ff1681565b348015610a9f575f80fd5b5061046e610aae366004614151565b6001600160a01b03165f908152600d602052604090205490565b348015610ad3575f80fd5b506103bc610ae2366004614259565b613549565b348015610af2575f80fd5b50610417610b01366004614259565b613558565b610417610b143660046142b7565b613941565b348015610b24575f80fd5b50610417610b33366004614521565b613d34565b348015610b43575f80fd5b506103bc610b52366004614259565b613e24565b348015610b62575f80fd5b50610417610b71366004614151565b613e33565b335f908152600c602052604090205460ff16610ba557604051634632ffe360e01b815260040160405180910390fd5b335f908152600e602052604090205460ff1615610bd557604051631894063360e21b815260040160405180910390fd5b6001600160a01b0381165f908152600b602052604090205460ff16610c0d5760405163abca351760e01b815260040160405180910390fd5b335f908152600e60209081526040808320805460ff191660011790556001600160a01b0384168352600d90915281205490600a821015610c4d5781610c50565b600a5b9050610c5c81836145a1565b6001600160a01b038481165f818152600d602090815260408083209590955584518681529081019190915290929187169133917f8044fa4da29a21540b095aa9cddd2e3f31d47978eb3d8440183b6ac98bf3bda1910160405180910390a450505050565b60606006805480602002602001604051908101604052809291908181526020018280548015610d2957602002820191905f5260205f20905f905b825461010083900a900460ff16815260206001928301818104948501949093039092029101808411610cfa5790505b5050505050905090565b60606008805480602002602001604051908101604052809291908181526020018280548015610d2957602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311610d6b575050505050905090565b60068181548110610da1575f80fd5b905f5260205f209060209182820401919006915054906101000a900460ff1681565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663af30ee3f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e1f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e4391906145b4565b6001600160a01b0316336001600160a01b031614610e7457604051630cb73db360e21b815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663af30ee3f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ed0573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ef491906145b4565b6001600160a01b03166108fc4790811502906040515f60405180830381858888f19350505050158015610f29573d5f803e3d5ffd5b50565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663af30ee3f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f88573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610fac91906145b4565b6001600160a01b0316336001600160a01b031614610fdd57604051630cb73db360e21b815260040160405180910390fd5b610fe960068383613ffb565b507f94e1ce80c1f560eae2d7da116779b3aacee5613170afb9876373e3c761aa1956828260405161101b9291906145cf565b60405180910390a15050565b5f80546001600160a01b031661103e57505f6111db565b5f8054604051633ff3649360e01b8152600481018590526001600160a01b0390911690633ff3649390602401602060405180830381865afa158015611085573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110a991906145b4565b90506001600160a01b0381166110c2575f9150506111db565b5f6110ef826040518060400160405280600a81526020016918dc9959195b9d1a585b60b21b815250613f2c565b90506001600160a01b038116611109575f925050506111db565b6040516001600160a01b0386811660248301525f91829184169060440160408051601f198184030181529181526020820180516001600160e01b03166370a0823160e01b1790525161115b9190614615565b5f60405180830381855afa9150503d805f8114611193576040519150601f19603f3d011682016040523d82523d5f602084013e611198565b606091505b50915091508115806111ab575060208151105b156111bc575f9450505050506111db565b5f818060200190518101906111d1919061462b565b1515955050505050505b92915050565b5f60055460ff1660028111156111f9576111f961416c565b1461121757604051635c07b6d760e11b815260040160405180910390fd5b6509184e72a00034101561123e5760405163cd1c886760e01b815260040160405180910390fd5b335f908152600b602052604090205460ff161561126e576040516314c4fea760e31b815260040160405180910390fd5b6007805460018181019092557fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c6880180546001600160a01b031916339081179091555f818152600b60209081526040808320805460ff1916909517909455600d90528281205590517f7dbd99091135732d8894a7112b904af6bf7fee8441105b31987f90c32329fdd9906113049034815260200190565b60405180910390a26509184e72a00034111561135357336108fc61132e6509184e72a000346145a1565b6040518115909202915f818181858888f19350505050158015610f29573d5f803e3d5ffd5b565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663af30ee3f6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156113b1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906113d591906145b4565b6001600160a01b0316336001600160a01b03161461140657604051630cb73db360e21b815260040160405180910390fd5b6005805482919060ff191660018360028111156114255761142561416c565b02179055507ea8b06dd72552dea96e97c9a96acf39a1908ada44765cefe367620485b2c7e18160405161145891906144a8565b60405180910390a150565b60085460609081908190806001600160401b0381111561148557611485614642565b6040519080825280602002602001820160405280156114ae578160200160208202803683370190505b509350806001600160401b038111156114c9576114c9614642565b6040519080825280602002602001820160405280156114f2578160200160208202803683370190505b509250806001600160401b0381111561150d5761150d614642565b604051908082528060200260200182016040528015611536578160200160208202803683370190505b5091505f5b8181101561161e575f6008828154811061155757611557614656565b905f5260205f20015f9054906101000a90046001600160a01b031690508086838151811061158757611587614656565b60200260200101906001600160a01b031690816001600160a01b031681525050806001600160a01b0316318583815181106115c4576115c4614656565b6020908102919091018101919091526001600160a01b0382165f908152600e9091526040902054845160ff9091169085908490811061160557611605614656565b911515602092830291909101909101525060010161153b565b5050909192565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663af30ee3f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611681573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116a591906145b4565b6001600160a01b0316336001600160a01b0316146116d657604051630cb73db360e21b815260040160405180910390fd5b6116df81612f89565b156116fd5760405163e0dbb1a760e01b815260040160405180910390fd5b6008805460018082019092557ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee30180546001600160a01b0319166001600160a01b0384169081179091555f818152600c6020526040808220805460ff1916909417909355915190917f07577ee4d7b640060b986e698b16d90aef8e3a4fffa36dd13d3b79195e70b3d691a250565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663af30ee3f6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156117e7573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061180b91906145b4565b6001600160a01b0316336001600160a01b03161461183c57604051630cb73db360e21b815260040160405180910390fd5b8215806118495750828114155b156118675760405163a9854bc960e01b815260040160405180910390fd5b5f805b828110156118a05783838281811061188457611884614656565b9050602002013582611896919061466a565b915060010161186a565b50806103e8146118c357604051636d2fd3c960e01b815260040160405180910390fd5b475f8190036118d3575050611a32565b5f5b858110156119ef575f8787838181106118f0576118f0614656565b90506020020160208101906119059190614151565b6001600160a01b0316146119e7575f6103e886868481811061192957611929614656565b905060200201358461193b919061467d565b61194591906146a8565b905080156119e5575f88888481811061196057611960614656565b90506020020160208101906119759190614151565b6001600160a01b0316826040515f6040518083038185875af1925050503d805f81146119bc576040519150601f19603f3d011682016040523d82523d5f602084013e6119c1565b606091505b50509050806119e357604051630ec6ac4160e21b815260040160405180910390fd5b505b505b6001016118d5565b507f5a31676f5fc71e56ec99e78f1f76a78352cdc05a4c1be0d3accdbb305a512ce48686868685604051611a279594939291906146f9565b60405180910390a150505b50505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663af30ee3f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a94573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611ab891906145b4565b6001600160a01b0316336001600160a01b031614611ae957604051630cb73db360e21b815260040160405180910390fd5b6001600160a01b038116611b185760405162461bcd60e51b8152600401611b0f9061474c565b60405180910390fd5b5f80546001600160a01b039092166001600160a01b0319928316811790915560028054909216179055565b7f0000000000000000000000000000000000000000000000000000000000000000421015611b8457604051638f86c6b360e01b815260040160405180910390fd5b600260055460ff166002811115611b9d57611b9d61416c565b03611bbb57604051636e2ab89360e11b815260040160405180910390fd5b6007545f03611bd3576005805460ff19166002179055565b5f805b600754811015611c32575f600d5f60078481548110611bf757611bf7614656565b5f9182526020808320909101546001600160a01b03168352820192909252604001902054905082811115611c29578092505b50600101611bd6565b506007545f906001600160401b03811115611c4f57611c4f614642565b604051908082528060200260200182016040528015611c78578160200160208202803683370190505b5090505f805b600754811015611d365783600d5f60078481548110611c9f57611c9f614656565b5f9182526020808320909101546001600160a01b0316835282019290925260400190205403611d2e5760078181548110611cdb57611cdb614656565b905f5260205f20015f9054906101000a90046001600160a01b0316838381518110611d0857611d08614656565b6001600160a01b039092166020928302919091019091015281611d2a81614775565b9250505b600101611c7e565b50806001600160401b03811115611d4f57611d4f614642565b604051908082528060200260200182016040528015611d78578160200160208202803683370190505b508051611d8d9160099160209091019061409f565b505f5b81811015611df557828181518110611daa57611daa614656565b602002602001015160098281548110611dc557611dc5614656565b5f91825260209091200180546001600160a01b0319166001600160a01b0392909216919091179055600101611d90565b50600a8390556005805460ff19166002179055475f8115801590611e1857505f83115b15611eca57611e2783836146a8565b90505f5b83811015611ec8575f60098281548110611e4757611e47614656565b5f9182526020822001546040516001600160a01b039091169185919081818185875af1925050503d805f8114611e98576040519150601f19603f3d011682016040523d82523d5f602084013e611e9d565b606091505b5050905080611ebf57604051630ec6ac4160e21b815260040160405180910390fd5b50600101611e2b565b505b7f8b8f0658aa11ba65d0656d3982f05a3d5d88b0190cc77264e6fc6aff7e711da06009600a548484604051611f02949392919061478d565b60405180910390a15050505050565b611f1a33612f89565b611f3757604051634632ffe360e01b815260040160405180910390fd5b6001600160a01b0382165f908152600d602052604081208054839290611f5e90849061466a565b90915550506040518181526001600160a01b0383169033907f8c1e155b9f22132fd0366f32e05296679a0174614fe6dc4b2f7e2fcfc0385534906020015b60405180910390a35050565b60098181548110611fb7575f80fd5b5f918252602090912001546001600160a01b0316905081565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663af30ee3f6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561202c573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061205091906145b4565b6001600160a01b0316336001600160a01b03161461208157604051630cb73db360e21b815260040160405180910390fd5b60018160ff161080612096575060068160ff16115b156120b45760405163560612c960e01b815260040160405180910390fd5b5f82815260106020908152604091829020805460ff191660ff85169081179091559151918252339184917fa5df98dd2060f5d5cfe17f03fee367e49d826fa19635fb6874523063191cc30e9101611f9c565b335f908152600c602052604090205460ff1661213557604051634632ffe360e01b815260040160405180910390fd5b335f908152600e602052604090205460ff161561216557604051631894063360e21b815260040160405180910390fd5b6001600160a01b0381165f908152600b602052604090205460ff1661219d5760405163abca351760e01b815260040160405180910390fd5b335f908152600e6020526040808220805460ff19166001179055815490516370b131c360e11b81526001600160a01b0384811660048301529091169063e162638690602401602060405180830381865afa1580156121fd573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612221919061462b565b9050805f036122695760405162461bcd60e51b8152602060048201526014602482015273283630bcb2b9103430b99037379039b2b1ba37b960611b6044820152606401611b0f565b5f8054604051633ff3649360e01b8152600481018490526001600160a01b0390911690633ff3649390602401602060405180830381865afa1580156122b0573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906122d491906145b4565b90506001600160a01b03811661231a5760405162461bcd60e51b815260206004820152600b60248201526a4e6f20726567697374727960a81b6044820152606401611b0f565b5f61234282604051806040016040528060058152602001647374616b6560d81b815250613f2c565b90506001600160a01b03811661238c5760405162461bcd60e51b815260206004820152600f60248201526e4e6f207374616b65206d6f64756c6560881b6044820152606401611b0f565b6001546001600160a01b03166123d65760405162461bcd60e51b815260206004820152600f60248201526e105d591a5d1bdc881b9bdd081cd95d608a1b6044820152606401611b0f565b6001546040516001600160a01b0383811660248301525f92839291169060440160408051601f198184030181529181526020820180516001600160e01b0316639d26080960e01b1790525161242b9190614615565b5f60405180830381855afa9150503d805f8114612463576040519150601f19603f3d011682016040523d82523d5f602084013e612468565b606091505b509150915081801561247c57506020815110155b6124bd5760405162461bcd60e51b8152602060048201526012602482015271105d591a5d0818da1958dac819985a5b195960721b6044820152606401611b0f565b5f818060200190518101906124d291906147f1565b90508060ff166004146125275760405162461bcd60e51b815260206004820152601960248201527f4e6f74206175646974656420666f7220636861707465722034000000000000006044820152606401611b0f565b5f8054604051633a02a42d60e01b81526001600160a01b038b8116600483015290911690633a02a42d90602401602060405180830381865afa15801561256f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612593919061462b565b905069021e19e0c9bab24000008110156125ef5760405162461bcd60e51b815260206004820152601d60248201527f4b696c6c65722068617320696e73756666696369656e74207374616b650000006044820152606401611b0f565b6040516001600160a01b038a811660248301525f919087169060440160408051601f198184030181529181526020820180516001600160e01b031663c96be4cb60e01b179052516126409190614615565b5f604051808303815f865af19150503d805f8114612679576040519150601f19603f3d011682016040523d82523d5f602084013e61267e565b606091505b50509050806126c35760405162461bcd60e51b815260206004820152601160248201527014db185cda0818d85b1b0819985a5b1959607a1b6044820152606401611b0f565b5f8054604051633a02a42d60e01b81526001600160a01b038d8116600483015290911690633a02a42d90602401602060405180830381865afa15801561270b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061272f919061462b565b9050801561279b5760405162461bcd60e51b815260206004820152603360248201527f536c61736820646964206e6f74206275726e207374616b65202d206d616c69636044820152721a5bdd5cc81cdd185ad94818dbdb9d1c9858dd606a1b6064820152608401611b0f565b69021e19e0c9bab24000006127b082856145a1565b101561280a5760405162461bcd60e51b8152602060048201526024808201527f536c61736820646964206e6f74206275726e2066756c6c207374616b6520616d6044820152631bdd5b9d60e21b6064820152608401611b0f565b604080515f80825260208201526001600160a01b03808d1692908e169133917f8044fa4da29a21540b095aa9cddd2e3f31d47978eb3d8440183b6ac98bf3bda1910160405180910390a45050505050505050505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663af30ee3f6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156128bd573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906128e191906145b4565b6001600160a01b0316336001600160a01b03161461291257604051630cb73db360e21b815260040160405180910390fd5b6001600160a01b0381166129385760405162461bcd60e51b8152600401611b0f9061474c565b600180546001600160a01b0319166001600160a01b0392909216919091179055565b60606007805480602002602001604051908101604052809291908181526020018280548015610d2957602002820191905f5260205f209081546001600160a01b03168152600190910190602001808311610d6b575050505050905090565b5f7f00000000000000000000000000000000000000000000000000000000000000004210158015612a005750600260055460ff1660028111156129fd576129fd61416c565b14155b905090565b5f546001600160a01b0316612a2d57604051631e0aa0c360e21b815260040160405180910390fd5b612a3632612f89565b612a5357604051634632ffe360e01b815260040160405180910390fd5b5f8054604051633ff3649360e01b8152600481018490526001600160a01b0390911690633ff3649390602401602060405180830381865afa158015612a9a573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612abe91906145b4565b90506001600160a01b038116612ae7576040516381d522f560e01b815260040160405180910390fd5b5f612b14826040518060400160405280600a81526020016918dc9959195b9d1a585b60b21b815250613f2c565b90506001600160a01b038116612b3d57604051635e5b1d7560e11b815260040160405180910390fd5b6001600160a01b0381163314612b6657604051635e5b1d7560e11b815260040160405180910390fd5b5f8054604051634650b04560e01b8152600481018690526001600160a01b0390911690634650b04590602401602060405180830381865afa158015612bad573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612bd191906145b4565b90506001600160a01b038116612bfa5760405163abca351760e01b815260040160405180910390fd5b325f908152600f602090815260408083206001600160a01b038516845290915290205460ff1615612c3e5760405163933099c160e01b815260040160405180910390fd5b325f908152600f602090815260408083206001600160a01b03851684528252808320805460ff19166001179055600d9091528120805460029290612c8390849061466a565b909155505060405133906001600160a01b0383169032907f8483d60736ac8e5fa0068cccf221544749b1c7acc419a99c12df90a44c966c9d905f90a450505050565b6002546001600160a01b03163314612cf05760405163cbf6cf7b60e01b815260040160405180910390fd5b5f805b600754811015612d4457826001600160a01b031660078281548110612d1a57612d1a614656565b5f918252602090912001546001600160a01b031603612d3c5760019150612d44565b600101612cf3565b5080612d635760405163abca351760e01b815260040160405180910390fd5b6001600160a01b0382165f908152600d60205260408120805460059290612d8b90849061466a565b90915550505050565b60048054612da19061480c565b80601f0160208091040260200160405190810160405280929190818152602001828054612dcd9061480c565b8015612e185780601f10612def57610100808354040283529160200191612e18565b820191905f5260205f20905b815481529060010190602001808311612dfb57829003601f168201915b505050505081565b6001546001600160a01b03163314612e4b5760405163f87c866960e01b815260040160405180910390fd5b5f805b600754811015612e9f57836001600160a01b031660078281548110612e7557612e75614656565b5f918252602090912001546001600160a01b031603612e975760019150612e9f565b600101612e4e565b5080612ebe5760405163abca351760e01b815260040160405180910390fd5b6001600160a01b0383165f908152600d602052604090205482811015612ef75760405163303e7a0760e01b815260040160405180910390fd5b612f0183826145a1565b6001600160a01b0385165f818152600d6020526040908190208390555190917f2d8ea5250bf29dafe8cda27d1a8c9aaf28837abf1505e7f02097a7f44bbee54c91612f5491878252602082015260400190565b60405180910390a250505050565b5f8181526010602052604081205460ff168015612f7f5780612f82565b60015b9392505050565b6001600160a01b0381165f908152600e602052604081205460ff1615612fb057505f919050565b506001600160a01b03165f908152600c602052604090205460ff1690565b60606009805480602002602001604051908101604052809291908181526020018280548015610d2957602002820191905f5260205f209081546001600160a01b03168152600190910190602001808311610d6b575050505050905090565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663af30ee3f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613088573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906130ac91906145b4565b6001600160a01b0316336001600160a01b0316146130dd57604051630cb73db360e21b815260040160405180910390fd5b8161311f5760405162461bcd60e51b8152602060048201526012602482015271139bc81c1a5b1bdd1cc81c1c9bdd9a59195960721b6044820152606401611b0f565b5f811161316e5760405162461bcd60e51b815260206004820152601760248201527f496e76616c6964206d696e696d756d2062616c616e63650000000000000000006044820152606401611b0f565b5f805b83811015613295575f85858381811061318c5761318c614656565b90506020020160208101906131a19190614151565b6001600160a01b03163190508381101561328c575f6131c082866145a1565b90505f8787858181106131d5576131d5614656565b90506020020160208101906131ea9190614151565b6001600160a01b0316826040515f6040518083038185875af1925050503d805f8114613231576040519150601f19603f3d011682016040523d82523d5f602084013e613236565b606091505b505090508061327d5760405162461bcd60e51b8152602060048201526013602482015272115512081d1c985b9cd9995c8819985a5b1959606a1b6044820152606401611b0f565b613287828661466a565b945050505b50600101613171565b505f6132a182346145a1565b90508015613330576040515f90339083908381818185875af1925050503d805f81146132e8576040519150601f19603f3d011682016040523d82523d5f602084013e6132ed565b606091505b505090508061332e5760405162461bcd60e51b815260206004820152600d60248201526c1499599d5b990819985a5b1959609a1b6044820152606401611b0f565b505b5050505050565b5f7f0000000000000000000000000000000000000000000000000000000000000000421061336457505f90565b612a00427f00000000000000000000000000000000000000000000000000000000000000006145a1565b6008546060908190806001600160401b038111156133ae576133ae614642565b6040519080825280602002602001820160405280156133d7578160200160208202803683370190505b509250806001600160401b038111156133f2576133f2614642565b60405190808252806020026020018201604052801561341b578160200160208202803683370190505b5091505f5b81811015613543575f6008828154811061343c5761343c614656565b905f5260205f20015f9054906101000a90046001600160a01b031690508085838151811061346c5761346c614656565b6001600160a01b039283166020918202929092010152600354161561351a576003546040516370a0823160e01b81526001600160a01b038381166004830152909116906370a0823190602401602060405180830381865afa1580156134d3573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906134f7919061462b565b84838151811061350957613509614656565b60200260200101818152505061353a565b5f84838151811061352d5761352d614656565b6020026020010181815250505b50600101613420565b50509091565b60088181548110611fb7575f80fd5b5f546001600160a01b031661358057604051631e0aa0c360e21b815260040160405180910390fd5b61358932612f89565b6135a657604051634632ffe360e01b815260040160405180910390fd5b5f8054604051633ff3649360e01b8152600481018490526001600160a01b0390911690633ff3649390602401602060405180830381865afa1580156135ed573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061361191906145b4565b90506001600160a01b03811661363a576040516381d522f560e01b815260040160405180910390fd5b5f613661826040518060400160405280600481526020016373616c6560e01b815250613f2c565b90506001600160a01b03811661368a57604051631b3473a560e21b815260040160405180910390fd5b6001600160a01b03811633146136b357604051631b3473a560e21b815260040160405180910390fd5b5f8054604051634650b04560e01b8152600481018690526001600160a01b0390911690634650b04590602401602060405180830381865afa1580156136fa573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061371e91906145b4565b90506001600160a01b0381166137475760405163abca351760e01b815260040160405180910390fd5b5f8481526010602052604081205460ff1690819003613764575060015b60068160ff16106137885760405163e2a31caf60e01b815260040160405180910390fd5b6003546040516370a0823160e01b81526001600160a01b038581166004830152690a7b667f19c28bf000009283929116906370a0823190602401602060405180830381865afa1580156137dd573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613801919061462b565b1015613820576040516317f5126160e11b815260040160405180910390fd5b6003546040516323b872dd60e01b81526001600160a01b03868116600483015230602483015260448201849052909116906323b872dd906064016020604051808303815f875af1158015613876573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061389a9190614844565b506001600160a01b0383165f908152600d602052604081208054600a92906138c390849061466a565b909155505f90506138d5836001614863565b5f88815260106020908152604091829020805460ff191660ff8516908117909155915191825291925032916001600160a01b038716918a917f6544a62572f716ddb5ef122f657bcced3130b4e6b6e7ea78bccf9f8694a27df4910160405180910390a450505050505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663af30ee3f6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561399d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906139c191906145b4565b6001600160a01b0316336001600160a01b0316146139f257604051630cb73db360e21b815260040160405180910390fd5b80613a345760405162461bcd60e51b8152602060048201526012602482015271139bc81c1a5b1bdd1cc81c1c9bdd9a59195960721b6044820152606401611b0f565b5f805b82811015613b3157613a69848483818110613a5457613a54614656565b90506020020160208101906109469190614151565b613b29576008848483818110613a8157613a81614656565b9050602002016020810190613a969190614151565b8154600180820184555f9384526020842090910180546001600160a01b0319166001600160a01b03939093169290921790915590600c90868685818110613adf57613adf614656565b9050602002016020810190613af49190614151565b6001600160a01b0316815260208101919091526040015f20805460ff191691151591909117905581613b2581614775565b9250505b600101613a37565b505f34118015613b4057505f81115b15613cf6575f613b5082346146a8565b90505f613b5d833461487c565b90505f5b84811015613cf2575f805f5b600854811015613c0157888885818110613b8957613b89614656565b9050602002016020810190613b9e9190614151565b6001600160a01b031660088281548110613bba57613bba614656565b5f918252602090912001546001600160a01b031603613bf95781613bdd81614775565b92505081600103613bf15760019250613bf9565b5f9250613c01565b600101613b6d565b50818015613c0e57505f85115b15613ce857848415613c2a57613c24858261466a565b90505f94505b5f898986818110613c3d57613c3d614656565b9050602002016020810190613c529190614151565b6001600160a01b0316826040515f6040518083038185875af1925050503d805f8114613c99576040519150601f19603f3d011682016040523d82523d5f602084013e613c9e565b606091505b5050905080613ce55760405162461bcd60e51b8152602060048201526013602482015272115512081d1c985b9cd9995c8819985a5b1959606a1b6044820152606401611b0f565b50505b5050600101613b61565b5050505b7fe117669371937de9be25bcb2289999348317901d98fc0f3329182571cf613c2c8383604051613d2792919061488f565b60405180910390a1505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663af30ee3f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613d90573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613db491906145b4565b6001600160a01b0316336001600160a01b031614613de557604051630cb73db360e21b815260040160405180910390fd5b6004613df28284836148f3565b507fd28e4ca79028f3e151e2b2496a82ad2095820d02b3e69b0fa88cac665a9a88ce828260405161101b9291906149ac565b60078181548110611fb7575f80fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663af30ee3f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613e8f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613eb391906145b4565b6001600160a01b0316336001600160a01b031614613ee457604051630cb73db360e21b815260040160405180910390fd5b6001600160a01b038116613f0a5760405162461bcd60e51b8152600401611b0f9061474c565b600380546001600160a01b0319166001600160a01b0392909216919091179055565b5f805f846001600160a01b031684604051602401613f4a9190614473565b60408051601f198184030181529181526020820180516001600160e01b031663099b0d6d60e41b17905251613f7f9190614615565b5f60405180830381855afa9150503d805f8114613fb7576040519150601f19603f3d011682016040523d82523d5f602084013e613fbc565b606091505b5091509150811580613fcf575060208151105b15613fde575f925050506111db565b80806020019051810190613ff291906145b4565b95945050505050565b828054828255905f5260205f2090601f0160209004810192821561408f579160200282015f5b8382111561406157833560ff1683826101000a81548160ff021916908360ff16021790555092602001926001016020815f01049283019260010302614021565b801561408d5782816101000a81549060ff02191690556001016020815f01049283019260010302614061565b505b5061409b9291506140f2565b5090565b828054828255905f5260205f2090810192821561408f579160200282015b8281111561408f57825182546001600160a01b0319166001600160a01b039091161782556020909201916001909101906140bd565b5b8082111561409b575f81556001016140f3565b6001600160a01b0381168114610f29575f80fd5b5f806040838503121561412b575f80fd5b823561413681614106565b9150602083013561414681614106565b809150509250929050565b5f60208284031215614161575f80fd5b8135612f8281614106565b634e487b7160e01b5f52602160045260245ffd5b6003811061419c57634e487b7160e01b5f52602160045260245ffd5b9052565b606081016141ae8286614180565b602082019390935260400152919050565b602080825282518282018190525f918401906040840190835b818110156141f957835160ff168352602093840193909201916001016141d8565b509095945050505050565b5f8151808452602084019350602083015f5b8281101561423d5781516001600160a01b0316865260209586019590910190600101614216565b5093949350505050565b602081525f612f826020830184614204565b5f60208284031215614269575f80fd5b5035919050565b5f8083601f840112614280575f80fd5b5081356001600160401b03811115614296575f80fd5b6020830191508360208260051b85010111156142b0575f80fd5b9250929050565b5f80602083850312156142c8575f80fd5b82356001600160401b038111156142dd575f80fd5b6142e985828601614270565b90969095509350505050565b5f8060408385031215614306575f80fd5b823561431181614106565b946020939093013593505050565b5f6020828403121561432f575f80fd5b813560038110612f82575f80fd5b5f8151808452602084019350602083015f5b8281101561423d57815186526020958601959091019060010161434f565b606081525f61437f6060830186614204565b8281036020840152614391818661433d565b8381036040850152845180825260208087019350909101905f5b818110156143cb57835115158352602093840193909201916001016143ab565b5090979650505050505050565b5f805f80604085870312156143eb575f80fd5b84356001600160401b03811115614400575f80fd5b61440c87828801614270565b90955093505060208501356001600160401b0381111561442a575f80fd5b61443687828801614270565b95989497509550505050565b60ff81168114610f29575f80fd5b5f8060408385031215614461575f80fd5b82359150602083013561414681614442565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b602081016111db8284614180565b5f805f604084860312156144c8575f80fd5b83356001600160401b038111156144dd575f80fd5b6144e986828701614270565b909790965060209590950135949350505050565b604081525f61450f6040830185614204565b8281036020840152613ff2818561433d565b5f8060208385031215614532575f80fd5b82356001600160401b03811115614547575f80fd5b8301601f81018513614557575f80fd5b80356001600160401b0381111561456c575f80fd5b85602082840101111561457d575f80fd5b6020919091019590945092505050565b634e487b7160e01b5f52601160045260245ffd5b818103818111156111db576111db61458d565b5f602082840312156145c4575f80fd5b8151612f8281614106565b602080825281018290525f8360408301825b8581101561460b5782356145f481614442565b60ff168252602092830192909101906001016145e1565b5095945050505050565b5f82518060208501845e5f920191825250919050565b5f6020828403121561463b575f80fd5b5051919050565b634e487b7160e01b5f52604160045260245ffd5b634e487b7160e01b5f52603260045260245ffd5b808201808211156111db576111db61458d565b80820281158282048414176111db576111db61458d565b634e487b7160e01b5f52601260045260245ffd5b5f826146b6576146b6614694565b500490565b8183526020830192505f815f5b8481101561423d5781356146db81614106565b6001600160a01b0316865260209586019591909101906001016146c8565b606081525f61470c6060830187896146bb565b82810360208401528481526001600160fb1b0385111561472a575f80fd5b8460051b80876020840137604093909301939093525001602001949350505050565b6020808252600f908201526e496e76616c6964206164647265737360881b604082015260600190565b5f600182016147865761478661458d565b5060010190565b608080825285549082018190525f86815260208120909160a0840190835b818110156147d25783546001600160a01b03168352600193840193602090930192016147ab565b5050602084019690965250506040810192909252606090910152919050565b5f60208284031215614801575f80fd5b8151612f8281614442565b600181811c9082168061482057607f821691505b60208210810361483e57634e487b7160e01b5f52602260045260245ffd5b50919050565b5f60208284031215614854575f80fd5b81518015158114612f82575f80fd5b60ff81811683821601908111156111db576111db61458d565b5f8261488a5761488a614694565b500690565b602081525f6148a26020830184866146bb565b949350505050565b601f8211156148ee57805f5260205f20601f840160051c810160208510156148cf5750805b601f840160051c820191505b81811015613330575f81556001016148db565b505050565b6001600160401b0383111561490a5761490a614642565b61491e83614918835461480c565b836148aa565b5f601f84116001811461494f575f85156149385750838201355b5f19600387901b1c1916600186901b178355613330565b5f83815260208120601f198716915b8281101561497e578685013582556020948501946001909201910161495e565b508682101561499a575f1960f88860031b161c19848701351681555b505060018560011b0183555050505050565b60208152816020820152818360408301375f818301604090810191909152601f909201601f1916010191905056fea26469706673582212205b3bac2216f03366b23ba16633b7a124ad19508b5fd3d806a9fe0c714e4dcad764736f6c634300081a0033000000000000000000000000cae3fec333be0c5f4bfe932f5cafcc6f86c4c887
Deployed Bytecode
0x60806040526004361061038a575f3560e01c80637fd6b2e7116101d3578063b7a17c4c116100fd578063ded72d1f1161009d578063e83267451161006d578063e832674514610b06578063f4e8b45014610b19578063f71d96cb14610b38578063fe74379114610b57575f80fd5b8063ded72d1f14610a66578063e085c53914610a94578063e19ddff314610ac8578063e5b42e9214610ae7575f80fd5b8063c7a77e2f116100d8578063c7a77e2f146109fe578063d529251d14610a11578063dac6270d14610a30578063dbb838a914610a44575f80fd5b8063b7a17c4c146109ab578063c19d93fb146109c4578063c2e52206146109ea575f80fd5b8063938a864511610173578063b2652ec411610143578063b2652ec41461092c578063b329be371461094b578063b33ac8aa1461095f578063b38321a21461097d575f80fd5b8063938a8645146108ae5780639e75143c146108cd578063a83b589c146108ee578063af331b651461090d575f80fd5b80638aa0cb6c116101ae5780638aa0cb6c146108485780638b5b9ccc146108675780638bb98fd91461087b5780639129ce391461088f575f80fd5b80637fd6b2e7146107d157806388aafa60146107f057806388f4e6eb14610829575f80fd5b8063516f4f30116102b45780637350f431116102545780637776282011610224578063777628201461075157806379390faa146107655780637bdd449c146107845780637df3c497146107a3575f80fd5b80637350f431146106ba5780637488ad24146106e8578063755b77b31461070757806376dd110f14610726575f80fd5b8063554c1b1f1161028f578063554c1b1f1461062657806356de96db1461065957806356df26be14610678578063620274061461069b575f80fd5b8063516f4f30146105d257806353aab43414610609578063546216f114610611575f80fd5b806318edd1781161032a57806344d9bc5f116102fa57806344d9bc5f1461054d57806348bb35a2146105805780634ded2e8e1461059f5780634ffac413146105be575f80fd5b806318edd178146104c6578063241e5622146104e75780632f5a90a6146105085780633ccfd60b14610539575f80fd5b806309c95e101161036557806309c95e101461041957806312065fe01461046057806316c44e6f1461047c5780631746bd1b1461049b575f80fd5b8063040141e5146103955780630642bc41146103d9578063093119f7146103f8575f80fd5b3661039157005b5f80fd5b3480156103a0575f80fd5b506103bc7382af49447d8a07e3bd95bd0d56f35241523fbab181565b6040516001600160a01b0390911681526020015b60405180910390f35b3480156103e4575f80fd5b506003546103bc906001600160a01b031681565b348015610403575f80fd5b5061041761041236600461411a565b610b76565b005b348015610424575f80fd5b50610450610433366004614151565b6001600160a01b03165f908152600b602052604090205460ff1690565b60405190151581526020016103d0565b34801561046b575f80fd5b50475b6040519081526020016103d0565b348015610487575f80fd5b506001546103bc906001600160a01b031681565b3480156104a6575f80fd5b506005546007546040516103d09260ff1691906509184e72a000906141a0565b3480156104d1575f80fd5b506104da610cc0565b6040516103d091906141bf565b3480156104f2575f80fd5b506104fb610d33565b6040516103d09190614247565b348015610513575f80fd5b50610527610522366004614259565b610d92565b60405160ff90911681526020016103d0565b348015610544575f80fd5b50610417610dc3565b348015610558575f80fd5b5061046e7f00000000000000000000000000000000000000000000000000000000691e1a7181565b34801561058b575f80fd5b5061041761059a3660046142b7565b610f2c565b3480156105aa575f80fd5b506104506105b93660046142f5565b611027565b3480156105c9575f80fd5b5060085461046e565b3480156105dd575f80fd5b506104506105ec366004614151565b6001600160a01b03165f908152600e602052604090205460ff1690565b6104176111e1565b34801561061c575f80fd5b5061046e600a5481565b348015610631575f80fd5b506103bc7f000000000000000000000000cae3fec333be0c5f4bfe932f5cafcc6f86c4c88781565b348015610664575f80fd5b5061041761067336600461431f565b611355565b348015610683575f80fd5b5061068c611463565b6040516103d09392919061436d565b3480156106a6575f80fd5b506104176106b5366004614151565b611625565b3480156106c5575f80fd5b506104506106d4366004614151565b600c6020525f908152604090205460ff1681565b3480156106f3575f80fd5b506104176107023660046143d8565b61178b565b348015610712575f80fd5b50610417610721366004614151565b611a38565b348015610731575f80fd5b5061046e610740366004614151565b600d6020525f908152604090205481565b34801561075c575f80fd5b50610417611b43565b348015610770575f80fd5b5061041761077f3660046142f5565b611f11565b34801561078f575f80fd5b506103bc61079e366004614259565b611fa8565b3480156107ae575f80fd5b506104506107bd366004614151565b600b6020525f908152604090205460ff1681565b3480156107dc575f80fd5b506104176107eb366004614450565b611fd0565b3480156107fb575f80fd5b5061045061080a36600461411a565b600f60209081525f928352604080842090915290825290205460ff1681565b348015610834575f80fd5b5061041761084336600461411a565b612106565b348015610853575f80fd5b50610417610862366004614151565b612861565b348015610872575f80fd5b506104fb61295a565b348015610886575f80fd5b506104506129b8565b34801561089a575f80fd5b506104176108a9366004614259565b612a05565b3480156108b9575f80fd5b506104176108c8366004614151565b612cc5565b3480156108d8575f80fd5b506108e1612d94565b6040516103d09190614473565b3480156108f9575f80fd5b506104176109083660046142f5565b612e20565b348015610918575f80fd5b50610527610927366004614259565b612f62565b348015610937575f80fd5b50610450610946366004614151565b612f89565b348015610956575f80fd5b506104fb612fce565b34801561096a575f80fd5b505f546103bc906001600160a01b031681565b348015610988575f80fd5b50610450610997366004614151565b600e6020525f908152604090205460ff1681565b3480156109b6575f80fd5b5061046e6509184e72a00081565b3480156109cf575f80fd5b506005546109dd9060ff1681565b6040516103d091906144a8565b3480156109f5575f80fd5b5060075461046e565b610417610a0c3660046144b6565b61302c565b348015610a1c575f80fd5b506002546103bc906001600160a01b031681565b348015610a3b575f80fd5b5061046e613337565b348015610a4f575f80fd5b50610a5861338e565b6040516103d09291906144fd565b348015610a71575f80fd5b50610527610a80366004614259565b60106020525f908152604090205460ff1681565b348015610a9f575f80fd5b5061046e610aae366004614151565b6001600160a01b03165f908152600d602052604090205490565b348015610ad3575f80fd5b506103bc610ae2366004614259565b613549565b348015610af2575f80fd5b50610417610b01366004614259565b613558565b610417610b143660046142b7565b613941565b348015610b24575f80fd5b50610417610b33366004614521565b613d34565b348015610b43575f80fd5b506103bc610b52366004614259565b613e24565b348015610b62575f80fd5b50610417610b71366004614151565b613e33565b335f908152600c602052604090205460ff16610ba557604051634632ffe360e01b815260040160405180910390fd5b335f908152600e602052604090205460ff1615610bd557604051631894063360e21b815260040160405180910390fd5b6001600160a01b0381165f908152600b602052604090205460ff16610c0d5760405163abca351760e01b815260040160405180910390fd5b335f908152600e60209081526040808320805460ff191660011790556001600160a01b0384168352600d90915281205490600a821015610c4d5781610c50565b600a5b9050610c5c81836145a1565b6001600160a01b038481165f818152600d602090815260408083209590955584518681529081019190915290929187169133917f8044fa4da29a21540b095aa9cddd2e3f31d47978eb3d8440183b6ac98bf3bda1910160405180910390a450505050565b60606006805480602002602001604051908101604052809291908181526020018280548015610d2957602002820191905f5260205f20905f905b825461010083900a900460ff16815260206001928301818104948501949093039092029101808411610cfa5790505b5050505050905090565b60606008805480602002602001604051908101604052809291908181526020018280548015610d2957602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311610d6b575050505050905090565b60068181548110610da1575f80fd5b905f5260205f209060209182820401919006915054906101000a900460ff1681565b7f000000000000000000000000cae3fec333be0c5f4bfe932f5cafcc6f86c4c8876001600160a01b031663af30ee3f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e1f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e4391906145b4565b6001600160a01b0316336001600160a01b031614610e7457604051630cb73db360e21b815260040160405180910390fd5b7f000000000000000000000000cae3fec333be0c5f4bfe932f5cafcc6f86c4c8876001600160a01b031663af30ee3f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ed0573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ef491906145b4565b6001600160a01b03166108fc4790811502906040515f60405180830381858888f19350505050158015610f29573d5f803e3d5ffd5b50565b7f000000000000000000000000cae3fec333be0c5f4bfe932f5cafcc6f86c4c8876001600160a01b031663af30ee3f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f88573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610fac91906145b4565b6001600160a01b0316336001600160a01b031614610fdd57604051630cb73db360e21b815260040160405180910390fd5b610fe960068383613ffb565b507f94e1ce80c1f560eae2d7da116779b3aacee5613170afb9876373e3c761aa1956828260405161101b9291906145cf565b60405180910390a15050565b5f80546001600160a01b031661103e57505f6111db565b5f8054604051633ff3649360e01b8152600481018590526001600160a01b0390911690633ff3649390602401602060405180830381865afa158015611085573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110a991906145b4565b90506001600160a01b0381166110c2575f9150506111db565b5f6110ef826040518060400160405280600a81526020016918dc9959195b9d1a585b60b21b815250613f2c565b90506001600160a01b038116611109575f925050506111db565b6040516001600160a01b0386811660248301525f91829184169060440160408051601f198184030181529181526020820180516001600160e01b03166370a0823160e01b1790525161115b9190614615565b5f60405180830381855afa9150503d805f8114611193576040519150601f19603f3d011682016040523d82523d5f602084013e611198565b606091505b50915091508115806111ab575060208151105b156111bc575f9450505050506111db565b5f818060200190518101906111d1919061462b565b1515955050505050505b92915050565b5f60055460ff1660028111156111f9576111f961416c565b1461121757604051635c07b6d760e11b815260040160405180910390fd5b6509184e72a00034101561123e5760405163cd1c886760e01b815260040160405180910390fd5b335f908152600b602052604090205460ff161561126e576040516314c4fea760e31b815260040160405180910390fd5b6007805460018181019092557fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c6880180546001600160a01b031916339081179091555f818152600b60209081526040808320805460ff1916909517909455600d90528281205590517f7dbd99091135732d8894a7112b904af6bf7fee8441105b31987f90c32329fdd9906113049034815260200190565b60405180910390a26509184e72a00034111561135357336108fc61132e6509184e72a000346145a1565b6040518115909202915f818181858888f19350505050158015610f29573d5f803e3d5ffd5b565b7f000000000000000000000000cae3fec333be0c5f4bfe932f5cafcc6f86c4c8876001600160a01b031663af30ee3f6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156113b1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906113d591906145b4565b6001600160a01b0316336001600160a01b03161461140657604051630cb73db360e21b815260040160405180910390fd5b6005805482919060ff191660018360028111156114255761142561416c565b02179055507ea8b06dd72552dea96e97c9a96acf39a1908ada44765cefe367620485b2c7e18160405161145891906144a8565b60405180910390a150565b60085460609081908190806001600160401b0381111561148557611485614642565b6040519080825280602002602001820160405280156114ae578160200160208202803683370190505b509350806001600160401b038111156114c9576114c9614642565b6040519080825280602002602001820160405280156114f2578160200160208202803683370190505b509250806001600160401b0381111561150d5761150d614642565b604051908082528060200260200182016040528015611536578160200160208202803683370190505b5091505f5b8181101561161e575f6008828154811061155757611557614656565b905f5260205f20015f9054906101000a90046001600160a01b031690508086838151811061158757611587614656565b60200260200101906001600160a01b031690816001600160a01b031681525050806001600160a01b0316318583815181106115c4576115c4614656565b6020908102919091018101919091526001600160a01b0382165f908152600e9091526040902054845160ff9091169085908490811061160557611605614656565b911515602092830291909101909101525060010161153b565b5050909192565b7f000000000000000000000000cae3fec333be0c5f4bfe932f5cafcc6f86c4c8876001600160a01b031663af30ee3f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611681573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116a591906145b4565b6001600160a01b0316336001600160a01b0316146116d657604051630cb73db360e21b815260040160405180910390fd5b6116df81612f89565b156116fd5760405163e0dbb1a760e01b815260040160405180910390fd5b6008805460018082019092557ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee30180546001600160a01b0319166001600160a01b0384169081179091555f818152600c6020526040808220805460ff1916909417909355915190917f07577ee4d7b640060b986e698b16d90aef8e3a4fffa36dd13d3b79195e70b3d691a250565b7f000000000000000000000000cae3fec333be0c5f4bfe932f5cafcc6f86c4c8876001600160a01b031663af30ee3f6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156117e7573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061180b91906145b4565b6001600160a01b0316336001600160a01b03161461183c57604051630cb73db360e21b815260040160405180910390fd5b8215806118495750828114155b156118675760405163a9854bc960e01b815260040160405180910390fd5b5f805b828110156118a05783838281811061188457611884614656565b9050602002013582611896919061466a565b915060010161186a565b50806103e8146118c357604051636d2fd3c960e01b815260040160405180910390fd5b475f8190036118d3575050611a32565b5f5b858110156119ef575f8787838181106118f0576118f0614656565b90506020020160208101906119059190614151565b6001600160a01b0316146119e7575f6103e886868481811061192957611929614656565b905060200201358461193b919061467d565b61194591906146a8565b905080156119e5575f88888481811061196057611960614656565b90506020020160208101906119759190614151565b6001600160a01b0316826040515f6040518083038185875af1925050503d805f81146119bc576040519150601f19603f3d011682016040523d82523d5f602084013e6119c1565b606091505b50509050806119e357604051630ec6ac4160e21b815260040160405180910390fd5b505b505b6001016118d5565b507f5a31676f5fc71e56ec99e78f1f76a78352cdc05a4c1be0d3accdbb305a512ce48686868685604051611a279594939291906146f9565b60405180910390a150505b50505050565b7f000000000000000000000000cae3fec333be0c5f4bfe932f5cafcc6f86c4c8876001600160a01b031663af30ee3f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a94573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611ab891906145b4565b6001600160a01b0316336001600160a01b031614611ae957604051630cb73db360e21b815260040160405180910390fd5b6001600160a01b038116611b185760405162461bcd60e51b8152600401611b0f9061474c565b60405180910390fd5b5f80546001600160a01b039092166001600160a01b0319928316811790915560028054909216179055565b7f00000000000000000000000000000000000000000000000000000000691e1a71421015611b8457604051638f86c6b360e01b815260040160405180910390fd5b600260055460ff166002811115611b9d57611b9d61416c565b03611bbb57604051636e2ab89360e11b815260040160405180910390fd5b6007545f03611bd3576005805460ff19166002179055565b5f805b600754811015611c32575f600d5f60078481548110611bf757611bf7614656565b5f9182526020808320909101546001600160a01b03168352820192909252604001902054905082811115611c29578092505b50600101611bd6565b506007545f906001600160401b03811115611c4f57611c4f614642565b604051908082528060200260200182016040528015611c78578160200160208202803683370190505b5090505f805b600754811015611d365783600d5f60078481548110611c9f57611c9f614656565b5f9182526020808320909101546001600160a01b0316835282019290925260400190205403611d2e5760078181548110611cdb57611cdb614656565b905f5260205f20015f9054906101000a90046001600160a01b0316838381518110611d0857611d08614656565b6001600160a01b039092166020928302919091019091015281611d2a81614775565b9250505b600101611c7e565b50806001600160401b03811115611d4f57611d4f614642565b604051908082528060200260200182016040528015611d78578160200160208202803683370190505b508051611d8d9160099160209091019061409f565b505f5b81811015611df557828181518110611daa57611daa614656565b602002602001015160098281548110611dc557611dc5614656565b5f91825260209091200180546001600160a01b0319166001600160a01b0392909216919091179055600101611d90565b50600a8390556005805460ff19166002179055475f8115801590611e1857505f83115b15611eca57611e2783836146a8565b90505f5b83811015611ec8575f60098281548110611e4757611e47614656565b5f9182526020822001546040516001600160a01b039091169185919081818185875af1925050503d805f8114611e98576040519150601f19603f3d011682016040523d82523d5f602084013e611e9d565b606091505b5050905080611ebf57604051630ec6ac4160e21b815260040160405180910390fd5b50600101611e2b565b505b7f8b8f0658aa11ba65d0656d3982f05a3d5d88b0190cc77264e6fc6aff7e711da06009600a548484604051611f02949392919061478d565b60405180910390a15050505050565b611f1a33612f89565b611f3757604051634632ffe360e01b815260040160405180910390fd5b6001600160a01b0382165f908152600d602052604081208054839290611f5e90849061466a565b90915550506040518181526001600160a01b0383169033907f8c1e155b9f22132fd0366f32e05296679a0174614fe6dc4b2f7e2fcfc0385534906020015b60405180910390a35050565b60098181548110611fb7575f80fd5b5f918252602090912001546001600160a01b0316905081565b7f000000000000000000000000cae3fec333be0c5f4bfe932f5cafcc6f86c4c8876001600160a01b031663af30ee3f6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561202c573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061205091906145b4565b6001600160a01b0316336001600160a01b03161461208157604051630cb73db360e21b815260040160405180910390fd5b60018160ff161080612096575060068160ff16115b156120b45760405163560612c960e01b815260040160405180910390fd5b5f82815260106020908152604091829020805460ff191660ff85169081179091559151918252339184917fa5df98dd2060f5d5cfe17f03fee367e49d826fa19635fb6874523063191cc30e9101611f9c565b335f908152600c602052604090205460ff1661213557604051634632ffe360e01b815260040160405180910390fd5b335f908152600e602052604090205460ff161561216557604051631894063360e21b815260040160405180910390fd5b6001600160a01b0381165f908152600b602052604090205460ff1661219d5760405163abca351760e01b815260040160405180910390fd5b335f908152600e6020526040808220805460ff19166001179055815490516370b131c360e11b81526001600160a01b0384811660048301529091169063e162638690602401602060405180830381865afa1580156121fd573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612221919061462b565b9050805f036122695760405162461bcd60e51b8152602060048201526014602482015273283630bcb2b9103430b99037379039b2b1ba37b960611b6044820152606401611b0f565b5f8054604051633ff3649360e01b8152600481018490526001600160a01b0390911690633ff3649390602401602060405180830381865afa1580156122b0573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906122d491906145b4565b90506001600160a01b03811661231a5760405162461bcd60e51b815260206004820152600b60248201526a4e6f20726567697374727960a81b6044820152606401611b0f565b5f61234282604051806040016040528060058152602001647374616b6560d81b815250613f2c565b90506001600160a01b03811661238c5760405162461bcd60e51b815260206004820152600f60248201526e4e6f207374616b65206d6f64756c6560881b6044820152606401611b0f565b6001546001600160a01b03166123d65760405162461bcd60e51b815260206004820152600f60248201526e105d591a5d1bdc881b9bdd081cd95d608a1b6044820152606401611b0f565b6001546040516001600160a01b0383811660248301525f92839291169060440160408051601f198184030181529181526020820180516001600160e01b0316639d26080960e01b1790525161242b9190614615565b5f60405180830381855afa9150503d805f8114612463576040519150601f19603f3d011682016040523d82523d5f602084013e612468565b606091505b509150915081801561247c57506020815110155b6124bd5760405162461bcd60e51b8152602060048201526012602482015271105d591a5d0818da1958dac819985a5b195960721b6044820152606401611b0f565b5f818060200190518101906124d291906147f1565b90508060ff166004146125275760405162461bcd60e51b815260206004820152601960248201527f4e6f74206175646974656420666f7220636861707465722034000000000000006044820152606401611b0f565b5f8054604051633a02a42d60e01b81526001600160a01b038b8116600483015290911690633a02a42d90602401602060405180830381865afa15801561256f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612593919061462b565b905069021e19e0c9bab24000008110156125ef5760405162461bcd60e51b815260206004820152601d60248201527f4b696c6c65722068617320696e73756666696369656e74207374616b650000006044820152606401611b0f565b6040516001600160a01b038a811660248301525f919087169060440160408051601f198184030181529181526020820180516001600160e01b031663c96be4cb60e01b179052516126409190614615565b5f604051808303815f865af19150503d805f8114612679576040519150601f19603f3d011682016040523d82523d5f602084013e61267e565b606091505b50509050806126c35760405162461bcd60e51b815260206004820152601160248201527014db185cda0818d85b1b0819985a5b1959607a1b6044820152606401611b0f565b5f8054604051633a02a42d60e01b81526001600160a01b038d8116600483015290911690633a02a42d90602401602060405180830381865afa15801561270b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061272f919061462b565b9050801561279b5760405162461bcd60e51b815260206004820152603360248201527f536c61736820646964206e6f74206275726e207374616b65202d206d616c69636044820152721a5bdd5cc81cdd185ad94818dbdb9d1c9858dd606a1b6064820152608401611b0f565b69021e19e0c9bab24000006127b082856145a1565b101561280a5760405162461bcd60e51b8152602060048201526024808201527f536c61736820646964206e6f74206275726e2066756c6c207374616b6520616d6044820152631bdd5b9d60e21b6064820152608401611b0f565b604080515f80825260208201526001600160a01b03808d1692908e169133917f8044fa4da29a21540b095aa9cddd2e3f31d47978eb3d8440183b6ac98bf3bda1910160405180910390a45050505050505050505050565b7f000000000000000000000000cae3fec333be0c5f4bfe932f5cafcc6f86c4c8876001600160a01b031663af30ee3f6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156128bd573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906128e191906145b4565b6001600160a01b0316336001600160a01b03161461291257604051630cb73db360e21b815260040160405180910390fd5b6001600160a01b0381166129385760405162461bcd60e51b8152600401611b0f9061474c565b600180546001600160a01b0319166001600160a01b0392909216919091179055565b60606007805480602002602001604051908101604052809291908181526020018280548015610d2957602002820191905f5260205f209081546001600160a01b03168152600190910190602001808311610d6b575050505050905090565b5f7f00000000000000000000000000000000000000000000000000000000691e1a714210158015612a005750600260055460ff1660028111156129fd576129fd61416c565b14155b905090565b5f546001600160a01b0316612a2d57604051631e0aa0c360e21b815260040160405180910390fd5b612a3632612f89565b612a5357604051634632ffe360e01b815260040160405180910390fd5b5f8054604051633ff3649360e01b8152600481018490526001600160a01b0390911690633ff3649390602401602060405180830381865afa158015612a9a573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612abe91906145b4565b90506001600160a01b038116612ae7576040516381d522f560e01b815260040160405180910390fd5b5f612b14826040518060400160405280600a81526020016918dc9959195b9d1a585b60b21b815250613f2c565b90506001600160a01b038116612b3d57604051635e5b1d7560e11b815260040160405180910390fd5b6001600160a01b0381163314612b6657604051635e5b1d7560e11b815260040160405180910390fd5b5f8054604051634650b04560e01b8152600481018690526001600160a01b0390911690634650b04590602401602060405180830381865afa158015612bad573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612bd191906145b4565b90506001600160a01b038116612bfa5760405163abca351760e01b815260040160405180910390fd5b325f908152600f602090815260408083206001600160a01b038516845290915290205460ff1615612c3e5760405163933099c160e01b815260040160405180910390fd5b325f908152600f602090815260408083206001600160a01b03851684528252808320805460ff19166001179055600d9091528120805460029290612c8390849061466a565b909155505060405133906001600160a01b0383169032907f8483d60736ac8e5fa0068cccf221544749b1c7acc419a99c12df90a44c966c9d905f90a450505050565b6002546001600160a01b03163314612cf05760405163cbf6cf7b60e01b815260040160405180910390fd5b5f805b600754811015612d4457826001600160a01b031660078281548110612d1a57612d1a614656565b5f918252602090912001546001600160a01b031603612d3c5760019150612d44565b600101612cf3565b5080612d635760405163abca351760e01b815260040160405180910390fd5b6001600160a01b0382165f908152600d60205260408120805460059290612d8b90849061466a565b90915550505050565b60048054612da19061480c565b80601f0160208091040260200160405190810160405280929190818152602001828054612dcd9061480c565b8015612e185780601f10612def57610100808354040283529160200191612e18565b820191905f5260205f20905b815481529060010190602001808311612dfb57829003601f168201915b505050505081565b6001546001600160a01b03163314612e4b5760405163f87c866960e01b815260040160405180910390fd5b5f805b600754811015612e9f57836001600160a01b031660078281548110612e7557612e75614656565b5f918252602090912001546001600160a01b031603612e975760019150612e9f565b600101612e4e565b5080612ebe5760405163abca351760e01b815260040160405180910390fd5b6001600160a01b0383165f908152600d602052604090205482811015612ef75760405163303e7a0760e01b815260040160405180910390fd5b612f0183826145a1565b6001600160a01b0385165f818152600d6020526040908190208390555190917f2d8ea5250bf29dafe8cda27d1a8c9aaf28837abf1505e7f02097a7f44bbee54c91612f5491878252602082015260400190565b60405180910390a250505050565b5f8181526010602052604081205460ff168015612f7f5780612f82565b60015b9392505050565b6001600160a01b0381165f908152600e602052604081205460ff1615612fb057505f919050565b506001600160a01b03165f908152600c602052604090205460ff1690565b60606009805480602002602001604051908101604052809291908181526020018280548015610d2957602002820191905f5260205f209081546001600160a01b03168152600190910190602001808311610d6b575050505050905090565b7f000000000000000000000000cae3fec333be0c5f4bfe932f5cafcc6f86c4c8876001600160a01b031663af30ee3f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613088573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906130ac91906145b4565b6001600160a01b0316336001600160a01b0316146130dd57604051630cb73db360e21b815260040160405180910390fd5b8161311f5760405162461bcd60e51b8152602060048201526012602482015271139bc81c1a5b1bdd1cc81c1c9bdd9a59195960721b6044820152606401611b0f565b5f811161316e5760405162461bcd60e51b815260206004820152601760248201527f496e76616c6964206d696e696d756d2062616c616e63650000000000000000006044820152606401611b0f565b5f805b83811015613295575f85858381811061318c5761318c614656565b90506020020160208101906131a19190614151565b6001600160a01b03163190508381101561328c575f6131c082866145a1565b90505f8787858181106131d5576131d5614656565b90506020020160208101906131ea9190614151565b6001600160a01b0316826040515f6040518083038185875af1925050503d805f8114613231576040519150601f19603f3d011682016040523d82523d5f602084013e613236565b606091505b505090508061327d5760405162461bcd60e51b8152602060048201526013602482015272115512081d1c985b9cd9995c8819985a5b1959606a1b6044820152606401611b0f565b613287828661466a565b945050505b50600101613171565b505f6132a182346145a1565b90508015613330576040515f90339083908381818185875af1925050503d805f81146132e8576040519150601f19603f3d011682016040523d82523d5f602084013e6132ed565b606091505b505090508061332e5760405162461bcd60e51b815260206004820152600d60248201526c1499599d5b990819985a5b1959609a1b6044820152606401611b0f565b505b5050505050565b5f7f00000000000000000000000000000000000000000000000000000000691e1a71421061336457505f90565b612a00427f00000000000000000000000000000000000000000000000000000000691e1a716145a1565b6008546060908190806001600160401b038111156133ae576133ae614642565b6040519080825280602002602001820160405280156133d7578160200160208202803683370190505b509250806001600160401b038111156133f2576133f2614642565b60405190808252806020026020018201604052801561341b578160200160208202803683370190505b5091505f5b81811015613543575f6008828154811061343c5761343c614656565b905f5260205f20015f9054906101000a90046001600160a01b031690508085838151811061346c5761346c614656565b6001600160a01b039283166020918202929092010152600354161561351a576003546040516370a0823160e01b81526001600160a01b038381166004830152909116906370a0823190602401602060405180830381865afa1580156134d3573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906134f7919061462b565b84838151811061350957613509614656565b60200260200101818152505061353a565b5f84838151811061352d5761352d614656565b6020026020010181815250505b50600101613420565b50509091565b60088181548110611fb7575f80fd5b5f546001600160a01b031661358057604051631e0aa0c360e21b815260040160405180910390fd5b61358932612f89565b6135a657604051634632ffe360e01b815260040160405180910390fd5b5f8054604051633ff3649360e01b8152600481018490526001600160a01b0390911690633ff3649390602401602060405180830381865afa1580156135ed573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061361191906145b4565b90506001600160a01b03811661363a576040516381d522f560e01b815260040160405180910390fd5b5f613661826040518060400160405280600481526020016373616c6560e01b815250613f2c565b90506001600160a01b03811661368a57604051631b3473a560e21b815260040160405180910390fd5b6001600160a01b03811633146136b357604051631b3473a560e21b815260040160405180910390fd5b5f8054604051634650b04560e01b8152600481018690526001600160a01b0390911690634650b04590602401602060405180830381865afa1580156136fa573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061371e91906145b4565b90506001600160a01b0381166137475760405163abca351760e01b815260040160405180910390fd5b5f8481526010602052604081205460ff1690819003613764575060015b60068160ff16106137885760405163e2a31caf60e01b815260040160405180910390fd5b6003546040516370a0823160e01b81526001600160a01b038581166004830152690a7b667f19c28bf000009283929116906370a0823190602401602060405180830381865afa1580156137dd573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613801919061462b565b1015613820576040516317f5126160e11b815260040160405180910390fd5b6003546040516323b872dd60e01b81526001600160a01b03868116600483015230602483015260448201849052909116906323b872dd906064016020604051808303815f875af1158015613876573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061389a9190614844565b506001600160a01b0383165f908152600d602052604081208054600a92906138c390849061466a565b909155505f90506138d5836001614863565b5f88815260106020908152604091829020805460ff191660ff8516908117909155915191825291925032916001600160a01b038716918a917f6544a62572f716ddb5ef122f657bcced3130b4e6b6e7ea78bccf9f8694a27df4910160405180910390a450505050505050565b7f000000000000000000000000cae3fec333be0c5f4bfe932f5cafcc6f86c4c8876001600160a01b031663af30ee3f6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561399d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906139c191906145b4565b6001600160a01b0316336001600160a01b0316146139f257604051630cb73db360e21b815260040160405180910390fd5b80613a345760405162461bcd60e51b8152602060048201526012602482015271139bc81c1a5b1bdd1cc81c1c9bdd9a59195960721b6044820152606401611b0f565b5f805b82811015613b3157613a69848483818110613a5457613a54614656565b90506020020160208101906109469190614151565b613b29576008848483818110613a8157613a81614656565b9050602002016020810190613a969190614151565b8154600180820184555f9384526020842090910180546001600160a01b0319166001600160a01b03939093169290921790915590600c90868685818110613adf57613adf614656565b9050602002016020810190613af49190614151565b6001600160a01b0316815260208101919091526040015f20805460ff191691151591909117905581613b2581614775565b9250505b600101613a37565b505f34118015613b4057505f81115b15613cf6575f613b5082346146a8565b90505f613b5d833461487c565b90505f5b84811015613cf2575f805f5b600854811015613c0157888885818110613b8957613b89614656565b9050602002016020810190613b9e9190614151565b6001600160a01b031660088281548110613bba57613bba614656565b5f918252602090912001546001600160a01b031603613bf95781613bdd81614775565b92505081600103613bf15760019250613bf9565b5f9250613c01565b600101613b6d565b50818015613c0e57505f85115b15613ce857848415613c2a57613c24858261466a565b90505f94505b5f898986818110613c3d57613c3d614656565b9050602002016020810190613c529190614151565b6001600160a01b0316826040515f6040518083038185875af1925050503d805f8114613c99576040519150601f19603f3d011682016040523d82523d5f602084013e613c9e565b606091505b5050905080613ce55760405162461bcd60e51b8152602060048201526013602482015272115512081d1c985b9cd9995c8819985a5b1959606a1b6044820152606401611b0f565b50505b5050600101613b61565b5050505b7fe117669371937de9be25bcb2289999348317901d98fc0f3329182571cf613c2c8383604051613d2792919061488f565b60405180910390a1505050565b7f000000000000000000000000cae3fec333be0c5f4bfe932f5cafcc6f86c4c8876001600160a01b031663af30ee3f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613d90573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613db491906145b4565b6001600160a01b0316336001600160a01b031614613de557604051630cb73db360e21b815260040160405180910390fd5b6004613df28284836148f3565b507fd28e4ca79028f3e151e2b2496a82ad2095820d02b3e69b0fa88cac665a9a88ce828260405161101b9291906149ac565b60078181548110611fb7575f80fd5b7f000000000000000000000000cae3fec333be0c5f4bfe932f5cafcc6f86c4c8876001600160a01b031663af30ee3f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613e8f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613eb391906145b4565b6001600160a01b0316336001600160a01b031614613ee457604051630cb73db360e21b815260040160405180910390fd5b6001600160a01b038116613f0a5760405162461bcd60e51b8152600401611b0f9061474c565b600380546001600160a01b0319166001600160a01b0392909216919091179055565b5f805f846001600160a01b031684604051602401613f4a9190614473565b60408051601f198184030181529181526020820180516001600160e01b031663099b0d6d60e41b17905251613f7f9190614615565b5f60405180830381855afa9150503d805f8114613fb7576040519150601f19603f3d011682016040523d82523d5f602084013e613fbc565b606091505b5091509150811580613fcf575060208151105b15613fde575f925050506111db565b80806020019051810190613ff291906145b4565b95945050505050565b828054828255905f5260205f2090601f0160209004810192821561408f579160200282015f5b8382111561406157833560ff1683826101000a81548160ff021916908360ff16021790555092602001926001016020815f01049283019260010302614021565b801561408d5782816101000a81549060ff02191690556001016020815f01049283019260010302614061565b505b5061409b9291506140f2565b5090565b828054828255905f5260205f2090810192821561408f579160200282015b8281111561408f57825182546001600160a01b0319166001600160a01b039091161782556020909201916001909101906140bd565b5b8082111561409b575f81556001016140f3565b6001600160a01b0381168114610f29575f80fd5b5f806040838503121561412b575f80fd5b823561413681614106565b9150602083013561414681614106565b809150509250929050565b5f60208284031215614161575f80fd5b8135612f8281614106565b634e487b7160e01b5f52602160045260245ffd5b6003811061419c57634e487b7160e01b5f52602160045260245ffd5b9052565b606081016141ae8286614180565b602082019390935260400152919050565b602080825282518282018190525f918401906040840190835b818110156141f957835160ff168352602093840193909201916001016141d8565b509095945050505050565b5f8151808452602084019350602083015f5b8281101561423d5781516001600160a01b0316865260209586019590910190600101614216565b5093949350505050565b602081525f612f826020830184614204565b5f60208284031215614269575f80fd5b5035919050565b5f8083601f840112614280575f80fd5b5081356001600160401b03811115614296575f80fd5b6020830191508360208260051b85010111156142b0575f80fd5b9250929050565b5f80602083850312156142c8575f80fd5b82356001600160401b038111156142dd575f80fd5b6142e985828601614270565b90969095509350505050565b5f8060408385031215614306575f80fd5b823561431181614106565b946020939093013593505050565b5f6020828403121561432f575f80fd5b813560038110612f82575f80fd5b5f8151808452602084019350602083015f5b8281101561423d57815186526020958601959091019060010161434f565b606081525f61437f6060830186614204565b8281036020840152614391818661433d565b8381036040850152845180825260208087019350909101905f5b818110156143cb57835115158352602093840193909201916001016143ab565b5090979650505050505050565b5f805f80604085870312156143eb575f80fd5b84356001600160401b03811115614400575f80fd5b61440c87828801614270565b90955093505060208501356001600160401b0381111561442a575f80fd5b61443687828801614270565b95989497509550505050565b60ff81168114610f29575f80fd5b5f8060408385031215614461575f80fd5b82359150602083013561414681614442565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b602081016111db8284614180565b5f805f604084860312156144c8575f80fd5b83356001600160401b038111156144dd575f80fd5b6144e986828701614270565b909790965060209590950135949350505050565b604081525f61450f6040830185614204565b8281036020840152613ff2818561433d565b5f8060208385031215614532575f80fd5b82356001600160401b03811115614547575f80fd5b8301601f81018513614557575f80fd5b80356001600160401b0381111561456c575f80fd5b85602082840101111561457d575f80fd5b6020919091019590945092505050565b634e487b7160e01b5f52601160045260245ffd5b818103818111156111db576111db61458d565b5f602082840312156145c4575f80fd5b8151612f8281614106565b602080825281018290525f8360408301825b8581101561460b5782356145f481614442565b60ff168252602092830192909101906001016145e1565b5095945050505050565b5f82518060208501845e5f920191825250919050565b5f6020828403121561463b575f80fd5b5051919050565b634e487b7160e01b5f52604160045260245ffd5b634e487b7160e01b5f52603260045260245ffd5b808201808211156111db576111db61458d565b80820281158282048414176111db576111db61458d565b634e487b7160e01b5f52601260045260245ffd5b5f826146b6576146b6614694565b500490565b8183526020830192505f815f5b8481101561423d5781356146db81614106565b6001600160a01b0316865260209586019591909101906001016146c8565b606081525f61470c6060830187896146bb565b82810360208401528481526001600160fb1b0385111561472a575f80fd5b8460051b80876020840137604093909301939093525001602001949350505050565b6020808252600f908201526e496e76616c6964206164647265737360881b604082015260600190565b5f600182016147865761478661458d565b5060010190565b608080825285549082018190525f86815260208120909160a0840190835b818110156147d25783546001600160a01b03168352600193840193602090930192016147ab565b5050602084019690965250506040810192909252606090910152919050565b5f60208284031215614801575f80fd5b8151612f8281614442565b600181811c9082168061482057607f821691505b60208210810361483e57634e487b7160e01b5f52602260045260245ffd5b50919050565b5f60208284031215614854575f80fd5b81518015158114612f82575f80fd5b60ff81811683821601908111156111db576111db61458d565b5f8261488a5761488a614694565b500690565b602081525f6148a26020830184866146bb565b949350505050565b601f8211156148ee57805f5260205f20601f840160051c810160208510156148cf5750805b601f840160051c820191505b81811015613330575f81556001016148db565b505050565b6001600160401b0383111561490a5761490a614642565b61491e83614918835461480c565b836148aa565b5f601f84116001811461494f575f85156149385750838201355b5f19600387901b1c1916600186901b178355613330565b5f83815260208120601f198716915b8281101561497e578685013582556020948501946001909201910161495e565b508682101561499a575f1960f88860031b161c19848701351681555b505060018560011b0183555050505050565b60208152816020820152818360408301375f818301604090810191909152601f909201601f1916010191905056fea26469706673582212205b3bac2216f03366b23ba16633b7a124ad19508b5fd3d806a9fe0c714e4dcad764736f6c634300081a0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000cae3fec333be0c5f4bfe932f5cafcc6f86c4c887
-----Decoded View---------------
Arg [0] : _universe (address): 0xcAe3fEC333BE0c5F4BfE932F5CafCC6F86c4c887
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000cae3fec333be0c5f4bfe932f5cafcc6f86c4c887
Net Worth in USD
Net Worth in ETH
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
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.