ETH Price: $3,465.92 (+5.33%)

Token

HYDRA (HYDRA)
 

Overview

Max Total Supply

839,553,099,872.726545773995669286 HYDRA

Holders

931

Market

Onchain Market Cap

$0.00

Circulating Supply Market Cap

-

Other Info

Token Contract (WITH 18 Decimals)

Filtered by Token Holder
h0nkl3r.eth
Balance
1,161,720.000000000000000003 HYDRA

Value
$0.00
0xc8e091023aa3E3A7413fec0D9e75039c65688628
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:
HYDRA

Compiler Version
v0.8.21+commit.d9974bed

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion
File 1 of 18 : Hydra.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.21;

import "../libs/constant.sol";

import "./openzeppelin/security/ReentrancyGuard.sol";
import "./openzeppelin/token/ERC20/ERC20.sol";
import "./openzeppelin/interfaces/IERC165.sol";

import "../interfaces/IHydra.sol";
import "../interfaces/IHydraOnBurn.sol";

import "../libs/TransferHelper.sol";

import "./OwnerInfo.sol";
import "./GlobalInfo.sol";
import "./MintInfo.sol";
import "./BurnInfo.sol";

//custom errors
error Hydra_InvalidCaller();
error Hydra_InsufficientProtocolFees();
error Hydra_NothingToDistribute();
error Hydra_InvalidAmount();
error Hydra_UnregisteredCA();
error Hydra_LPTokensHasMinted();
error Hydra_NotSupportedContract();
error Hydra_InvalidAddress();
error Hydra_MaxedWalletMints();
error Hydra_InvalidMintLadderInterval();
error Hydra_InvalidMintLadderRange();
error Hydra_InvalidBatchCount();
error Hydra_InvalidBurnRewardPercent();
error Hydra_InsufficientBurnAllowance();

/** @title HYDRA */
contract HYDRA is ERC20, OwnerInfo, GlobalInfo, MintInfo, BurnInfo, ReentrancyGuard {
    /** Storage Variables */
    /** @dev stores genesis wallet address */
    address private s_genesisAddress;

    /** @dev Current Hydra buy and burn contract address */
    address private s_buyAndBurnAddress;

    /** @dev Tracks Hydra buy and burn contract addresses status
     * Specifically used for burning Hydra in registered CA */
    mapping(address => bool) s_buyAndBurnAddressRegistry;

    /** @dev tracks if initial LP tokens has minted or not */
    bool private s_initialLPMinted;

    /** @dev tracks collected protocol fees until it is distributed */
    uint256 private s_undistributedFees;

    /** @dev TitanX incentive fee dividend amount */
    uint256 private s_TitanXIncentiveDividend;

    /** @dev tracks funds for vortex */
    uint256 private s_vortexTitanX;
    uint256 private s_vortexDragonX;

    /** @dev tracks user + project burn mints allowance */
    mapping(address => mapping(address => uint256)) private s_allowanceBurnMints;

    /** Events */
    event ProtocolFeeRecevied(address indexed user, uint256 indexed day, uint256 indexed fee);
    event FeesDistributed(address indexed caller, uint256 indexed amount);
    event VortexReceived(
        address indexed from,
        uint256 indexed day,
        address project,
        uint256 indexed amount
    );
    event VortexTriggered(
        uint256 indexed day,
        uint256 indexed vortexTitanX,
        uint256 indexed vortexDragonX
    );
    event ApproveBurnMints(address indexed user, address indexed project, uint256 indexed amount);

    constructor(address genesisAddress, address buyAndBurnAddress) ERC20("HYDRA", "HYDRA") {
        if (genesisAddress == address(0)) revert Hydra_InvalidAddress();
        if (buyAndBurnAddress == address(0)) revert Hydra_InvalidAddress();
        s_genesisAddress = genesisAddress;
        s_buyAndBurnAddress = buyAndBurnAddress;
        s_buyAndBurnAddressRegistry[buyAndBurnAddress] = true;
        s_TitanXIncentiveDividend = 3300;
        IERC20(TITANX).approve(address(this), type(uint256).max);
        IERC20(DRAGONX).approve(address(this), type(uint256).max);
    }

    /** @notice Set BuyAndBurn Contract Address.
     * Only owner can call this function
     * @param contractAddress BuyAndBurn contract address
     */
    function setBuyAndBurnContractAddress(address contractAddress) external onlyOwner {
        if (contractAddress == address(0)) revert Hydra_InvalidAddress();
        /* Only able to change to supported buyandburn contract address.
         * Also prevents owner from registering EOA address into s_buyAndBurnAddressRegistry and call burnHydra to burn user's tokens.
         */
        if (
            !IHydra(contractAddress).supportsInterface(IERC165.supportsInterface.selector) ||
            !IHydra(contractAddress).supportsInterface(type(IHydra).interfaceId)
        ) revert Hydra_NotSupportedContract();
        s_buyAndBurnAddress = contractAddress;
        s_buyAndBurnAddressRegistry[contractAddress] = true;
    }

    /** @notice Remove BuyAndBurn Contract Address from registry.
     * Only owner can call this function
     * @param contractAddress BuyAndBurn contract address
     */
    function unRegisterBuyAndBurnContractAddress(address contractAddress) external onlyOwner {
        if (contractAddress == address(0)) revert Hydra_InvalidAddress();
        s_buyAndBurnAddressRegistry[contractAddress] = false;
    }

    /** @notice Set to new genesis wallet. Only genesis wallet can call this function
     * @param newAddress new genesis wallet address
     */
    function setNewGenesisAddress(address newAddress) external {
        if (msg.sender != s_genesisAddress) revert Hydra_InvalidCaller();
        if (newAddress == address(0)) revert Hydra_InvalidAddress();
        s_genesisAddress = newAddress;
    }

    /** @notice set incentive fee percentage callable by owner only
     * amount is in 10000 scaling factor, which means 0.33 is 0.33 * 10000 = 3300
     * @param amount amount between 1 - 10000
     */
    function setTitanXIncentiveFeeDividend(uint256 amount) external dailyUpdate onlyOwner {
        if (amount == 0 || amount > 10000) revert Hydra_InvalidAmount();
        s_TitanXIncentiveDividend = amount;
    }

    /** @notice One-time function to mint inital LP tokens. Only callable by BuyAndBurn contract address.
     * @param amount tokens amount
     */
    function mintLPTokens(uint256 amount) external {
        if (msg.sender != s_buyAndBurnAddress) revert Hydra_InvalidCaller();
        if (s_initialLPMinted) revert Hydra_LPTokensHasMinted();
        s_initialLPMinted = true;
        _mint(s_buyAndBurnAddress, amount);
    }

    /** @notice burn Hydra in BuyAndBurn contract.
     * Only burns registered contract address
     */
    function burnCAHydra(address contractAddress) external {
        if (!s_buyAndBurnAddressRegistry[contractAddress]) revert Hydra_UnregisteredCA();
        _burn(contractAddress, balanceOf(contractAddress));
    }

    /** @notice Collect liquid TitanX as protocol fee to start mint
     * @param mintPower 1 - 100k
     * @param numOfDays mint length of 1 - 88
     */
    function startMint(
        uint256 mintPower,
        uint256 numOfDays
    ) external payable dailyUpdate nonReentrant {
        if (getUserLatestMintId(msg.sender) + 1 > MAX_MINT_PER_WALLET)
            revert Hydra_MaxedWalletMints();

        uint256 gMintPower = getGlobalMintPower() + mintPower;
        uint256 currentHRank = getGlobalHRank() + 1;
        uint256 gMinting = getTotalMinting() +
            _startMint(
                msg.sender,
                mintPower,
                numOfDays,
                getCurrentMintableHydra(),
                gMintPower,
                currentHRank,
                getBatchMintCost(mintPower, 1)
            );
        _updateMintStats(currentHRank, gMintPower, gMinting);
        _protocolFees(mintPower, 1, MintStatus.ACTIVE);
    }

    /** @notice create new mints in ladder up to 100 mints
     * @param mintPower 1 - 100k
     * @param minDay minimum mint length
     * @param maxDay maximum mint lenght
     * @param dayInterval day increase from previous mint length
     * @param countPerInterval how many mints per mint length
     */
    function batchMintLadder(
        uint256 mintPower,
        uint256 minDay,
        uint256 maxDay,
        uint256 dayInterval,
        uint256 countPerInterval
    ) external payable nonReentrant dailyUpdate {
        if (dayInterval == 0) revert Hydra_InvalidMintLadderInterval();
        if (maxDay < minDay || minDay == 0 || maxDay > MAX_MINT_LENGTH)
            revert Hydra_InvalidMintLadderRange();

        uint256 count = getBatchMintLadderCount(minDay, maxDay, dayInterval, countPerInterval);
        if (count == 0 || count > MAX_BATCH_MINT_COUNT) revert Hydra_InvalidBatchCount();
        if (getUserLatestMintId(msg.sender) + count > MAX_MINT_PER_WALLET)
            revert Hydra_MaxedWalletMints();

        uint256 mintCost = getBatchMintCost(mintPower, 1); //only need 1 mint cost for all mints info

        _startbatchMintLadder(
            msg.sender,
            mintPower,
            minDay,
            maxDay,
            dayInterval,
            countPerInterval,
            getCurrentMintableHydra(),
            mintCost
        );
        _protocolFees(mintPower, count, MintStatus.ACTIVE);
    }

    /** @notice claim a matured mint
     * @param id mint id
     */
    function claimMint(uint256 id) external dailyUpdate nonReentrant {
        _mintReward(_claimMint(msg.sender, id, MintAction.CLAIM));
    }

    /** @notice early end a mint
     * @param id mint id
     */
    function earlyEndMint(uint256 id) external payable nonReentrant dailyUpdate {
        (uint256 reward, uint256 mintPower) = _earlyEndMint(msg.sender, id);
        _protocolFees(mintPower, 1, MintStatus.EARLYENDED);
        _mintReward(reward);
    }

    /** @notice distribute collected fees to different pools, caller receive a small incentive fee  */
    function distributeFees() public dailyUpdate nonReentrant {
        uint256 accumulatedFees = s_undistributedFees;
        if (accumulatedFees == 0) revert Hydra_NothingToDistribute();
        s_undistributedFees = 0;

        //caller incentive fee
        uint256 incentiveFee = (accumulatedFees * s_TitanXIncentiveDividend) /
            INCENTIVE_FEE_PERCENT_BASE;
        accumulatedFees -= incentiveFee;
        TransferHelper.safeTransferFrom(TITANX, address(this), msg.sender, incentiveFee);

        //TitanX vortex
        uint256 vortex = (accumulatedFees * TITANX_VORTEX_PERCENT) / PERCENT_BPS;
        s_vortexTitanX += vortex;

        //DragonX vault
        uint256 vaultAmount = (accumulatedFees * DRAGONX_VAULT_PERCENT) / PERCENT_BPS;
        TransferHelper.safeTransferFrom(TITANX, address(this), DRAGONX, vaultAmount);

        //Buy and Burn funds
        TransferHelper.safeTransferFrom(
            TITANX,
            address(this),
            s_buyAndBurnAddress,
            accumulatedFees - vortex - vaultAmount
        );

        emit FeesDistributed(msg.sender, accumulatedFees);
    }

    /** @notice callable by anyone to fund the Vortex TitanX
     */
    function fundVortexTitanX(uint256 amount) external dailyUpdate nonReentrant {
        TransferHelper.safeTransferFrom(TITANX, msg.sender, address(this), amount);
        s_vortexTitanX += amount;

        emit VortexReceived(msg.sender, getCurrentContractDay(), TITANX, amount);
    }

    /** @notice callable by anyone to fund the Vortex DragonX
     */
    function fundVortexDragonX(uint256 amount) external dailyUpdate nonReentrant {
        TransferHelper.safeTransferFrom(DRAGONX, msg.sender, address(this), amount);
        s_vortexDragonX += amount;

        emit VortexReceived(msg.sender, getCurrentContractDay(), DRAGONX, amount);
    }

    //send accumulated TitanX and DragonX to buyandburn contract
    function triggerVortex() public dailyUpdate nonReentrant {
        uint256 currentContractDay = getCurrentContractDay();
        //check against cylce payout maturity day
        if (currentContractDay < getNextCyclePayoutDay(DAY98)) return;

        //update the next cycle payout day regardless of payout triggered succesfully or not
        _setNextCyclePayoutDay(DAY98);

        //TitanX vortex
        uint256 vortexTitanX = s_vortexTitanX;
        if (vortexTitanX != 0) {
            s_vortexTitanX = 0;
            TransferHelper.safeTransferFrom(
                TITANX,
                address(this),
                s_buyAndBurnAddress,
                vortexTitanX
            );
        }

        //DragonX vortex
        uint256 vortexDragonX = s_vortexDragonX;
        if (vortexDragonX != 0) {
            s_vortexDragonX = 0;
            TransferHelper.safeTransferFrom(
                DRAGONX,
                address(this),
                s_buyAndBurnAddress,
                vortexDragonX
            );
        }

        emit VortexTriggered(currentContractDay, vortexTitanX, vortexDragonX);
    }

    //Private Functions
    /** @dev calcualte required protocol fees */
    function _protocolFees(uint256 mintPower, uint256 count, MintStatus status) private {
        uint256 protocolFee = getBatchMintCost(mintPower, count);
        if (status == MintStatus.EARLYENDED)
            protocolFee = (protocolFee * EARLY_END_MINT_COST_PERCENT) / PERCENT_BPS;

        TransferHelper.safeTransferFrom(TITANX, msg.sender, address(this), protocolFee);
        s_undistributedFees += protocolFee;

        emit ProtocolFeeRecevied(msg.sender, getCurrentContractDay(), protocolFee);
    }

    /** @dev burn liquid Hydra through other project.
     * called by other contracts for proof of burn 2.0 with up to 8% for both builder fee and user rebate
     * @param user user address
     * @param amount liquid Hydra amount
     * @param userRebatePercentage percentage for user rebate in liquid Hydra (0 - 8)
     * @param rewardPaybackPercentage percentage for builder fee in liquid Hydra (0 - 8)
     * @param rewardPaybackAddress builder can opt to receive fee in another address
     */
    function _burnLiquidHydra(
        address user,
        uint256 amount,
        uint256 userRebatePercentage,
        uint256 rewardPaybackPercentage,
        address rewardPaybackAddress
    ) private {
        if (amount == 0) revert Hydra_InvalidAmount();
        _spendAllowance(user, msg.sender, amount);
        _burnbefore(userRebatePercentage, rewardPaybackPercentage);
        _burn(user, amount);
        _burnAfter(
            user,
            amount,
            userRebatePercentage,
            rewardPaybackPercentage,
            rewardPaybackAddress,
            BurnSource.LIQUID
        );
    }

    /** @dev burn mint through other project.
     * called by other contracts for proof of burn 2.0
     * burn mint has no builder reward and no user rebate
     * @param user user address
     * @param id mint id
     */
    function _burnMint(address user, uint256 id) private {
        _spendBurnMintAllowance(user);
        _burnbefore(0, 0);
        uint256 amount = _claimMint(user, id, MintAction.BURN);
        _mint(s_genesisAddress, (amount * 8_000) / PERCENT_BPS);
        _burnAfter(user, amount, 0, 0, msg.sender, BurnSource.MINT);
    }

    /** @dev perform checks before burning starts.
     * check reward percentage and check if called by supported contract
     * @param userRebatePercentage percentage for user rebate
     * @param rewardPaybackPercentage percentage for builder fee
     */
    function _burnbefore(
        uint256 userRebatePercentage,
        uint256 rewardPaybackPercentage
    ) private view {
        if (rewardPaybackPercentage + userRebatePercentage > MAX_BURN_REWARD_PERCENT)
            revert Hydra_InvalidBurnRewardPercent();

        //Only supported contracts is allowed to call this function
        if (
            !IERC165(msg.sender).supportsInterface(IERC165.supportsInterface.selector) ||
            !IERC165(msg.sender).supportsInterface(type(IHydraOnBurn).interfaceId)
        ) revert Hydra_NotSupportedContract();
    }

    /** @dev update burn stats and mint reward to builder or user if applicable
     * @param user user address
     * @param amount Hydra amount burned
     * @param userRebatePercentage percentage for user rebate in liquid Hydra (0 - 8)
     * @param rewardPaybackPercentage percentage for builder fee in liquid Hydra (0 - 8)
     * @param rewardPaybackAddress builder can opt to receive fee in another address
     * @param source liquid/mint
     */
    function _burnAfter(
        address user,
        uint256 amount,
        uint256 userRebatePercentage,
        uint256 rewardPaybackPercentage,
        address rewardPaybackAddress,
        BurnSource source
    ) private {
        _updateBurnAmount(user, msg.sender, amount, source);

        uint256 devFee;
        uint256 userRebate;
        if (rewardPaybackPercentage != 0)
            devFee = (amount * rewardPaybackPercentage * PERCENT_BPS) / (100 * PERCENT_BPS);
        if (userRebatePercentage != 0)
            userRebate = (amount * userRebatePercentage * PERCENT_BPS) / (100 * PERCENT_BPS);

        if (devFee != 0) _mint(rewardPaybackAddress, devFee);
        if (userRebate != 0) _mint(user, userRebate);

        IHydraOnBurn(msg.sender).onBurn(user, amount);
    }

    /** @dev mint reward to user
     * @param reward Hydra amount
     */
    function _mintReward(uint256 reward) private {
        _mint(msg.sender, reward);
        _mint(s_genesisAddress, (reward * 8_000) / PERCENT_BPS);
    }

    /** @dev reduce user's allowance for caller (spender/project) by 1 (burn 1 mint at a time)
     * Does not update the allowance amount in case of infinite allowance.
     * Revert if not enough allowance is available.
     * @param user user address
     */
    function _spendBurnMintAllowance(address user) private {
        uint256 currentAllowance = allowanceBurnMints(user, msg.sender);
        if (currentAllowance != type(uint256).max) {
            if (currentAllowance == 0) revert Hydra_InsufficientBurnAllowance();
            --s_allowanceBurnMints[user][msg.sender];
        }
    }

    //views
    /** @notice returns user's burn mints allowance of a project
     * @param user user address
     * @param spender project address
     */
    function allowanceBurnMints(address user, address spender) public view returns (uint256) {
        return s_allowanceBurnMints[user][spender];
    }

    /** @notice Returns current buy and burn contract address
     * @return address current buy and burn contract address
     */
    function getBuyAndBurnAddress() public view returns (address) {
        return s_buyAndBurnAddress;
    }

    /** @notice Returns status of the given address
     * @return status 0 (INACTIVE) or 1 (Active)
     */
    function getBuyAndBurnAddressRegistry(address contractAddress) public view returns (bool) {
        return s_buyAndBurnAddressRegistry[contractAddress];
    }

    /** @notice get current incentive fee dividend
     * @return amount
     */
    function getTitanXIncentiveDividend() public view returns (uint256) {
        return s_TitanXIncentiveDividend;
    }

    /** @notice get undistributed TitanX balance
     * @return amount TitanX
     */
    function getUndistributedFees() public view returns (uint256) {
        return s_undistributedFees;
    }

    /** @notice get vortex TitanX balance
     * @return amount TitanX
     */
    function getVortexTitanX() public view returns (uint256) {
        return s_vortexTitanX;
    }

    /** @notice get vortex DragonX balance
     * @return amount DragonX
     */
    function getVortexDragonX() public view returns (uint256) {
        return s_vortexDragonX;
    }

    //Public functions for devs to intergrate with Hydra
    /** @notice allow anyone to sync dailyUpdate manually */
    function manualDailyUpdate() public dailyUpdate {}

    /** @notice Burn Hydra tokens and creates Proof-Of-Burn record to be used by connected DeFi and fee is paid to specified address
     * @param user user address
     * @param amount Hydra amount
     * @param userRebatePercentage percentage for user rebate in liquid Hydra (0 - 8)
     * @param rewardPaybackPercentage percentage for builder fee in liquid Hydra (0 - 8)
     * @param rewardPaybackAddress builder can opt to receive fee in another address
     */
    function burnTokensToPayAddress(
        address user,
        uint256 amount,
        uint256 userRebatePercentage,
        uint256 rewardPaybackPercentage,
        address rewardPaybackAddress
    ) public nonReentrant {
        _burnLiquidHydra(
            user,
            amount,
            userRebatePercentage,
            rewardPaybackPercentage,
            rewardPaybackAddress
        );
    }

    /** @notice Burn Hydra tokens and creates Proof-Of-Burn record to be used by connected DeFi and fee is paid to specified address
     * @param user user address
     * @param amount Hydra amount
     * @param userRebatePercentage percentage for user rebate in liquid Hydra (0 - 8)
     * @param rewardPaybackPercentage percentage for builder fee in liquid Hydra (0 - 8)
     */
    function burnTokens(
        address user,
        uint256 amount,
        uint256 userRebatePercentage,
        uint256 rewardPaybackPercentage
    ) public nonReentrant {
        _burnLiquidHydra(user, amount, userRebatePercentage, rewardPaybackPercentage, msg.sender);
    }

    /** @notice allows user to burn liquid Hydra directly from contract
     * @param amount Hydra amount
     */
    function userBurnTokens(uint256 amount) public nonReentrant {
        if (amount == 0) revert Hydra_InvalidAmount();
        _burn(msg.sender, amount);
        _updateBurnAmount(msg.sender, address(0), amount, BurnSource.LIQUID);
    }

    /** @notice Burn mint and creates Proof-Of-Burn record to be used by connected DeFi.
     * Burn mint has no project reward or user rebate
     * @param user user address
     * @param id mint id
     */
    function burnMint(address user, uint256 id) public dailyUpdate nonReentrant {
        _burnMint(user, id);
    }

    /** @notice allows user to burn mint directly from contract
     * @param id mint id
     */
    function userBurnMint(uint256 id) public dailyUpdate nonReentrant {
        _updateBurnAmount(
            msg.sender,
            address(0),
            _claimMint(msg.sender, id, MintAction.BURN),
            BurnSource.MINT
        );
    }

    /** @notice Sets `amount` as the allowance of `spender` over the caller's (user) mints.
     * @param spender contract address
     * @param amount allowance amount
     */
    function approveBurnMints(address spender, uint256 amount) public returns (bool) {
        if (spender == address(0)) revert Hydra_InvalidAddress();
        s_allowanceBurnMints[msg.sender][spender] = amount;
        emit ApproveBurnMints(msg.sender, spender, amount);
        return true;
    }
}

File 2 of 18 : BurnInfo.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.21;

import "../libs/constant.sol";
import "../libs/enum.sol";

/**
 * @title BurnInfo
 * @dev this contract is meant to be inherited into main contract
 * @notice It has the variables and functions specifically for tracking burn amount
 */

abstract contract BurnInfo {
    //Variables
    //track the total Hydra burn amount
    uint256 private s_totalHydraBurned;

    //mappings
    //track wallet address -> total Hydra burn amount
    mapping(address => uint256) private s_userBurnAmount;
    //track contract/project address -> total Hydra burn amount
    mapping(address => uint256) private s_project_BurnAmount;
    //track contract/project address, wallet address -> total Hydra burn amount
    mapping(address => mapping(address => uint256)) private s_projectUser_BurnAmount;

    //events
    /** @dev log user burn Hydra event
     * project can be address(0) if user burns Hydra directly from Hydra contract
     * Source 0=Liquid, 1=Mint
     */
    event HydraBurned(
        address indexed user,
        address indexed project,
        uint256 amount,
        BurnSource source
    );

    //functions
    /** @dev update the burn amount
     * @param user wallet address
     * @param project contract address
     * @param amount Hydra amount burned
     * @param source burn source LIQUID/MINT
     */
    function _updateBurnAmount(
        address user,
        address project,
        uint256 amount,
        BurnSource source
    ) internal {
        s_userBurnAmount[user] += amount;
        s_totalHydraBurned += amount;

        if (project != address(0)) {
            s_project_BurnAmount[project] += amount;
            s_projectUser_BurnAmount[project][user] += amount;
        }

        emit HydraBurned(user, project, amount, source);
    }

    //views
    /** @notice return total burned Hydra amount from all users burn or projects burn
     * @return totalBurnAmount returns entire burned Hydra
     */
    function getTotalBurnTotal() public view returns (uint256) {
        return s_totalHydraBurned;
    }

    /** @notice return user address total burned Hydra
     * @return userBurnAmount returns user address total burned Hydra
     */
    function getUserBurnTotal(address user) public view returns (uint256) {
        return s_userBurnAmount[user];
    }

    /** @notice return project address total burned Hydra amount
     * @return projectTotalBurnAmount returns project total burned Hydra
     */
    function getProjectBurnTotal(address contractAddress) public view returns (uint256) {
        return s_project_BurnAmount[contractAddress];
    }

    /** @notice return user address total burned Hydra amount via a project address
     * @param contractAddress project address
     * @param user user address
     * @return projectUserTotalBurnAmount returns user address total burned Hydra via a project address
     */
    function getProjectUserBurnTotal(
        address contractAddress,
        address user
    ) public view returns (uint256) {
        return s_projectUser_BurnAmount[contractAddress][user];
    }
}

File 3 of 18 : MintInfo.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.21;

import "../libs/enum.sol";
import "../libs/constant.sol";
import "../libs/calcFunctions.sol";

//custom errors
error Hydra_InvalidMintLength();
error Hydra_InvalidMintPower();
error Hydra_NoMintExists();
error Hydra_MintHasClaimed();
error Hydra_MintNotMature();
error Hydra_MintHasBurned();
error Hydra_MintMaturityNotMet();
error Hydra_MintHasEnded();

abstract contract MintInfo {
    //variables
    /** @dev track global hRank */
    uint256 private s_globalHRank;
    /** @dev track total mint claimed */
    uint256 private s_globalMintClaim;
    /** @dev track total mint burned */
    uint256 private s_globalMintBurn;
    /** @dev track total Hydra minting */
    uint256 private s_globalHydraMinting;
    /** @dev track total Hydra penalty */
    uint256 private s_globalHydraMintPenalty;
    /** @dev track global mint power */
    uint256 private s_globalMintPower;
    /** @dev track total mint early ended */
    uint256 private s_globalMintEarlyEnded;

    //mappings
    /** @dev track address => mintId */
    mapping(address => uint256) private s_addressMId;
    /** @dev track address, mintId => hRank info (gTrank, gMintPower) */
    mapping(address => mapping(uint256 => HRankInfo)) private s_addressMIdToHRankInfo;
    /** @dev track global hRank => mintInfo*/
    mapping(uint256 => UserMintInfo) private s_hRankToMintInfo;

    //structs
    struct UserMintInfo {
        uint16 mintPower;
        uint8 numOfDays;
        uint104 mintableHydra;
        uint48 mintStartTs;
        uint48 maturityTs;
        uint104 mintedHydra;
        uint104 mintCost;
        MintStatus status;
    }

    struct HRankInfo {
        uint256 hRank;
        uint256 gMintPower;
    }

    struct UserMint {
        uint256 mId;
        uint256 hRank;
        uint256 gMintPower;
        UserMintInfo mintInfo;
    }

    //events
    event MintStarted(
        address indexed user,
        uint256 indexed hRank,
        uint256 indexed gMintpower,
        UserMintInfo userMintInfo
    );

    event MintClaimed(
        address indexed user,
        uint256 indexed hRank,
        uint256 rewardMinted,
        uint256 indexed penalty,
        uint256 mintPenalty
    );

    event MintEarlyEnded(
        address indexed user,
        uint256 indexed hRank,
        uint256 rewardMinted,
        uint256 indexed penalty
    );

    //functions
    /** @dev create a new mint
     * @param user user address
     * @param mintPower mint power
     * @param numOfDays mint lenght
     * @param mintableHydra mintable Hydra
     * @param gMintPower global mint power
     * @param currentHRank current global hRank
     * @param mintCost actual mint cost paid for a mint
     */
    function _startMint(
        address user,
        uint256 mintPower,
        uint256 numOfDays,
        uint256 mintableHydra,
        uint256 gMintPower,
        uint256 currentHRank,
        uint256 mintCost
    ) internal returns (uint256 mintable) {
        if (numOfDays == 0 || numOfDays > MAX_MINT_LENGTH) revert Hydra_InvalidMintLength();
        if (mintPower == 0 || mintPower > MAX_MINT_POWER_CAP) revert Hydra_InvalidMintPower();

        //calculate mint reward up front with the provided params
        mintable = calculateMintReward(mintPower, numOfDays, mintableHydra);

        //store variables into mint info
        UserMintInfo memory userMintInfo = UserMintInfo({
            mintPower: uint16(mintPower),
            numOfDays: uint8(numOfDays),
            mintableHydra: uint104(mintable),
            mintStartTs: uint48(block.timestamp),
            maturityTs: uint48(block.timestamp + (numOfDays * SECONDS_IN_DAY)),
            mintedHydra: 0,
            mintCost: uint104(mintCost),
            status: MintStatus.ACTIVE
        });

        /** s_addressMId[user] tracks mintId for each addrress
         * s_addressMIdToHRankInfo[user][id] tracks current mint hRank and gPowerMint
         *  s_hRankToMintInfo[currentHRank] stores mint info
         */
        uint256 id = ++s_addressMId[user];
        s_addressMIdToHRankInfo[user][id].hRank = currentHRank;
        s_addressMIdToHRankInfo[user][id].gMintPower = gMintPower;
        s_hRankToMintInfo[currentHRank] = userMintInfo;

        emit MintStarted(user, currentHRank, gMintPower, userMintInfo);
    }

    /** @dev create new mint in a batch of up to max 100 mints with different mint length
     * @param user user address
     * @param mintPower mint power
     * @param minDay minimum start day
     * @param maxDay maximum end day
     * @param dayInterval days interval between each new mint length
     * @param countPerInterval number of mint(s) to create in each mint length interval
     * @param mintableHydra mintable Hydra
     * @param mintCost actual mint cost paid for a mint
     */
    function _startbatchMintLadder(
        address user,
        uint256 mintPower,
        uint256 minDay,
        uint256 maxDay,
        uint256 dayInterval,
        uint256 countPerInterval,
        uint256 mintableHydra,
        uint256 mintCost
    ) internal {
        uint256 gMintPower = s_globalMintPower;
        uint256 currentHRank = s_globalHRank;
        uint256 gMinting = s_globalHydraMinting;

        /**first for loop is used to determine mint length
         * minDay is the starting mint length
         * maxDay is the max mint length where it stops
         * dayInterval increases the minDay for the next mint
         */
        for (; minDay <= maxDay; minDay += dayInterval) {
            /**first for loop is used to determine mint length
             * second for loop is to create number mints per mint length
             */
            for (uint256 j = 0; j < countPerInterval; j++) {
                gMintPower += mintPower;
                gMinting += _startMint(
                    user,
                    mintPower,
                    minDay,
                    mintableHydra,
                    gMintPower,
                    ++currentHRank,
                    mintCost
                );
            }
        }
        _updateMintStats(currentHRank, gMintPower, gMinting);
    }

    /** @dev update variables
     * @param currentHRank current hRank
     * @param gMintPower current global mint power
     * @param gMinting current global minting
     */
    function _updateMintStats(uint256 currentHRank, uint256 gMintPower, uint256 gMinting) internal {
        s_globalHRank = currentHRank;
        s_globalMintPower = gMintPower;
        s_globalHydraMinting = gMinting;
    }

    /** @dev calculate reward for claim mint or burn mint.
     * Claim mint has maturity check while burn mint would bypass maturity check.
     * @param user user address
     * @param id mint id
     * @param action claim mint or burn mint
     * @return reward calculated final reward after all bonuses and penalty (if any)
     */
    function _claimMint(
        address user,
        uint256 id,
        MintAction action
    ) internal returns (uint256 reward) {
        uint256 hRank = s_addressMIdToHRankInfo[user][id].hRank;
        if (hRank == 0) revert Hydra_NoMintExists();

        UserMintInfo memory mint = s_hRankToMintInfo[hRank];
        if (mint.status == MintStatus.CLAIMED) revert Hydra_MintHasClaimed();
        if (mint.status == MintStatus.BURNED) revert Hydra_MintHasBurned();
        if (mint.status == MintStatus.EARLYENDED) revert Hydra_MintHasEnded();

        //Only check maturity for claim mint action, burn mint bypass this check
        if (mint.maturityTs > block.timestamp && action == MintAction.CLAIM)
            revert Hydra_MintNotMature();

        s_globalHydraMinting -= mint.mintableHydra;
        reward = _calculateClaimReward(user, hRank, mint, action);
    }

    /** @dev calculate final reward with bonuses and penalty (if any)
     * @param user user address
     * @param hRank mint's hRank
     * @param userMintInfo mint's info
     * @param action claim mint or burn mint
     * @return reward calculated final reward after all bonuses and penalty (if any)
     */
    function _calculateClaimReward(
        address user,
        uint256 hRank,
        UserMintInfo memory userMintInfo,
        MintAction action
    ) private returns (uint256 reward) {
        if (action == MintAction.CLAIM) s_hRankToMintInfo[hRank].status = MintStatus.CLAIMED;
        if (action == MintAction.BURN) s_hRankToMintInfo[hRank].status = MintStatus.BURNED;

        uint256 penaltyAmount;
        uint256 penalty;

        //only calculate penalty when current block timestamp > maturity timestamp
        if (block.timestamp > userMintInfo.maturityTs) {
            penalty = calculateClaimMintPenalty(block.timestamp - userMintInfo.maturityTs);
        }

        uint256 mintableSupply = uint256(userMintInfo.mintableHydra);
        penaltyAmount = (mintableSupply * penalty) / 100;
        reward = mintableSupply - penaltyAmount;

        if (action == MintAction.CLAIM) ++s_globalMintClaim;
        if (action == MintAction.BURN) ++s_globalMintBurn;
        if (penaltyAmount != 0) s_globalHydraMintPenalty += penaltyAmount;

        //only stored minted amount for claim mint
        if (action == MintAction.CLAIM) s_hRankToMintInfo[hRank].mintedHydra = uint104(reward);

        emit MintClaimed(user, hRank, reward, penalty, penaltyAmount);
    }

    /**
     * @dev early end a mint that hasn't mature and already matured at least 8 days
     * @param user user address
     * @param id mint id
     * @return reward calculated reward based on number of days matured, capped at 50% max
     * @return mintPower mint's power
     */
    function _earlyEndMint(
        address user,
        uint256 id
    ) internal returns (uint256 reward, uint256 mintPower) {
        uint256 hRank = s_addressMIdToHRankInfo[user][id].hRank;
        if (hRank == 0) revert Hydra_NoMintExists();

        UserMintInfo memory mint = s_hRankToMintInfo[hRank];
        if (mint.status == MintStatus.CLAIMED) revert Hydra_MintHasClaimed();
        if (mint.status == MintStatus.BURNED) revert Hydra_MintHasBurned();
        if (mint.status == MintStatus.EARLYENDED) revert Hydra_MintHasEnded();

        //revert if miner has matured or less than 3 days
        uint256 daysMatured = (block.timestamp - mint.mintStartTs) / 1 days;
        if (mint.maturityTs <= block.timestamp || daysMatured < 3)
            revert Hydra_MintMaturityNotMet();

        s_hRankToMintInfo[hRank].status = MintStatus.EARLYENDED;

        uint256 mintableSupply = mint.mintableHydra;
        uint256 earlyEndSupply = (mintableSupply * daysMatured) / mint.numOfDays;
        uint256 maxCapAmount = (mintableSupply * EARLYEND_MAX_CAP_PERCENT) / PERCENT_BPS;
        if (earlyEndSupply > maxCapAmount) earlyEndSupply = maxCapAmount;

        s_hRankToMintInfo[hRank].mintedHydra = uint104(earlyEndSupply);
        s_globalHydraMinting -= mintableSupply;
        s_globalHydraMintPenalty += mintableSupply - earlyEndSupply;
        ++s_globalMintEarlyEnded;
        reward = earlyEndSupply;
        mintPower = mint.mintPower;

        emit MintEarlyEnded(user, hRank, reward, mintableSupply - earlyEndSupply);
    }

    //views
    /** @notice Returns the latest Mint Id of an address
     * @param user address
     * @return mId latest mint id
     */
    function getUserLatestMintId(address user) public view returns (uint256) {
        return s_addressMId[user];
    }

    /** @notice Returns mint info of an address + mint id
     * @param user address
     * @param id mint id
     * @return mintInfo user mint info
     */
    function getUserMintInfo(
        address user,
        uint256 id
    ) public view returns (UserMintInfo memory mintInfo) {
        return s_hRankToMintInfo[s_addressMIdToHRankInfo[user][id].hRank];
    }

    /** @notice Return all mints info of an address
     * @param user address
     * @return mintInfos all mints info of an address including mint id, hRank and gMintPower
     */
    function getUserMints(address user) public view returns (UserMint[] memory mintInfos) {
        uint256 count = s_addressMId[user];
        mintInfos = new UserMint[](count);

        for (uint256 i = 1; i <= count; i++) {
            mintInfos[i - 1] = UserMint({
                mId: i,
                hRank: s_addressMIdToHRankInfo[user][i].hRank,
                gMintPower: s_addressMIdToHRankInfo[user][i].gMintPower,
                mintInfo: getUserMintInfo(user, i)
            });
        }
    }

    /** @notice Return total mints burned
     * @return totalMintBurned total mints burned
     */
    function getTotalMintBurn() public view returns (uint256) {
        return s_globalMintBurn;
    }

    /** @notice Return current gobal hRank
     * @return globalHRank global hRank
     */
    function getGlobalHRank() public view returns (uint256) {
        return s_globalHRank;
    }

    /** @notice Return current gobal mint power
     * @return globalMintPower global mint power
     */
    function getGlobalMintPower() public view returns (uint256) {
        return s_globalMintPower;
    }

    /** @notice Return total mints claimed
     * @return totalMintClaimed total mints claimed
     */
    function getTotalMintClaim() public view returns (uint256) {
        return s_globalMintClaim;
    }

    /** @notice Return total active mints (exluded claimed and burned mints)
     * @return totalActiveMints total active mints
     */
    function getTotalActiveMints() public view returns (uint256) {
        return s_globalHRank - s_globalMintClaim - s_globalMintBurn;
    }

    /** @notice Return total minting Hydra
     * @return totalMinting total minting Hydra
     */
    function getTotalMinting() public view returns (uint256) {
        return s_globalHydraMinting;
    }

    /** @notice Return total mint penalty
     * @return totalHydraPenalty total mint penalty
     */
    function getTotalMintPenalty() public view returns (uint256) {
        return s_globalHydraMintPenalty;
    }

    /** @notice Return total early ended mint
     * @return totalHydraPenalty total Hydra penalty
     */
    function getTotalMintEarlyEnded() public view returns (uint256) {
        return s_globalMintEarlyEnded;
    }
}

File 4 of 18 : GlobalInfo.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.21;

import "../libs/constant.sol";

abstract contract GlobalInfo {
    //Variables
    //deployed timestamp
    uint256 private immutable i_genesisTs;

    /** @dev track current contract day */
    uint256 private s_currentContractDay;
    /** @dev mintableHydra starts 800m ether decreases and capped at 80k ether, uint96 has enough size */
    uint96 private s_currentMintableHydra;

    /** @dev track when is the next cycle payout day for each cycle day
     * eg. s_nextCyclePayoutDay[DAY98] = 98
     *     s_nextCyclePayoutDay[DAY369] = 369
     */
    mapping(uint256 => uint256) s_nextCyclePayoutDay;

    //event
    event GlobalDailyUpdateStats(uint256 indexed day, uint256 indexed mintableHydra);

    /** @dev Update variables in terms of day, modifier is used in all external/public functions (exclude view)
     * Every interaction to the contract would run this function to update variables
     */
    modifier dailyUpdate() {
        _dailyUpdate();
        _;
    }

    constructor() {
        i_genesisTs = block.timestamp;
        s_currentContractDay = 1;
        s_currentMintableHydra = uint96(START_MAX_MINTABLE_PER_DAY);
        s_nextCyclePayoutDay[DAY98] = DAY98;
    }

    /** @dev calculate and update variables daily and reset triggers flag */
    function _dailyUpdate() private {
        uint256 currentContractDay = s_currentContractDay;
        uint256 currentBlockDay = ((block.timestamp - i_genesisTs) / 1 days) + 1;

        if (currentBlockDay > currentContractDay) {
            //get last day info ready for calculation
            uint256 newMintableHydra = s_currentMintableHydra;
            uint256 dayDifference = currentBlockDay - currentContractDay;

            /** Reason for a for loop to update Mint supply
             * Ideally, user interaction happens daily, so Mint supply is synced in every day
             *      (cylceDifference = 1)
             * However, if there's no interaction for more than 1 day, then
             *      Mint supply isn't updated correctly due to cylceDifference > 1 day
             * Eg. 2 days of no interaction, then interaction happens in 3rd day.
             *     It's incorrect to only decrease the Mint supply one time as now it's in 3rd day.
             *   And if this happens, there will be no tracked data for the skipped days as not needed
             */
            for (uint256 i; i < dayDifference; i++) {
                newMintableHydra =
                    (newMintableHydra * DAILY_SUPPLY_MINTABLE_REDUCTION) /
                    PERCENT_BPS;

                if (newMintableHydra < CAPPED_MIN_DAILY_TITAN_MINTABLE) {
                    newMintableHydra = CAPPED_MIN_DAILY_TITAN_MINTABLE;
                }

                emit GlobalDailyUpdateStats(++currentContractDay, newMintableHydra);
            }

            s_currentMintableHydra = uint96(newMintableHydra);
            s_currentContractDay = currentBlockDay;
        }
    }

    /** @dev calculate and update the next payout day for specified cycleNo
     * the formula will update the payout day based on current contract day
     * this is to make sure the value is correct when for some reason has skipped more than one cycle payout
     * @param cycleNo cycle day 98
     */
    function _setNextCyclePayoutDay(uint256 cycleNo) internal {
        uint256 maturityDay = s_nextCyclePayoutDay[cycleNo];
        uint256 currentContractDay = s_currentContractDay;
        if (currentContractDay >= maturityDay) {
            s_nextCyclePayoutDay[cycleNo] +=
                cycleNo *
                (((currentContractDay - maturityDay) / cycleNo) + 1);
        }
    }

    /** Views */
    /** @notice Returns contract deployment block timestamp
     * @return timestamp in seconds
     */
    function genesisTs() public view returns (uint256) {
        return i_genesisTs;
    }

    /** @notice Returns current block timestamp
     * @return currentBlockTs current block timestamp
     */
    function getCurrentBlockTimeStamp() public view returns (uint256) {
        return block.timestamp;
    }

    /** @notice Returns current contract day
     * @return currentContractDay current contract day
     */
    function getCurrentContractDay() public view returns (uint256) {
        return s_currentContractDay;
    }

    /** @notice Returns current mint cost
     * @return currentMintCost current block timestamp
     */
    function getCurrentMintCost() public pure returns (uint256) {
        return START_MAX_MINT_COST;
    }

    /** @notice Returns current mintable Hydra
     * @return currentMintableHydra current mintable Hydra
     */
    function getCurrentMintableHydra() public view returns (uint256) {
        return s_currentMintableHydra;
    }

    /** @notice Returns next payout day for the specified cycle day
     * @param cycleNo cycle day 98
     * @return nextPayoutDay next payout day
     */
    function getNextCyclePayoutDay(uint256 cycleNo) public view returns (uint256) {
        return s_nextCyclePayoutDay[cycleNo];
    }
}

File 5 of 18 : OwnerInfo.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.21;

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

error Hydra_NotOnwer();

abstract contract OwnerInfo is Context {
    address private s_owner;

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor() {
        s_owner = msg.sender;
    }

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

    /**
     * @dev Throws if the sender is not the owner.
     */
    function _checkOwner() internal view virtual {
        if (s_owner != msg.sender) revert Hydra_NotOnwer();
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby disabling any functionality that is only available to the owner.
     */
    function renounceOwnership() public onlyOwner {
        _setOwner(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 onlyOwner {
        _setOwner(newOwner);
    }

    function _setOwner(address newOwner) private {
        s_owner = newOwner;
    }
}

File 6 of 18 : TransferHelper.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.6.0;

import "../contracts/openzeppelin/token/ERC20/IERC20.sol";

library TransferHelper {
    /// @notice Transfers tokens from the targeted address to the given destination
    /// @notice Errors with 'STF' if transfer fails
    /// @param token The contract address of the token to be transferred
    /// @param from The originating address from which the tokens will be transferred
    /// @param to The destination address of the transfer
    /// @param value The amount to be transferred
    function safeTransferFrom(
        address token,
        address from,
        address to,
        uint256 value
    ) internal {
        (bool success, bytes memory data) = token.call(
            abi.encodeWithSelector(
                IERC20.transferFrom.selector,
                from,
                to,
                value
            )
        );
        require(
            success && (data.length == 0 || abi.decode(data, (bool))),
            "STF"
        );
    }

    /// @notice Transfers tokens from msg.sender to a recipient
    /// @dev Errors with ST if transfer fails
    /// @param token The contract address of the token which will be transferred
    /// @param to The recipient of the transfer
    /// @param value The value of the transfer
    function safeTransfer(address token, address to, uint256 value) internal {
        (bool success, bytes memory data) = token.call(
            abi.encodeWithSelector(IERC20.transfer.selector, to, value)
        );
        require(
            success && (data.length == 0 || abi.decode(data, (bool))),
            "ST"
        );
    }

    /// @notice Approves the stipulated contract to spend the given allowance in the given token
    /// @dev Errors with 'SA' if transfer fails
    /// @param token The contract address of the token to be approved
    /// @param to The target of the approval
    /// @param value The amount of the given token the target will be allowed to spend
    function safeApprove(address token, address to, uint256 value) internal {
        (bool success, bytes memory data) = token.call(
            abi.encodeWithSelector(IERC20.approve.selector, to, value)
        );
        require(
            success && (data.length == 0 || abi.decode(data, (bool))),
            "SA"
        );
    }

    /// @notice Transfers ETH to the recipient address
    /// @dev Fails with `STE`
    /// @param to The destination of the transfer
    /// @param value The value to be transferred
    function safeTransferETH(address to, uint256 value) internal {
        (bool success, ) = to.call{value: value}(new bytes(0));
        require(success, "STE");
    }
}

File 7 of 18 : IHydraOnBurn.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.21;

interface IHydraOnBurn {
    function onBurn(address user, uint256 amount) external;
}

File 8 of 18 : IHydra.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.21;

interface IHydra {
    function mintLPTokens(uint256 amount) external;

    function burnCAHydra(address contractAddress) external;

    function fundVortexTitanX(uint256 amount) external;

    function fundVortexDragonX(uint256 amount) external;

    function supportsInterface(bytes4 interfaceId) external returns (bool);
}

File 9 of 18 : IERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (interfaces/IERC165.sol)

pragma solidity ^0.8.0;

import "../utils/introspection/IERC165.sol";

File 10 of 18 : ERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/ERC20.sol)

pragma solidity ^0.8.0;

import "./IERC20.sol";
import "./extensions/IERC20Metadata.sol";
import "../../utils/Context.sol";

/**
 * @dev Implementation of the {IERC20} interface.
 *
 * This implementation is agnostic to the way tokens are created. This means
 * that a supply mechanism has to be added in a derived contract using {_mint}.
 * For a generic mechanism see {ERC20PresetMinterPauser}.
 *
 * TIP: For a detailed writeup see our guide
 * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How
 * to implement supply mechanisms].
 *
 * We have followed general OpenZeppelin Contracts guidelines: functions revert
 * instead returning `false` on failure. This behavior is nonetheless
 * conventional and does not conflict with the expectations of ERC20
 * applications.
 *
 * Additionally, an {Approval} event is emitted on calls to {transferFrom}.
 * This allows applications to reconstruct the allowance for all accounts just
 * by listening to said events. Other implementations of the EIP may not emit
 * these events, as it isn't required by the specification.
 *
 * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
 * functions have been added to mitigate the well-known issues around setting
 * allowances. See {IERC20-approve}.
 */
contract ERC20 is Context, IERC20, IERC20Metadata {
    mapping(address => uint256) private _balances;

    mapping(address => mapping(address => uint256)) private _allowances;

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;

    /**
     * @dev Sets the values for {name} and {symbol}.
     *
     * The default value of {decimals} is 18. To select a different value for
     * {decimals} you should overload it.
     *
     * All two of these values are immutable: they can only be set once during
     * construction.
     */
    constructor(string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
    }

    /**
     * @dev Returns the name of the token.
     */
    function name() public view virtual override returns (string memory) {
        return _name;
    }

    /**
     * @dev Returns the symbol of the token, usually a shorter version of the
     * name.
     */
    function symbol() public view virtual override returns (string memory) {
        return _symbol;
    }

    /**
     * @dev Returns the number of decimals used to get its user representation.
     * For example, if `decimals` equals `2`, a balance of `505` tokens should
     * be displayed to a user as `5.05` (`505 / 10 ** 2`).
     *
     * Tokens usually opt for a value of 18, imitating the relationship between
     * Ether and Wei. This is the value {ERC20} uses, unless this function is
     * overridden;
     *
     * NOTE: This information is only used for _display_ purposes: it in
     * no way affects any of the arithmetic of the contract, including
     * {IERC20-balanceOf} and {IERC20-transfer}.
     */
    function decimals() public view virtual override returns (uint8) {
        return 18;
    }

    /**
     * @dev See {IERC20-totalSupply}.
     */
    function totalSupply() public view virtual override returns (uint256) {
        return _totalSupply;
    }

    /**
     * @dev See {IERC20-balanceOf}.
     */
    function balanceOf(address account) public view virtual override returns (uint256) {
        return _balances[account];
    }

    /**
     * @dev See {IERC20-transfer}.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - the caller must have a balance of at least `amount`.
     */
    function transfer(address to, uint256 amount) public virtual override returns (bool) {
        address owner = _msgSender();
        _transfer(owner, to, amount);
        return true;
    }

    /**
     * @dev See {IERC20-allowance}.
     */
    function allowance(
        address owner,
        address spender
    ) public view virtual override returns (uint256) {
        return _allowances[owner][spender];
    }

    /**
     * @dev See {IERC20-approve}.
     *
     * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on
     * `transferFrom`. This is semantically equivalent to an infinite approval.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function approve(address spender, uint256 amount) public virtual override returns (bool) {
        address owner = _msgSender();
        _approve(owner, spender, amount);
        return true;
    }

    /**
     * @dev See {IERC20-transferFrom}.
     *
     * Emits an {Approval} event indicating the updated allowance. This is not
     * required by the EIP. See the note at the beginning of {ERC20}.
     *
     * NOTE: Does not update the allowance if the current allowance
     * is the maximum `uint256`.
     *
     * Requirements:
     *
     * - `from` and `to` cannot be the zero address.
     * - `from` must have a balance of at least `amount`.
     * - the caller must have allowance for ``from``'s tokens of at least
     * `amount`.
     */
    function transferFrom(
        address from,
        address to,
        uint256 amount
    ) public virtual override returns (bool) {
        address spender = _msgSender();
        _spendAllowance(from, spender, amount);
        _transfer(from, to, amount);
        return true;
    }

    /**
     * @dev Moves `amount` of tokens from `from` to `to`.
     *
     * This internal function is equivalent to {transfer}, and can be used to
     * e.g. implement automatic token fees, slashing mechanisms, etc.
     *
     * Emits a {Transfer} event.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `from` must have a balance of at least `amount`.
     */
    function _transfer(address from, address to, uint256 amount) internal virtual {
        require(from != address(0), "ERC20: transfer from the zero address");
        require(to != address(0), "ERC20: transfer to the zero address");

        _beforeTokenTransfer(from, to, amount);

        uint256 fromBalance = _balances[from];
        require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
        unchecked {
            _balances[from] = fromBalance - amount;
            // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by
            // decrementing then incrementing.
            _balances[to] += amount;
        }

        emit Transfer(from, to, amount);

        _afterTokenTransfer(from, to, amount);
    }

    /** @dev Creates `amount` tokens and assigns them to `account`, increasing
     * the total supply.
     *
     * Emits a {Transfer} event with `from` set to the zero address.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     */
    function _mint(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: mint to the zero address");

        _beforeTokenTransfer(address(0), account, amount);

        _totalSupply += amount;
        unchecked {
            // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.
            _balances[account] += amount;
        }
        emit Transfer(address(0), account, amount);

        _afterTokenTransfer(address(0), account, amount);
    }

    /**
     * @dev Destroys `amount` tokens from `account`, reducing the
     * total supply.
     *
     * Emits a {Transfer} event with `to` set to the zero address.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     * - `account` must have at least `amount` tokens.
     */
    function _burn(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: burn from the zero address");

        _beforeTokenTransfer(account, address(0), amount);

        uint256 accountBalance = _balances[account];
        require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
        unchecked {
            _balances[account] = accountBalance - amount;
            // Overflow not possible: amount <= accountBalance <= totalSupply.
            _totalSupply -= amount;
        }

        emit Transfer(account, address(0), amount);

        _afterTokenTransfer(account, address(0), amount);
    }

    /**
     * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
     *
     * This internal function is equivalent to `approve`, and can be used to
     * e.g. set automatic allowances for certain subsystems, etc.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `owner` cannot be the zero address.
     * - `spender` cannot be the zero address.
     */
    function _approve(address owner, address spender, uint256 amount) internal virtual {
        require(owner != address(0), "ERC20: approve from the zero address");
        require(spender != address(0), "ERC20: approve to the zero address");

        _allowances[owner][spender] = amount;
        emit Approval(owner, spender, amount);
    }

    /**
     * @dev Updates `owner` s allowance for `spender` based on spent `amount`.
     *
     * Does not update the allowance amount in case of infinite allowance.
     * Revert if not enough allowance is available.
     *
     * Might emit an {Approval} event.
     */
    function _spendAllowance(address owner, address spender, uint256 amount) internal virtual {
        uint256 currentAllowance = allowance(owner, spender);
        if (currentAllowance != type(uint256).max) {
            require(currentAllowance >= amount, "ERC20: insufficient allowance");
            unchecked {
                _approve(owner, spender, currentAllowance - amount);
            }
        }
    }

    /**
     * @dev Hook that is called before any transfer of tokens. This includes
     * minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
     * will be transferred to `to`.
     * - when `from` is zero, `amount` tokens will be minted for `to`.
     * - when `to` is zero, `amount` of ``from``'s tokens will be burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {}

    /**
     * @dev Hook that is called after any transfer of tokens. This includes
     * minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
     * has been transferred to `to`.
     * - when `from` is zero, `amount` tokens have been minted for `to`.
     * - when `to` is zero, `amount` of ``from``'s tokens have been burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {}
}

File 11 of 18 : ReentrancyGuard.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (security/ReentrancyGuard.sol)

pragma solidity ^0.8.0;

/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
 * available, which can be applied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 *
 * TIP: If you would like to learn more about reentrancy and alternative ways
 * to protect against it, check out our blog post
 * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
 */
abstract contract ReentrancyGuard {
    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

    // The values being non-zero value makes deployment a bit more expensive,
    // but in exchange the refund on every call to nonReentrant will be lower in
    // amount. Since refunds are capped to a percentage of the total
    // transaction's gas, it is best to keep them low in cases like this one, to
    // increase the likelihood of the full refund coming into effect.
    uint256 private constant _NOT_ENTERED = 1;
    uint256 private constant _ENTERED = 2;

    uint256 private _status;

    constructor() {
        _status = _NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and making it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        _nonReentrantBefore();
        _;
        _nonReentrantAfter();
    }

    function _nonReentrantBefore() private {
        // On the first call to nonReentrant, _status will be _NOT_ENTERED
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

        // Any calls to nonReentrant after this point will fail
        _status = _ENTERED;
    }

    function _nonReentrantAfter() private {
        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        _status = _NOT_ENTERED;
    }

    /**
     * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
     * `nonReentrant` function in the call stack.
     */
    function _reentrancyGuardEntered() internal view returns (bool) {
        return _status == _ENTERED;
    }
}

File 12 of 18 : constant.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.21;

address constant TITANX = 0xF19308F923582A6f7c465e5CE7a9Dc1BEC6665B1;
address constant DRAGONX = 0x96a5399D07896f757Bd4c6eF56461F58DB951862;

// ===================== common ==========================================
uint256 constant DAY98 = 98;

uint256 constant SCALING_FACTOR_1e6 = 1e6;

uint256 constant SECONDS_IN_DAY = 86400;

uint256 constant TITANX_VORTEX_PERCENT = 10_000;
uint256 constant DRAGONX_VAULT_PERCENT = 20_000;
uint256 constant PERCENT_BPS = 100_000;
uint256 constant INCENTIVE_FEE_PERCENT_BASE = 1_000_000;

//Hydra Supply Variables
uint256 constant START_MAX_MINTABLE_PER_DAY = 800_000_000 ether;
uint256 constant CAPPED_MIN_DAILY_TITAN_MINTABLE = 80_000 ether;
uint256 constant DAILY_SUPPLY_MINTABLE_REDUCTION = 99_972;
uint256 constant START_MAX_MINT_COST = 1e11 ether;
uint256 constant EARLY_END_MINT_COST_PERCENT = 50_000;
uint256 constant EARLYEND_MAX_CAP_PERCENT = 50_000;

// ===================== mintInfo ==========================================
uint256 constant MAX_MINT_POWER_CAP = 10_000;
uint256 constant MAX_MINT_LENGTH = 88;
uint256 constant CLAIM_MINT_GRACE_PERIOD = 7;
uint256 constant MAX_BATCH_MINT_COUNT = 100;
uint256 constant MAX_MINT_PER_WALLET = 1000;
uint256 constant MINT_DAILY_REDUCTION = 11_0;

// ===================== burnInfo ==========================================
uint256 constant MAX_BURN_REWARD_PERCENT = 8;

File 13 of 18 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);

    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `from` to `to` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address from,
        address to,
        uint256 amount
    ) external returns (bool);
}

File 14 of 18 : 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 15 of 18 : IERC20Metadata.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)

pragma solidity ^0.8.0;

import "../IERC20.sol";

/**
 * @dev Interface for the optional metadata functions from the ERC20 standard.
 *
 * _Available since v4.1._
 */
interface IERC20Metadata is IERC20 {
    /**
     * @dev Returns the name of the token.
     */
    function name() external view returns (string memory);

    /**
     * @dev Returns the symbol of the token.
     */
    function symbol() external view returns (string memory);

    /**
     * @dev Returns the decimals places of the token.
     */
    function decimals() external view returns (uint8);
}

File 16 of 18 : IERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[EIP].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165 {
    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

File 17 of 18 : calcFunctions.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.21;

import "./constant.sol";

//Hydra
/**@notice get batch mint ladder total count
 * @param minDay minimum mint length
 * @param maxDay maximum mint length, cap at 280
 * @param dayInterval day increase from previous mint length
 * @param countPerInterval number of mints per minth length
 * @return count total mints
 */
function getBatchMintLadderCount(
    uint256 minDay,
    uint256 maxDay,
    uint256 dayInterval,
    uint256 countPerInterval
) pure returns (uint256 count) {
    if (maxDay > minDay) {
        count = (((maxDay - minDay) / dayInterval) + 1) * countPerInterval;
    }
}

/** @notice get batch mint cost
 * @param mintPower mint power (1 - 100)
 * @param count number of mints
 * @return mintCost total mint cost
 */
function getBatchMintCost(uint256 mintPower, uint256 count) pure returns (uint256) {
    return (START_MAX_MINT_COST * mintPower * count) / MAX_MINT_POWER_CAP;
}

//MintInfo
/** @notice the formula to calculate mint reward at create new mint
 * @param mintPower mint power 1 - 10000
 * @param numOfDays mint length 1 - 88
 * @param mintableHydra current contract day mintable Hydra
 * @return reward base Hydra amount
 */
function calculateMintReward(
    uint256 mintPower,
    uint256 numOfDays,
    uint256 mintableHydra
) pure returns (uint256 reward) {
    uint256 baseReward = (mintableHydra * mintPower * numOfDays);

    if (numOfDays != 1)
        baseReward -= (baseReward * MINT_DAILY_REDUCTION * (numOfDays - 1)) / PERCENT_BPS;

    reward = baseReward / MAX_MINT_POWER_CAP;
}

/**
 * @dev Return penalty percentage based on number of days late after the grace period of 7 days
 * @param secsLate seconds late (block timestamp - maturity timestamp)
 * @return penalty penalty in percentage
 */
function calculateClaimMintPenalty(uint256 secsLate) pure returns (uint256 penalty) {
    if (secsLate <= CLAIM_MINT_GRACE_PERIOD * SECONDS_IN_DAY) return 0;
    if (secsLate <= (CLAIM_MINT_GRACE_PERIOD + 1) * SECONDS_IN_DAY) return 1;
    if (secsLate <= (CLAIM_MINT_GRACE_PERIOD + 2) * SECONDS_IN_DAY) return 3;
    if (secsLate <= (CLAIM_MINT_GRACE_PERIOD + 3) * SECONDS_IN_DAY) return 8;
    if (secsLate <= (CLAIM_MINT_GRACE_PERIOD + 4) * SECONDS_IN_DAY) return 17;
    if (secsLate <= (CLAIM_MINT_GRACE_PERIOD + 5) * SECONDS_IN_DAY) return 35;
    if (secsLate <= (CLAIM_MINT_GRACE_PERIOD + 6) * SECONDS_IN_DAY) return 72;
    return 99;
}

File 18 of 18 : enum.sol
//Enum
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.21;

enum MintAction {
    CLAIM,
    BURN
}
enum MintStatus {
    ACTIVE,
    CLAIMED,
    BURNED,
    EARLYENDED
}
enum BurnSource {
    LIQUID,
    MINT
}

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  }
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"genesisAddress","type":"address"},{"internalType":"address","name":"buyAndBurnAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"Hydra_InsufficientBurnAllowance","type":"error"},{"inputs":[],"name":"Hydra_InvalidAddress","type":"error"},{"inputs":[],"name":"Hydra_InvalidAmount","type":"error"},{"inputs":[],"name":"Hydra_InvalidBatchCount","type":"error"},{"inputs":[],"name":"Hydra_InvalidBurnRewardPercent","type":"error"},{"inputs":[],"name":"Hydra_InvalidCaller","type":"error"},{"inputs":[],"name":"Hydra_InvalidMintLadderInterval","type":"error"},{"inputs":[],"name":"Hydra_InvalidMintLadderRange","type":"error"},{"inputs":[],"name":"Hydra_InvalidMintLength","type":"error"},{"inputs":[],"name":"Hydra_InvalidMintPower","type":"error"},{"inputs":[],"name":"Hydra_LPTokensHasMinted","type":"error"},{"inputs":[],"name":"Hydra_MaxedWalletMints","type":"error"},{"inputs":[],"name":"Hydra_MintHasBurned","type":"error"},{"inputs":[],"name":"Hydra_MintHasClaimed","type":"error"},{"inputs":[],"name":"Hydra_MintHasEnded","type":"error"},{"inputs":[],"name":"Hydra_MintMaturityNotMet","type":"error"},{"inputs":[],"name":"Hydra_MintNotMature","type":"error"},{"inputs":[],"name":"Hydra_NoMintExists","type":"error"},{"inputs":[],"name":"Hydra_NotOnwer","type":"error"},{"inputs":[],"name":"Hydra_NotSupportedContract","type":"error"},{"inputs":[],"name":"Hydra_NothingToDistribute","type":"error"},{"inputs":[],"name":"Hydra_UnregisteredCA","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"project","type":"address"},{"indexed":true,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ApproveBurnMints","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"FeesDistributed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"day","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"mintableHydra","type":"uint256"}],"name":"GlobalDailyUpdateStats","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"project","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"enum BurnSource","name":"source","type":"uint8"}],"name":"HydraBurned","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"hRank","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"rewardMinted","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"penalty","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"mintPenalty","type":"uint256"}],"name":"MintClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"hRank","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"rewardMinted","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"penalty","type":"uint256"}],"name":"MintEarlyEnded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"hRank","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"gMintpower","type":"uint256"},{"components":[{"internalType":"uint16","name":"mintPower","type":"uint16"},{"internalType":"uint8","name":"numOfDays","type":"uint8"},{"internalType":"uint104","name":"mintableHydra","type":"uint104"},{"internalType":"uint48","name":"mintStartTs","type":"uint48"},{"internalType":"uint48","name":"maturityTs","type":"uint48"},{"internalType":"uint104","name":"mintedHydra","type":"uint104"},{"internalType":"uint104","name":"mintCost","type":"uint104"},{"internalType":"enum MintStatus","name":"status","type":"uint8"}],"indexed":false,"internalType":"struct MintInfo.UserMintInfo","name":"userMintInfo","type":"tuple"}],"name":"MintStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"day","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"fee","type":"uint256"}],"name":"ProtocolFeeRecevied","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"uint256","name":"day","type":"uint256"},{"indexed":false,"internalType":"address","name":"project","type":"address"},{"indexed":true,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"VortexReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"day","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"vortexTitanX","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"vortexDragonX","type":"uint256"}],"name":"VortexTriggered","type":"event"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowanceBurnMints","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approveBurnMints","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"mintPower","type":"uint256"},{"internalType":"uint256","name":"minDay","type":"uint256"},{"internalType":"uint256","name":"maxDay","type":"uint256"},{"internalType":"uint256","name":"dayInterval","type":"uint256"},{"internalType":"uint256","name":"countPerInterval","type":"uint256"}],"name":"batchMintLadder","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"contractAddress","type":"address"}],"name":"burnCAHydra","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"burnMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"userRebatePercentage","type":"uint256"},{"internalType":"uint256","name":"rewardPaybackPercentage","type":"uint256"}],"name":"burnTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"userRebatePercentage","type":"uint256"},{"internalType":"uint256","name":"rewardPaybackPercentage","type":"uint256"},{"internalType":"address","name":"rewardPaybackAddress","type":"address"}],"name":"burnTokensToPayAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"claimMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"distributeFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"earlyEndMint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"fundVortexDragonX","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"fundVortexTitanX","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"genesisTs","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBuyAndBurnAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"contractAddress","type":"address"}],"name":"getBuyAndBurnAddressRegistry","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentBlockTimeStamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentContractDay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentMintCost","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getCurrentMintableHydra","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getGlobalHRank","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getGlobalMintPower","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"cycleNo","type":"uint256"}],"name":"getNextCyclePayoutDay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"contractAddress","type":"address"}],"name":"getProjectBurnTotal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"address","name":"user","type":"address"}],"name":"getProjectUserBurnTotal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTitanXIncentiveDividend","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalActiveMints","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalBurnTotal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalMintBurn","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalMintClaim","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalMintEarlyEnded","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalMintPenalty","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalMinting","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getUndistributedFees","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getUserBurnTotal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getUserLatestMintId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getUserMintInfo","outputs":[{"components":[{"internalType":"uint16","name":"mintPower","type":"uint16"},{"internalType":"uint8","name":"numOfDays","type":"uint8"},{"internalType":"uint104","name":"mintableHydra","type":"uint104"},{"internalType":"uint48","name":"mintStartTs","type":"uint48"},{"internalType":"uint48","name":"maturityTs","type":"uint48"},{"internalType":"uint104","name":"mintedHydra","type":"uint104"},{"internalType":"uint104","name":"mintCost","type":"uint104"},{"internalType":"enum MintStatus","name":"status","type":"uint8"}],"internalType":"struct MintInfo.UserMintInfo","name":"mintInfo","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getUserMints","outputs":[{"components":[{"internalType":"uint256","name":"mId","type":"uint256"},{"internalType":"uint256","name":"hRank","type":"uint256"},{"internalType":"uint256","name":"gMintPower","type":"uint256"},{"components":[{"internalType":"uint16","name":"mintPower","type":"uint16"},{"internalType":"uint8","name":"numOfDays","type":"uint8"},{"internalType":"uint104","name":"mintableHydra","type":"uint104"},{"internalType":"uint48","name":"mintStartTs","type":"uint48"},{"internalType":"uint48","name":"maturityTs","type":"uint48"},{"internalType":"uint104","name":"mintedHydra","type":"uint104"},{"internalType":"uint104","name":"mintCost","type":"uint104"},{"internalType":"enum MintStatus","name":"status","type":"uint8"}],"internalType":"struct MintInfo.UserMintInfo","name":"mintInfo","type":"tuple"}],"internalType":"struct MintInfo.UserMint[]","name":"mintInfos","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getVortexDragonX","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getVortexTitanX","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"manualDailyUpdate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"mintLPTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"contractAddress","type":"address"}],"name":"setBuyAndBurnContractAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newAddress","type":"address"}],"name":"setNewGenesisAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"setTitanXIncentiveFeeDividend","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"mintPower","type":"uint256"},{"internalType":"uint256","name":"numOfDays","type":"uint256"}],"name":"startMint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"triggerVortex","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"contractAddress","type":"address"}],"name":"unRegisterBuyAndBurnContractAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"userBurnMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"userBurnTokens","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60a060405234801562000010575f80fd5b5060405162003d1e38038062003d1e8339810160408190526200003391620002a7565b604080518082018252600580825264485944524160d81b60208084018290528451808601909552918452908301529060036200007083826200037d565b5060046200007f82826200037d565b5050600580546001600160a01b03191633179055504260805260016006819055600780546001600160601b0319166b0295be96e64066972000000017905560625f81905260086020527f3eae06187ba0198e7de2db0a13c35f0d744282a7db7e055bcdaaf6ee7879e669556017556001600160a01b0382166200011557604051633692283d60e21b815260040160405180910390fd5b6001600160a01b0381166200013d57604051633692283d60e21b815260040160405180910390fd5b601880546001600160a01b038481166001600160a01b0319928316179092556019805492841692909116821790555f908152601a602052604090819020805460ff19166001179055610ce4601d555163095ea7b360e01b81523060048201525f19602482015273f19308f923582a6f7c465e5ce7a9dc1bec6665b19063095ea7b3906044016020604051808303815f875af1158015620001df573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019062000205919062000445565b5060405163095ea7b360e01b81523060048201525f1960248201527396a5399d07896f757bd4c6ef56461f58db9518629063095ea7b3906044016020604051808303815f875af11580156200025c573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019062000282919062000445565b5050506200046d565b80516001600160a01b0381168114620002a2575f80fd5b919050565b5f8060408385031215620002b9575f80fd5b620002c4836200028b565b9150620002d4602084016200028b565b90509250929050565b634e487b7160e01b5f52604160045260245ffd5b600181811c908216806200030657607f821691505b6020821081036200032557634e487b7160e01b5f52602260045260245ffd5b50919050565b601f82111562000378575f81815260208120601f850160051c81016020861015620003535750805b601f850160051c820191505b8181101562000374578281556001016200035f565b5050505b505050565b81516001600160401b03811115620003995762000399620002dd565b620003b181620003aa8454620002f1565b846200032b565b602080601f831160018114620003e7575f8415620003cf5750858301515b5f19600386901b1c1916600185901b17855562000374565b5f85815260208120601f198616915b828110156200041757888601518255948401946001909101908401620003f6565b50858210156200043557878501515f19600388901b60f8161c191681555b5050505050600190811b01905550565b5f6020828403121562000456575f80fd5b8151801515811462000466575f80fd5b9392505050565b6080516138916200048d5f395f81816109e80152611a3501526138915ff3fe608060405260043610610387575f3560e01c8063707f6dda116101d3578063c50312ad116100fd578063e45fa5a51161009d578063f2fde38b1161006d578063f2fde38b14610a8f578063f80b0cfb14610aae578063fe73e37914610ac2578063ffb75cab14610ad5575f80fd5b8063e45fa5a514610a0c578063e745646114610a20578063e805217414610a34578063e90225cb14610a68575f80fd5b8063d9af94af116100d8578063d9af94af14610970578063dd62ed3e14610982578063dff96e9a146109c6578063e3af6d0a146109da575f80fd5b8063c50312ad146108fc578063d1f7363814610930578063d819e19814610944575f80fd5b80638e449fdc11610173578063a1bbd7b911610143578063a1bbd7b91461088d578063a9059cbb146108aa578063baf20eef146108c9578063bb57ad20146108e8575f80fd5b80638e449fdc1461083357806392c1df541461084657806395d89b411461085a5780639ed992201461086e575f80fd5b80637b763a2c116101ae5780637b763a2c146107c25780637c872f87146107e15780637d6b3253146108005780637ec26dca1461081f575f80fd5b8063707f6dda1461075b57806370a082311461077a578063715018a6146107ae575f80fd5b8063313ce567116102b45780634d235aa2116102545780635c5ef4b6116102245780635c5ef4b6146106f6578063635d70f41461071557806367921d68146107285780636f6096331461073c575f80fd5b80634d235aa21461064a5780635109c57c14610669578063544a6c59146106a057806354f5d028146106e2575f80fd5b806337c4f8c41161028f57806337c4f8c4146105d95780633a9693e1146105f85780633c34267f146106175780633cef7cc314610636575f80fd5b8063313ce5671461058057806333f3fd781461059b5780633765d723146105ba575f80fd5b80631ce392b11161032a57806329b70d7a116102fa57806329b70d7a146104ee5780632d02347a146105225780632f7719511461054d578063300284f214610561575f80fd5b80631ce392b114610493578063216630b4146104a757806323639385146104bb57806323b872dd146104cf575f80fd5b806313aad5101161036557806313aad5101461043657806318160ddd1461044c5780631ae409c0146104605780631c911f2b14610474575f80fd5b806306fdde031461038b578063095ea7b3146103b55780631371bb40146103e4575b5f80fd5b348015610396575f80fd5b5061039f610b01565b6040516103ac91906133df565b60405180910390f35b3480156103c0575f80fd5b506103d46103cf36600461342c565b610b91565b60405190151581526020016103ac565b3480156103ef575f80fd5b506104286103fe366004613454565b6001600160a01b039182165f90815260166020908152604080832093909416825291909152205490565b6040519081526020016103ac565b348015610441575f80fd5b5061044a610baa565b005b348015610457575f80fd5b50600254610428565b34801561046b575f80fd5b50600654610428565b34801561047f575f80fd5b5061044a61048e366004613485565b610bb4565b34801561049e575f80fd5b50601e54610428565b3480156104b2575f80fd5b50600c54610428565b3480156104c6575f80fd5b50610428610c03565b3480156104da575f80fd5b506103d46104e936600461349e565b610c26565b3480156104f9575f80fd5b50610428610508366004613485565b6001600160a01b03165f9081526015602052604090205490565b34801561052d575f80fd5b5061042861053c3660046134d7565b5f9081526008602052604090205490565b348015610558575f80fd5b50600b54610428565b34801561056c575f80fd5b506103d461057b36600461342c565b610c49565b34801561058b575f80fd5b50604051601281526020016103ac565b3480156105a6575f80fd5b5061044a6105b53660046134ee565b610cc6565b3480156105c5575f80fd5b5061044a6105d43660046134d7565b610cec565b3480156105e4575f80fd5b5061044a6105f33660046134d7565b610d61565b348015610603575f80fd5b5061044a610612366004613485565b610d93565b348015610622575f80fd5b5061044a6106313660046134d7565b610e07565b348015610641575f80fd5b5061044a610e45565b348015610655575f80fd5b5061044a6106643660046134d7565b610f57565b348015610674575f80fd5b506103d4610683366004613485565b6001600160a01b03165f908152601a602052604090205460ff1690565b3480156106ab575f80fd5b506104286106ba366004613454565b6001600160a01b039182165f9081526020808052604080832093909416825291909152205490565b3480156106ed575f80fd5b50601354610428565b348015610701575f80fd5b5061044a610710366004613485565b610f98565b61044a61072336600461353a565b610ff7565b348015610733575f80fd5b50601c54610428565b348015610747575f80fd5b506c01431e0fae6d7217caa0000000610428565b348015610766575f80fd5b5061044a6107753660046134d7565b6110dd565b348015610785575f80fd5b50610428610794366004613485565b6001600160a01b03165f9081526020819052604090205490565b3480156107b9575f80fd5b5061044a61117c565b3480156107cd575f80fd5b5061044a6107dc36600461342c565b61118d565b3480156107ec575f80fd5b5061044a6107fb3660046134d7565b6111b1565b34801561080b575f80fd5b5061044a61081a366004613485565b611242565b34801561082a575f80fd5b50600954610428565b61044a61084136600461355a565b6113a6565b348015610851575f80fd5b50600e54610428565b348015610865575f80fd5b5061039f6114c8565b348015610879575f80fd5b5061044a610888366004613591565b6114d7565b348015610898575f80fd5b506007546001600160601b0316610428565b3480156108b5575f80fd5b506103d46108c436600461342c565b6114fc565b3480156108d4575f80fd5b5061044a6108e33660046134d7565b611509565b3480156108f3575f80fd5b5061044a61152c565b348015610907575f80fd5b50610428610916366004613485565b6001600160a01b03165f9081526010602052604090205490565b34801561093b575f80fd5b50601f54610428565b34801561094f575f80fd5b5061096361095e36600461342c565b6116b1565b6040516103ac9190613681565b34801561097b575f80fd5b5042610428565b34801561098d575f80fd5b5061042861099c366004613454565b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205490565b3480156109d1575f80fd5b50600d54610428565b3480156109e5575f80fd5b507f0000000000000000000000000000000000000000000000000000000000000000610428565b348015610a17575f80fd5b50600f54610428565b348015610a2b575f80fd5b50601d54610428565b348015610a3f575f80fd5b50610428610a4e366004613485565b6001600160a01b03165f9081526014602052604090205490565b348015610a73575f80fd5b506019546040516001600160a01b0390911681526020016103ac565b348015610a9a575f80fd5b5061044a610aa9366004613485565b61179c565b348015610ab9575f80fd5b50600a54610428565b61044a610ad03660046134d7565b6117ad565b348015610ae0575f80fd5b50610af4610aef366004613485565b6117ef565b6040516103ac9190613690565b606060038054610b1090613700565b80601f0160208091040260200160405190810160405280929190818152602001828054610b3c90613700565b8015610b875780601f10610b5e57610100808354040283529160200191610b87565b820191905f5260205f20905b815481529060010190602001808311610b6a57829003601f168201915b5050505050905090565b5f33610b9e8185856118ff565b60019150505b92915050565b610bb2611a28565b565b610bbc611b4f565b6001600160a01b038116610be357604051633692283d60e21b815260040160405180910390fd5b6001600160a01b03165f908152601a60205260409020805460ff19169055565b5f600b54600a54600954610c17919061374c565b610c21919061374c565b905090565b5f33610c33858285611b7a565b610c3e858585611c04565b506001949350505050565b5f6001600160a01b038316610c7157604051633692283d60e21b815260040160405180910390fd5b335f818152602080805260408083206001600160a01b038816808552925280832086905551859391927ff8e109bcddf5e12132b7cd8a8517d97498f50c7ac595874d6f513243098b079891a450600192915050565b610cce611da6565b610cdb8585858585611dff565b610ce56001601755565b5050505050565b6019546001600160a01b03163314610d1757604051637b28105560e11b815260040160405180910390fd5b601b5460ff1615610d3b576040516371cad2dd60e11b815260040160405180910390fd5b601b805460ff19166001179055601954610d5e906001600160a01b031682611e4c565b50565b610d69611a28565b610d71611da6565b610d89335f610d8233856001611f09565b6001612133565b610d5e6001601755565b6018546001600160a01b03163314610dbe57604051637b28105560e11b815260040160405180910390fd5b6001600160a01b038116610de557604051633692283d60e21b815260040160405180910390fd5b601880546001600160a01b0319166001600160a01b0392909216919091179055565b610e0f611da6565b805f03610e2f57604051637133514760e11b815260040160405180910390fd5b610e393382612241565b610d89335f835f612133565b610e4d611a28565b610e55611da6565b5f610e5f60065490565b60625f5260086020527f3eae06187ba0198e7de2db0a13c35f0d744282a7db7e055bcdaaf6ee7879e66954909150811015610e9a5750610f4d565b610ea4606261236e565b601e548015610edf575f601e55601954610edf9073f19308f923582a6f7c465e5ce7a9dc1bec6665b19030906001600160a01b0316846123d7565b601f548015610f1a575f601f55601954610f1a907396a5399d07896f757bd4c6ef56461f58db9518629030906001600160a01b0316846123d7565b8082847f10c98735795e0571a6953e9af4a856a063c221909e07483422446ccbf710af4060405160405180910390a45050505b610bb26001601755565b610f5f611a28565b610f67611b4f565b801580610f75575061271081115b15610f9357604051637133514760e11b815260040160405180910390fd5b601d55565b6001600160a01b0381165f908152601a602052604090205460ff16610fd057604051630a5cfbdb60e11b815260040160405180910390fd5b610d5e81610ff2836001600160a01b03165f9081526020819052604090205490565b612241565b610fff611a28565b611007611da6565b335f908152601060205260409020546103e89061102590600161375f565b1115611044576040516335aabe6960e11b815260040160405180910390fd5b5f8261104f600e5490565b611059919061375f565b90505f61106560095490565b61107090600161375f565b90505f61109d33868661108b6007546001600160601b031690565b87876110988c60016124dc565b612513565b600c546110aa919061375f565b90506110c0828483600992909255600e55600c55565b6110cc8560015f6127ae565b5050506110d96001601755565b5050565b6110e5611a28565b6110ed611da6565b61110d7396a5399d07896f757bd4c6ef56461f58db9518623330846123d7565b80601f5f82825461111e919061375f565b909155505060065481906040517396a5399d07896f757bd4c6ef56461f58db951862815233907fc0eadb8b1414d09241a441cb47087f29af42c6b281bc64bc445a6aed0c9bff24906020015b60405180910390a4610d5e6001601755565b611184611b4f565b610bb25f61285c565b611195611a28565b61119d611da6565b6111a7828261287e565b6110d96001601755565b6111b9611a28565b6111c1611da6565b6111e173f19308f923582a6f7c465e5ce7a9dc1bec6665b13330846123d7565b80601e5f8282546111f2919061375f565b9091555050600654819060405173f19308f923582a6f7c465e5ce7a9dc1bec6665b1815233907fc0eadb8b1414d09241a441cb47087f29af42c6b281bc64bc445a6aed0c9bff249060200161116a565b61124a611b4f565b6001600160a01b03811661127157604051633692283d60e21b815260040160405180910390fd5b6040516301ffc9a760e01b80825260048201526001600160a01b038216906301ffc9a7906024016020604051808303815f875af11580156112b4573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112d89190613772565b158061134f57506040516301ffc9a760e01b815263663ca86f60e01b60048201526001600160a01b038216906301ffc9a7906024016020604051808303815f875af1158015611329573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061134d9190613772565b155b1561136d5760405163a3600d0960e01b815260040160405180910390fd5b601980546001600160a01b039092166001600160a01b0319909216821790555f908152601a60205260409020805460ff19166001179055565b6113ae611da6565b6113b6611a28565b815f036113d6576040516301742a3360e21b815260040160405180910390fd5b838310806113e2575083155b806113ed5750605883115b1561140b57604051634741150960e11b815260040160405180910390fd5b5f611418858585856128df565b90508015806114275750606481115b15611445576040516373c1ffd360e11b815260040160405180910390fd5b335f908152601060205260409020546103e89061146390839061375f565b1115611482576040516335aabe6960e11b815260040160405180910390fd5b5f61148e8760016124dc565b90506114b13388888888886114ab6007546001600160601b031690565b8861291e565b6114bc87835f6127ae565b5050610ce56001601755565b606060048054610b1090613700565b6114df611da6565b6114ec8484848433611dff565b6114f66001601755565b50505050565b5f33610b9e818585611c04565b611511611a28565b611519611da6565b610d8961152733835f611f09565b6129b0565b611534611a28565b61153c611da6565b601c545f81900361156057604051636d8af89f60e11b815260040160405180910390fd5b5f601c819055601d54620f4240906115789084613791565b61158291906137a8565b905061158e818361374c565b91506115b073f19308f923582a6f7c465e5ce7a9dc1bec6665b13033846123d7565b5f620186a06115c161271085613791565b6115cb91906137a8565b905080601e5f8282546115de919061375f565b909155505f9050620186a06115f5614e2086613791565b6115ff91906137a8565b905061163573f19308f923582a6f7c465e5ce7a9dc1bec6665b1307396a5399d07896f757bd4c6ef56461f58db951862846123d7565b6019546116779073f19308f923582a6f7c465e5ce7a9dc1bec6665b19030906001600160a01b031684611668878a61374c565b611672919061374c565b6123d7565b604051849033907f63be20cc905d5ba0cf65db405c4999f99f2575e521875f13a8009d6eed7a09d9905f90a350505050610bb26001601755565b6116b9613354565b6001600160a01b0383165f90815260116020908152604080832085845282528083205483526012825291829020825161010081018452815461ffff8116825260ff6201000082048116948301949094526001600160681b036301000000820481169583019590955265ffffffffffff600160801b820481166060840152600160b01b909104166080820152600182015480851660a0830152600160681b810490941660c082015292909160e0840191600160d01b9004166003811115611781576117816135c7565b6003811115611792576117926135c7565b9052509392505050565b6117a4611b4f565b610d5e8161285c565b6117b5611da6565b6117bd611a28565b5f806117c933846129da565b915091506117da81600160036127ae565b6117e3826129b0565b5050610d5e6001601755565b6001600160a01b0381165f908152601060205260409020546060908067ffffffffffffffff811115611823576118236137c7565b60405190808252806020026020018201604052801561185c57816020015b611849613398565b8152602001906001900390816118415790505b50915060015b8181116118f857604080516080810182528281526001600160a01b0386165f908152601160209081528382208583528082528483208054838601529286905290526001015491810191909152606081016118bc86846116b1565b9052836118ca60018461374c565b815181106118da576118da6137db565b602002602001018190525080806118f0906137ef565b915050611862565b5050919050565b6001600160a01b0383166119665760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b60648201526084015b60405180910390fd5b6001600160a01b0382166119c75760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b606482015260840161195d565b6001600160a01b038381165f8181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b6006545f62015180611a5a7f00000000000000000000000000000000000000000000000000000000000000004261374c565b611a6491906137a8565b611a6f90600161375f565b9050818111156110d9576007546001600160601b03165f611a90848461374c565b90505f5b81811015611b2257620186a0611aad6201868485613791565b611ab791906137a8565b92506910f0cf064dd592000000831015611ad9576910f0cf064dd59200000092505b82611ae3866137ef565b60405190965086907f502806f7cf43435d83b251173d47f99095d52c72115be741aa35f763db4a8140905f90a380611b1a816137ef565b915050611a94565b5050600780546bffffffffffffffffffffffff19166001600160601b039290921691909117905560065550565b6005546001600160a01b03163314610bb257604051637550a7dd60e11b815260040160405180910390fd5b6001600160a01b038381165f908152600160209081526040808320938616835292905220545f1981146114f65781811015611bf75760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e6365000000604482015260640161195d565b6114f684848484036118ff565b6001600160a01b038316611c685760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b606482015260840161195d565b6001600160a01b038216611cca5760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b606482015260840161195d565b6001600160a01b0383165f9081526020819052604090205481811015611d415760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b606482015260840161195d565b6001600160a01b038481165f81815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a36114f6565b600260175403611df85760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640161195d565b6002601755565b835f03611e1f57604051637133514760e11b815260040160405180910390fd5b611e2a853386611b7a565b611e348383612d42565b611e3e8585612241565b610ce585858585855f612e55565b6001600160a01b038216611ea25760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015260640161195d565b8060025f828254611eb3919061375f565b90915550506001600160a01b0382165f81815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b6001600160a01b0383165f908152601160209081526040808320858452909152812054808203611f4c57604051632e914a1360e01b815260040160405180910390fd5b5f818152601260209081526040808320815161010081018352815461ffff8116825260ff6201000082048116958301959095526001600160681b036301000000820481169483019490945265ffffffffffff600160801b820481166060840152600160b01b909104166080820152600182015480841660a0830152600160681b810490931660c082015292909160e0840191600160d01b909104166003811115611ff857611ff86135c7565b6003811115612009576120096135c7565b905250905060018160e001516003811115612026576120266135c7565b036120445760405163130a46d560e21b815260040160405180910390fd5b60028160e00151600381111561205c5761205c6135c7565b0361207a57604051638c64dced60e01b815260040160405180910390fd5b60038160e001516003811115612092576120926135c7565b036120b0576040516351852dd960e11b815260040160405180910390fd5b42816080015165ffffffffffff161180156120db57505f8460018111156120d9576120d96135c7565b145b156120f957604051631cc0f42b60e01b815260040160405180910390fd5b80604001516001600160681b0316600c5f828254612117919061374c565b90915550612129905086838387612f5a565b9695505050505050565b6001600160a01b0384165f908152601460205260408120805484929061215a90849061375f565b925050819055508160135f828254612172919061375f565b90915550506001600160a01b038316156121ee576001600160a01b0383165f90815260156020526040812080548492906121ad90849061375f565b90915550506001600160a01b038084165f908152601660209081526040808320938816835292905290812080548492906121e890849061375f565b90915550505b826001600160a01b0316846001600160a01b03167f083dcb7ef00c446abbb046896579428741dad18e02f48b3b9706129ee06707a38484604051612233929190613807565b60405180910390a350505050565b6001600160a01b0382166122a15760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b606482015260840161195d565b6001600160a01b0382165f90815260208190526040902054818110156123145760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b606482015260840161195d565b6001600160a01b0383165f818152602081815260408083208686039055600280548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9101611a1b565b505050565b5f818152600860205260409020546006548181106123695782612391838361374c565b61239b91906137a8565b6123a690600161375f565b6123b09084613791565b5f84815260086020526040812080549091906123cd90849061375f565b9091555050505050565b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291515f9283929088169161243a919061382b565b5f604051808303815f865af19150503d805f8114612473576040519150601f19603f3d011682016040523d82523d5f602084013e612478565b606091505b50915091508180156124a25750805115806124a25750808060200190518101906124a29190613772565b6124d45760405162461bcd60e51b815260206004820152600360248201526229aa2360e91b604482015260640161195d565b505050505050565b5f612710826124f8856c01431e0fae6d7217caa0000000613791565b6125029190613791565b61250c91906137a8565b9392505050565b5f8515806125215750605886115b1561253f5760405163ad314fd960e01b815260040160405180910390fd5b86158061254d575061271087115b1561256b5760405163282d398b60e11b815260040160405180910390fd5b612576878787613150565b90505f6040518061010001604052808961ffff1681526020018860ff168152602001836001600160681b031681526020014265ffffffffffff16815260200162015180896125c49190613791565b6125ce904261375f565b65ffffffffffff1681525f602082018190526001600160681b03861660408301526060909101526001600160a01b038a165f90815260106020526040812080549293509091829061261e906137ef565b91829055506001600160a01b038b165f908152601160209081526040808320848452825280832089815560019081018b90558984526012835292819020865181549388015192880151606089015160808a015161ffff90931662ffffff19909616959095176201000060ff909516949094029390931775ffffffffffffffffffffffffffffffffffffff000000191663010000006001600160681b039485160265ffffffffffff60801b191617600160801b65ffffffffffff958616021765ffffffffffff60b01b1916600160b01b949091169390930292909217825560a0860151928201805460c08801519483166001600160d01b031990911617600160681b94909216939093021780835560e0860151939450859391929060ff60d01b1916600160d01b836003811115612756576127566135c7565b021790555090505085858b6001600160a01b03167fa695be83040d0421ae4df4376ee65ef8a31c127f7115482b231953ec35869a07856040516127999190613681565b60405180910390a45050979650505050505050565b5f6127b984846124dc565b905060038260038111156127cf576127cf6135c7565b036127f157620186a06127e461c35083613791565b6127ee91906137a8565b90505b61281173f19308f923582a6f7c465e5ce7a9dc1bec6665b13330846123d7565b80601c5f828254612822919061375f565b9091555050600654819060405133907fd833e83f161e4ddfb1306cdf11a374a0a23393f008f9394b85999b988c232e36905f90a450505050565b600580546001600160a01b0319166001600160a01b0392909216919091179055565b612887826131c1565b6128915f80612d42565b5f61289e83836001611f09565b6018549091506128d0906001600160a01b0316620186a06128c184611f40613791565b6128cb91906137a8565b611e4c565b61236983825f80336001612e55565b5f848411156129165781836128f4878761374c565b6128fe91906137a8565b61290990600161375f565b6129139190613791565b90505b949350505050565b600e54600954600c545b87891161298f575f5b8681101561297d576129438b8561375f565b935061295f8c8c8c8988612956896137ef565b9850888b612513565b612969908361375f565b915080612975816137ef565b915050612931565b50612988878a61375f565b9850612928565b6129a3828483600992909255600e55600c55565b5050505050505050505050565b6129ba3382611e4c565b601854610d5e906001600160a01b0316620186a06128c184611f40613791565b6001600160a01b0382165f9081526011602090815260408083208484529091528120548190808203612a1f57604051632e914a1360e01b815260040160405180910390fd5b5f818152601260209081526040808320815161010081018352815461ffff8116825260ff6201000082048116958301959095526001600160681b036301000000820481169483019490945265ffffffffffff600160801b820481166060840152600160b01b909104166080820152600182015480841660a0830152600160681b810490931660c082015292909160e0840191600160d01b909104166003811115612acb57612acb6135c7565b6003811115612adc57612adc6135c7565b905250905060018160e001516003811115612af957612af96135c7565b03612b175760405163130a46d560e21b815260040160405180910390fd5b60028160e001516003811115612b2f57612b2f6135c7565b03612b4d57604051638c64dced60e01b815260040160405180910390fd5b60038160e001516003811115612b6557612b656135c7565b03612b83576040516351852dd960e11b815260040160405180910390fd5b5f62015180826060015165ffffffffffff1642612ba0919061374c565b612baa91906137a8565b905042826080015165ffffffffffff16111580612bc75750600381105b15612be5576040516305d8f6dd60e01b815260040160405180910390fd5b5f838152601260209081526040808320600101805460ff60d01b1916600360d01b179055840151908401516001600160681b03909116919060ff16612c2a8484613791565b612c3491906137a8565b90505f620186a0612c4761c35085613791565b612c5191906137a8565b905080821115612c5f578091505b5f86815260126020526040812060010180546cffffffffffffffffffffffffff19166001600160681b038516179055600c8054859290612ca090849061374c565b90915550612cb09050828461374c565b600d5f828254612cc0919061375f565b9091555050600f80545f90612cd4906137ef565b90915550845191975061ffff90911695508690612cf1828461374c565b868b6001600160a01b03167f0a4a5a6b9bb9ce91ec0775f7273d9386e58600280767378ff02bb28b0e3202458b604051612d2d91815260200190565b60405180910390a45050505050509250929050565b6008612d4e838361375f565b1115612d6d57604051630cb7a9ff60e01b815260040160405180910390fd5b6040516301ffc9a760e01b808252600482015233906301ffc9a790602401602060405180830381865afa158015612da6573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612dca9190613772565b1580612e3757506040516301ffc9a760e01b81526311686e4b60e21b600482015233906301ffc9a790602401602060405180830381865afa158015612e11573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612e359190613772565b155b156110d95760405163a3600d0960e01b815260040160405180910390fd5b612e6186338784612133565b5f808415612e9c57612e77620186a06064613791565b620186a0612e85878a613791565b612e8f9190613791565b612e9991906137a8565b91505b8515612ed557612eb0620186a06064613791565b620186a0612ebe888a613791565b612ec89190613791565b612ed291906137a8565b90505b8115612ee557612ee58483611e4c565b8015612ef557612ef58882611e4c565b6040516311686e4b60e21b81526001600160a01b03891660048201526024810188905233906345a1b92c906044015f604051808303815f87803b158015612f3a575f80fd5b505af1158015612f4c573d5f803e3d5ffd5b505050505050505050505050565b5f80826001811115612f6e57612f6e6135c7565b03612f95575f848152601260205260409020600101805460ff60d01b1916600160d01b1790555b6001826001811115612fa957612fa96135c7565b03612fd0575f848152601260205260409020600101805460ff60d01b1916600160d11b1790555b5f80846080015165ffffffffffff1642111561300957613006856080015165ffffffffffff1642613001919061374c565b613240565b90505b60408501516001600160681b031660646130238383613791565b61302d91906137a8565b9250613039838261374c565b93505f85600181111561304e5761304e6135c7565b0361306657600a5f8154613061906137ef565b909155505b600185600181111561307a5761307a6135c7565b0361309257600b5f815461308d906137ef565b909155505b82156130af5782600d5f8282546130a9919061375f565b90915550505b5f8560018111156130c2576130c26135c7565b036130f7575f87815260126020526040902060010180546cffffffffffffffffffffffffff19166001600160681b0386161790555b8187896001600160a01b03167fbd866a3fbf35e201f790e87581b1afbb3165e879df5d35313a4875a70b9f3b36878760405161313d929190918252602082015260400190565b60405180910390a4505050949350505050565b5f808361315d8685613791565b6131679190613791565b9050836001146131ac57620186a061318060018661374c565b61318b606e84613791565b6131959190613791565b61319f91906137a8565b6131a9908261374c565b90505b6131b8612710826137a8565b95945050505050565b6001600160a01b0381165f908152602080805260408083203384529091529020545f1981146110d957805f0361320a576040516301fb15f960e31b815260040160405180910390fd5b6001600160a01b0382165f908152602080805260408083203384529091528120805490919061323890613846565b909155505050565b5f61324f620151806007613791565b821161325c57505f919050565b6201518061326c6007600161375f565b6132769190613791565b821161328457506001919050565b620151806132946007600261375f565b61329e9190613791565b82116132ac57506003919050565b620151806132bc6007600361375f565b6132c69190613791565b82116132d457506008919050565b620151806132e46007600461375f565b6132ee9190613791565b82116132fc57506011919050565b6201518061330c6007600561375f565b6133169190613791565b821161332457506023919050565b620151806133346007600661375f565b61333e9190613791565b821161334c57506048919050565b506063919050565b60408051610100810182525f80825260208201819052918101829052606081018290526080810182905260a0810182905260c081018290529060e08201905b905290565b60405180608001604052805f81526020015f81526020015f8152602001613393613354565b5f5b838110156133d75781810151838201526020016133bf565b50505f910152565b602081525f82518060208401526133fd8160408501602087016133bd565b601f01601f19169190910160400192915050565b80356001600160a01b0381168114613427575f80fd5b919050565b5f806040838503121561343d575f80fd5b61344683613411565b946020939093013593505050565b5f8060408385031215613465575f80fd5b61346e83613411565b915061347c60208401613411565b90509250929050565b5f60208284031215613495575f80fd5b61250c82613411565b5f805f606084860312156134b0575f80fd5b6134b984613411565b92506134c760208501613411565b9150604084013590509250925092565b5f602082840312156134e7575f80fd5b5035919050565b5f805f805f60a08688031215613502575f80fd5b61350b86613411565b945060208601359350604086013592506060860135915061352e60808701613411565b90509295509295909350565b5f806040838503121561354b575f80fd5b50508035926020909101359150565b5f805f805f60a0868803121561356e575f80fd5b505083359560208501359550604085013594606081013594506080013592509050565b5f805f80608085870312156135a4575f80fd5b6135ad85613411565b966020860135965060408601359560600135945092505050565b634e487b7160e01b5f52602160045260245ffd5b600481106135eb576135eb6135c7565b9052565b61ffff815116825260ff60208201511660208301526001600160681b036040820151166040830152606081015165ffffffffffff8082166060850152806080840151166080850152505060a081015161365360a08401826001600160681b03169052565b5060c081015161366e60c08401826001600160681b03169052565b5060e081015161236960e08401826135db565b6101008101610ba482846135ef565b602080825282518282018190525f919060409081850190868401855b828110156136f35781518051855286810151878601528581015186860152606090810151906136dd818701836135ef565b50506101609390930192908501906001016136ac565b5091979650505050505050565b600181811c9082168061371457607f821691505b60208210810361373257634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52601160045260245ffd5b81810381811115610ba457610ba4613738565b80820180821115610ba457610ba4613738565b5f60208284031215613782575f80fd5b8151801515811461250c575f80fd5b8082028115828204841417610ba457610ba4613738565b5f826137c257634e487b7160e01b5f52601260045260245ffd5b500490565b634e487b7160e01b5f52604160045260245ffd5b634e487b7160e01b5f52603260045260245ffd5b5f6001820161380057613800613738565b5060010190565b828152604081016002831061381e5761381e6135c7565b8260208301529392505050565b5f825161383c8184602087016133bd565b9190910192915050565b5f8161385457613854613738565b505f19019056fea264697066735822122027b6d5c3dbb94d275b5dbfa3e47907441fadf2e70216925877ef9b3ac05e5e8364736f6c63430008150033000000000000000000000000b8a03f9cb2f5e5692cb0b64378ddce843fbfa47b000000000000000000000000fef10de0823f58df4f5f24856ab4274ededa6a5c

Deployed Bytecode

0x608060405260043610610387575f3560e01c8063707f6dda116101d3578063c50312ad116100fd578063e45fa5a51161009d578063f2fde38b1161006d578063f2fde38b14610a8f578063f80b0cfb14610aae578063fe73e37914610ac2578063ffb75cab14610ad5575f80fd5b8063e45fa5a514610a0c578063e745646114610a20578063e805217414610a34578063e90225cb14610a68575f80fd5b8063d9af94af116100d8578063d9af94af14610970578063dd62ed3e14610982578063dff96e9a146109c6578063e3af6d0a146109da575f80fd5b8063c50312ad146108fc578063d1f7363814610930578063d819e19814610944575f80fd5b80638e449fdc11610173578063a1bbd7b911610143578063a1bbd7b91461088d578063a9059cbb146108aa578063baf20eef146108c9578063bb57ad20146108e8575f80fd5b80638e449fdc1461083357806392c1df541461084657806395d89b411461085a5780639ed992201461086e575f80fd5b80637b763a2c116101ae5780637b763a2c146107c25780637c872f87146107e15780637d6b3253146108005780637ec26dca1461081f575f80fd5b8063707f6dda1461075b57806370a082311461077a578063715018a6146107ae575f80fd5b8063313ce567116102b45780634d235aa2116102545780635c5ef4b6116102245780635c5ef4b6146106f6578063635d70f41461071557806367921d68146107285780636f6096331461073c575f80fd5b80634d235aa21461064a5780635109c57c14610669578063544a6c59146106a057806354f5d028146106e2575f80fd5b806337c4f8c41161028f57806337c4f8c4146105d95780633a9693e1146105f85780633c34267f146106175780633cef7cc314610636575f80fd5b8063313ce5671461058057806333f3fd781461059b5780633765d723146105ba575f80fd5b80631ce392b11161032a57806329b70d7a116102fa57806329b70d7a146104ee5780632d02347a146105225780632f7719511461054d578063300284f214610561575f80fd5b80631ce392b114610493578063216630b4146104a757806323639385146104bb57806323b872dd146104cf575f80fd5b806313aad5101161036557806313aad5101461043657806318160ddd1461044c5780631ae409c0146104605780631c911f2b14610474575f80fd5b806306fdde031461038b578063095ea7b3146103b55780631371bb40146103e4575b5f80fd5b348015610396575f80fd5b5061039f610b01565b6040516103ac91906133df565b60405180910390f35b3480156103c0575f80fd5b506103d46103cf36600461342c565b610b91565b60405190151581526020016103ac565b3480156103ef575f80fd5b506104286103fe366004613454565b6001600160a01b039182165f90815260166020908152604080832093909416825291909152205490565b6040519081526020016103ac565b348015610441575f80fd5b5061044a610baa565b005b348015610457575f80fd5b50600254610428565b34801561046b575f80fd5b50600654610428565b34801561047f575f80fd5b5061044a61048e366004613485565b610bb4565b34801561049e575f80fd5b50601e54610428565b3480156104b2575f80fd5b50600c54610428565b3480156104c6575f80fd5b50610428610c03565b3480156104da575f80fd5b506103d46104e936600461349e565b610c26565b3480156104f9575f80fd5b50610428610508366004613485565b6001600160a01b03165f9081526015602052604090205490565b34801561052d575f80fd5b5061042861053c3660046134d7565b5f9081526008602052604090205490565b348015610558575f80fd5b50600b54610428565b34801561056c575f80fd5b506103d461057b36600461342c565b610c49565b34801561058b575f80fd5b50604051601281526020016103ac565b3480156105a6575f80fd5b5061044a6105b53660046134ee565b610cc6565b3480156105c5575f80fd5b5061044a6105d43660046134d7565b610cec565b3480156105e4575f80fd5b5061044a6105f33660046134d7565b610d61565b348015610603575f80fd5b5061044a610612366004613485565b610d93565b348015610622575f80fd5b5061044a6106313660046134d7565b610e07565b348015610641575f80fd5b5061044a610e45565b348015610655575f80fd5b5061044a6106643660046134d7565b610f57565b348015610674575f80fd5b506103d4610683366004613485565b6001600160a01b03165f908152601a602052604090205460ff1690565b3480156106ab575f80fd5b506104286106ba366004613454565b6001600160a01b039182165f9081526020808052604080832093909416825291909152205490565b3480156106ed575f80fd5b50601354610428565b348015610701575f80fd5b5061044a610710366004613485565b610f98565b61044a61072336600461353a565b610ff7565b348015610733575f80fd5b50601c54610428565b348015610747575f80fd5b506c01431e0fae6d7217caa0000000610428565b348015610766575f80fd5b5061044a6107753660046134d7565b6110dd565b348015610785575f80fd5b50610428610794366004613485565b6001600160a01b03165f9081526020819052604090205490565b3480156107b9575f80fd5b5061044a61117c565b3480156107cd575f80fd5b5061044a6107dc36600461342c565b61118d565b3480156107ec575f80fd5b5061044a6107fb3660046134d7565b6111b1565b34801561080b575f80fd5b5061044a61081a366004613485565b611242565b34801561082a575f80fd5b50600954610428565b61044a61084136600461355a565b6113a6565b348015610851575f80fd5b50600e54610428565b348015610865575f80fd5b5061039f6114c8565b348015610879575f80fd5b5061044a610888366004613591565b6114d7565b348015610898575f80fd5b506007546001600160601b0316610428565b3480156108b5575f80fd5b506103d46108c436600461342c565b6114fc565b3480156108d4575f80fd5b5061044a6108e33660046134d7565b611509565b3480156108f3575f80fd5b5061044a61152c565b348015610907575f80fd5b50610428610916366004613485565b6001600160a01b03165f9081526010602052604090205490565b34801561093b575f80fd5b50601f54610428565b34801561094f575f80fd5b5061096361095e36600461342c565b6116b1565b6040516103ac9190613681565b34801561097b575f80fd5b5042610428565b34801561098d575f80fd5b5061042861099c366004613454565b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205490565b3480156109d1575f80fd5b50600d54610428565b3480156109e5575f80fd5b507f0000000000000000000000000000000000000000000000000000000066ea7bfb610428565b348015610a17575f80fd5b50600f54610428565b348015610a2b575f80fd5b50601d54610428565b348015610a3f575f80fd5b50610428610a4e366004613485565b6001600160a01b03165f9081526014602052604090205490565b348015610a73575f80fd5b506019546040516001600160a01b0390911681526020016103ac565b348015610a9a575f80fd5b5061044a610aa9366004613485565b61179c565b348015610ab9575f80fd5b50600a54610428565b61044a610ad03660046134d7565b6117ad565b348015610ae0575f80fd5b50610af4610aef366004613485565b6117ef565b6040516103ac9190613690565b606060038054610b1090613700565b80601f0160208091040260200160405190810160405280929190818152602001828054610b3c90613700565b8015610b875780601f10610b5e57610100808354040283529160200191610b87565b820191905f5260205f20905b815481529060010190602001808311610b6a57829003601f168201915b5050505050905090565b5f33610b9e8185856118ff565b60019150505b92915050565b610bb2611a28565b565b610bbc611b4f565b6001600160a01b038116610be357604051633692283d60e21b815260040160405180910390fd5b6001600160a01b03165f908152601a60205260409020805460ff19169055565b5f600b54600a54600954610c17919061374c565b610c21919061374c565b905090565b5f33610c33858285611b7a565b610c3e858585611c04565b506001949350505050565b5f6001600160a01b038316610c7157604051633692283d60e21b815260040160405180910390fd5b335f818152602080805260408083206001600160a01b038816808552925280832086905551859391927ff8e109bcddf5e12132b7cd8a8517d97498f50c7ac595874d6f513243098b079891a450600192915050565b610cce611da6565b610cdb8585858585611dff565b610ce56001601755565b5050505050565b6019546001600160a01b03163314610d1757604051637b28105560e11b815260040160405180910390fd5b601b5460ff1615610d3b576040516371cad2dd60e11b815260040160405180910390fd5b601b805460ff19166001179055601954610d5e906001600160a01b031682611e4c565b50565b610d69611a28565b610d71611da6565b610d89335f610d8233856001611f09565b6001612133565b610d5e6001601755565b6018546001600160a01b03163314610dbe57604051637b28105560e11b815260040160405180910390fd5b6001600160a01b038116610de557604051633692283d60e21b815260040160405180910390fd5b601880546001600160a01b0319166001600160a01b0392909216919091179055565b610e0f611da6565b805f03610e2f57604051637133514760e11b815260040160405180910390fd5b610e393382612241565b610d89335f835f612133565b610e4d611a28565b610e55611da6565b5f610e5f60065490565b60625f5260086020527f3eae06187ba0198e7de2db0a13c35f0d744282a7db7e055bcdaaf6ee7879e66954909150811015610e9a5750610f4d565b610ea4606261236e565b601e548015610edf575f601e55601954610edf9073f19308f923582a6f7c465e5ce7a9dc1bec6665b19030906001600160a01b0316846123d7565b601f548015610f1a575f601f55601954610f1a907396a5399d07896f757bd4c6ef56461f58db9518629030906001600160a01b0316846123d7565b8082847f10c98735795e0571a6953e9af4a856a063c221909e07483422446ccbf710af4060405160405180910390a45050505b610bb26001601755565b610f5f611a28565b610f67611b4f565b801580610f75575061271081115b15610f9357604051637133514760e11b815260040160405180910390fd5b601d55565b6001600160a01b0381165f908152601a602052604090205460ff16610fd057604051630a5cfbdb60e11b815260040160405180910390fd5b610d5e81610ff2836001600160a01b03165f9081526020819052604090205490565b612241565b610fff611a28565b611007611da6565b335f908152601060205260409020546103e89061102590600161375f565b1115611044576040516335aabe6960e11b815260040160405180910390fd5b5f8261104f600e5490565b611059919061375f565b90505f61106560095490565b61107090600161375f565b90505f61109d33868661108b6007546001600160601b031690565b87876110988c60016124dc565b612513565b600c546110aa919061375f565b90506110c0828483600992909255600e55600c55565b6110cc8560015f6127ae565b5050506110d96001601755565b5050565b6110e5611a28565b6110ed611da6565b61110d7396a5399d07896f757bd4c6ef56461f58db9518623330846123d7565b80601f5f82825461111e919061375f565b909155505060065481906040517396a5399d07896f757bd4c6ef56461f58db951862815233907fc0eadb8b1414d09241a441cb47087f29af42c6b281bc64bc445a6aed0c9bff24906020015b60405180910390a4610d5e6001601755565b611184611b4f565b610bb25f61285c565b611195611a28565b61119d611da6565b6111a7828261287e565b6110d96001601755565b6111b9611a28565b6111c1611da6565b6111e173f19308f923582a6f7c465e5ce7a9dc1bec6665b13330846123d7565b80601e5f8282546111f2919061375f565b9091555050600654819060405173f19308f923582a6f7c465e5ce7a9dc1bec6665b1815233907fc0eadb8b1414d09241a441cb47087f29af42c6b281bc64bc445a6aed0c9bff249060200161116a565b61124a611b4f565b6001600160a01b03811661127157604051633692283d60e21b815260040160405180910390fd5b6040516301ffc9a760e01b80825260048201526001600160a01b038216906301ffc9a7906024016020604051808303815f875af11580156112b4573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112d89190613772565b158061134f57506040516301ffc9a760e01b815263663ca86f60e01b60048201526001600160a01b038216906301ffc9a7906024016020604051808303815f875af1158015611329573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061134d9190613772565b155b1561136d5760405163a3600d0960e01b815260040160405180910390fd5b601980546001600160a01b039092166001600160a01b0319909216821790555f908152601a60205260409020805460ff19166001179055565b6113ae611da6565b6113b6611a28565b815f036113d6576040516301742a3360e21b815260040160405180910390fd5b838310806113e2575083155b806113ed5750605883115b1561140b57604051634741150960e11b815260040160405180910390fd5b5f611418858585856128df565b90508015806114275750606481115b15611445576040516373c1ffd360e11b815260040160405180910390fd5b335f908152601060205260409020546103e89061146390839061375f565b1115611482576040516335aabe6960e11b815260040160405180910390fd5b5f61148e8760016124dc565b90506114b13388888888886114ab6007546001600160601b031690565b8861291e565b6114bc87835f6127ae565b5050610ce56001601755565b606060048054610b1090613700565b6114df611da6565b6114ec8484848433611dff565b6114f66001601755565b50505050565b5f33610b9e818585611c04565b611511611a28565b611519611da6565b610d8961152733835f611f09565b6129b0565b611534611a28565b61153c611da6565b601c545f81900361156057604051636d8af89f60e11b815260040160405180910390fd5b5f601c819055601d54620f4240906115789084613791565b61158291906137a8565b905061158e818361374c565b91506115b073f19308f923582a6f7c465e5ce7a9dc1bec6665b13033846123d7565b5f620186a06115c161271085613791565b6115cb91906137a8565b905080601e5f8282546115de919061375f565b909155505f9050620186a06115f5614e2086613791565b6115ff91906137a8565b905061163573f19308f923582a6f7c465e5ce7a9dc1bec6665b1307396a5399d07896f757bd4c6ef56461f58db951862846123d7565b6019546116779073f19308f923582a6f7c465e5ce7a9dc1bec6665b19030906001600160a01b031684611668878a61374c565b611672919061374c565b6123d7565b604051849033907f63be20cc905d5ba0cf65db405c4999f99f2575e521875f13a8009d6eed7a09d9905f90a350505050610bb26001601755565b6116b9613354565b6001600160a01b0383165f90815260116020908152604080832085845282528083205483526012825291829020825161010081018452815461ffff8116825260ff6201000082048116948301949094526001600160681b036301000000820481169583019590955265ffffffffffff600160801b820481166060840152600160b01b909104166080820152600182015480851660a0830152600160681b810490941660c082015292909160e0840191600160d01b9004166003811115611781576117816135c7565b6003811115611792576117926135c7565b9052509392505050565b6117a4611b4f565b610d5e8161285c565b6117b5611da6565b6117bd611a28565b5f806117c933846129da565b915091506117da81600160036127ae565b6117e3826129b0565b5050610d5e6001601755565b6001600160a01b0381165f908152601060205260409020546060908067ffffffffffffffff811115611823576118236137c7565b60405190808252806020026020018201604052801561185c57816020015b611849613398565b8152602001906001900390816118415790505b50915060015b8181116118f857604080516080810182528281526001600160a01b0386165f908152601160209081528382208583528082528483208054838601529286905290526001015491810191909152606081016118bc86846116b1565b9052836118ca60018461374c565b815181106118da576118da6137db565b602002602001018190525080806118f0906137ef565b915050611862565b5050919050565b6001600160a01b0383166119665760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b60648201526084015b60405180910390fd5b6001600160a01b0382166119c75760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b606482015260840161195d565b6001600160a01b038381165f8181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b6006545f62015180611a5a7f0000000000000000000000000000000000000000000000000000000066ea7bfb4261374c565b611a6491906137a8565b611a6f90600161375f565b9050818111156110d9576007546001600160601b03165f611a90848461374c565b90505f5b81811015611b2257620186a0611aad6201868485613791565b611ab791906137a8565b92506910f0cf064dd592000000831015611ad9576910f0cf064dd59200000092505b82611ae3866137ef565b60405190965086907f502806f7cf43435d83b251173d47f99095d52c72115be741aa35f763db4a8140905f90a380611b1a816137ef565b915050611a94565b5050600780546bffffffffffffffffffffffff19166001600160601b039290921691909117905560065550565b6005546001600160a01b03163314610bb257604051637550a7dd60e11b815260040160405180910390fd5b6001600160a01b038381165f908152600160209081526040808320938616835292905220545f1981146114f65781811015611bf75760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e6365000000604482015260640161195d565b6114f684848484036118ff565b6001600160a01b038316611c685760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b606482015260840161195d565b6001600160a01b038216611cca5760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b606482015260840161195d565b6001600160a01b0383165f9081526020819052604090205481811015611d415760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b606482015260840161195d565b6001600160a01b038481165f81815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a36114f6565b600260175403611df85760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640161195d565b6002601755565b835f03611e1f57604051637133514760e11b815260040160405180910390fd5b611e2a853386611b7a565b611e348383612d42565b611e3e8585612241565b610ce585858585855f612e55565b6001600160a01b038216611ea25760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015260640161195d565b8060025f828254611eb3919061375f565b90915550506001600160a01b0382165f81815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b6001600160a01b0383165f908152601160209081526040808320858452909152812054808203611f4c57604051632e914a1360e01b815260040160405180910390fd5b5f818152601260209081526040808320815161010081018352815461ffff8116825260ff6201000082048116958301959095526001600160681b036301000000820481169483019490945265ffffffffffff600160801b820481166060840152600160b01b909104166080820152600182015480841660a0830152600160681b810490931660c082015292909160e0840191600160d01b909104166003811115611ff857611ff86135c7565b6003811115612009576120096135c7565b905250905060018160e001516003811115612026576120266135c7565b036120445760405163130a46d560e21b815260040160405180910390fd5b60028160e00151600381111561205c5761205c6135c7565b0361207a57604051638c64dced60e01b815260040160405180910390fd5b60038160e001516003811115612092576120926135c7565b036120b0576040516351852dd960e11b815260040160405180910390fd5b42816080015165ffffffffffff161180156120db57505f8460018111156120d9576120d96135c7565b145b156120f957604051631cc0f42b60e01b815260040160405180910390fd5b80604001516001600160681b0316600c5f828254612117919061374c565b90915550612129905086838387612f5a565b9695505050505050565b6001600160a01b0384165f908152601460205260408120805484929061215a90849061375f565b925050819055508160135f828254612172919061375f565b90915550506001600160a01b038316156121ee576001600160a01b0383165f90815260156020526040812080548492906121ad90849061375f565b90915550506001600160a01b038084165f908152601660209081526040808320938816835292905290812080548492906121e890849061375f565b90915550505b826001600160a01b0316846001600160a01b03167f083dcb7ef00c446abbb046896579428741dad18e02f48b3b9706129ee06707a38484604051612233929190613807565b60405180910390a350505050565b6001600160a01b0382166122a15760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b606482015260840161195d565b6001600160a01b0382165f90815260208190526040902054818110156123145760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b606482015260840161195d565b6001600160a01b0383165f818152602081815260408083208686039055600280548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9101611a1b565b505050565b5f818152600860205260409020546006548181106123695782612391838361374c565b61239b91906137a8565b6123a690600161375f565b6123b09084613791565b5f84815260086020526040812080549091906123cd90849061375f565b9091555050505050565b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291515f9283929088169161243a919061382b565b5f604051808303815f865af19150503d805f8114612473576040519150601f19603f3d011682016040523d82523d5f602084013e612478565b606091505b50915091508180156124a25750805115806124a25750808060200190518101906124a29190613772565b6124d45760405162461bcd60e51b815260206004820152600360248201526229aa2360e91b604482015260640161195d565b505050505050565b5f612710826124f8856c01431e0fae6d7217caa0000000613791565b6125029190613791565b61250c91906137a8565b9392505050565b5f8515806125215750605886115b1561253f5760405163ad314fd960e01b815260040160405180910390fd5b86158061254d575061271087115b1561256b5760405163282d398b60e11b815260040160405180910390fd5b612576878787613150565b90505f6040518061010001604052808961ffff1681526020018860ff168152602001836001600160681b031681526020014265ffffffffffff16815260200162015180896125c49190613791565b6125ce904261375f565b65ffffffffffff1681525f602082018190526001600160681b03861660408301526060909101526001600160a01b038a165f90815260106020526040812080549293509091829061261e906137ef565b91829055506001600160a01b038b165f908152601160209081526040808320848452825280832089815560019081018b90558984526012835292819020865181549388015192880151606089015160808a015161ffff90931662ffffff19909616959095176201000060ff909516949094029390931775ffffffffffffffffffffffffffffffffffffff000000191663010000006001600160681b039485160265ffffffffffff60801b191617600160801b65ffffffffffff958616021765ffffffffffff60b01b1916600160b01b949091169390930292909217825560a0860151928201805460c08801519483166001600160d01b031990911617600160681b94909216939093021780835560e0860151939450859391929060ff60d01b1916600160d01b836003811115612756576127566135c7565b021790555090505085858b6001600160a01b03167fa695be83040d0421ae4df4376ee65ef8a31c127f7115482b231953ec35869a07856040516127999190613681565b60405180910390a45050979650505050505050565b5f6127b984846124dc565b905060038260038111156127cf576127cf6135c7565b036127f157620186a06127e461c35083613791565b6127ee91906137a8565b90505b61281173f19308f923582a6f7c465e5ce7a9dc1bec6665b13330846123d7565b80601c5f828254612822919061375f565b9091555050600654819060405133907fd833e83f161e4ddfb1306cdf11a374a0a23393f008f9394b85999b988c232e36905f90a450505050565b600580546001600160a01b0319166001600160a01b0392909216919091179055565b612887826131c1565b6128915f80612d42565b5f61289e83836001611f09565b6018549091506128d0906001600160a01b0316620186a06128c184611f40613791565b6128cb91906137a8565b611e4c565b61236983825f80336001612e55565b5f848411156129165781836128f4878761374c565b6128fe91906137a8565b61290990600161375f565b6129139190613791565b90505b949350505050565b600e54600954600c545b87891161298f575f5b8681101561297d576129438b8561375f565b935061295f8c8c8c8988612956896137ef565b9850888b612513565b612969908361375f565b915080612975816137ef565b915050612931565b50612988878a61375f565b9850612928565b6129a3828483600992909255600e55600c55565b5050505050505050505050565b6129ba3382611e4c565b601854610d5e906001600160a01b0316620186a06128c184611f40613791565b6001600160a01b0382165f9081526011602090815260408083208484529091528120548190808203612a1f57604051632e914a1360e01b815260040160405180910390fd5b5f818152601260209081526040808320815161010081018352815461ffff8116825260ff6201000082048116958301959095526001600160681b036301000000820481169483019490945265ffffffffffff600160801b820481166060840152600160b01b909104166080820152600182015480841660a0830152600160681b810490931660c082015292909160e0840191600160d01b909104166003811115612acb57612acb6135c7565b6003811115612adc57612adc6135c7565b905250905060018160e001516003811115612af957612af96135c7565b03612b175760405163130a46d560e21b815260040160405180910390fd5b60028160e001516003811115612b2f57612b2f6135c7565b03612b4d57604051638c64dced60e01b815260040160405180910390fd5b60038160e001516003811115612b6557612b656135c7565b03612b83576040516351852dd960e11b815260040160405180910390fd5b5f62015180826060015165ffffffffffff1642612ba0919061374c565b612baa91906137a8565b905042826080015165ffffffffffff16111580612bc75750600381105b15612be5576040516305d8f6dd60e01b815260040160405180910390fd5b5f838152601260209081526040808320600101805460ff60d01b1916600360d01b179055840151908401516001600160681b03909116919060ff16612c2a8484613791565b612c3491906137a8565b90505f620186a0612c4761c35085613791565b612c5191906137a8565b905080821115612c5f578091505b5f86815260126020526040812060010180546cffffffffffffffffffffffffff19166001600160681b038516179055600c8054859290612ca090849061374c565b90915550612cb09050828461374c565b600d5f828254612cc0919061375f565b9091555050600f80545f90612cd4906137ef565b90915550845191975061ffff90911695508690612cf1828461374c565b868b6001600160a01b03167f0a4a5a6b9bb9ce91ec0775f7273d9386e58600280767378ff02bb28b0e3202458b604051612d2d91815260200190565b60405180910390a45050505050509250929050565b6008612d4e838361375f565b1115612d6d57604051630cb7a9ff60e01b815260040160405180910390fd5b6040516301ffc9a760e01b808252600482015233906301ffc9a790602401602060405180830381865afa158015612da6573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612dca9190613772565b1580612e3757506040516301ffc9a760e01b81526311686e4b60e21b600482015233906301ffc9a790602401602060405180830381865afa158015612e11573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612e359190613772565b155b156110d95760405163a3600d0960e01b815260040160405180910390fd5b612e6186338784612133565b5f808415612e9c57612e77620186a06064613791565b620186a0612e85878a613791565b612e8f9190613791565b612e9991906137a8565b91505b8515612ed557612eb0620186a06064613791565b620186a0612ebe888a613791565b612ec89190613791565b612ed291906137a8565b90505b8115612ee557612ee58483611e4c565b8015612ef557612ef58882611e4c565b6040516311686e4b60e21b81526001600160a01b03891660048201526024810188905233906345a1b92c906044015f604051808303815f87803b158015612f3a575f80fd5b505af1158015612f4c573d5f803e3d5ffd5b505050505050505050505050565b5f80826001811115612f6e57612f6e6135c7565b03612f95575f848152601260205260409020600101805460ff60d01b1916600160d01b1790555b6001826001811115612fa957612fa96135c7565b03612fd0575f848152601260205260409020600101805460ff60d01b1916600160d11b1790555b5f80846080015165ffffffffffff1642111561300957613006856080015165ffffffffffff1642613001919061374c565b613240565b90505b60408501516001600160681b031660646130238383613791565b61302d91906137a8565b9250613039838261374c565b93505f85600181111561304e5761304e6135c7565b0361306657600a5f8154613061906137ef565b909155505b600185600181111561307a5761307a6135c7565b0361309257600b5f815461308d906137ef565b909155505b82156130af5782600d5f8282546130a9919061375f565b90915550505b5f8560018111156130c2576130c26135c7565b036130f7575f87815260126020526040902060010180546cffffffffffffffffffffffffff19166001600160681b0386161790555b8187896001600160a01b03167fbd866a3fbf35e201f790e87581b1afbb3165e879df5d35313a4875a70b9f3b36878760405161313d929190918252602082015260400190565b60405180910390a4505050949350505050565b5f808361315d8685613791565b6131679190613791565b9050836001146131ac57620186a061318060018661374c565b61318b606e84613791565b6131959190613791565b61319f91906137a8565b6131a9908261374c565b90505b6131b8612710826137a8565b95945050505050565b6001600160a01b0381165f908152602080805260408083203384529091529020545f1981146110d957805f0361320a576040516301fb15f960e31b815260040160405180910390fd5b6001600160a01b0382165f908152602080805260408083203384529091528120805490919061323890613846565b909155505050565b5f61324f620151806007613791565b821161325c57505f919050565b6201518061326c6007600161375f565b6132769190613791565b821161328457506001919050565b620151806132946007600261375f565b61329e9190613791565b82116132ac57506003919050565b620151806132bc6007600361375f565b6132c69190613791565b82116132d457506008919050565b620151806132e46007600461375f565b6132ee9190613791565b82116132fc57506011919050565b6201518061330c6007600561375f565b6133169190613791565b821161332457506023919050565b620151806133346007600661375f565b61333e9190613791565b821161334c57506048919050565b506063919050565b60408051610100810182525f80825260208201819052918101829052606081018290526080810182905260a0810182905260c081018290529060e08201905b905290565b60405180608001604052805f81526020015f81526020015f8152602001613393613354565b5f5b838110156133d75781810151838201526020016133bf565b50505f910152565b602081525f82518060208401526133fd8160408501602087016133bd565b601f01601f19169190910160400192915050565b80356001600160a01b0381168114613427575f80fd5b919050565b5f806040838503121561343d575f80fd5b61344683613411565b946020939093013593505050565b5f8060408385031215613465575f80fd5b61346e83613411565b915061347c60208401613411565b90509250929050565b5f60208284031215613495575f80fd5b61250c82613411565b5f805f606084860312156134b0575f80fd5b6134b984613411565b92506134c760208501613411565b9150604084013590509250925092565b5f602082840312156134e7575f80fd5b5035919050565b5f805f805f60a08688031215613502575f80fd5b61350b86613411565b945060208601359350604086013592506060860135915061352e60808701613411565b90509295509295909350565b5f806040838503121561354b575f80fd5b50508035926020909101359150565b5f805f805f60a0868803121561356e575f80fd5b505083359560208501359550604085013594606081013594506080013592509050565b5f805f80608085870312156135a4575f80fd5b6135ad85613411565b966020860135965060408601359560600135945092505050565b634e487b7160e01b5f52602160045260245ffd5b600481106135eb576135eb6135c7565b9052565b61ffff815116825260ff60208201511660208301526001600160681b036040820151166040830152606081015165ffffffffffff8082166060850152806080840151166080850152505060a081015161365360a08401826001600160681b03169052565b5060c081015161366e60c08401826001600160681b03169052565b5060e081015161236960e08401826135db565b6101008101610ba482846135ef565b602080825282518282018190525f919060409081850190868401855b828110156136f35781518051855286810151878601528581015186860152606090810151906136dd818701836135ef565b50506101609390930192908501906001016136ac565b5091979650505050505050565b600181811c9082168061371457607f821691505b60208210810361373257634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52601160045260245ffd5b81810381811115610ba457610ba4613738565b80820180821115610ba457610ba4613738565b5f60208284031215613782575f80fd5b8151801515811461250c575f80fd5b8082028115828204841417610ba457610ba4613738565b5f826137c257634e487b7160e01b5f52601260045260245ffd5b500490565b634e487b7160e01b5f52604160045260245ffd5b634e487b7160e01b5f52603260045260245ffd5b5f6001820161380057613800613738565b5060010190565b828152604081016002831061381e5761381e6135c7565b8260208301529392505050565b5f825161383c8184602087016133bd565b9190910192915050565b5f8161385457613854613738565b505f19019056fea264697066735822122027b6d5c3dbb94d275b5dbfa3e47907441fadf2e70216925877ef9b3ac05e5e8364736f6c63430008150033

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

000000000000000000000000b8a03f9cb2f5e5692cb0b64378ddce843fbfa47b000000000000000000000000fef10de0823f58df4f5f24856ab4274ededa6a5c

-----Decoded View---------------
Arg [0] : genesisAddress (address): 0xb8a03F9CB2F5E5692cB0b64378ddce843FbFa47B
Arg [1] : buyAndBurnAddress (address): 0xfEF10De0823F58DF4f5F24856aB4274EdeDa6A5c

-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000b8a03f9cb2f5e5692cb0b64378ddce843fbfa47b
Arg [1] : 000000000000000000000000fef10de0823f58df4f5f24856ab4274ededa6a5c


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.