ETH Price: $3,454.42 (-0.00%)
Gas: 6 Gwei

Token

 

Overview

Max Total Supply

389

Holders

89

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A

Other Info

Filtered by Token Holder
hhiker42.kongz.eth
0xa4fcf064131db228cfa72bfb64f0f50b940538fc
Loading...
Loading
Loading...
Loading
Loading...
Loading

Click here to update the token information / general information
# Exchange Pair Price  24H Volume % Volume

Contract Source Code Verified (Exact Match)

Contract Name:
PlayerHousing

Compiler Version
v0.8.14+commit.80d49f37

Optimization Enabled:
Yes with 10000 runs

Other Settings:
default evmVersion
File 1 of 8 : PlayerHousing.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.14;

import "openzeppelin/access/Ownable.sol";
import "openzeppelin/utils/Strings.sol";

import "./ERC1155B.sol";
import "./ILockManager.sol";
import "./ITickets.sol";

/// @title Solarbots Player Housing
/// @author Solarbots (https://solarbots.io)
contract PlayerHousing is ERC1155B, Ownable {
    // ---------- CONSTANTS ----------

    /// @notice Maximum amount of tokens that can be minted per faction
    /// Arboria tokens use IDs 0-5999, Illskagaard tokens use IDs 6000-11999,
    /// and Lacrean Empire tokens use IDs 12000-17999 for a total of 18000 tokens
    uint256 public constant MAX_SUPPLY_PER_FACTION = 6000;

    /// @notice Illskagaard tokens use IDs 6000-11999
    uint256 public constant ID_OFFSET_ILLSKAGAARD = 6000;

    /// @notice Lacrean Empire tokens use IDs 12000-17999
    uint256 public constant ID_OFFSET_LACREAN = 12000;

    /// @notice Maximum amount of tokens that can be minted per transaction
    uint256 public constant MAX_MINT_AMOUNT_PER_TX = 5;

    /// @notice Price to mint one token
    uint256 public constant MINT_PRICE = 0.1 ether;

    /// @notice Token ID of whitelist ticket in tickets contract
    uint256 public constant WHITELIST_TICKET_ID = 0;

    /// @notice FOA rewards emitted per second per token
    /// @dev 600_000_000e18 / 18_000 / 10 / 365 / 24 / 60 / 60
    uint256 public constant REWARDS_PER_SECOND = 105699306612548;

    string public constant ERROR_NO_CONTRACT_MINTING = "PlayerHousing: No contract minting";
    string public constant ERROR_NO_METADATA = "PlayerHousing: No metadata";
    string public constant ERROR_NOT_APPROVED_FOR_REWARDS = "PlayerHousing: Not approved for rewards";
    string public constant ERROR_OVER_MAX_AMOUNT_PER_TX_ARBORIA = "PlayerHousing: Arboria over max amount per tx";
    string public constant ERROR_OVER_MAX_AMOUNT_PER_TX_ILLSKAGAARD = "PlayerHousing: Illskagaard over max amount per tx";
    string public constant ERROR_OVER_MAX_AMOUNT_PER_TX_LACREAN = "PlayerHousing: Lacrean Empire over max amount per tx";
    string public constant ERROR_OVER_MAX_AMOUNT_PER_TX_TOTAL = "PlayerHousing: Total over max amount per tx";
    string public constant ERROR_REACHED_MAX_SUPPLY_ARBORIA = "PlayerHousing: Reached max Arboria supply";
    string public constant ERROR_REACHED_MAX_SUPPLY_ILLSKAGAARD = "PlayerHousing: Reached max Illskagaard supply";
    string public constant ERROR_REACHED_MAX_SUPPLY_LACREAN = "PlayerHousing: Reached max Lacrean Empire supply";
    string public constant ERROR_SALE_NOT_READY_WHITELIST = "PlayerHousing: Whitelist sale not ready";
    string public constant ERROR_SALE_NOT_READY_PUBLIC = "PlayerHousing: Public sale not ready";
    string public constant ERROR_TOKEN_LOCKED = "PlayerHousing: Token locked";
    string public constant ERROR_TOTAL_AMOUNT_BELOW_TWO = "PlayerHousing: Total amount below 2";
    string public constant ERROR_WRONG_PRICE = "PlayerHousing: Wrong price";

    /// @notice End of FOA rewards emittance
    uint256 public immutable TIMESTAMP_REWARDS_END;

    /// @notice Start of whitelist sale
    uint256 public immutable TIMESTAMP_SALE_WHITELIST;

    /// @notice Start of public sale
    uint256 public immutable TIMESTAMP_SALE_PUBLIC;

    /// @notice Tickets contract
    /// @custom:security non-reentrant
    ITickets public immutable TICKETS;

    uint256 private constant _BITSHIFT_TOTAL_SUPPLY_ILLSKAGAARD = 16;
    uint256 private constant _BITSHIFT_TOTAL_SUPPLY_LACREAN = 32;

    uint256 private constant _BITSHIFT_REWARDS_LAST_UPDATED = 16;
    uint256 private constant _BITSHIFT_REWARDS_BALANCE = 48;

    uint256 private constant _BITMASK_TOTAL_SUPPLY = type(uint16).max;
    uint256 private constant _BITMASK_TOTAL_SUPPLY_ARBORIA = ~_BITMASK_TOTAL_SUPPLY;
    uint256 private constant _BITMASK_TOTAL_SUPPLY_ILLSKAGAARD = ~(_BITMASK_TOTAL_SUPPLY << _BITSHIFT_TOTAL_SUPPLY_ILLSKAGAARD);
    uint256 private constant _BITMASK_TOTAL_SUPPLY_LACREAN = ~(_BITMASK_TOTAL_SUPPLY << _BITSHIFT_TOTAL_SUPPLY_LACREAN);

    uint256 private constant _BITMASK_REWARDS_TOKEN_BALANCE = type(uint16).max;
    uint256 private constant _BITMASK_REWARDS_LAST_UPDATED = type(uint32).max;

    // ---------- STATE ----------

    /// @notice Contains rewards balance, token balance, and timestamp of last rewards update for each token owner
    /// @dev Bit Layout:
    /// [0-15] Token balance - `tokenBalance`
    /// [16-47] Timestamp of last rewards update - `lastUpdated`
    /// [48-255] Rewards balance - `rewardsBalance`
    mapping(address => uint256) public rewardsBitField;

    /// @notice Approved addresses have write access to `rewardsBitField`
    /// @custom:security write-protection="onlyOwner()"
    mapping(address => bool) public isApprovedForRewards;

    /// @notice Lock manager contract
    /// @custom:security non-reentrant
    /// @custom:security write-protection="onlyOwner()"
    ILockManager public lockManager;

    /// @notice Metadata base URI
    /// @custom:security write-protection="onlyOwner()"
    string public baseURI;

    /// @notice Metadata URI suffix
    /// @custom:security write-protection="onlyOwner()"
    string public uriSuffix;

    /// @notice Contains total supply of each faction
    /// @dev Bit Layout:
    /// [0-15] Total supply of Arboria tokens - `totalSupplyArboria`
    /// [16-31] Total supply of Illskagard tokens - `totalSupplyIllskagard`
    /// [32-47] Total supply of Lacrean Empire tokens - `totalSupplyLacrean`
    uint256 private _totalSupplyBitField;

    // ---------- EVENTS ----------

    event ApprovalForRewards(address indexed operator, bool approved);

    event LockManagerTransfer(address indexed previousLockManager, address indexed newLockManager);

    // ---------- CONSTRUCTOR ----------

    /// @param owner Contract owner
    /// @param timestampSaleWhitelist Start of whitelist sale
    /// @param timestampSalePublic Start of public sale
    /// @param timestampRewardsEnd End of FOA rewards emittance
    /// @param tickets Address of tickets contract
    /// @param _lockManager Address of lock manager contract
    // slither-disable-next-line protected-vars
    constructor(
        address owner,
        uint256 timestampSaleWhitelist,
        uint256 timestampSalePublic,
        uint256 timestampRewardsEnd,
        address tickets,
        address _lockManager
    ) {
        _transferOwnership(owner);
        TIMESTAMP_SALE_WHITELIST = timestampSaleWhitelist;
        TIMESTAMP_SALE_PUBLIC = timestampSalePublic;
        TIMESTAMP_REWARDS_END = timestampRewardsEnd;
        TICKETS = ITickets(tickets);
        lockManager = ILockManager(_lockManager);
    }

    // ---------- METADATA ----------

    /// @notice Get metadata URI
    /// @param id Token ID
    /// @return Metadata URI of token ID `id`
    function uri(uint256 id) public view override returns (string memory) {
        require(bytes(baseURI).length > 0, ERROR_NO_METADATA);
        require(id < MAX_SUPPLY, ERROR_INVALID_ID);
        return string(abi.encodePacked(baseURI, Strings.toString(id), uriSuffix));
    }

    /// @notice Set metadata base URI
    /// @param _baseURI New metadata base URI
    /// @dev Doesn't emit URI event, because `id` argument isn't used
    function setBaseURI(string calldata _baseURI) external onlyOwner {
        baseURI = _baseURI;
    }

    /// @notice Set metadata URI suffix
    /// @param _uriSuffix New metadata URI suffix
    /// @dev Doesn't emit URI event, because `id` argument isn't used
    function setURISuffix(string calldata _uriSuffix) external onlyOwner {
        uriSuffix = _uriSuffix;
    }

    // ---------- TOTAL SUPPLY ----------

    function totalSupplyArboria() public view returns (uint256) {
        return _totalSupplyBitField & _BITMASK_TOTAL_SUPPLY;
    }

    function totalSupplyIllskagaard() public view returns (uint256) {
        return _totalSupplyBitField >> _BITSHIFT_TOTAL_SUPPLY_ILLSKAGAARD & _BITMASK_TOTAL_SUPPLY;
    }

    function totalSupplyLacrean() public view returns (uint256) {
        return _totalSupplyBitField >> _BITSHIFT_TOTAL_SUPPLY_LACREAN;
    }

    function totalSupply() external view returns (uint256) {
        return totalSupplyArboria() + totalSupplyIllskagaard() + totalSupplyLacrean();
    }

    // ---------- LOCK MANAGER ----------

    function setLockManager(address _lockManager) external onlyOwner {
        emit LockManagerTransfer(address(lockManager), _lockManager);
        lockManager = ILockManager(_lockManager);
    }

    // ---------- REWARDS ----------

    function setApprovalForRewards(address operator, bool approved) external onlyOwner {
        isApprovedForRewards[operator] = approved;
        emit ApprovalForRewards(operator, approved);
    }

    function setRewardsBitField(address owner, uint256 _rewardsBitField) external {
        require(isApprovedForRewards[msg.sender], ERROR_NOT_APPROVED_FOR_REWARDS);
        rewardsBitField[owner] = _rewardsBitField;
    }

    /// @notice Returns the token balance of the given address
    /// @param owner Address to check
    function balanceOf(address owner) public view returns (uint256) {
        return rewardsBitField[owner] & _BITMASK_REWARDS_TOKEN_BALANCE;
    }

    /// @notice Returns the FOA rewards balance of the given address
    /// @param owner Address to check
    function rewardsOf(address owner) external view returns (uint256 rewardsBalance) {
        rewardsBalance = rewardsBitField[owner] >> _BITSHIFT_REWARDS_BALANCE;
        uint256 lastUpdated = rewardsBitField[owner] >> _BITSHIFT_REWARDS_LAST_UPDATED & _BITMASK_REWARDS_LAST_UPDATED;

        if (lastUpdated != TIMESTAMP_REWARDS_END) {
            // Use current block timestamp or rewards end timestamp if reached
            uint256 timestamp = block.timestamp < TIMESTAMP_REWARDS_END ? block.timestamp : TIMESTAMP_REWARDS_END;
            uint256 tokenBalance = balanceOf(owner);

            // Calculate rewards collected since last update and add them to balance
            if (lastUpdated > 0) {
                uint256 secondsSinceLastUpdate = timestamp - lastUpdated;
                rewardsBalance += secondsSinceLastUpdate * REWARDS_PER_SECOND * tokenBalance;
            }
        }
    }

    function _updateRewardsForTransfer(address from, address to, uint256 tokenAmount) internal {
        // Use current block timestamp or rewards end timestamp if reached
        uint256 timestamp = block.timestamp < TIMESTAMP_REWARDS_END ? block.timestamp : TIMESTAMP_REWARDS_END;

        // Store bit field in memory to reduce number of SLOADs
        uint256 _rewardsBitField = rewardsBitField[from];
        uint256 lastUpdated = _rewardsBitField >> _BITSHIFT_REWARDS_LAST_UPDATED & _BITMASK_REWARDS_LAST_UPDATED;

        // Update rewards bit field of `from`, unless it has already been updated since the reward emittence ended
        if (lastUpdated != TIMESTAMP_REWARDS_END) {
            uint256 tokenBalance = _rewardsBitField & _BITMASK_REWARDS_TOKEN_BALANCE;
            uint256 rewardsBalance = _rewardsBitField >> _BITSHIFT_REWARDS_BALANCE;

            // Calculate rewards collected since last update and add them to balance
            if (lastUpdated > 0) {
                uint256 secondsSinceLastUpdate = timestamp - lastUpdated;
                unchecked {
                    rewardsBalance += secondsSinceLastUpdate * REWARDS_PER_SECOND * tokenBalance;
                }
            }

            unchecked {
                // Update rewards bit field of `from` with new token balance, last updated timestamp, and rewards balance
                rewardsBitField[from] = tokenBalance - tokenAmount | timestamp << _BITSHIFT_REWARDS_LAST_UPDATED | rewardsBalance << _BITSHIFT_REWARDS_BALANCE;
            }
        }

        // Store bit field in memory to reduce number of SLOADs
        _rewardsBitField = rewardsBitField[to];
        lastUpdated = _rewardsBitField >> _BITSHIFT_REWARDS_LAST_UPDATED & _BITMASK_REWARDS_LAST_UPDATED;

        // Update rewards bit field of `to`, unless it has already been updated since the reward emittence ended
        if (lastUpdated != TIMESTAMP_REWARDS_END) {
            uint256 tokenBalance = _rewardsBitField & _BITMASK_REWARDS_TOKEN_BALANCE;
            uint256 rewardsBalance = _rewardsBitField >> _BITSHIFT_REWARDS_BALANCE;

            // Calculate rewards collected since last update and add them to balance
            if (lastUpdated > 0) {
                uint256 secondsSinceLastUpdate = timestamp - lastUpdated;
                unchecked {
                    rewardsBalance += secondsSinceLastUpdate * REWARDS_PER_SECOND * tokenBalance;
                }
            }

            unchecked {
                // Update rewards bit field of `to` with new token balance, last updated timestamp, and rewards balance
                rewardsBitField[to] = tokenBalance + tokenAmount | timestamp << _BITSHIFT_REWARDS_LAST_UPDATED | rewardsBalance << _BITSHIFT_REWARDS_BALANCE;
            }
        }
    }

    function _updateRewardsForMint(address to, uint256 tokenAmount) internal {
        // Store bit field in memory to reduce number of SLOADs
        uint256 _rewardsBitField = rewardsBitField[to];
        uint256 tokenBalance = _rewardsBitField & _BITMASK_REWARDS_TOKEN_BALANCE;
        uint256 lastUpdated = _rewardsBitField >> _BITSHIFT_REWARDS_LAST_UPDATED & _BITMASK_REWARDS_LAST_UPDATED;
        uint256 rewardsBalance = _rewardsBitField >> _BITSHIFT_REWARDS_BALANCE;

        // Calculate rewards collected since last update and add them to balance
        if (lastUpdated > 0) {
            uint256 secondsSinceLastUpdate = block.timestamp - lastUpdated;
            unchecked {
                rewardsBalance += secondsSinceLastUpdate * REWARDS_PER_SECOND * tokenBalance;
            }
        }

        unchecked {
            // Update rewards bit field of `to` with new token balance, last updated timestamp, and rewards balance
            rewardsBitField[to] = tokenBalance + tokenAmount | block.timestamp << _BITSHIFT_REWARDS_LAST_UPDATED | rewardsBalance << _BITSHIFT_REWARDS_BALANCE;
        }
    }

    // ---------- TRANSFER ----------

    function safeTransferFrom(
        address from,
        address to,
        uint256 id,
        uint256 amount,
        bytes calldata data
    ) public override {
        require(msg.sender == from || isApprovedForAll[from][msg.sender], ERROR_NOT_AUTHORIZED);
        require(id < MAX_SUPPLY, ERROR_INVALID_ID);
        require(amount == 1, ERROR_INVALID_AMOUNT);
        require(!lockManager.isLocked(address(this), msg.sender, from, to, id), ERROR_TOKEN_LOCKED);

        /// @solidity memory-safe-assembly
        assembly {
            // Calculate storage slot of `ownerOf[id]`
            let ownerOfIdSlot := add(ownerOf.slot, id)
            // Load address stored in `ownerOf[id]`
            let ownerOfId := sload(ownerOfIdSlot)
            // Make sure we're only using the first 160 bits of the storage slot
            // as the remaining 96 bits might not be zero
            ownerOfId := and(ownerOfId, _BITMASK_ADDRESS)

            // Revert with message "ERC1155B: From not token owner" if `ownerOf[id]` is not `from`
            if xor(ownerOfId, from) {
                // Load free memory position
                let freeMemory := mload(0x40)
                // Store "Error(string)" signature: bytes32(bytes4(keccak256("Error(string)")))
                mstore(freeMemory, _ERROR_FUNCTION_SIGNATURE)
                // Store data offset
                mstore(add(freeMemory, 0x04), 0x20)
                // Store length of revert message
                mstore(add(freeMemory, 0x24), _ERROR_LENGTH_FROM_NOT_TOKEN_OWNER)
                // Store revert message
                mstore(add(freeMemory, 0x44), _ERROR_ENCODED_FROM_NOT_TOKEN_OWNER)
                revert(freeMemory, 0x64)
            }

            // Store address of `to` in `ownerOf[id]`
            sstore(ownerOfIdSlot, to)
        }

        _updateRewardsForTransfer(from, to, amount);
        emit TransferSingle(msg.sender, from, to, id, amount);

        if (to.code.length != 0) {
            require(
                ERC1155TokenReceiver(to).onERC1155Received(msg.sender, from, id, amount, data) ==
                    ERC1155TokenReceiver.onERC1155Received.selector,
                ERROR_UNSAFE_RECIPIENT
            );
        } else require(to != address(0), ERROR_INVALID_RECIPIENT);
    }

    function safeBatchTransferFrom(
        address from,
        address to,
        uint256[] calldata ids,
        uint256[] calldata amounts,
        bytes calldata data
    ) public override {
        require(ids.length == amounts.length, ERROR_ARRAY_LENGTH_MISMATCH);
        require(msg.sender == from || isApprovedForAll[from][msg.sender], ERROR_NOT_AUTHORIZED);
        require(!lockManager.isLocked(address(this), msg.sender, from, to, ids), ERROR_TOKEN_LOCKED);

        /// @solidity memory-safe-assembly
        assembly {
            // Calculate length of arrays `ids` and `amounts` in bytes
            let arrayLength := mul(ids.length, 0x20)

            // Loop over all values in `ids` and `amounts` by starting
            // with an index offset of 0 to access the first array element
            // and incrementing this index by 32 after each iteration to
            // access the next array element until the offset reaches the end
            // of the arrays, at which point all values the arrays contain
            // have been accessed
            for
                { let indexOffset := 0x00 }
                lt(indexOffset, arrayLength)
                { indexOffset := add(indexOffset, 0x20) }
            {
                // Load current array elements by adding offset of current
                // array index to start of each array's data area inside calldata
                let id := calldataload(add(ids.offset, indexOffset))

                // Revert with message "ERC1155B: Invalid ID" if `id` is higher than `MAX_ID`
                if gt(id, MAX_ID) {
                    // Load free memory position
                    // slither-disable-next-line variable-scope
                    let freeMemory := mload(0x40)
                    // Store "Error(string)" signature: bytes32(bytes4(keccak256("Error(string)")))
                    mstore(freeMemory, _ERROR_FUNCTION_SIGNATURE)
                    // Store data offset
                    mstore(add(freeMemory, 0x04), 0x20)
                    // Store length of revert message
                    mstore(add(freeMemory, 0x24), _ERROR_LENGTH_INVALID_ID)
                    // Store revert message
                    mstore(add(freeMemory, 0x44), _ERROR_ENCODED_INVALID_ID)
                    revert(freeMemory, 0x64)
                }

                // Revert with message "ERC1155B: Invalid amount" if amount is not 1
                if xor(calldataload(add(amounts.offset, indexOffset)), 1) {
                    // Load free memory position
                    let freeMemory := mload(0x40)
                    // Store "Error(string)" signature: bytes32(bytes4(keccak256("Error(string)")))
                    mstore(freeMemory, _ERROR_FUNCTION_SIGNATURE)
                    // Store data offset
                    mstore(add(freeMemory, 0x04), 0x20)
                    // Store length of revert message
                    mstore(add(freeMemory, 0x24), _ERROR_LENGTH_INVALID_AMOUNT)
                    // Store revert message
                    mstore(add(freeMemory, 0x44), _ERROR_ENCODED_INVALID_AMOUNT)
                    revert(freeMemory, 0x64)
                }

                // Calculate storage slot of `ownerOf[id]`
                let ownerOfIdSlot := add(ownerOf.slot, id)
                // Load address stored in `ownerOf[id]`
                let ownerOfId := sload(ownerOfIdSlot)
                // Make sure we're only using the first 160 bits of the storage slot
                // as the remaining 96 bits might not be zero
                ownerOfId := and(ownerOfId, _BITMASK_ADDRESS)

                // Revert with message "ERC1155B: From not token owner" if `ownerOf[id]` is not `from`
                if xor(ownerOfId, from) {
                    // Load free memory position
                    let freeMemory := mload(0x40)
                    // Store "Error(string)" signature: bytes32(bytes4(keccak256("Error(string)")))
                    mstore(freeMemory, _ERROR_FUNCTION_SIGNATURE)
                    // Store data offset
                    mstore(add(freeMemory, 0x04), 0x20)
                    // Store length of revert message
                    mstore(add(freeMemory, 0x24), _ERROR_LENGTH_FROM_NOT_TOKEN_OWNER)
                    // Store revert message
                    mstore(add(freeMemory, 0x44), _ERROR_ENCODED_FROM_NOT_TOKEN_OWNER)
                    revert(freeMemory, 0x64)
                }

                // Store address of `to` in `ownerOf[id]`
                sstore(ownerOfIdSlot, to)
            }
        }

        _updateRewardsForTransfer(from, to, ids.length);
        emit TransferBatch(msg.sender, from, to, ids, amounts);

        if (to.code.length != 0) {
            require(
                ERC1155TokenReceiver(to).onERC1155BatchReceived(msg.sender, from, ids, amounts, data) ==
                    ERC1155TokenReceiver.onERC1155BatchReceived.selector,
                ERROR_UNSAFE_RECIPIENT
            );
        } else require(to != address(0), ERROR_INVALID_RECIPIENT);
    }

    // ---------- WHITELIST SALE ----------

    /// @notice Mint a single Arboria token during whitelist sale
    function mintWhitelistArboria() external payable {
        require(msg.sender == tx.origin, ERROR_NO_CONTRACT_MINTING);
        require(block.timestamp >= TIMESTAMP_SALE_WHITELIST, ERROR_SALE_NOT_READY_WHITELIST);
        require(msg.value == MINT_PRICE, ERROR_WRONG_PRICE);

        // Burn whitelist ticket
        TICKETS.burn(msg.sender, WHITELIST_TICKET_ID, 1);

        _mintArboria(msg.sender);
    }

    /// @notice Mint a single Illskagaard token during whitelist sale
    function mintWhitelistIllskagaard() external payable {
        require(msg.sender == tx.origin, ERROR_NO_CONTRACT_MINTING);
        require(block.timestamp >= TIMESTAMP_SALE_WHITELIST, ERROR_SALE_NOT_READY_WHITELIST);
        require(msg.value == MINT_PRICE, ERROR_WRONG_PRICE);

        // Burn whitelist ticket
        TICKETS.burn(msg.sender, WHITELIST_TICKET_ID, 1);

        _mintIllskagaard(msg.sender);
    }

    /// @notice Mint a single Lacrean Empire token during whitelist sale
    function mintWhitelistLacrean() external payable {
        require(msg.sender == tx.origin, ERROR_NO_CONTRACT_MINTING);
        require(block.timestamp >= TIMESTAMP_SALE_WHITELIST, ERROR_SALE_NOT_READY_WHITELIST);
        require(msg.value == MINT_PRICE, ERROR_WRONG_PRICE);

        // Burn whitelist ticket
        TICKETS.burn(msg.sender, WHITELIST_TICKET_ID, 1);

        _mintLacrean(msg.sender);
    }

    /// @notice Batch mint specified amount of tokens during whitelist sale
    /// @param amountArboria Amount of Arboria tokens to mint
    /// @param amountIllskagaard Amount of Illskagaard tokens to mint
    /// @param amountLacrean Amount of Lacrean tokens to mint
    function batchMintWhitelist(uint256 amountArboria, uint256 amountIllskagaard, uint256 amountLacrean) external payable {
        require(msg.sender == tx.origin, ERROR_NO_CONTRACT_MINTING);
        require(block.timestamp >= TIMESTAMP_SALE_WHITELIST, ERROR_SALE_NOT_READY_WHITELIST);

        // Doing these checks and later calculating the total amount unchecked costs less gas
        // than not doing these checks and calculating the total amount checked
        require(amountArboria <= MAX_MINT_AMOUNT_PER_TX, ERROR_OVER_MAX_AMOUNT_PER_TX_ARBORIA);
        require(amountIllskagaard <= MAX_MINT_AMOUNT_PER_TX, ERROR_OVER_MAX_AMOUNT_PER_TX_ILLSKAGAARD);
        require(amountLacrean <= MAX_MINT_AMOUNT_PER_TX, ERROR_OVER_MAX_AMOUNT_PER_TX_LACREAN);

        uint256 amountTotal;
        unchecked {
            amountTotal = amountArboria + amountIllskagaard + amountLacrean;
        }
        require(amountTotal <= MAX_MINT_AMOUNT_PER_TX, ERROR_OVER_MAX_AMOUNT_PER_TX_TOTAL);
        require(amountTotal > 1, ERROR_TOTAL_AMOUNT_BELOW_TWO);
        unchecked {
            require(msg.value == amountTotal * MINT_PRICE, ERROR_WRONG_PRICE);
        }

        // Burn whitelist tickets
        TICKETS.burn(msg.sender, WHITELIST_TICKET_ID, amountTotal);

        _batchMint(msg.sender, amountArboria, amountIllskagaard, amountLacrean, amountTotal);
    }

    // ---------- PUBLIC SALE ----------

    /// @notice Mint a single Arboria token during public sale
    function mintPublicArboria() external payable {
        require(msg.sender == tx.origin, ERROR_NO_CONTRACT_MINTING);
        require(block.timestamp >= TIMESTAMP_SALE_PUBLIC, ERROR_SALE_NOT_READY_PUBLIC);
        require(msg.value == MINT_PRICE, ERROR_WRONG_PRICE);
        _mintArboria(msg.sender);
    }

    /// @notice Mint a single Illskagaard token during public sale
    function mintPublicIllskagaard() external payable {
        require(msg.sender == tx.origin, ERROR_NO_CONTRACT_MINTING);
        require(block.timestamp >= TIMESTAMP_SALE_PUBLIC, ERROR_SALE_NOT_READY_PUBLIC);
        require(msg.value == MINT_PRICE, ERROR_WRONG_PRICE);
        _mintIllskagaard(msg.sender);
    }

    /// @notice Mint a single Lacrean Empire token during public sale
    function mintPublicLacrean() external payable {
        require(msg.sender == tx.origin, ERROR_NO_CONTRACT_MINTING);
        require(block.timestamp >= TIMESTAMP_SALE_PUBLIC, ERROR_SALE_NOT_READY_PUBLIC);
        require(msg.value == MINT_PRICE, ERROR_WRONG_PRICE);
        _mintLacrean(msg.sender);
    }

    /// @notice Batch mint specified amount of tokens during public sale
    /// @param amountArboria Amount of Arboria tokens to mint
    /// @param amountIllskagaard Amount of Illskagaard tokens to mint
    /// @param amountLacrean Amount of Lacrean tokens to mint
    function batchMintPublic(uint256 amountArboria, uint256 amountIllskagaard, uint256 amountLacrean) external payable {
        require(msg.sender == tx.origin, ERROR_NO_CONTRACT_MINTING);
        require(block.timestamp >= TIMESTAMP_SALE_PUBLIC, ERROR_SALE_NOT_READY_PUBLIC);

        // Doing these checks and later calculating the total amount unchecked costs less gas
        // than not doing these checks and calculating the total amount checked
        require(amountArboria <= MAX_MINT_AMOUNT_PER_TX, ERROR_OVER_MAX_AMOUNT_PER_TX_ARBORIA);
        require(amountIllskagaard <= MAX_MINT_AMOUNT_PER_TX, ERROR_OVER_MAX_AMOUNT_PER_TX_ILLSKAGAARD);
        require(amountLacrean <= MAX_MINT_AMOUNT_PER_TX, ERROR_OVER_MAX_AMOUNT_PER_TX_LACREAN);

        uint256 amountTotal;
        unchecked {
            amountTotal = amountArboria + amountIllskagaard + amountLacrean;
        }
        require(amountTotal <= MAX_MINT_AMOUNT_PER_TX, ERROR_OVER_MAX_AMOUNT_PER_TX_TOTAL);
        require(amountTotal > 1, ERROR_TOTAL_AMOUNT_BELOW_TWO);
        unchecked {
            require(msg.value == amountTotal * MINT_PRICE, ERROR_WRONG_PRICE);
        }

        _batchMint(msg.sender, amountArboria, amountIllskagaard, amountLacrean, amountTotal);
    }

    // ---------- MINT ----------

    /// @notice Mint a single Lacrean Empire token as contract owner
    /// @param to Receiver of minted token
    function mintOwnerLacrean(address to) external onlyOwner {
        _mintLacrean(to);
    }

    /// @notice Batch mint as contract owner
    /// @param tos Receivers of minted tokens
    /// @param amountsArboria Amounts of Arboria tokens to mint
    /// @param amountsIllskagaard Amounts of Illskagaard tokens to mint
    /// @param amountsLacrean Amounts of Lacrean tokens to mint
    function batchMintOwner(
        address[] calldata tos,
        uint256[] calldata amountsArboria,
        uint256[] calldata amountsIllskagaard,
        uint256[] calldata amountsLacrean
    ) external onlyOwner {
        require(
            tos.length == amountsArboria.length &&
            amountsArboria.length == amountsIllskagaard.length &&
            amountsIllskagaard.length == amountsLacrean.length,
            ERROR_ARRAY_LENGTH_MISMATCH
        );

        // Calculate array length in bytes
        uint256 arrayLength;
        unchecked {
            arrayLength = tos.length * 0x20;
        }

        for (uint256 indexOffset = 0x00; indexOffset < arrayLength;) {
            address to;
            uint256 amountArboria;
            uint256 amountIllskagaard;
            uint256 amountLacrean;

            /// @solidity memory-safe-assembly
            assembly {
                // Load current array elements by adding offset of current
                // array index to start of each array's data area inside calldata
                to := calldataload(add(tos.offset, indexOffset))
                amountArboria := calldataload(add(amountsArboria.offset, indexOffset))
                amountIllskagaard := calldataload(add(amountsIllskagaard.offset, indexOffset))
                amountLacrean := calldataload(add(amountsLacrean.offset, indexOffset))

                // Increment index offset by 32 for next iteration
                indexOffset := add(indexOffset, 0x20)
            }

            unchecked {
                uint256 amountTotal = amountArboria + amountIllskagaard + amountLacrean;
                _batchMint(to, amountArboria, amountIllskagaard, amountLacrean, amountTotal);
            }
        }
    }

    /// @dev Mint a single Arboria token
    /// @param to Receiver of minted token
    function _mintArboria(address to) internal {
        // Total supply of Arboria tokens is stored in the first 16 bits of the bit field
        uint256 id = _totalSupplyBitField & _BITMASK_TOTAL_SUPPLY;
        require(id < MAX_SUPPLY_PER_FACTION, ERROR_REACHED_MAX_SUPPLY_ARBORIA);

        /// @solidity memory-safe-assembly
        assembly {
            // Calculate storage slot of `ownerOf[id]`
            let ownerOfIdSlot := add(ownerOf.slot, id)
            // Store address of `to` in `ownerOf[id]`
            sstore(ownerOfIdSlot, to)
        }

        unchecked {
            // Incrementing the whole bit field increments just the total supply of
            // Arboria tokens, because only the value stored in the first bits gets updated
            _totalSupplyBitField++;
        }

        _updateRewardsForMint(to, 1);
        emit TransferSingle(msg.sender, address(0), to, id, 1);
    }

    /// @dev Mint a single Illskagaard token
    /// @param to Receiver of minted token
    function _mintIllskagaard(address to) internal {
        // Store bit field in memory to reduce number of SLOADs
        uint256 totalSupplyBitField = _totalSupplyBitField;
        // Total supply of Illskagaard tokens is stored in the second 16 bits of the bit field
        uint256 _totalSupplyIllskagaard = totalSupplyBitField >> _BITSHIFT_TOTAL_SUPPLY_ILLSKAGAARD & _BITMASK_TOTAL_SUPPLY;
        require(_totalSupplyIllskagaard < MAX_SUPPLY_PER_FACTION, ERROR_REACHED_MAX_SUPPLY_ILLSKAGAARD);

        uint256 id;
        unchecked {
            // Illskagaard token IDs start at 6000
            id = ID_OFFSET_ILLSKAGAARD + _totalSupplyIllskagaard;
        }

        /// @solidity memory-safe-assembly
        assembly {
            // Calculate storage slot of `ownerOf[id]`
            let ownerOfIdSlot := add(ownerOf.slot, id)
            // Store address of `to` in `ownerOf[id]`
            sstore(ownerOfIdSlot, to)
        }

        unchecked {
            // Second 16 bits need to be all set to 0 before the new total supply of
            // Illskagaard tokens can be stored
            _totalSupplyBitField = totalSupplyBitField & _BITMASK_TOTAL_SUPPLY_ILLSKAGAARD | ++_totalSupplyIllskagaard << _BITSHIFT_TOTAL_SUPPLY_ILLSKAGAARD;
        }

        _updateRewardsForMint(to, 1);
        emit TransferSingle(msg.sender, address(0), to, id, 1);
    }

    /// @dev Mint a single Lacrean Empire token
    /// @param to Receiver of minted token
    function _mintLacrean(address to) internal {
        // Store bit field in memory to reduce number of SLOADs
        uint256 totalSupplyBitField = _totalSupplyBitField;
        // Total supply of Lacrean Empire tokens is stored in the third 16 bits of the bit field
        uint256 _totalSupplyLacrean = totalSupplyBitField >> _BITSHIFT_TOTAL_SUPPLY_LACREAN;
        require(_totalSupplyLacrean < MAX_SUPPLY_PER_FACTION, ERROR_REACHED_MAX_SUPPLY_LACREAN);

        uint256 id;
        unchecked {
            // Lacrean Empire token IDs start at 12000
            id = ID_OFFSET_LACREAN + _totalSupplyLacrean;
        }

        /// @solidity memory-safe-assembly
        assembly {
            // Calculate storage slot of `ownerOf[id]`
            let ownerOfIdSlot := add(ownerOf.slot, id)
            // Store address of `to` in `ownerOf[id]`
            sstore(ownerOfIdSlot, to)
        }

        unchecked {
            // Third 16 bits need to be all set to 0 before the new total supply of
            // Lacrean Empire tokens can be stored
            _totalSupplyBitField = totalSupplyBitField & _BITMASK_TOTAL_SUPPLY_LACREAN | ++_totalSupplyLacrean << _BITSHIFT_TOTAL_SUPPLY_LACREAN;
        }

        _updateRewardsForMint(to, 1);
        emit TransferSingle(msg.sender, address(0), to, id, 1);
    }

    /// @notice Batch mint specified amount of tokens
    /// @param to Receiver of minted tokens
    /// @param amountArboria Amount of Arboria tokens to mint
    /// @param amountIllskagaard Amount of Illskagaard tokens to mint
    /// @param amountLacrean Amount of Lacrean tokens to mint
    /// @param amountTotal Total amount of tokens to mint
    function _batchMint(
        address to,
        uint256 amountArboria,
        uint256 amountIllskagaard,
        uint256 amountLacrean,
        uint256 amountTotal
    ) internal {
        // Token IDs and amounts are collected in arrays to later emit the TransferBatch event
        uint256[] memory ids = new uint256[](amountTotal);
        // Token amounts are all 1
        uint256[] memory amounts = new uint256[](amountTotal);

        // Keep track of the current index offsets for each array
        uint256 offsetIds;
        uint256 offsetAmounts;

        /// @solidity memory-safe-assembly
        assembly {
            // Skip the first 32 bytes containing the array length
            offsetIds := add(ids, 0x20)
            offsetAmounts := add(amounts, 0x20)
        }

        // Store bit field in memory to reduce number of SLOADs
        uint256 totalSupplyBitField = _totalSupplyBitField;
        // New bit field gets updated in memory to reduce number of SSTOREs
        // _totalSupplyBitField is only updated once after all tokens are minted
        uint256 newTotalSupplyBitField = totalSupplyBitField;

        if (amountArboria > 0) {
            // Total supply of Arboria tokens is stored in the first 16 bits of the bit field
            uint256 _totalSupplyArboria = totalSupplyBitField & _BITMASK_TOTAL_SUPPLY;
            uint256 newTotalSupplyArboria;
            unchecked {
                newTotalSupplyArboria = _totalSupplyArboria + amountArboria;
            }
            require(newTotalSupplyArboria <= MAX_SUPPLY_PER_FACTION, ERROR_REACHED_MAX_SUPPLY_ARBORIA);

            /// @solidity memory-safe-assembly
            assembly {
                // Set owner of Arboria token IDs
                for { let id := _totalSupplyArboria } lt(id, newTotalSupplyArboria) { id := add(id, 1) } {
                    // Calculate storage slot of `ownerOf[id]`
                    let ownerOfIdSlot := add(ownerOf.slot, id)
                    // Store address of `to` in `ownerOf[id]`
                    sstore(ownerOfIdSlot, to)

                    // Store id and amount in the corresponding memory arrays
                    mstore(offsetIds, id)
                    mstore(offsetAmounts, 1)

                    // Increment index offsets by 32 for next iteration
                    offsetIds := add(offsetIds, 0x20)
                    offsetAmounts := add(offsetAmounts, 0x20)
                }
            }

            // First 16 bits need to be all set to 0 before the new total supply of Arboria tokens can be stored
            newTotalSupplyBitField = newTotalSupplyBitField & _BITMASK_TOTAL_SUPPLY_ARBORIA | newTotalSupplyArboria;
        }

        if (amountIllskagaard > 0) {
            // Total supply of Illskagaard tokens is stored in the second 16 bits of the bit field
            uint256 _totalSupplyIllskagaard = totalSupplyBitField >> _BITSHIFT_TOTAL_SUPPLY_ILLSKAGAARD & _BITMASK_TOTAL_SUPPLY;
            uint256 newTotalSupplyIllskagaard;
            unchecked {
                newTotalSupplyIllskagaard = _totalSupplyIllskagaard + amountIllskagaard;
            }
            require(newTotalSupplyIllskagaard <= MAX_SUPPLY_PER_FACTION, ERROR_REACHED_MAX_SUPPLY_ILLSKAGAARD);

            /// @solidity memory-safe-assembly
            assembly {
                // Set owner of Illskagaard token IDs
                for { let i := _totalSupplyIllskagaard } lt(i, newTotalSupplyIllskagaard) { i := add(i, 1) } {
                    // Illskagaard token IDs start at 6000
                    let id := add(ID_OFFSET_ILLSKAGAARD, i)

                    // Calculate storage slot of `ownerOf[id]`
                    let ownerOfIdSlot := add(ownerOf.slot, id)
                    // Store address of `to` in `ownerOf[id]`
                    sstore(ownerOfIdSlot, to)

                    // Store id and amount in the corresponding memory arrays
                    mstore(offsetIds, id)
                    mstore(offsetAmounts, 1)

                    // Increment index offsets by 32 for next iteration
                    offsetIds := add(offsetIds, 0x20)
                    offsetAmounts := add(offsetAmounts, 0x20)
                }
            }

            // Second 16 bits need to be all set to 0 before the new total supply of Illskagaard tokens can be stored
            newTotalSupplyBitField = newTotalSupplyBitField & _BITMASK_TOTAL_SUPPLY_ILLSKAGAARD | newTotalSupplyIllskagaard << _BITSHIFT_TOTAL_SUPPLY_ILLSKAGAARD;
        }

        if (amountLacrean > 0) {
            // Total supply of Lacrean Empire tokens is stored in the third 16 bits of the bit field
            uint256 _totalSupplyLacrean = totalSupplyBitField >> _BITSHIFT_TOTAL_SUPPLY_LACREAN;
            uint256 newTotalSupplyLacrean;
            unchecked {
                newTotalSupplyLacrean = _totalSupplyLacrean + amountLacrean;
            }
            require(newTotalSupplyLacrean <= MAX_SUPPLY_PER_FACTION, ERROR_REACHED_MAX_SUPPLY_LACREAN);

            /// @solidity memory-safe-assembly
            assembly {
                // Set owner of Lacrean Empire token IDs
                for { let i := _totalSupplyLacrean } lt(i, newTotalSupplyLacrean) { i := add(i, 1) } {
                    // Lacrean Empire token IDs start at 12000
                    let id := add(ID_OFFSET_LACREAN, i)

                    // Calculate storage slot of `ownerOf[id]`
                    let ownerOfIdSlot := add(ownerOf.slot, id)
                    // Store address of `to` in `ownerOf[id]`
                    sstore(ownerOfIdSlot, to)

                    // Store id and amount in the corresponding memory arrays
                    mstore(offsetIds, id)
                    mstore(offsetAmounts, 1)

                    // Increment index offsets by 32 for next iteration
                    offsetIds := add(offsetIds, 0x20)
                    offsetAmounts := add(offsetAmounts, 0x20)
                }
            }

            // Third 16 bits need to be all set to 0 before the new total supply of Lacrean Empire tokens can be stored
            newTotalSupplyBitField = newTotalSupplyBitField & _BITMASK_TOTAL_SUPPLY_LACREAN | newTotalSupplyLacrean << _BITSHIFT_TOTAL_SUPPLY_LACREAN;
        }

        // slither-disable-next-line costly-loop
        _totalSupplyBitField = newTotalSupplyBitField;
        _updateRewardsForMint(to, amountTotal);
        emit TransferBatch(msg.sender, address(0), to, ids, amounts);
    }

    // ---------- OWNERS ----------

    function owners() external view returns (address[MAX_SUPPLY] memory) {
        return ownerOf;
    }

    // ---------- WITHDRAW ----------

    /// @notice Withdraw all Ether stored in this contract to address of contract owner
    function withdraw() external onlyOwner {
        payable(msg.sender).transfer(address(this).balance);
    }
}

File 2 of 8 : Ownable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)

pragma solidity ^0.8.0;

import "../utils/Context.sol";

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is Context {
    address private _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor() {
        _transferOwnership(_msgSender());
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        _checkOwner();
        _;
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if the sender is not the owner.
     */
    function _checkOwner() internal view virtual {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions anymore. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby removing any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

File 3 of 8 : Strings.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol)

pragma solidity ^0.8.0;

/**
 * @dev String operations.
 */
library Strings {
    bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";
    uint8 private constant _ADDRESS_LENGTH = 20;

    /**
     * @dev Converts a `uint256` to its ASCII `string` decimal representation.
     */
    function toString(uint256 value) internal pure returns (string memory) {
        // Inspired by OraclizeAPI's implementation - MIT licence
        // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol

        if (value == 0) {
            return "0";
        }
        uint256 temp = value;
        uint256 digits;
        while (temp != 0) {
            digits++;
            temp /= 10;
        }
        bytes memory buffer = new bytes(digits);
        while (value != 0) {
            digits -= 1;
            buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
            value /= 10;
        }
        return string(buffer);
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
     */
    function toHexString(uint256 value) internal pure returns (string memory) {
        if (value == 0) {
            return "0x00";
        }
        uint256 temp = value;
        uint256 length = 0;
        while (temp != 0) {
            length++;
            temp >>= 8;
        }
        return toHexString(value, length);
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
     */
    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
        bytes memory buffer = new bytes(2 * length + 2);
        buffer[0] = "0";
        buffer[1] = "x";
        for (uint256 i = 2 * length + 1; i > 1; --i) {
            buffer[i] = _HEX_SYMBOLS[value & 0xf];
            value >>= 4;
        }
        require(value == 0, "Strings: hex length insufficient");
        return string(buffer);
    }

    /**
     * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.
     */
    function toHexString(address addr) internal pure returns (string memory) {
        return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
    }
}

File 4 of 8 : ERC1155B.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.14;

import {ERC1155TokenReceiver} from "solmate/tokens/ERC1155.sol";

/// @title Minimalist and gas efficient ERC1155 implementation optimized for single supply ids
/// @author Solarbots (https://solarbots.io)
/// @notice Based on Solmate implementation (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC1155B.sol)
abstract contract ERC1155B {
    // ---------- CONSTANTS ----------

    /// @notice Maximum amount of tokens that can be minted
    uint256 public constant MAX_SUPPLY = 18_000;

    /// @notice Maximum token ID
    /// @dev Inline assembly does not support non-number constants like `MAX_SUPPLY - 1`
    uint256 public constant MAX_ID = 17_999;

    string public constant ERROR_ARRAY_LENGTH_MISMATCH = "ERC1155B: Array length mismatch";
    string public constant ERROR_FROM_NOT_TOKEN_OWNER = "ERC1155B: From not token owner";
    string public constant ERROR_ID_ALREADY_MINTED = "ERC1155B: ID already minted";
    string public constant ERROR_ID_NOT_MINTED = "ERC1155B: ID not minted";
    string public constant ERROR_INVALID_AMOUNT = "ERC1155B: Invalid amount";
    string public constant ERROR_INVALID_FROM = "ERC1155B: Invalid from";
    string public constant ERROR_INVALID_ID = "ERC1155B: Invalid ID";
    string public constant ERROR_INVALID_RECIPIENT = "ERC1155B: Invalid recipient";
    string public constant ERROR_NOT_AUTHORIZED = "ERC1155B: Not authorized";
    string public constant ERROR_UNSAFE_RECIPIENT = "ERC1155B: Unsafe recipient";

    /// @dev bytes32(abi.encodePacked("ERC1155B: Invalid ID"))
    bytes32 internal constant _ERROR_ENCODED_INVALID_ID = 0x45524331313535423a20496e76616c6964204944000000000000000000000000;

    /// @dev bytes32(abi.encodePacked("ERC1155B: Invalid amount"))
    bytes32 internal constant _ERROR_ENCODED_INVALID_AMOUNT = 0x45524331313535423a20496e76616c696420616d6f756e740000000000000000;

    /// @dev bytes32(abi.encodePacked("ERC1155B: From not token owner"))
    bytes32 internal constant _ERROR_ENCODED_FROM_NOT_TOKEN_OWNER = 0x45524331313535423a2046726f6d206e6f7420746f6b656e206f776e65720000;

    /// @dev "ERC1155B: Invalid ID" is 20 characters long
    uint256 internal constant _ERROR_LENGTH_INVALID_ID = 20;

    /// @dev "ERC1155B: Invalid amount" is 24 characters long
    uint256 internal constant _ERROR_LENGTH_INVALID_AMOUNT = 24;

    /// @dev "ERC1155B: From not token owner" is 30 characters long
    uint256 internal constant _ERROR_LENGTH_FROM_NOT_TOKEN_OWNER = 30;

    /// @dev "Error(string)" signature: bytes32(bytes4(keccak256("Error(string)")))
    bytes32 internal constant _ERROR_FUNCTION_SIGNATURE = 0x08c379a000000000000000000000000000000000000000000000000000000000;

    /// @dev Inline assembly does not support non-number constants like `type(uint160).max`
    uint256 internal constant _BITMASK_ADDRESS = 0x000000000000000000000000ffffffffffffffffffffffffffffffffffffffff;

    // ---------- STATE ----------

    address[MAX_SUPPLY] public ownerOf;

    mapping(address => mapping(address => bool)) public isApprovedForAll;

    // ---------- EVENTS ----------

    event URI(string value, uint256 indexed id);

    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    event TransferSingle(
        address indexed operator,
        address indexed from,
        address indexed to,
        uint256 id,
        uint256 amount
    );

    event TransferBatch(
        address indexed operator,
        address indexed from,
        address indexed to,
        uint256[] ids,
        uint256[] amounts
    );

    // ---------- ERC-165 ----------

    // slither-disable-next-line external-function
    function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
        return
            interfaceId == 0x01ffc9a7 || // ERC165 Interface ID for ERC165
            interfaceId == 0xd9b67a26 || // ERC165 Interface ID for ERC1155
            interfaceId == 0x0e89341c; // ERC165 Interface ID for ERC1155MetadataURI
    }

    // ---------- METADATA ----------

    // slither-disable-next-line external-function
    function uri(uint256 id) public view virtual returns (string memory);

    // ---------- APPROVAL ----------

    // slither-disable-next-line external-function
    function setApprovalForAll(address operator, bool approved) public virtual {
        isApprovedForAll[msg.sender][operator] = approved;

        emit ApprovalForAll(msg.sender, operator, approved);
    }

    // ---------- BALANCE ----------

    function balanceOf(address owner, uint256 id) public view virtual returns (uint256 bal) {
        address idOwner = ownerOf[id];

        assembly {
            // We avoid branching by using assembly to take
            // the bool output of eq() and use it as a uint.
            bal := eq(idOwner, owner)
        }
    }

    // slither-disable-next-line external-function
    function balanceOfBatch(address[] calldata owners, uint256[] calldata ids)
        public
        view
        virtual
        returns (uint256[] memory balances)
    {
        require(owners.length == ids.length, ERROR_ARRAY_LENGTH_MISMATCH);

        balances = new uint256[](owners.length);

        // Unchecked because the only math done is incrementing
        // the array index counter which cannot possibly overflow.
        unchecked {
            for (uint256 i = 0; i < owners.length; ++i) {
                balances[i] = balanceOf(owners[i], ids[i]);
            }
        }
    }

    // ---------- TRANSFER ----------

    // slither-disable-next-line external-function
    function safeTransferFrom(
        address from,
        address to,
        uint256 id,
        uint256 amount,
        bytes calldata data
    ) public virtual {
        require(msg.sender == from || isApprovedForAll[from][msg.sender], ERROR_NOT_AUTHORIZED);
        require(id < MAX_SUPPLY, ERROR_INVALID_ID);
        require(amount == 1, ERROR_INVALID_AMOUNT);

        /// @solidity memory-safe-assembly
        assembly {
            // Calculate storage slot of `ownerOf[id]`
            let ownerOfIdSlot := add(ownerOf.slot, id)
            // Load address stored in `ownerOf[id]`
            let ownerOfId := sload(ownerOfIdSlot)
            // Make sure we're only using the first 160 bits of the storage slot
            // as the remaining 96 bits might not be zero
            ownerOfId := and(ownerOfId, _BITMASK_ADDRESS)

            // Revert with message "ERC1155B: From not token owner" if `ownerOf[id]` is not `from`
            if xor(ownerOfId, from) {
                // Load free memory position
                let freeMemory := mload(0x40)
                // Store "Error(string)" signature: bytes32(bytes4(keccak256("Error(string)")))
                mstore(freeMemory, _ERROR_FUNCTION_SIGNATURE)
                // Store data offset
                mstore(add(freeMemory, 0x04), 0x20)
                // Store length of revert message
                mstore(add(freeMemory, 0x24), _ERROR_LENGTH_FROM_NOT_TOKEN_OWNER)
                // Store revert message
                mstore(add(freeMemory, 0x44), _ERROR_ENCODED_FROM_NOT_TOKEN_OWNER)
                revert(freeMemory, 0x64)
            }

            // Store address of `to` in `ownerOf[id]`
            sstore(ownerOfIdSlot, to)
        }

        emit TransferSingle(msg.sender, from, to, id, amount);

        if (to.code.length != 0) {
            require(
                ERC1155TokenReceiver(to).onERC1155Received(msg.sender, from, id, amount, data) ==
                    ERC1155TokenReceiver.onERC1155Received.selector,
                ERROR_UNSAFE_RECIPIENT
            );
        } else require(to != address(0), ERROR_INVALID_RECIPIENT);
    }

    // slither-disable-next-line external-function
    function safeBatchTransferFrom(
        address from,
        address to,
        uint256[] calldata ids,
        uint256[] calldata amounts,
        bytes calldata data
    ) public virtual {
        require(ids.length == amounts.length, ERROR_ARRAY_LENGTH_MISMATCH);
        require(msg.sender == from || isApprovedForAll[from][msg.sender], ERROR_NOT_AUTHORIZED);

        /// @solidity memory-safe-assembly
        assembly {
            // Calculate length of arrays `ids` and `amounts` in bytes
            let arrayLength := mul(ids.length, 0x20)

            // Loop over all values in `ids` and `amounts` by starting
            // with an index offset of 0 to access the first array element
            // and incrementing this index by 32 after each iteration to
            // access the next array element until the offset reaches the end
            // of the arrays, at which point all values the arrays contain
            // have been accessed
            for
                { let indexOffset := 0x00 }
                lt(indexOffset, arrayLength)
                { indexOffset := add(indexOffset, 0x20) }
            {
                // Load current array elements by adding offset of current
                // array index to start of each array's data area inside calldata
                let id := calldataload(add(ids.offset, indexOffset))

                // Revert with message "ERC1155B: Invalid ID" if `id` is higher than `MAX_ID`
                if gt(id, MAX_ID) {
                    // Load free memory position
                    // slither-disable-next-line variable-scope
                    let freeMemory := mload(0x40)
                    // Store "Error(string)" signature: bytes32(bytes4(keccak256("Error(string)")))
                    mstore(freeMemory, _ERROR_FUNCTION_SIGNATURE)
                    // Store data offset
                    mstore(add(freeMemory, 0x04), 0x20)
                    // Store length of revert message
                    mstore(add(freeMemory, 0x24), _ERROR_LENGTH_INVALID_ID)
                    // Store revert message
                    mstore(add(freeMemory, 0x44), _ERROR_ENCODED_INVALID_ID)
                    revert(freeMemory, 0x64)
                }

                // Revert with message "ERC1155B: Invalid amount" if amount is not 1
                if xor(calldataload(add(amounts.offset, indexOffset)), 1) {
                    // Load free memory position
                    let freeMemory := mload(0x40)
                    // Store "Error(string)" signature: bytes32(bytes4(keccak256("Error(string)")))
                    mstore(freeMemory, _ERROR_FUNCTION_SIGNATURE)
                    // Store data offset
                    mstore(add(freeMemory, 0x04), 0x20)
                    // Store length of revert message
                    mstore(add(freeMemory, 0x24), _ERROR_LENGTH_INVALID_AMOUNT)
                    // Store revert message
                    mstore(add(freeMemory, 0x44), _ERROR_ENCODED_INVALID_AMOUNT)
                    revert(freeMemory, 0x64)
                }

                // Calculate storage slot of `ownerOf[id]`
                let ownerOfIdSlot := add(ownerOf.slot, id)
                // Load address stored in `ownerOf[id]`
                let ownerOfId := sload(ownerOfIdSlot)
                // Make sure we're only using the first 160 bits of the storage slot
                // as the remaining 96 bits might not be zero
                ownerOfId := and(ownerOfId, _BITMASK_ADDRESS)

                // Revert with message "ERC1155B: From not token owner" if `ownerOf[id]` is not `from`
                if xor(ownerOfId, from) {
                    // Load free memory position
                    let freeMemory := mload(0x40)
                    // Store "Error(string)" signature: bytes32(bytes4(keccak256("Error(string)")))
                    mstore(freeMemory, _ERROR_FUNCTION_SIGNATURE)
                    // Store data offset
                    mstore(add(freeMemory, 0x04), 0x20)
                    // Store length of revert message
                    mstore(add(freeMemory, 0x24), _ERROR_LENGTH_FROM_NOT_TOKEN_OWNER)
                    // Store revert message
                    mstore(add(freeMemory, 0x44), _ERROR_ENCODED_FROM_NOT_TOKEN_OWNER)
                    revert(freeMemory, 0x64)
                }

                // Store address of `to` in `ownerOf[id]`
                sstore(ownerOfIdSlot, to)
            }
        }

        emit TransferBatch(msg.sender, from, to, ids, amounts);

        if (to.code.length != 0) {
            require(
                ERC1155TokenReceiver(to).onERC1155BatchReceived(msg.sender, from, ids, amounts, data) ==
                    ERC1155TokenReceiver.onERC1155BatchReceived.selector,
                ERROR_UNSAFE_RECIPIENT
            );
        } else require(to != address(0), ERROR_INVALID_RECIPIENT);
    }

    // ---------- MINT ----------

    // slither-disable-next-line dead-code
    function _mint(
        address to,
        uint256 id,
        bytes memory data
    ) internal virtual {
        // Minting twice would effectively be a force transfer.
        require(ownerOf[id] == address(0), ERROR_ID_ALREADY_MINTED);

        ownerOf[id] = to;

        emit TransferSingle(msg.sender, address(0), to, id, 1);

        if (to.code.length != 0) {
            require(
                ERC1155TokenReceiver(to).onERC1155Received(msg.sender, address(0), id, 1, data) ==
                    ERC1155TokenReceiver.onERC1155Received.selector,
                ERROR_UNSAFE_RECIPIENT
            );
        } else require(to != address(0), ERROR_INVALID_RECIPIENT);
    }

    // slither-disable-next-line dead-code
    function _batchMint(
        address to,
        uint256[] memory ids,
        bytes memory data
    ) internal virtual {
        uint256 idsLength = ids.length; // Saves MLOADs.

        // Generate an amounts array locally to use in the event below.
        uint256[] memory amounts = new uint256[](idsLength);

        uint256 id; // Storing outside the loop saves ~7 gas per iteration.

        // Unchecked because the only math done is incrementing
        // the array index counter which cannot possibly overflow.
        unchecked {
            for (uint256 i = 0; i < idsLength; ++i) {
                id = ids[i];

                // Minting twice would effectively be a force transfer.
                require(ownerOf[id] == address(0), ERROR_ID_ALREADY_MINTED);

                ownerOf[id] = to;

                amounts[i] = 1;
            }
        }

        emit TransferBatch(msg.sender, address(0), to, ids, amounts);

        if (to.code.length != 0) {
            require(
                ERC1155TokenReceiver(to).onERC1155BatchReceived(msg.sender, address(0), ids, amounts, data) ==
                    ERC1155TokenReceiver.onERC1155BatchReceived.selector,
                ERROR_UNSAFE_RECIPIENT
            );
        } else require(to != address(0), ERROR_INVALID_RECIPIENT);
    }

    // ---------- BURN ----------

    // slither-disable-next-line dead-code
    function _burn(uint256 id) internal virtual {
        address owner = ownerOf[id];

        require(owner != address(0), ERROR_ID_NOT_MINTED);

        ownerOf[id] = address(0);

        emit TransferSingle(msg.sender, owner, address(0), id, 1);
    }

    // slither-disable-next-line dead-code
    function _batchBurn(address from, uint256[] memory ids) internal virtual {
        // Burning unminted tokens makes no sense.
        require(from != address(0), ERROR_INVALID_FROM);

        uint256 idsLength = ids.length; // Saves MLOADs.

        // Generate an amounts array locally to use in the event below.
        uint256[] memory amounts = new uint256[](idsLength);

        uint256 id; // Storing outside the loop saves ~7 gas per iteration.

        // Unchecked because the only math done is incrementing
        // the array index counter which cannot possibly overflow.
        unchecked {
            for (uint256 i = 0; i < idsLength; ++i) {
                id = ids[i];

                require(from == ownerOf[id], ERROR_FROM_NOT_TOKEN_OWNER);

                ownerOf[id] = address(0);

                amounts[i] = 1;
            }
        }

        emit TransferBatch(msg.sender, from, address(0), ids, amounts);
    }
}

File 5 of 8 : ILockManager.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.14;

/// @title Solarbots Lock Manager Interface
/// @author Solarbots (https://solarbots.io)
interface ILockManager {
    function isLocked(address collection, address operator, address from, address to, uint256 id) external returns (bool);
    function isLocked(address collection, address operator, address from, address to, uint256[] calldata ids) external returns (bool);
}

File 6 of 8 : ITickets.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.14;

/// @title Solarbots Tickets Interface
/// @author Solarbots (https://solarbots.io)
interface ITickets {
    function burn(address from, uint256 id, uint256 amount) external;
}

File 7 of 8 : Context.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)

pragma solidity ^0.8.0;

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
}

File 8 of 8 : ERC1155.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;

/// @notice Minimalist and gas efficient standard ERC1155 implementation.
/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC1155.sol)
abstract contract ERC1155 {
    /*//////////////////////////////////////////////////////////////
                                 EVENTS
    //////////////////////////////////////////////////////////////*/

    event TransferSingle(
        address indexed operator,
        address indexed from,
        address indexed to,
        uint256 id,
        uint256 amount
    );

    event TransferBatch(
        address indexed operator,
        address indexed from,
        address indexed to,
        uint256[] ids,
        uint256[] amounts
    );

    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    event URI(string value, uint256 indexed id);

    /*//////////////////////////////////////////////////////////////
                             ERC1155 STORAGE
    //////////////////////////////////////////////////////////////*/

    mapping(address => mapping(uint256 => uint256)) public balanceOf;

    mapping(address => mapping(address => bool)) public isApprovedForAll;

    /*//////////////////////////////////////////////////////////////
                             METADATA LOGIC
    //////////////////////////////////////////////////////////////*/

    function uri(uint256 id) public view virtual returns (string memory);

    /*//////////////////////////////////////////////////////////////
                              ERC1155 LOGIC
    //////////////////////////////////////////////////////////////*/

    function setApprovalForAll(address operator, bool approved) public virtual {
        isApprovedForAll[msg.sender][operator] = approved;

        emit ApprovalForAll(msg.sender, operator, approved);
    }

    function safeTransferFrom(
        address from,
        address to,
        uint256 id,
        uint256 amount,
        bytes calldata data
    ) public virtual {
        require(msg.sender == from || isApprovedForAll[from][msg.sender], "NOT_AUTHORIZED");

        balanceOf[from][id] -= amount;
        balanceOf[to][id] += amount;

        emit TransferSingle(msg.sender, from, to, id, amount);

        if (to.code.length != 0) {
            require(
                ERC1155TokenReceiver(to).onERC1155Received(msg.sender, from, id, amount, data) ==
                    ERC1155TokenReceiver.onERC1155Received.selector,
                "UNSAFE_RECIPIENT"
            );
        } else require(to != address(0), "INVALID_RECIPIENT");
    }

    function safeBatchTransferFrom(
        address from,
        address to,
        uint256[] calldata ids,
        uint256[] calldata amounts,
        bytes calldata data
    ) public virtual {
        require(ids.length == amounts.length, "LENGTH_MISMATCH");

        require(msg.sender == from || isApprovedForAll[from][msg.sender], "NOT_AUTHORIZED");

        // Storing these outside the loop saves ~15 gas per iteration.
        uint256 id;
        uint256 amount;

        for (uint256 i = 0; i < ids.length; ) {
            id = ids[i];
            amount = amounts[i];

            balanceOf[from][id] -= amount;
            balanceOf[to][id] += amount;

            // An array can't have a total length
            // larger than the max uint256 value.
            unchecked {
                ++i;
            }
        }

        emit TransferBatch(msg.sender, from, to, ids, amounts);

        if (to.code.length != 0) {
            require(
                ERC1155TokenReceiver(to).onERC1155BatchReceived(msg.sender, from, ids, amounts, data) ==
                    ERC1155TokenReceiver.onERC1155BatchReceived.selector,
                "UNSAFE_RECIPIENT"
            );
        } else require(to != address(0), "INVALID_RECIPIENT");
    }

    function balanceOfBatch(address[] calldata owners, uint256[] calldata ids)
        public
        view
        virtual
        returns (uint256[] memory balances)
    {
        require(owners.length == ids.length, "LENGTH_MISMATCH");

        balances = new uint256[](owners.length);

        // Unchecked because the only math done is incrementing
        // the array index counter which cannot possibly overflow.
        unchecked {
            for (uint256 i = 0; i < owners.length; ++i) {
                balances[i] = balanceOf[owners[i]][ids[i]];
            }
        }
    }

    /*//////////////////////////////////////////////////////////////
                              ERC165 LOGIC
    //////////////////////////////////////////////////////////////*/

    function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
        return
            interfaceId == 0x01ffc9a7 || // ERC165 Interface ID for ERC165
            interfaceId == 0xd9b67a26 || // ERC165 Interface ID for ERC1155
            interfaceId == 0x0e89341c; // ERC165 Interface ID for ERC1155MetadataURI
    }

    /*//////////////////////////////////////////////////////////////
                        INTERNAL MINT/BURN LOGIC
    //////////////////////////////////////////////////////////////*/

    function _mint(
        address to,
        uint256 id,
        uint256 amount,
        bytes memory data
    ) internal virtual {
        balanceOf[to][id] += amount;

        emit TransferSingle(msg.sender, address(0), to, id, amount);

        if (to.code.length != 0) {
            require(
                ERC1155TokenReceiver(to).onERC1155Received(msg.sender, address(0), id, amount, data) ==
                    ERC1155TokenReceiver.onERC1155Received.selector,
                "UNSAFE_RECIPIENT"
            );
        } else require(to != address(0), "INVALID_RECIPIENT");
    }

    function _batchMint(
        address to,
        uint256[] memory ids,
        uint256[] memory amounts,
        bytes memory data
    ) internal virtual {
        uint256 idsLength = ids.length; // Saves MLOADs.

        require(idsLength == amounts.length, "LENGTH_MISMATCH");

        for (uint256 i = 0; i < idsLength; ) {
            balanceOf[to][ids[i]] += amounts[i];

            // An array can't have a total length
            // larger than the max uint256 value.
            unchecked {
                ++i;
            }
        }

        emit TransferBatch(msg.sender, address(0), to, ids, amounts);

        if (to.code.length != 0) {
            require(
                ERC1155TokenReceiver(to).onERC1155BatchReceived(msg.sender, address(0), ids, amounts, data) ==
                    ERC1155TokenReceiver.onERC1155BatchReceived.selector,
                "UNSAFE_RECIPIENT"
            );
        } else require(to != address(0), "INVALID_RECIPIENT");
    }

    function _batchBurn(
        address from,
        uint256[] memory ids,
        uint256[] memory amounts
    ) internal virtual {
        uint256 idsLength = ids.length; // Saves MLOADs.

        require(idsLength == amounts.length, "LENGTH_MISMATCH");

        for (uint256 i = 0; i < idsLength; ) {
            balanceOf[from][ids[i]] -= amounts[i];

            // An array can't have a total length
            // larger than the max uint256 value.
            unchecked {
                ++i;
            }
        }

        emit TransferBatch(msg.sender, from, address(0), ids, amounts);
    }

    function _burn(
        address from,
        uint256 id,
        uint256 amount
    ) internal virtual {
        balanceOf[from][id] -= amount;

        emit TransferSingle(msg.sender, from, address(0), id, amount);
    }
}

/// @notice A generic interface for a contract which properly accepts ERC1155 tokens.
/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC1155.sol)
abstract contract ERC1155TokenReceiver {
    function onERC1155Received(
        address,
        address,
        uint256,
        uint256,
        bytes calldata
    ) external virtual returns (bytes4) {
        return ERC1155TokenReceiver.onERC1155Received.selector;
    }

    function onERC1155BatchReceived(
        address,
        address,
        uint256[] calldata,
        uint256[] calldata,
        bytes calldata
    ) external virtual returns (bytes4) {
        return ERC1155TokenReceiver.onERC1155BatchReceived.selector;
    }
}

Settings
{
  "remappings": [
    "ds-test/=lib/solmate/lib/ds-test/src/",
    "forge-std/=lib/forge-std/src/",
    "openzeppelin-contracts/=lib/openzeppelin-contracts/",
    "openzeppelin/=lib/openzeppelin-contracts/contracts/",
    "script/=script/",
    "solmate/=lib/solmate/src/",
    "src/=src/",
    "test/=test/",
    "src/=src/",
    "test/=test/",
    "script/=script/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 10000
  },
  "metadata": {
    "bytecodeHash": "ipfs"
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "london",
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"timestampSaleWhitelist","type":"uint256"},{"internalType":"uint256","name":"timestampSalePublic","type":"uint256"},{"internalType":"uint256","name":"timestampRewardsEnd","type":"uint256"},{"internalType":"address","name":"tickets","type":"address"},{"internalType":"address","name":"_lockManager","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForRewards","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousLockManager","type":"address"},{"indexed":true,"internalType":"address","name":"newLockManager","type":"address"}],"name":"LockManagerTransfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"name":"TransferBatch","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"TransferSingle","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"value","type":"string"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"URI","type":"event"},{"inputs":[],"name":"ERROR_ARRAY_LENGTH_MISMATCH","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERROR_FROM_NOT_TOKEN_OWNER","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERROR_ID_ALREADY_MINTED","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERROR_ID_NOT_MINTED","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERROR_INVALID_AMOUNT","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERROR_INVALID_FROM","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERROR_INVALID_ID","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERROR_INVALID_RECIPIENT","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERROR_NOT_APPROVED_FOR_REWARDS","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERROR_NOT_AUTHORIZED","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERROR_NO_CONTRACT_MINTING","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERROR_NO_METADATA","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERROR_OVER_MAX_AMOUNT_PER_TX_ARBORIA","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERROR_OVER_MAX_AMOUNT_PER_TX_ILLSKAGAARD","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERROR_OVER_MAX_AMOUNT_PER_TX_LACREAN","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERROR_OVER_MAX_AMOUNT_PER_TX_TOTAL","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERROR_REACHED_MAX_SUPPLY_ARBORIA","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERROR_REACHED_MAX_SUPPLY_ILLSKAGAARD","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERROR_REACHED_MAX_SUPPLY_LACREAN","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERROR_SALE_NOT_READY_PUBLIC","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERROR_SALE_NOT_READY_WHITELIST","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERROR_TOKEN_LOCKED","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERROR_TOTAL_AMOUNT_BELOW_TWO","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERROR_UNSAFE_RECIPIENT","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERROR_WRONG_PRICE","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ID_OFFSET_ILLSKAGAARD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ID_OFFSET_LACREAN","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_ID","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_MINT_AMOUNT_PER_TX","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_SUPPLY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_SUPPLY_PER_FACTION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MINT_PRICE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REWARDS_PER_SECOND","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TICKETS","outputs":[{"internalType":"contract ITickets","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TIMESTAMP_REWARDS_END","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TIMESTAMP_SALE_PUBLIC","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TIMESTAMP_SALE_WHITELIST","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WHITELIST_TICKET_ID","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"bal","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"owners","type":"address[]"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"}],"name":"balanceOfBatch","outputs":[{"internalType":"uint256[]","name":"balances","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"tos","type":"address[]"},{"internalType":"uint256[]","name":"amountsArboria","type":"uint256[]"},{"internalType":"uint256[]","name":"amountsIllskagaard","type":"uint256[]"},{"internalType":"uint256[]","name":"amountsLacrean","type":"uint256[]"}],"name":"batchMintOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountArboria","type":"uint256"},{"internalType":"uint256","name":"amountIllskagaard","type":"uint256"},{"internalType":"uint256","name":"amountLacrean","type":"uint256"}],"name":"batchMintPublic","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountArboria","type":"uint256"},{"internalType":"uint256","name":"amountIllskagaard","type":"uint256"},{"internalType":"uint256","name":"amountLacrean","type":"uint256"}],"name":"batchMintWhitelist","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isApprovedForRewards","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lockManager","outputs":[{"internalType":"contract ILockManager","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"mintOwnerLacrean","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"mintPublicArboria","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"mintPublicIllskagaard","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"mintPublicLacrean","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"mintWhitelistArboria","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"mintWhitelistIllskagaard","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"mintWhitelistLacrean","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owners","outputs":[{"internalType":"address[18000]","name":"","type":"address[18000]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"rewardsBitField","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"rewardsOf","outputs":[{"internalType":"uint256","name":"rewardsBalance","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeBatchTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_baseURI","type":"string"}],"name":"setBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_lockManager","type":"address"}],"name":"setLockManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"_rewardsBitField","type":"uint256"}],"name":"setRewardsBitField","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_uriSuffix","type":"string"}],"name":"setURISuffix","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupplyArboria","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupplyIllskagaard","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupplyLacrean","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"uri","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"uriSuffix","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]

6101006040523480156200001257600080fd5b5060405162004a1a38038062004a1a8339810160408190526200003591620000f5565b620000403362000085565b6200004b8662000085565b60a09490945260c0929092526080526001600160a01b0390811660e05261465480546001600160a01b03191691909216179055506200015b565b61465180546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b80516001600160a01b0381168114620000f057600080fd5b919050565b60008060008060008060c087890312156200010f57600080fd5b6200011a87620000d8565b95506020870151945060408701519350606087015192506200013f60808801620000d8565b91506200014f60a08801620000d8565b90509295509295509295565b60805160a05160c05160e0516148006200021a6000396000818161070a01528181611b81015281816121a50152818161247e015261294b01526000818161076b015281816111ae01528181611d5b015281816125b20152612a12015260008181610a0b01528181611a8e01528181611f770152818161238b0152612858015260008181610b2201528181611c1b01528181611c4401528181611c6b0152818161356b01528181613592015281816135e2015261368a01526148006000f3fe60806040526004361061053c5760003560e01c806370a08231116102af578063affe39c111610179578063dd74d3b7116100d6578063efd52b8b1161008a578063f242432a1161006f578063f242432a14610fb0578063f2fde38b14610fd0578063f806b10114610ff057600080fd5b8063efd52b8b14610f86578063f1d91b1214610f9b57600080fd5b8063e4a1ada4116100bb578063e4a1ada414610f20578063e985e9c514610f35578063ea39260014610f7157600080fd5b8063dd74d3b714610ecf578063deedfdbd14610f0057600080fd5b8063c1049e801161012d578063c8d3403911610112578063c8d3403914610e1f578063d39fbaa414610e68578063dbcfd08f14610eb157600080fd5b8063c1049e8014610db6578063c64a0b8b14610dff57600080fd5b8063bdb6fe2a1161015e578063bdb6fe2a14610d7d578063bfd7253f14610d92578063c002d23d14610d9a57600080fd5b8063affe39c114610d53578063b9be77b214610d7557600080fd5b80638da5cb5b11610227578063a113152b116101db578063a42bfe6d116101c0578063a42bfe6d14610cf2578063a4a4003814610d12578063acca30a214610d3257600080fd5b8063a113152b14610c89578063a22cb46514610cd257600080fd5b80639030d1bb1161020c5780639030d1bb14610c4c57806398c7798414610c6c578063a0afde1514610c8157600080fd5b80638da5cb5b14610c255780638f13c2a414610c4457600080fd5b8063802e79181161027e57806386aaf9341161026357806386aaf93414610b7e578063873b4aa914610bc7578063878de91e14610c1057600080fd5b8063802e791814610b4457806381b3e57514610b5e57600080fd5b806370a0823114610a77578063715018a614610ab25780637999567114610ac75780637aeb357314610b1057600080fd5b80632eb2c2d61161040b5780634ee6262d11610368578063576793491161031c5780636352211e116103015780636352211e14610a2d5780636a01be5314610a4d5780636c0360eb14610a6257600080fd5b806357679349146109b057806358e96d5f146109f957600080fd5b806351f977041161034d57806351f97704146109685780635503a0e81461097b57806355f804b31461099057600080fd5b80634ee6262d1461091f5780634f9bba2c1461083957600080fd5b8063479ba7ae116103bf5780634d58026c116103a45780634d58026c146108a15780634d7e41d5146108a95780634e1273f4146108f257600080fd5b8063479ba7ae1461086c5780634c09e3e61461088c57600080fd5b806335f743ae116103f057806335f743ae146108395780633ccfd60b1461084f5780633e4af9c51461086457600080fd5b80632eb2c2d61461080357806332cb6b0c1461082357600080fd5b80630e89341c116104b95780631adc62d81161046d578063207e3cc311610452578063207e3cc3146107a75780632552a1d0146107d55780632d960a4c146107ea57600080fd5b80631adc62d8146107595780631d84cee91461078d57600080fd5b806318160ddd1161049e57806318160ddd146106e357806318c33e46146106f8578063192d4df61461074457600080fd5b80630e89341c146106ad57806317bac052146106cd57600080fd5b80630ae349f4116105105780630d6f23cd116104f55780630d6f23cd146106065780630df1f7c71461064f5780630e0847211461069857600080fd5b80630ae349f4146105db5780630b32f0b2146105f157600080fd5b8062fdd58e1461054157806301ffc9a71461057457806303e56262146105a457806309ef6527146105c6575b600080fd5b34801561054d57600080fd5b5061056161055c366004613b70565b611039565b6040519081526020015b60405180910390f35b34801561058057600080fd5b5061059461058f366004613bc8565b611066565b604051901515815260200161056b565b3480156105b057600080fd5b506105b961114b565b60405161056b9190613c18565b3480156105d257600080fd5b50610561600581565b3480156105e757600080fd5b50610561612ee081565b6106046105ff366004613c69565b611167565b005b34801561061257600080fd5b506105b96040518060400160405280601881526020017f45524331313535423a20496e76616c696420616d6f756e74000000000000000081525081565b34801561065b57600080fd5b506105b96040518060400160405280601881526020017f45524331313535423a204e6f7420617574686f72697a6564000000000000000081525081565b3480156106a457600080fd5b506105b96113b3565b3480156106b957600080fd5b506105b96106c8366004613c95565b6113cf565b3480156106d957600080fd5b5061056161464f81565b3480156106ef57600080fd5b506105616114c7565b34801561070457600080fd5b5061072c7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200161056b565b34801561075057600080fd5b506105b9611508565b34801561076557600080fd5b506105617f000000000000000000000000000000000000000000000000000000000000000081565b34801561079957600080fd5b50610561656022099fa74481565b3480156107b357600080fd5b506105616107c2366004613cae565b6146526020526000908152604090205481565b3480156107e157600080fd5b506105b9611524565b3480156107f657600080fd5b506146575460201c610561565b34801561080f57600080fd5b5061060461081e366004613d57565b611540565b34801561082f57600080fd5b5061056161465081565b34801561084557600080fd5b5061056161177081565b34801561085b57600080fd5b50610604611a19565b610604611a50565b34801561087857600080fd5b50610561610887366004613cae565b611bf0565b34801561089857600080fd5b506105b9611d01565b610604611d1d565b3480156108b557600080fd5b506105b96040518060400160405280601a81526020017f506c61796572486f7573696e673a2057726f6e6720707269636500000000000081525081565b3480156108fe57600080fd5b5061091261090d366004613e12565b611e1b565b60405161056b9190613eb9565b34801561092b57600080fd5b506105b96040518060400160405280601781526020017f45524331313535423a204944206e6f74206d696e74656400000000000000000081525081565b610604610976366004613c69565b611f39565b34801561098757600080fd5b506105b9612216565b34801561099c57600080fd5b506106046109ab366004613ecc565b6122a5565b3480156109bc57600080fd5b506105b96040518060400160405280601e81526020017f45524331313535423a2046726f6d206e6f7420746f6b656e206f776e6572000081525081565b348015610a0557600080fd5b506105617f000000000000000000000000000000000000000000000000000000000000000081565b348015610a3957600080fd5b5061072c610a48366004613c95565b6122bf565b348015610a5957600080fd5b506105b96122e0565b348015610a6e57600080fd5b506105b96122fc565b348015610a8357600080fd5b50610561610a92366004613cae565b6001600160a01b03166000908152614652602052604090205461ffff1690565b348015610abe57600080fd5b5061060461230a565b348015610ad357600080fd5b506105b96040518060400160405280601a81526020017f45524331313535423a20556e7361666520726563697069656e7400000000000081525081565b348015610b1c57600080fd5b506105617f000000000000000000000000000000000000000000000000000000000000000081565b348015610b5057600080fd5b506146575461ffff16610561565b348015610b6a57600080fd5b50610604610b79366004613ecc565b61231c565b348015610b8a57600080fd5b506105b96040518060400160405280601481526020017f45524331313535423a20496e76616c696420494400000000000000000000000081525081565b348015610bd357600080fd5b506105b96040518060400160405280601a81526020017f506c61796572486f7573696e673a204e6f206d6574616461746100000000000081525081565b348015610c1c57600080fd5b506105b9612331565b348015610c3157600080fd5b50614651546001600160a01b031661072c565b61060461234d565b348015610c5857600080fd5b50610604610c67366004613b70565b6124eb565b348015610c7857600080fd5b506105b9612558565b610604612574565b348015610c9557600080fd5b506105b96040518060400160405280601b81526020017f45524331313535423a20494420616c7265616479206d696e746564000000000081525081565b348015610cde57600080fd5b50610604610ced366004613f1c565b612672565b348015610cfe57600080fd5b50610604610d0d366004613f53565b6126fd565b348015610d1e57600080fd5b50610604610d2d366004613cae565b6127c1565b348015610d3e57600080fd5b506146545461072c906001600160a01b031681565b348015610d5f57600080fd5b50610d686127d2565b60405161056b9190614003565b61060461281a565b348015610d8957600080fd5b506105b96129b8565b6106046129d4565b348015610da657600080fd5b5061056167016345785d8a000081565b348015610dc257600080fd5b506105b96040518060400160405280601681526020017f45524331313535423a20496e76616c69642066726f6d0000000000000000000081525081565b348015610e0b57600080fd5b50610604610e1a366004613f1c565b612ad2565b348015610e2b57600080fd5b506105b96040518060400160405280601b81526020017f45524331313535423a20496e76616c696420726563697069656e74000000000081525081565b348015610e7457600080fd5b506105b96040518060400160405280601b81526020017f506c61796572486f7573696e673a20546f6b656e206c6f636b6564000000000081525081565b348015610ebd57600080fd5b506105616146575460101c61ffff1690565b348015610edb57600080fd5b50610594610eea366004613cae565b6146536020526000908152604090205460ff1681565b348015610f0c57600080fd5b50610604610f1b366004613cae565b612b58565b348015610f2c57600080fd5b506105b9612bd6565b348015610f4157600080fd5b50610594610f50366004614040565b61465060209081526000928352604080842090915290825290205460ff1681565b348015610f7d57600080fd5b50610561600081565b348015610f9257600080fd5b506105b9612bf2565b348015610fa757600080fd5b506105b9612c0e565b348015610fbc57600080fd5b50610604610fcb366004614073565b612c2a565b348015610fdc57600080fd5b50610604610feb366004613cae565b613098565b348015610ffc57600080fd5b506105b96040518060400160405280601f81526020017f45524331313535423a204172726179206c656e677468206d69736d617463680081525081565b6000806000836146508110611050576110506140eb565b01546001600160a01b0316939093149392505050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831614806110f957507fd9b67a26000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b8061114557507f0e89341c000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b6040518060600160405280602b8152602001614684602b913981565b6040805160608101909152602280825233321491906146056020830139906111ab5760405162461bcd60e51b81526004016111a29190613c18565b60405180910390fd5b507f00000000000000000000000000000000000000000000000000000000000000004210156040518060600160405280602481526020016146af60249139906112075760405162461bcd60e51b81526004016111a29190613c18565b5060058311156040518060600160405280602d8152602001614657602d9139906112445760405162461bcd60e51b81526004016111a29190613c18565b50600582111560405180606001604052806031815260200161474660319139906112815760405162461bcd60e51b81526004016111a29190613c18565b5060058111156040518060600160405280603481526020016145d160349139906112be5760405162461bcd60e51b81526004016111a29190613c18565b5060008183850101905060058111156040518060600160405280602b8152602001614684602b9139906113045760405162461bcd60e51b81526004016111a29190613c18565b50600181116040518060600160405280602381526020016146d360239139906113405760405162461bcd60e51b81526004016111a29190613c18565b5060408051808201909152601a81527f506c61796572486f7573696e673a2057726f6e6720707269636500000000000060208201523467016345785d8a000083021461139f5760405162461bcd60e51b81526004016111a29190613c18565b506113ad3385858585613125565b50505050565b6040518060600160405280602481526020016146af6024913981565b6060600061465580546113e19061411a565b9050116040518060400160405280601a81526020017f506c61796572486f7573696e673a204e6f206d65746164617461000000000000815250906114385760405162461bcd60e51b81526004016111a29190613c18565b5060408051808201909152601481527f45524331313535423a20496e76616c69642049440000000000000000000000006020820152614650831061148f5760405162461bcd60e51b81526004016111a29190613c18565b5061465561149c8361342a565b6146566040516020016114b193929190614237565b6040516020818303038152906040529050919050565b60006114d66146575460201c90565b6114e76146575460101c61ffff1690565b6146575461ffff166114f99190614299565b6115039190614299565b905090565b6040518060600160405280602281526020016146056022913981565b6040518060600160405280602781526020016147776027913981565b60408051808201909152601f81527f45524331313535423a204172726179206c656e677468206d69736d617463680060208201528584146115945760405162461bcd60e51b81526004016111a29190613c18565b50336001600160a01b03891614806115d057506001600160a01b03881660009081526146506020908152604080832033845290915290205460ff165b6040518060400160405280601881526020017f45524331313535423a204e6f7420617574686f72697a65640000000000000000815250906116245760405162461bcd60e51b81526004016111a29190613c18565b50614654546040517fc2d638ef0000000000000000000000000000000000000000000000000000000081526001600160a01b039091169063c2d638ef9061167990309033908d908d908d908d90600401614300565b6020604051808303816000875af1158015611698573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116bc9190614349565b156040518060400160405280601b81526020017f506c61796572486f7573696e673a20546f6b656e206c6f636b65640000000000815250906117115760405162461bcd60e51b81526004016111a29190613c18565b506020850260005b81811015611827578088013561464f8111156117745760405162461bcd60e51b815260206004820152601460248201527f45524331313535423a20496e76616c69642049440000000000000000000000006044820152606481fd5b868201356001146117c45760405162461bcd60e51b815260206004820152601860248201527f45524331313535423a20496e76616c696420616d6f756e7400000000000000006044820152606481fd5b80546001600160a01b03168b811461181b5760405162461bcd60e51b815260206004820152601e60248201527f45524331313535423a2046726f6d206e6f7420746f6b656e206f776e657200006044820152606481fd5b50899055602001611719565b506118359050888887613567565b866001600160a01b0316886001600160a01b0316336001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb898989896040516118889493929190614366565b60405180910390a46001600160a01b0387163b156119b2576040517fbc197c8100000000000000000000000000000000000000000000000000000000808252906001600160a01b0389169063bc197c81906118f59033908d908c908c908c908c908c908c906004016143d6565b6020604051808303816000875af1158015611914573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611938919061443a565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916146040518060400160405280601a81526020017f45524331313535423a20556e7361666520726563697069656e74000000000000815250906119ac5760405162461bcd60e51b81526004016111a29190613c18565b50611a0f565b60408051808201909152601b81527f45524331313535423a20496e76616c696420726563697069656e74000000000060208201526001600160a01b038816611a0d5760405162461bcd60e51b81526004016111a29190613c18565b505b5050505050505050565b611a2161370f565b60405133904780156108fc02916000818181858888f19350505050158015611a4d573d6000803e3d6000fd5b50565b604080516060810190915260228082523332149190614605602083013990611a8b5760405162461bcd60e51b81526004016111a29190613c18565b507f00000000000000000000000000000000000000000000000000000000000000004210156040518060600160405280602781526020016147776027913990611ae75760405162461bcd60e51b81526004016111a29190613c18565b5060408051808201909152601a81527f506c61796572486f7573696e673a2057726f6e6720707269636500000000000060208201523467016345785d8a000014611b445760405162461bcd60e51b81526004016111a29190613c18565b506040517ff5298aca00000000000000000000000000000000000000000000000000000000815233600482015260006024820152600160448201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063f5298aca90606401600060405180830381600087803b158015611bcd57600080fd5b505af1158015611be1573d6000803e3d6000fd5b50505050611bee3361376a565b565b6001600160a01b03811660009081526146526020526040902054603081901c9060101c63ffffffff167f00000000000000000000000000000000000000000000000000000000000000008114611cfb5760007f00000000000000000000000000000000000000000000000000000000000000004210611c8f577f0000000000000000000000000000000000000000000000000000000000000000611c91565b425b90506000611cb9856001600160a01b03166000908152614652602052604090205461ffff1690565b90508215611cf8576000611ccd8484614457565b905081611ce0656022099fa7448361446e565b611cea919061446e565b611cf49086614299565b9450505b50505b50919050565b6040518060600160405280602781526020016146f66027913981565b604080516060810190915260228082523332149190614605602083013990611d585760405162461bcd60e51b81526004016111a29190613c18565b507f00000000000000000000000000000000000000000000000000000000000000004210156040518060600160405280602481526020016146af6024913990611db45760405162461bcd60e51b81526004016111a29190613c18565b5060408051808201909152601a81527f506c61796572486f7573696e673a2057726f6e6720707269636500000000000060208201523467016345785d8a000014611e115760405162461bcd60e51b81526004016111a29190613c18565b50611bee3361384a565b60408051808201909152601f81527f45524331313535423a204172726179206c656e677468206d69736d61746368006020820152606090848314611e725760405162461bcd60e51b81526004016111a29190613c18565b508367ffffffffffffffff811115611e8c57611e8c6144ab565b604051908082528060200260200182016040528015611eb5578160200160208202803683370190505b50905060005b84811015611f3057611f0b868683818110611ed857611ed86140eb565b9050602002016020810190611eed9190613cae565b858584818110611eff57611eff6140eb565b90506020020135611039565b828281518110611f1d57611f1d6140eb565b6020908102919091010152600101611ebb565b50949350505050565b604080516060810190915260228082523332149190614605602083013990611f745760405162461bcd60e51b81526004016111a29190613c18565b507f00000000000000000000000000000000000000000000000000000000000000004210156040518060600160405280602781526020016147776027913990611fd05760405162461bcd60e51b81526004016111a29190613c18565b5060058311156040518060600160405280602d8152602001614657602d91399061200d5760405162461bcd60e51b81526004016111a29190613c18565b506005821115604051806060016040528060318152602001614746603191399061204a5760405162461bcd60e51b81526004016111a29190613c18565b5060058111156040518060600160405280603481526020016145d160349139906120875760405162461bcd60e51b81526004016111a29190613c18565b5060008183850101905060058111156040518060600160405280602b8152602001614684602b9139906120cd5760405162461bcd60e51b81526004016111a29190613c18565b50600181116040518060600160405280602381526020016146d360239139906121095760405162461bcd60e51b81526004016111a29190613c18565b5060408051808201909152601a81527f506c61796572486f7573696e673a2057726f6e6720707269636500000000000060208201523467016345785d8a00008302146121685760405162461bcd60e51b81526004016111a29190613c18565b506040517ff5298aca00000000000000000000000000000000000000000000000000000000815233600482015260006024820152604481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063f5298aca90606401600060405180830381600087803b1580156121f157600080fd5b505af1158015612205573d6000803e3d6000fd5b505050506113ad3385858585613125565b61465680546122249061411a565b80601f01602080910402602001604051908101604052809291908181526020018280546122509061411a565b801561229d5780601f106122725761010080835404028352916020019161229d565b820191906000526020600020905b81548152906001019060200180831161228057829003601f168201915b505050505081565b6122ad61370f565b6122ba6146558383613a7c565b505050565b60008161465081106122d057600080fd5b01546001600160a01b0316905081565b6040518060600160405280602d8152602001614657602d913981565b61465580546122249061411a565b61231261370f565b611bee60006138d8565b61232461370f565b6122ba6146568383613a7c565b60405180606001604052806029815260200161471d6029913981565b6040805160608101909152602280825233321491906146056020830139906123885760405162461bcd60e51b81526004016111a29190613c18565b507f000000000000000000000000000000000000000000000000000000000000000042101560405180606001604052806027815260200161477760279139906123e45760405162461bcd60e51b81526004016111a29190613c18565b5060408051808201909152601a81527f506c61796572486f7573696e673a2057726f6e6720707269636500000000000060208201523467016345785d8a0000146124415760405162461bcd60e51b81526004016111a29190613c18565b506040517ff5298aca00000000000000000000000000000000000000000000000000000000815233600482015260006024820152600160448201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063f5298aca90606401600060405180830381600087803b1580156124ca57600080fd5b505af11580156124de573d6000803e3d6000fd5b50505050611bee3361384a565b336000908152614653602090815260409182902054825160608101909352602780845260ff90911692916146f6908301399061253a5760405162461bcd60e51b81526004016111a29190613c18565b506001600160a01b0390911660009081526146526020526040902055565b6040518060600160405280602381526020016146d36023913981565b6040805160608101909152602280825233321491906146056020830139906125af5760405162461bcd60e51b81526004016111a29190613c18565b507f00000000000000000000000000000000000000000000000000000000000000004210156040518060600160405280602481526020016146af602491399061260b5760405162461bcd60e51b81526004016111a29190613c18565b5060408051808201909152601a81527f506c61796572486f7573696e673a2057726f6e6720707269636500000000000060208201523467016345785d8a0000146126685760405162461bcd60e51b81526004016111a29190613c18565b50611bee3361376a565b336000818152614650602090815260408083206001600160a01b0387168085529083529281902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b61270561370f565b868514801561271357508483145b801561271e57508281145b6040518060400160405280601f81526020017f45524331313535423a204172726179206c656e677468206d69736d6174636800815250906127725760405162461bcd60e51b81526004016111a29190613c18565b506020870260005b818110156127b55760208101908a810135908981013590888101359087013581830181016127ab8585858585613125565b505050505061277a565b50505050505050505050565b6127c961370f565b611a4d8161384a565b6127da613b1e565b604080516208ca00810191829052906000906146509082845b81546001600160a01b031681526001909101906020018083116127f3575050505050905090565b6040805160608101909152602280825233321491906146056020830139906128555760405162461bcd60e51b81526004016111a29190613c18565b507f000000000000000000000000000000000000000000000000000000000000000042101560405180606001604052806027815260200161477760279139906128b15760405162461bcd60e51b81526004016111a29190613c18565b5060408051808201909152601a81527f506c61796572486f7573696e673a2057726f6e6720707269636500000000000060208201523467016345785d8a00001461290e5760405162461bcd60e51b81526004016111a29190613c18565b506040517ff5298aca00000000000000000000000000000000000000000000000000000000815233600482015260006024820152600160448201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063f5298aca90606401600060405180830381600087803b15801561299757600080fd5b505af11580156129ab573d6000803e3d6000fd5b50505050611bee33613943565b6040518060600160405280603181526020016147466031913981565b604080516060810190915260228082523332149190614605602083013990612a0f5760405162461bcd60e51b81526004016111a29190613c18565b507f00000000000000000000000000000000000000000000000000000000000000004210156040518060600160405280602481526020016146af6024913990612a6b5760405162461bcd60e51b81526004016111a29190613c18565b5060408051808201909152601a81527f506c61796572486f7573696e673a2057726f6e6720707269636500000000000060208201523467016345785d8a000014612ac85760405162461bcd60e51b81526004016111a29190613c18565b50611bee33613943565b612ada61370f565b6001600160a01b0382166000818152614653602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001685151590811790915591519182527f7b708b778140a177a5a50654ade8c6bef195eb041b31c374ae3e9d82e0de9233910160405180910390a25050565b612b6061370f565b614654546040516001600160a01b038084169216907f606d63a4236a3485ccb92cec46cd7387dac870c31434cd4f8ab856020c78598c90600090a361465480547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6040518060600160405280603081526020016146276030913981565b6040518060600160405280603481526020016145d16034913981565b6040518060600160405280602d815260200161479e602d913981565b336001600160a01b0387161480612c6557506001600160a01b03861660009081526146506020908152604080832033845290915290205460ff165b6040518060400160405280601881526020017f45524331313535423a204e6f7420617574686f72697a6564000000000000000081525090612cb95760405162461bcd60e51b81526004016111a29190613c18565b5060408051808201909152601481527f45524331313535423a20496e76616c696420494400000000000000000000000060208201526146508510612d105760405162461bcd60e51b81526004016111a29190613c18565b5060408051808201909152601881527f45524331313535423a20496e76616c696420616d6f756e740000000000000000602082015260018414612d665760405162461bcd60e51b81526004016111a29190613c18565b50614654546040517fcbc3fb560000000000000000000000000000000000000000000000000000000081523060048201523360248201526001600160a01b0388811660448301528781166064830152608482018790529091169063cbc3fb569060a4016020604051808303816000875af1158015612de8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e0c9190614349565b156040518060400160405280601b81526020017f506c61796572486f7573696e673a20546f6b656e206c6f636b6564000000000081525090612e615760405162461bcd60e51b81526004016111a29190613c18565b50835484906001600160a01b0316878114612ebb5760405162461bcd60e51b815260206004820152601e60248201527f45524331313535423a2046726f6d206e6f7420746f6b656e206f776e657200006044820152606481fd5b50859055612eca868685613567565b60408051858152602081018590526001600160a01b03808816929089169133917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a46001600160a01b0385163b15613033576040517ff23a6e6100000000000000000000000000000000000000000000000000000000808252906001600160a01b0387169063f23a6e6190612f769033908b908a908a908a908a906004016144da565b6020604051808303816000875af1158015612f95573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fb9919061443a565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916146040518060400160405280601a81526020017f45524331313535423a20556e7361666520726563697069656e740000000000008152509061302d5760405162461bcd60e51b81526004016111a29190613c18565b50613090565b60408051808201909152601b81527f45524331313535423a20496e76616c696420726563697069656e74000000000060208201526001600160a01b03861661308e5760405162461bcd60e51b81526004016111a29190613c18565b505b505050505050565b6130a061370f565b6001600160a01b03811661311c5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016111a2565b611a4d816138d8565b60008167ffffffffffffffff811115613140576131406144ab565b604051908082528060200260200182016040528015613169578160200160208202803683370190505b50905060008267ffffffffffffffff811115613187576131876144ab565b6040519080825280602002602001820160405280156131b0578160200160208202803683370190505b506146575490915060208381019190830190808915613263576040805160608101909152602980825261ffff8416918c830191611770831115919061471d6020830139906132115760405162461bcd60e51b81526004016111a29190613c18565b50815b81811015613237578d815580875260018087526020978801979096019501613214565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00009290921690911790505b881561330f576040805160608101909152602d808252601084901c61ffff16918b830191611770831115919061479e6020830139906132b55760405162461bcd60e51b81526004016111a29190613c18565b50815b818110156132df5761177081018e81558752600180875260209788019790960195016132b8565b5060101b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000ffff929092169190911790505b87156133b55760408051606081019091526030808252602084811c928b84019261177084111592614627908301399061335b5760405162461bcd60e51b81526004016111a29190613c18565b50815b8181101561338557612ee081018e815587526001808752602097880197909601950161335e565b5060201b7fffffffffffffffffffffffffffffffffffffffffffffffffffff0000ffffffff929092169190911790505b6146578190556133c58b886139f6565b8a6001600160a01b031660006001600160a01b0316336001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8989604051613415929190614513565b60405180910390a45050505050505050505050565b60608160000361346d57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115613497578061348181614541565b91506134909050600a836145a8565b9150613471565b60008167ffffffffffffffff8111156134b2576134b26144ab565b6040519080825280601f01601f1916602001820160405280156134dc576020820181803683370190505b5090505b841561355f576134f1600183614457565b91506134fe600a866145bc565b613509906030614299565b60f81b81838151811061351e5761351e6140eb565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350613558600a866145a8565b94506134e0565b949350505050565b60007f000000000000000000000000000000000000000000000000000000000000000042106135b6577f00000000000000000000000000000000000000000000000000000000000000006135b8565b425b6001600160a01b03851660009081526146526020526040902054909150601081901c63ffffffff167f000000000000000000000000000000000000000000000000000000000000000081146136615761ffff8216603083901c82156136345760006136238487614457565b8302656022099fa744029190910190505b6001600160a01b03881660009081526146526020526040902091869003601086901b1760309190911b1790555b50506001600160a01b03831660009081526146526020526040902054601081901c63ffffffff167f000000000000000000000000000000000000000000000000000000000000000081146130905761ffff8216603083901c82156136dc5760006136cb8487614457565b8302656022099fa744029190910190505b6001600160a01b038716600090815261465260205260409020918601601086901b1760309190911b179055505050505050565b614651546001600160a01b03163314611bee5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016111a2565b614657546040805160608101909152602d808252601083901c61ffff169161177083109161479e6020830139906137b45760405162461bcd60e51b81526004016111a29190613c18565b5061177081018381556001918201601081901b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000ffff85161761465755916137fb9085906139f6565b60408051828152600160208201526001600160a01b0386169160009133917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a450505050565b6146575460408051606081019091526030808252602083811c92611770841092909161462790830139906138915760405162461bcd60e51b81526004016111a29190613c18565b50612ee081018381556001918201602081901b7fffffffffffffffffffffffffffffffffffffffffffffffffffff0000ffffffff85161761465755916137fb9085906139f6565b61465180546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600061ffff801661465754169050611770811060405180606001604052806029815260200161471d602991399061398d5760405162461bcd60e51b81526004016111a29190613c18565b50818155614657805460019081019091556139a99083906139f6565b60408051828152600160208201526001600160a01b0384169160009133917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a45050565b6001600160a01b0382166000908152614652602052604090205461ffff8116601082901c63ffffffff16603083901c8115613a48576000613a378342614457565b8402656022099fa744029190910190505b6001600160a01b03909516600090815261465260205260409020919093014260101b1760309490941b939093179092555050565b828054613a889061411a565b90600052602060002090601f016020900481019282613aaa5760008555613b0e565b82601f10613ae1578280017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00823516178555613b0e565b82800160010185558215613b0e579182015b82811115613b0e578235825591602001919060010190613af3565b50613b1a929150613b3f565b5090565b604051806208ca000160405280614650906020820280368337509192915050565b5b80821115613b1a5760008155600101613b40565b80356001600160a01b0381168114613b6b57600080fd5b919050565b60008060408385031215613b8357600080fd5b613b8c83613b54565b946020939093013593505050565b7fffffffff0000000000000000000000000000000000000000000000000000000081168114611a4d57600080fd5b600060208284031215613bda57600080fd5b8135613be581613b9a565b9392505050565b60005b83811015613c07578181015183820152602001613bef565b838111156113ad5750506000910152565b6020815260008251806020840152613c37816040850160208701613bec565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b600080600060608486031215613c7e57600080fd5b505081359360208301359350604090920135919050565b600060208284031215613ca757600080fd5b5035919050565b600060208284031215613cc057600080fd5b613be582613b54565b60008083601f840112613cdb57600080fd5b50813567ffffffffffffffff811115613cf357600080fd5b6020830191508360208260051b8501011115613d0e57600080fd5b9250929050565b60008083601f840112613d2757600080fd5b50813567ffffffffffffffff811115613d3f57600080fd5b602083019150836020828501011115613d0e57600080fd5b60008060008060008060008060a0898b031215613d7357600080fd5b613d7c89613b54565b9750613d8a60208a01613b54565b9650604089013567ffffffffffffffff80821115613da757600080fd5b613db38c838d01613cc9565b909850965060608b0135915080821115613dcc57600080fd5b613dd88c838d01613cc9565b909650945060808b0135915080821115613df157600080fd5b50613dfe8b828c01613d15565b999c989b5096995094979396929594505050565b60008060008060408587031215613e2857600080fd5b843567ffffffffffffffff80821115613e4057600080fd5b613e4c88838901613cc9565b90965094506020870135915080821115613e6557600080fd5b50613e7287828801613cc9565b95989497509550505050565b600081518084526020808501945080840160005b83811015613eae57815187529582019590820190600101613e92565b509495945050505050565b602081526000613be56020830184613e7e565b60008060208385031215613edf57600080fd5b823567ffffffffffffffff811115613ef657600080fd5b613f0285828601613d15565b90969095509350505050565b8015158114611a4d57600080fd5b60008060408385031215613f2f57600080fd5b613f3883613b54565b91506020830135613f4881613f0e565b809150509250929050565b6000806000806000806000806080898b031215613f6f57600080fd5b883567ffffffffffffffff80821115613f8757600080fd5b613f938c838d01613cc9565b909a50985060208b0135915080821115613fac57600080fd5b613fb88c838d01613cc9565b909850965060408b0135915080821115613fd157600080fd5b613fdd8c838d01613cc9565b909650945060608b0135915080821115613ff657600080fd5b50613dfe8b828c01613cc9565b6208ca008101818360005b6146508110156140375781516001600160a01b031683526020928301929091019060010161400e565b50505092915050565b6000806040838503121561405357600080fd5b61405c83613b54565b915061406a60208401613b54565b90509250929050565b60008060008060008060a0878903121561408c57600080fd5b61409587613b54565b95506140a360208801613b54565b94506040870135935060608701359250608087013567ffffffffffffffff8111156140cd57600080fd5b6140d989828a01613d15565b979a9699509497509295939492505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600181811c9082168061412e57607f821691505b602082108103611cfb577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b8054600090600181811c908083168061418157607f831692505b602080841082036141bb577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b8180156141cf57600181146141fe5761422b565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0086168952848901965061422b565b60008881526020902060005b868110156142235781548b82015290850190830161420a565b505084890196505b50505050505092915050565b60006142438286614167565b8451614253818360208901613bec565b61425f81830186614167565b979650505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156142ac576142ac61426a565b500190565b81835260007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8311156142e357600080fd5b8260051b8083602087013760009401602001938452509192915050565b60006001600160a01b0380891683528088166020840152808716604084015280861660608401525060a0608083015261433d60a0830184866142b1565b98975050505050505050565b60006020828403121561435b57600080fd5b8151613be581613f0e565b60408152600061437a6040830186886142b1565b828103602084015261425f8185876142b1565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b60006001600160a01b03808b168352808a1660208401525060a0604083015261440360a08301888a6142b1565b82810360608401526144168187896142b1565b9050828103608084015261442b81858761438d565b9b9a5050505050505050505050565b60006020828403121561444c57600080fd5b8151613be581613b9a565b6000828210156144695761446961426a565b500390565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156144a6576144a661426a565b500290565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006001600160a01b03808916835280881660208401525085604083015284606083015260a0608083015261433d60a08301848661438d565b6040815260006145266040830185613e7e565b82810360208401526145388185613e7e565b95945050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036145725761457261426a565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826145b7576145b7614579565b500490565b6000826145cb576145cb614579565b50069056fe506c61796572486f7573696e673a204c61637265616e20456d70697265206f766572206d617820616d6f756e7420706572207478506c61796572486f7573696e673a204e6f20636f6e7472616374206d696e74696e67506c61796572486f7573696e673a2052656163686564206d6178204c61637265616e20456d7069726520737570706c79506c61796572486f7573696e673a204172626f726961206f766572206d617820616d6f756e7420706572207478506c61796572486f7573696e673a20546f74616c206f766572206d617820616d6f756e7420706572207478506c61796572486f7573696e673a205075626c69632073616c65206e6f74207265616479506c61796572486f7573696e673a20546f74616c20616d6f756e742062656c6f772032506c61796572486f7573696e673a204e6f7420617070726f76656420666f722072657761726473506c61796572486f7573696e673a2052656163686564206d6178204172626f72696120737570706c79506c61796572486f7573696e673a20496c6c736b616761617264206f766572206d617820616d6f756e7420706572207478506c61796572486f7573696e673a2057686974656c6973742073616c65206e6f74207265616479506c61796572486f7573696e673a2052656163686564206d617820496c6c736b61676161726420737570706c79a2646970667358221220ab14a4c15a796cfa7eaba33e0bae8b63ce81e69700e041524da59d7937d7a8b164736f6c634300080e00330000000000000000000000005a5fe90cd115d691ee99d90d3607f7005ea817e50000000000000000000000000000000000000000000000000000000062dae5a00000000000000000000000000000000000000000000000000000000062dd88a00000000000000000000000000000000000000000000000000000000075a6e8a0000000000000000000000000544d219c227856935bf9678e21a2cd012bcc8bd8000000000000000000000000616e6b2ba922968af8d46df9400fc3da17589c5f

Deployed Bytecode

0x60806040526004361061053c5760003560e01c806370a08231116102af578063affe39c111610179578063dd74d3b7116100d6578063efd52b8b1161008a578063f242432a1161006f578063f242432a14610fb0578063f2fde38b14610fd0578063f806b10114610ff057600080fd5b8063efd52b8b14610f86578063f1d91b1214610f9b57600080fd5b8063e4a1ada4116100bb578063e4a1ada414610f20578063e985e9c514610f35578063ea39260014610f7157600080fd5b8063dd74d3b714610ecf578063deedfdbd14610f0057600080fd5b8063c1049e801161012d578063c8d3403911610112578063c8d3403914610e1f578063d39fbaa414610e68578063dbcfd08f14610eb157600080fd5b8063c1049e8014610db6578063c64a0b8b14610dff57600080fd5b8063bdb6fe2a1161015e578063bdb6fe2a14610d7d578063bfd7253f14610d92578063c002d23d14610d9a57600080fd5b8063affe39c114610d53578063b9be77b214610d7557600080fd5b80638da5cb5b11610227578063a113152b116101db578063a42bfe6d116101c0578063a42bfe6d14610cf2578063a4a4003814610d12578063acca30a214610d3257600080fd5b8063a113152b14610c89578063a22cb46514610cd257600080fd5b80639030d1bb1161020c5780639030d1bb14610c4c57806398c7798414610c6c578063a0afde1514610c8157600080fd5b80638da5cb5b14610c255780638f13c2a414610c4457600080fd5b8063802e79181161027e57806386aaf9341161026357806386aaf93414610b7e578063873b4aa914610bc7578063878de91e14610c1057600080fd5b8063802e791814610b4457806381b3e57514610b5e57600080fd5b806370a0823114610a77578063715018a614610ab25780637999567114610ac75780637aeb357314610b1057600080fd5b80632eb2c2d61161040b5780634ee6262d11610368578063576793491161031c5780636352211e116103015780636352211e14610a2d5780636a01be5314610a4d5780636c0360eb14610a6257600080fd5b806357679349146109b057806358e96d5f146109f957600080fd5b806351f977041161034d57806351f97704146109685780635503a0e81461097b57806355f804b31461099057600080fd5b80634ee6262d1461091f5780634f9bba2c1461083957600080fd5b8063479ba7ae116103bf5780634d58026c116103a45780634d58026c146108a15780634d7e41d5146108a95780634e1273f4146108f257600080fd5b8063479ba7ae1461086c5780634c09e3e61461088c57600080fd5b806335f743ae116103f057806335f743ae146108395780633ccfd60b1461084f5780633e4af9c51461086457600080fd5b80632eb2c2d61461080357806332cb6b0c1461082357600080fd5b80630e89341c116104b95780631adc62d81161046d578063207e3cc311610452578063207e3cc3146107a75780632552a1d0146107d55780632d960a4c146107ea57600080fd5b80631adc62d8146107595780631d84cee91461078d57600080fd5b806318160ddd1161049e57806318160ddd146106e357806318c33e46146106f8578063192d4df61461074457600080fd5b80630e89341c146106ad57806317bac052146106cd57600080fd5b80630ae349f4116105105780630d6f23cd116104f55780630d6f23cd146106065780630df1f7c71461064f5780630e0847211461069857600080fd5b80630ae349f4146105db5780630b32f0b2146105f157600080fd5b8062fdd58e1461054157806301ffc9a71461057457806303e56262146105a457806309ef6527146105c6575b600080fd5b34801561054d57600080fd5b5061056161055c366004613b70565b611039565b6040519081526020015b60405180910390f35b34801561058057600080fd5b5061059461058f366004613bc8565b611066565b604051901515815260200161056b565b3480156105b057600080fd5b506105b961114b565b60405161056b9190613c18565b3480156105d257600080fd5b50610561600581565b3480156105e757600080fd5b50610561612ee081565b6106046105ff366004613c69565b611167565b005b34801561061257600080fd5b506105b96040518060400160405280601881526020017f45524331313535423a20496e76616c696420616d6f756e74000000000000000081525081565b34801561065b57600080fd5b506105b96040518060400160405280601881526020017f45524331313535423a204e6f7420617574686f72697a6564000000000000000081525081565b3480156106a457600080fd5b506105b96113b3565b3480156106b957600080fd5b506105b96106c8366004613c95565b6113cf565b3480156106d957600080fd5b5061056161464f81565b3480156106ef57600080fd5b506105616114c7565b34801561070457600080fd5b5061072c7f000000000000000000000000544d219c227856935bf9678e21a2cd012bcc8bd881565b6040516001600160a01b03909116815260200161056b565b34801561075057600080fd5b506105b9611508565b34801561076557600080fd5b506105617f0000000000000000000000000000000000000000000000000000000062dd88a081565b34801561079957600080fd5b50610561656022099fa74481565b3480156107b357600080fd5b506105616107c2366004613cae565b6146526020526000908152604090205481565b3480156107e157600080fd5b506105b9611524565b3480156107f657600080fd5b506146575460201c610561565b34801561080f57600080fd5b5061060461081e366004613d57565b611540565b34801561082f57600080fd5b5061056161465081565b34801561084557600080fd5b5061056161177081565b34801561085b57600080fd5b50610604611a19565b610604611a50565b34801561087857600080fd5b50610561610887366004613cae565b611bf0565b34801561089857600080fd5b506105b9611d01565b610604611d1d565b3480156108b557600080fd5b506105b96040518060400160405280601a81526020017f506c61796572486f7573696e673a2057726f6e6720707269636500000000000081525081565b3480156108fe57600080fd5b5061091261090d366004613e12565b611e1b565b60405161056b9190613eb9565b34801561092b57600080fd5b506105b96040518060400160405280601781526020017f45524331313535423a204944206e6f74206d696e74656400000000000000000081525081565b610604610976366004613c69565b611f39565b34801561098757600080fd5b506105b9612216565b34801561099c57600080fd5b506106046109ab366004613ecc565b6122a5565b3480156109bc57600080fd5b506105b96040518060400160405280601e81526020017f45524331313535423a2046726f6d206e6f7420746f6b656e206f776e6572000081525081565b348015610a0557600080fd5b506105617f0000000000000000000000000000000000000000000000000000000062dae5a081565b348015610a3957600080fd5b5061072c610a48366004613c95565b6122bf565b348015610a5957600080fd5b506105b96122e0565b348015610a6e57600080fd5b506105b96122fc565b348015610a8357600080fd5b50610561610a92366004613cae565b6001600160a01b03166000908152614652602052604090205461ffff1690565b348015610abe57600080fd5b5061060461230a565b348015610ad357600080fd5b506105b96040518060400160405280601a81526020017f45524331313535423a20556e7361666520726563697069656e7400000000000081525081565b348015610b1c57600080fd5b506105617f0000000000000000000000000000000000000000000000000000000075a6e8a081565b348015610b5057600080fd5b506146575461ffff16610561565b348015610b6a57600080fd5b50610604610b79366004613ecc565b61231c565b348015610b8a57600080fd5b506105b96040518060400160405280601481526020017f45524331313535423a20496e76616c696420494400000000000000000000000081525081565b348015610bd357600080fd5b506105b96040518060400160405280601a81526020017f506c61796572486f7573696e673a204e6f206d6574616461746100000000000081525081565b348015610c1c57600080fd5b506105b9612331565b348015610c3157600080fd5b50614651546001600160a01b031661072c565b61060461234d565b348015610c5857600080fd5b50610604610c67366004613b70565b6124eb565b348015610c7857600080fd5b506105b9612558565b610604612574565b348015610c9557600080fd5b506105b96040518060400160405280601b81526020017f45524331313535423a20494420616c7265616479206d696e746564000000000081525081565b348015610cde57600080fd5b50610604610ced366004613f1c565b612672565b348015610cfe57600080fd5b50610604610d0d366004613f53565b6126fd565b348015610d1e57600080fd5b50610604610d2d366004613cae565b6127c1565b348015610d3e57600080fd5b506146545461072c906001600160a01b031681565b348015610d5f57600080fd5b50610d686127d2565b60405161056b9190614003565b61060461281a565b348015610d8957600080fd5b506105b96129b8565b6106046129d4565b348015610da657600080fd5b5061056167016345785d8a000081565b348015610dc257600080fd5b506105b96040518060400160405280601681526020017f45524331313535423a20496e76616c69642066726f6d0000000000000000000081525081565b348015610e0b57600080fd5b50610604610e1a366004613f1c565b612ad2565b348015610e2b57600080fd5b506105b96040518060400160405280601b81526020017f45524331313535423a20496e76616c696420726563697069656e74000000000081525081565b348015610e7457600080fd5b506105b96040518060400160405280601b81526020017f506c61796572486f7573696e673a20546f6b656e206c6f636b6564000000000081525081565b348015610ebd57600080fd5b506105616146575460101c61ffff1690565b348015610edb57600080fd5b50610594610eea366004613cae565b6146536020526000908152604090205460ff1681565b348015610f0c57600080fd5b50610604610f1b366004613cae565b612b58565b348015610f2c57600080fd5b506105b9612bd6565b348015610f4157600080fd5b50610594610f50366004614040565b61465060209081526000928352604080842090915290825290205460ff1681565b348015610f7d57600080fd5b50610561600081565b348015610f9257600080fd5b506105b9612bf2565b348015610fa757600080fd5b506105b9612c0e565b348015610fbc57600080fd5b50610604610fcb366004614073565b612c2a565b348015610fdc57600080fd5b50610604610feb366004613cae565b613098565b348015610ffc57600080fd5b506105b96040518060400160405280601f81526020017f45524331313535423a204172726179206c656e677468206d69736d617463680081525081565b6000806000836146508110611050576110506140eb565b01546001600160a01b0316939093149392505050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831614806110f957507fd9b67a26000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b8061114557507f0e89341c000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b6040518060600160405280602b8152602001614684602b913981565b6040805160608101909152602280825233321491906146056020830139906111ab5760405162461bcd60e51b81526004016111a29190613c18565b60405180910390fd5b507f0000000000000000000000000000000000000000000000000000000062dd88a04210156040518060600160405280602481526020016146af60249139906112075760405162461bcd60e51b81526004016111a29190613c18565b5060058311156040518060600160405280602d8152602001614657602d9139906112445760405162461bcd60e51b81526004016111a29190613c18565b50600582111560405180606001604052806031815260200161474660319139906112815760405162461bcd60e51b81526004016111a29190613c18565b5060058111156040518060600160405280603481526020016145d160349139906112be5760405162461bcd60e51b81526004016111a29190613c18565b5060008183850101905060058111156040518060600160405280602b8152602001614684602b9139906113045760405162461bcd60e51b81526004016111a29190613c18565b50600181116040518060600160405280602381526020016146d360239139906113405760405162461bcd60e51b81526004016111a29190613c18565b5060408051808201909152601a81527f506c61796572486f7573696e673a2057726f6e6720707269636500000000000060208201523467016345785d8a000083021461139f5760405162461bcd60e51b81526004016111a29190613c18565b506113ad3385858585613125565b50505050565b6040518060600160405280602481526020016146af6024913981565b6060600061465580546113e19061411a565b9050116040518060400160405280601a81526020017f506c61796572486f7573696e673a204e6f206d65746164617461000000000000815250906114385760405162461bcd60e51b81526004016111a29190613c18565b5060408051808201909152601481527f45524331313535423a20496e76616c69642049440000000000000000000000006020820152614650831061148f5760405162461bcd60e51b81526004016111a29190613c18565b5061465561149c8361342a565b6146566040516020016114b193929190614237565b6040516020818303038152906040529050919050565b60006114d66146575460201c90565b6114e76146575460101c61ffff1690565b6146575461ffff166114f99190614299565b6115039190614299565b905090565b6040518060600160405280602281526020016146056022913981565b6040518060600160405280602781526020016147776027913981565b60408051808201909152601f81527f45524331313535423a204172726179206c656e677468206d69736d617463680060208201528584146115945760405162461bcd60e51b81526004016111a29190613c18565b50336001600160a01b03891614806115d057506001600160a01b03881660009081526146506020908152604080832033845290915290205460ff165b6040518060400160405280601881526020017f45524331313535423a204e6f7420617574686f72697a65640000000000000000815250906116245760405162461bcd60e51b81526004016111a29190613c18565b50614654546040517fc2d638ef0000000000000000000000000000000000000000000000000000000081526001600160a01b039091169063c2d638ef9061167990309033908d908d908d908d90600401614300565b6020604051808303816000875af1158015611698573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116bc9190614349565b156040518060400160405280601b81526020017f506c61796572486f7573696e673a20546f6b656e206c6f636b65640000000000815250906117115760405162461bcd60e51b81526004016111a29190613c18565b506020850260005b81811015611827578088013561464f8111156117745760405162461bcd60e51b815260206004820152601460248201527f45524331313535423a20496e76616c69642049440000000000000000000000006044820152606481fd5b868201356001146117c45760405162461bcd60e51b815260206004820152601860248201527f45524331313535423a20496e76616c696420616d6f756e7400000000000000006044820152606481fd5b80546001600160a01b03168b811461181b5760405162461bcd60e51b815260206004820152601e60248201527f45524331313535423a2046726f6d206e6f7420746f6b656e206f776e657200006044820152606481fd5b50899055602001611719565b506118359050888887613567565b866001600160a01b0316886001600160a01b0316336001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb898989896040516118889493929190614366565b60405180910390a46001600160a01b0387163b156119b2576040517fbc197c8100000000000000000000000000000000000000000000000000000000808252906001600160a01b0389169063bc197c81906118f59033908d908c908c908c908c908c908c906004016143d6565b6020604051808303816000875af1158015611914573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611938919061443a565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916146040518060400160405280601a81526020017f45524331313535423a20556e7361666520726563697069656e74000000000000815250906119ac5760405162461bcd60e51b81526004016111a29190613c18565b50611a0f565b60408051808201909152601b81527f45524331313535423a20496e76616c696420726563697069656e74000000000060208201526001600160a01b038816611a0d5760405162461bcd60e51b81526004016111a29190613c18565b505b5050505050505050565b611a2161370f565b60405133904780156108fc02916000818181858888f19350505050158015611a4d573d6000803e3d6000fd5b50565b604080516060810190915260228082523332149190614605602083013990611a8b5760405162461bcd60e51b81526004016111a29190613c18565b507f0000000000000000000000000000000000000000000000000000000062dae5a04210156040518060600160405280602781526020016147776027913990611ae75760405162461bcd60e51b81526004016111a29190613c18565b5060408051808201909152601a81527f506c61796572486f7573696e673a2057726f6e6720707269636500000000000060208201523467016345785d8a000014611b445760405162461bcd60e51b81526004016111a29190613c18565b506040517ff5298aca00000000000000000000000000000000000000000000000000000000815233600482015260006024820152600160448201527f000000000000000000000000544d219c227856935bf9678e21a2cd012bcc8bd86001600160a01b03169063f5298aca90606401600060405180830381600087803b158015611bcd57600080fd5b505af1158015611be1573d6000803e3d6000fd5b50505050611bee3361376a565b565b6001600160a01b03811660009081526146526020526040902054603081901c9060101c63ffffffff167f0000000000000000000000000000000000000000000000000000000075a6e8a08114611cfb5760007f0000000000000000000000000000000000000000000000000000000075a6e8a04210611c8f577f0000000000000000000000000000000000000000000000000000000075a6e8a0611c91565b425b90506000611cb9856001600160a01b03166000908152614652602052604090205461ffff1690565b90508215611cf8576000611ccd8484614457565b905081611ce0656022099fa7448361446e565b611cea919061446e565b611cf49086614299565b9450505b50505b50919050565b6040518060600160405280602781526020016146f66027913981565b604080516060810190915260228082523332149190614605602083013990611d585760405162461bcd60e51b81526004016111a29190613c18565b507f0000000000000000000000000000000000000000000000000000000062dd88a04210156040518060600160405280602481526020016146af6024913990611db45760405162461bcd60e51b81526004016111a29190613c18565b5060408051808201909152601a81527f506c61796572486f7573696e673a2057726f6e6720707269636500000000000060208201523467016345785d8a000014611e115760405162461bcd60e51b81526004016111a29190613c18565b50611bee3361384a565b60408051808201909152601f81527f45524331313535423a204172726179206c656e677468206d69736d61746368006020820152606090848314611e725760405162461bcd60e51b81526004016111a29190613c18565b508367ffffffffffffffff811115611e8c57611e8c6144ab565b604051908082528060200260200182016040528015611eb5578160200160208202803683370190505b50905060005b84811015611f3057611f0b868683818110611ed857611ed86140eb565b9050602002016020810190611eed9190613cae565b858584818110611eff57611eff6140eb565b90506020020135611039565b828281518110611f1d57611f1d6140eb565b6020908102919091010152600101611ebb565b50949350505050565b604080516060810190915260228082523332149190614605602083013990611f745760405162461bcd60e51b81526004016111a29190613c18565b507f0000000000000000000000000000000000000000000000000000000062dae5a04210156040518060600160405280602781526020016147776027913990611fd05760405162461bcd60e51b81526004016111a29190613c18565b5060058311156040518060600160405280602d8152602001614657602d91399061200d5760405162461bcd60e51b81526004016111a29190613c18565b506005821115604051806060016040528060318152602001614746603191399061204a5760405162461bcd60e51b81526004016111a29190613c18565b5060058111156040518060600160405280603481526020016145d160349139906120875760405162461bcd60e51b81526004016111a29190613c18565b5060008183850101905060058111156040518060600160405280602b8152602001614684602b9139906120cd5760405162461bcd60e51b81526004016111a29190613c18565b50600181116040518060600160405280602381526020016146d360239139906121095760405162461bcd60e51b81526004016111a29190613c18565b5060408051808201909152601a81527f506c61796572486f7573696e673a2057726f6e6720707269636500000000000060208201523467016345785d8a00008302146121685760405162461bcd60e51b81526004016111a29190613c18565b506040517ff5298aca00000000000000000000000000000000000000000000000000000000815233600482015260006024820152604481018290527f000000000000000000000000544d219c227856935bf9678e21a2cd012bcc8bd86001600160a01b03169063f5298aca90606401600060405180830381600087803b1580156121f157600080fd5b505af1158015612205573d6000803e3d6000fd5b505050506113ad3385858585613125565b61465680546122249061411a565b80601f01602080910402602001604051908101604052809291908181526020018280546122509061411a565b801561229d5780601f106122725761010080835404028352916020019161229d565b820191906000526020600020905b81548152906001019060200180831161228057829003601f168201915b505050505081565b6122ad61370f565b6122ba6146558383613a7c565b505050565b60008161465081106122d057600080fd5b01546001600160a01b0316905081565b6040518060600160405280602d8152602001614657602d913981565b61465580546122249061411a565b61231261370f565b611bee60006138d8565b61232461370f565b6122ba6146568383613a7c565b60405180606001604052806029815260200161471d6029913981565b6040805160608101909152602280825233321491906146056020830139906123885760405162461bcd60e51b81526004016111a29190613c18565b507f0000000000000000000000000000000000000000000000000000000062dae5a042101560405180606001604052806027815260200161477760279139906123e45760405162461bcd60e51b81526004016111a29190613c18565b5060408051808201909152601a81527f506c61796572486f7573696e673a2057726f6e6720707269636500000000000060208201523467016345785d8a0000146124415760405162461bcd60e51b81526004016111a29190613c18565b506040517ff5298aca00000000000000000000000000000000000000000000000000000000815233600482015260006024820152600160448201527f000000000000000000000000544d219c227856935bf9678e21a2cd012bcc8bd86001600160a01b03169063f5298aca90606401600060405180830381600087803b1580156124ca57600080fd5b505af11580156124de573d6000803e3d6000fd5b50505050611bee3361384a565b336000908152614653602090815260409182902054825160608101909352602780845260ff90911692916146f6908301399061253a5760405162461bcd60e51b81526004016111a29190613c18565b506001600160a01b0390911660009081526146526020526040902055565b6040518060600160405280602381526020016146d36023913981565b6040805160608101909152602280825233321491906146056020830139906125af5760405162461bcd60e51b81526004016111a29190613c18565b507f0000000000000000000000000000000000000000000000000000000062dd88a04210156040518060600160405280602481526020016146af602491399061260b5760405162461bcd60e51b81526004016111a29190613c18565b5060408051808201909152601a81527f506c61796572486f7573696e673a2057726f6e6720707269636500000000000060208201523467016345785d8a0000146126685760405162461bcd60e51b81526004016111a29190613c18565b50611bee3361376a565b336000818152614650602090815260408083206001600160a01b0387168085529083529281902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b61270561370f565b868514801561271357508483145b801561271e57508281145b6040518060400160405280601f81526020017f45524331313535423a204172726179206c656e677468206d69736d6174636800815250906127725760405162461bcd60e51b81526004016111a29190613c18565b506020870260005b818110156127b55760208101908a810135908981013590888101359087013581830181016127ab8585858585613125565b505050505061277a565b50505050505050505050565b6127c961370f565b611a4d8161384a565b6127da613b1e565b604080516208ca00810191829052906000906146509082845b81546001600160a01b031681526001909101906020018083116127f3575050505050905090565b6040805160608101909152602280825233321491906146056020830139906128555760405162461bcd60e51b81526004016111a29190613c18565b507f0000000000000000000000000000000000000000000000000000000062dae5a042101560405180606001604052806027815260200161477760279139906128b15760405162461bcd60e51b81526004016111a29190613c18565b5060408051808201909152601a81527f506c61796572486f7573696e673a2057726f6e6720707269636500000000000060208201523467016345785d8a00001461290e5760405162461bcd60e51b81526004016111a29190613c18565b506040517ff5298aca00000000000000000000000000000000000000000000000000000000815233600482015260006024820152600160448201527f000000000000000000000000544d219c227856935bf9678e21a2cd012bcc8bd86001600160a01b03169063f5298aca90606401600060405180830381600087803b15801561299757600080fd5b505af11580156129ab573d6000803e3d6000fd5b50505050611bee33613943565b6040518060600160405280603181526020016147466031913981565b604080516060810190915260228082523332149190614605602083013990612a0f5760405162461bcd60e51b81526004016111a29190613c18565b507f0000000000000000000000000000000000000000000000000000000062dd88a04210156040518060600160405280602481526020016146af6024913990612a6b5760405162461bcd60e51b81526004016111a29190613c18565b5060408051808201909152601a81527f506c61796572486f7573696e673a2057726f6e6720707269636500000000000060208201523467016345785d8a000014612ac85760405162461bcd60e51b81526004016111a29190613c18565b50611bee33613943565b612ada61370f565b6001600160a01b0382166000818152614653602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001685151590811790915591519182527f7b708b778140a177a5a50654ade8c6bef195eb041b31c374ae3e9d82e0de9233910160405180910390a25050565b612b6061370f565b614654546040516001600160a01b038084169216907f606d63a4236a3485ccb92cec46cd7387dac870c31434cd4f8ab856020c78598c90600090a361465480547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6040518060600160405280603081526020016146276030913981565b6040518060600160405280603481526020016145d16034913981565b6040518060600160405280602d815260200161479e602d913981565b336001600160a01b0387161480612c6557506001600160a01b03861660009081526146506020908152604080832033845290915290205460ff165b6040518060400160405280601881526020017f45524331313535423a204e6f7420617574686f72697a6564000000000000000081525090612cb95760405162461bcd60e51b81526004016111a29190613c18565b5060408051808201909152601481527f45524331313535423a20496e76616c696420494400000000000000000000000060208201526146508510612d105760405162461bcd60e51b81526004016111a29190613c18565b5060408051808201909152601881527f45524331313535423a20496e76616c696420616d6f756e740000000000000000602082015260018414612d665760405162461bcd60e51b81526004016111a29190613c18565b50614654546040517fcbc3fb560000000000000000000000000000000000000000000000000000000081523060048201523360248201526001600160a01b0388811660448301528781166064830152608482018790529091169063cbc3fb569060a4016020604051808303816000875af1158015612de8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e0c9190614349565b156040518060400160405280601b81526020017f506c61796572486f7573696e673a20546f6b656e206c6f636b6564000000000081525090612e615760405162461bcd60e51b81526004016111a29190613c18565b50835484906001600160a01b0316878114612ebb5760405162461bcd60e51b815260206004820152601e60248201527f45524331313535423a2046726f6d206e6f7420746f6b656e206f776e657200006044820152606481fd5b50859055612eca868685613567565b60408051858152602081018590526001600160a01b03808816929089169133917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a46001600160a01b0385163b15613033576040517ff23a6e6100000000000000000000000000000000000000000000000000000000808252906001600160a01b0387169063f23a6e6190612f769033908b908a908a908a908a906004016144da565b6020604051808303816000875af1158015612f95573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fb9919061443a565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916146040518060400160405280601a81526020017f45524331313535423a20556e7361666520726563697069656e740000000000008152509061302d5760405162461bcd60e51b81526004016111a29190613c18565b50613090565b60408051808201909152601b81527f45524331313535423a20496e76616c696420726563697069656e74000000000060208201526001600160a01b03861661308e5760405162461bcd60e51b81526004016111a29190613c18565b505b505050505050565b6130a061370f565b6001600160a01b03811661311c5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016111a2565b611a4d816138d8565b60008167ffffffffffffffff811115613140576131406144ab565b604051908082528060200260200182016040528015613169578160200160208202803683370190505b50905060008267ffffffffffffffff811115613187576131876144ab565b6040519080825280602002602001820160405280156131b0578160200160208202803683370190505b506146575490915060208381019190830190808915613263576040805160608101909152602980825261ffff8416918c830191611770831115919061471d6020830139906132115760405162461bcd60e51b81526004016111a29190613c18565b50815b81811015613237578d815580875260018087526020978801979096019501613214565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00009290921690911790505b881561330f576040805160608101909152602d808252601084901c61ffff16918b830191611770831115919061479e6020830139906132b55760405162461bcd60e51b81526004016111a29190613c18565b50815b818110156132df5761177081018e81558752600180875260209788019790960195016132b8565b5060101b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000ffff929092169190911790505b87156133b55760408051606081019091526030808252602084811c928b84019261177084111592614627908301399061335b5760405162461bcd60e51b81526004016111a29190613c18565b50815b8181101561338557612ee081018e815587526001808752602097880197909601950161335e565b5060201b7fffffffffffffffffffffffffffffffffffffffffffffffffffff0000ffffffff929092169190911790505b6146578190556133c58b886139f6565b8a6001600160a01b031660006001600160a01b0316336001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8989604051613415929190614513565b60405180910390a45050505050505050505050565b60608160000361346d57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115613497578061348181614541565b91506134909050600a836145a8565b9150613471565b60008167ffffffffffffffff8111156134b2576134b26144ab565b6040519080825280601f01601f1916602001820160405280156134dc576020820181803683370190505b5090505b841561355f576134f1600183614457565b91506134fe600a866145bc565b613509906030614299565b60f81b81838151811061351e5761351e6140eb565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350613558600a866145a8565b94506134e0565b949350505050565b60007f0000000000000000000000000000000000000000000000000000000075a6e8a042106135b6577f0000000000000000000000000000000000000000000000000000000075a6e8a06135b8565b425b6001600160a01b03851660009081526146526020526040902054909150601081901c63ffffffff167f0000000000000000000000000000000000000000000000000000000075a6e8a081146136615761ffff8216603083901c82156136345760006136238487614457565b8302656022099fa744029190910190505b6001600160a01b03881660009081526146526020526040902091869003601086901b1760309190911b1790555b50506001600160a01b03831660009081526146526020526040902054601081901c63ffffffff167f0000000000000000000000000000000000000000000000000000000075a6e8a081146130905761ffff8216603083901c82156136dc5760006136cb8487614457565b8302656022099fa744029190910190505b6001600160a01b038716600090815261465260205260409020918601601086901b1760309190911b179055505050505050565b614651546001600160a01b03163314611bee5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016111a2565b614657546040805160608101909152602d808252601083901c61ffff169161177083109161479e6020830139906137b45760405162461bcd60e51b81526004016111a29190613c18565b5061177081018381556001918201601081901b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000ffff85161761465755916137fb9085906139f6565b60408051828152600160208201526001600160a01b0386169160009133917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a450505050565b6146575460408051606081019091526030808252602083811c92611770841092909161462790830139906138915760405162461bcd60e51b81526004016111a29190613c18565b50612ee081018381556001918201602081901b7fffffffffffffffffffffffffffffffffffffffffffffffffffff0000ffffffff85161761465755916137fb9085906139f6565b61465180546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600061ffff801661465754169050611770811060405180606001604052806029815260200161471d602991399061398d5760405162461bcd60e51b81526004016111a29190613c18565b50818155614657805460019081019091556139a99083906139f6565b60408051828152600160208201526001600160a01b0384169160009133917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a45050565b6001600160a01b0382166000908152614652602052604090205461ffff8116601082901c63ffffffff16603083901c8115613a48576000613a378342614457565b8402656022099fa744029190910190505b6001600160a01b03909516600090815261465260205260409020919093014260101b1760309490941b939093179092555050565b828054613a889061411a565b90600052602060002090601f016020900481019282613aaa5760008555613b0e565b82601f10613ae1578280017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00823516178555613b0e565b82800160010185558215613b0e579182015b82811115613b0e578235825591602001919060010190613af3565b50613b1a929150613b3f565b5090565b604051806208ca000160405280614650906020820280368337509192915050565b5b80821115613b1a5760008155600101613b40565b80356001600160a01b0381168114613b6b57600080fd5b919050565b60008060408385031215613b8357600080fd5b613b8c83613b54565b946020939093013593505050565b7fffffffff0000000000000000000000000000000000000000000000000000000081168114611a4d57600080fd5b600060208284031215613bda57600080fd5b8135613be581613b9a565b9392505050565b60005b83811015613c07578181015183820152602001613bef565b838111156113ad5750506000910152565b6020815260008251806020840152613c37816040850160208701613bec565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b600080600060608486031215613c7e57600080fd5b505081359360208301359350604090920135919050565b600060208284031215613ca757600080fd5b5035919050565b600060208284031215613cc057600080fd5b613be582613b54565b60008083601f840112613cdb57600080fd5b50813567ffffffffffffffff811115613cf357600080fd5b6020830191508360208260051b8501011115613d0e57600080fd5b9250929050565b60008083601f840112613d2757600080fd5b50813567ffffffffffffffff811115613d3f57600080fd5b602083019150836020828501011115613d0e57600080fd5b60008060008060008060008060a0898b031215613d7357600080fd5b613d7c89613b54565b9750613d8a60208a01613b54565b9650604089013567ffffffffffffffff80821115613da757600080fd5b613db38c838d01613cc9565b909850965060608b0135915080821115613dcc57600080fd5b613dd88c838d01613cc9565b909650945060808b0135915080821115613df157600080fd5b50613dfe8b828c01613d15565b999c989b5096995094979396929594505050565b60008060008060408587031215613e2857600080fd5b843567ffffffffffffffff80821115613e4057600080fd5b613e4c88838901613cc9565b90965094506020870135915080821115613e6557600080fd5b50613e7287828801613cc9565b95989497509550505050565b600081518084526020808501945080840160005b83811015613eae57815187529582019590820190600101613e92565b509495945050505050565b602081526000613be56020830184613e7e565b60008060208385031215613edf57600080fd5b823567ffffffffffffffff811115613ef657600080fd5b613f0285828601613d15565b90969095509350505050565b8015158114611a4d57600080fd5b60008060408385031215613f2f57600080fd5b613f3883613b54565b91506020830135613f4881613f0e565b809150509250929050565b6000806000806000806000806080898b031215613f6f57600080fd5b883567ffffffffffffffff80821115613f8757600080fd5b613f938c838d01613cc9565b909a50985060208b0135915080821115613fac57600080fd5b613fb88c838d01613cc9565b909850965060408b0135915080821115613fd157600080fd5b613fdd8c838d01613cc9565b909650945060608b0135915080821115613ff657600080fd5b50613dfe8b828c01613cc9565b6208ca008101818360005b6146508110156140375781516001600160a01b031683526020928301929091019060010161400e565b50505092915050565b6000806040838503121561405357600080fd5b61405c83613b54565b915061406a60208401613b54565b90509250929050565b60008060008060008060a0878903121561408c57600080fd5b61409587613b54565b95506140a360208801613b54565b94506040870135935060608701359250608087013567ffffffffffffffff8111156140cd57600080fd5b6140d989828a01613d15565b979a9699509497509295939492505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600181811c9082168061412e57607f821691505b602082108103611cfb577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b8054600090600181811c908083168061418157607f831692505b602080841082036141bb577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b8180156141cf57600181146141fe5761422b565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0086168952848901965061422b565b60008881526020902060005b868110156142235781548b82015290850190830161420a565b505084890196505b50505050505092915050565b60006142438286614167565b8451614253818360208901613bec565b61425f81830186614167565b979650505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156142ac576142ac61426a565b500190565b81835260007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8311156142e357600080fd5b8260051b8083602087013760009401602001938452509192915050565b60006001600160a01b0380891683528088166020840152808716604084015280861660608401525060a0608083015261433d60a0830184866142b1565b98975050505050505050565b60006020828403121561435b57600080fd5b8151613be581613f0e565b60408152600061437a6040830186886142b1565b828103602084015261425f8185876142b1565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b60006001600160a01b03808b168352808a1660208401525060a0604083015261440360a08301888a6142b1565b82810360608401526144168187896142b1565b9050828103608084015261442b81858761438d565b9b9a5050505050505050505050565b60006020828403121561444c57600080fd5b8151613be581613b9a565b6000828210156144695761446961426a565b500390565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156144a6576144a661426a565b500290565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006001600160a01b03808916835280881660208401525085604083015284606083015260a0608083015261433d60a08301848661438d565b6040815260006145266040830185613e7e565b82810360208401526145388185613e7e565b95945050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036145725761457261426a565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826145b7576145b7614579565b500490565b6000826145cb576145cb614579565b50069056fe506c61796572486f7573696e673a204c61637265616e20456d70697265206f766572206d617820616d6f756e7420706572207478506c61796572486f7573696e673a204e6f20636f6e7472616374206d696e74696e67506c61796572486f7573696e673a2052656163686564206d6178204c61637265616e20456d7069726520737570706c79506c61796572486f7573696e673a204172626f726961206f766572206d617820616d6f756e7420706572207478506c61796572486f7573696e673a20546f74616c206f766572206d617820616d6f756e7420706572207478506c61796572486f7573696e673a205075626c69632073616c65206e6f74207265616479506c61796572486f7573696e673a20546f74616c20616d6f756e742062656c6f772032506c61796572486f7573696e673a204e6f7420617070726f76656420666f722072657761726473506c61796572486f7573696e673a2052656163686564206d6178204172626f72696120737570706c79506c61796572486f7573696e673a20496c6c736b616761617264206f766572206d617820616d6f756e7420706572207478506c61796572486f7573696e673a2057686974656c6973742073616c65206e6f74207265616479506c61796572486f7573696e673a2052656163686564206d617820496c6c736b61676161726420737570706c79a2646970667358221220ab14a4c15a796cfa7eaba33e0bae8b63ce81e69700e041524da59d7937d7a8b164736f6c634300080e0033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

0000000000000000000000005a5fe90cd115d691ee99d90d3607f7005ea817e50000000000000000000000000000000000000000000000000000000062dae5a00000000000000000000000000000000000000000000000000000000062dd88a00000000000000000000000000000000000000000000000000000000075a6e8a0000000000000000000000000544d219c227856935bf9678e21a2cd012bcc8bd8000000000000000000000000616e6b2ba922968af8d46df9400fc3da17589c5f

-----Decoded View---------------
Arg [0] : owner (address): 0x5a5fe90CD115d691EE99d90D3607f7005Ea817e5
Arg [1] : timestampSaleWhitelist (uint256): 1658512800
Arg [2] : timestampSalePublic (uint256): 1658685600
Arg [3] : timestampRewardsEnd (uint256): 1973872800
Arg [4] : tickets (address): 0x544D219c227856935Bf9678E21A2CD012bCC8bd8
Arg [5] : _lockManager (address): 0x616E6b2Ba922968Af8D46DF9400Fc3DA17589C5f

-----Encoded View---------------
6 Constructor Arguments found :
Arg [0] : 0000000000000000000000005a5fe90cd115d691ee99d90d3607f7005ea817e5
Arg [1] : 0000000000000000000000000000000000000000000000000000000062dae5a0
Arg [2] : 0000000000000000000000000000000000000000000000000000000062dd88a0
Arg [3] : 0000000000000000000000000000000000000000000000000000000075a6e8a0
Arg [4] : 000000000000000000000000544d219c227856935bf9678e21a2cd012bcc8bd8
Arg [5] : 000000000000000000000000616e6b2ba922968af8d46df9400fc3da17589c5f


Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.