ETH Price: $3,390.44 (+0.99%)

Contract

0xc5d5B9F30AA674aA210a0ec24941bAd7D8b42069
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Token Holdings

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Create Share Pro...215018562024-12-28 15:27:473 hrs ago1735399667IN
0xc5d5B9F3...7D8b42069
0 ETH0.007108546.3471308
Create Share Pro...215018402024-12-28 15:24:353 hrs ago1735399475IN
0xc5d5B9F3...7D8b42069
0 ETH0.007129036.43611183
Vote215016322024-12-28 14:42:593 hrs ago1735396979IN
0xc5d5B9F3...7D8b42069
0 ETH0.004335947.12059304
Propose New Hard...215016292024-12-28 14:42:233 hrs ago1735396943IN
0xc5d5B9F3...7D8b42069
0 ETH0.003101347.3415924
Increase Vote Po...215016262024-12-28 14:41:473 hrs ago1735396907IN
0xc5d5B9F3...7D8b42069
0 ETH0.000630917.09649421
Vote215016022024-12-28 14:36:593 hrs ago1735396619IN
0xc5d5B9F3...7D8b42069
0 ETH0.003625955.95461962
Propose New Hard...215015952024-12-28 14:35:353 hrs ago1735396535IN
0xc5d5B9F3...7D8b42069
0 ETH0.002586056.12177734
Increase Vote Po...215015902024-12-28 14:34:353 hrs ago1735396475IN
0xc5d5B9F3...7D8b42069
0 ETH0.000565126.35648117
Create Share Pro...215015152024-12-28 14:19:354 hrs ago1735395575IN
0xc5d5B9F3...7D8b42069
0 ETH0.007254876.34189483
Vote215010752024-12-28 12:50:595 hrs ago1735390259IN
0xc5d5B9F3...7D8b42069
0 ETH0.001241565.18337232
Create Share Pro...215010732024-12-28 12:50:355 hrs ago1735390235IN
0xc5d5B9F3...7D8b42069
0 ETH0.005726155.06624291
Vote215010722024-12-28 12:50:235 hrs ago1735390223IN
0xc5d5B9F3...7D8b42069
0 ETH0.002414413.96501003
Propose New Hard...215010692024-12-28 12:49:475 hrs ago1735390187IN
0xc5d5B9F3...7D8b42069
0 ETH0.001791874.24165862
Propose New Hard...215010692024-12-28 12:49:475 hrs ago1735390187IN
0xc5d5B9F3...7D8b42069
0 ETH0.001985475.08033162
Increase Vote Po...215010672024-12-28 12:49:235 hrs ago1735390163IN
0xc5d5B9F3...7D8b42069
0 ETH0.000388274.36731818
Vote215008872024-12-28 12:13:116 hrs ago1735387991IN
0xc5d5B9F3...7D8b42069
0 ETH0.002984154.90064142
Propose New Hard...215008832024-12-28 12:12:236 hrs ago1735387943IN
0xc5d5B9F3...7D8b42069
0 ETH0.002044534.83988067
Increase Vote Po...215008802024-12-28 12:11:476 hrs ago1735387907IN
0xc5d5B9F3...7D8b42069
0 ETH0.00045115.07397781
Create Share Pro...215006702024-12-28 11:29:237 hrs ago1735385363IN
0xc5d5B9F3...7D8b42069
0 ETH0.005003254.46739583
Create Share Pro...215001272024-12-28 9:40:238 hrs ago1735378823IN
0xc5d5B9F3...7D8b42069
0 ETH0.004652394.08216282
Create Share Pro...214994422024-12-28 7:22:5911 hrs ago1735370579IN
0xc5d5B9F3...7D8b42069
0 ETH0.004276653.81857069
Vote214993722024-12-28 7:08:5911 hrs ago1735369739IN
0xc5d5B9F3...7D8b42069
0 ETH0.002687534.41352257
Propose New Hard...214993692024-12-28 7:08:2311 hrs ago1735369703IN
0xc5d5B9F3...7D8b42069
0 ETH0.001993284.71869832
Increase Vote Po...214993612024-12-28 7:06:4711 hrs ago1735369607IN
0xc5d5B9F3...7D8b42069
0 ETH0.000461635.19250641
Create Share Pro...214993382024-12-28 7:01:5911 hrs ago1735369319IN
0xc5d5B9F3...7D8b42069
0 ETH0.004890074.22724052
View all transactions

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
HyperCycleShareManagerV2

Compiler Version
v0.8.26+commit.8a97fa7a

Optimization Enabled:
Yes with 200 runs

Other Settings:
paris EvmVersion
File 1 of 22 : HyperCycleShareManagerV2.sol
// SPDX-License-Identifier: MIT
/*
Version 1 of the HyperCycle Share Manager contract.
*/

pragma solidity 0.8.26;

import {Context} from '@openzeppelin/contracts/utils/Context.sol';
import "@openzeppelin/contracts/access/Ownable.sol";
import {ERC721Holder} from '@openzeppelin/contracts/token/ERC721/utils/ERC721Holder.sol';
import {ERC1155Holder} from '@openzeppelin/contracts/token/ERC1155/utils/ERC1155Holder.sol';
import {ShareManagerErrors as Errors} from '../libs/ShareManagerErrorsV2.sol';
import {ShareManagerEvents as Events} from '../libs/ShareManagerEventsV2.sol';
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import {ShareManagerTypes as Types, IHYPCSwapV2, IHyperCycleLicense, IHyperCycleShareTokensV2, IHYPC} from '../libs/ShareManagerTypesV2.sol';

/**
@title HyperCycle Share ManagerV2, revenue sharing manager.
@author Barry Rowe, Rodolfo Cova
@notice HyperCycle is a network of AI computation nodes offering different AI services in a 
    decentralized manner. In this system, there are license holders, token holders, hardware
    operators, and AI developers. Using the HyperCycleSwapV2 contract, an amount of HyPC (erc20)
    can be swapped for a cHyPC (containerized HyPC) token, which can then point towards a
    license (HyperCycleLicense) NFT id. At this point, the owner of this license can assign
    their license to some hardware running the HyperCycle Node Manager, and can from then
    on accept AI service requests on the network. 

    The HyperCycle Share Manager (This contract) allows the chypc owner to create a revenue sharing proposal, 
    to understand in deep the Share Token Contract, please refer to he Share Token Contract 
    documentation, See {HyperCycleShareTokensV2}.

    The main idea of the Share Manager is to be the one holding and managing the Share Token,
    being able to use the same benefits of the Share Tokens and extend it with the votations that
    share token holders can execute for the Share.

    To create a Share Proposal with the Share Manager, the chypc owner needs to call 
    `createShareProposal` function, this function will create a new Share Proposal and transfer
    the chypc to the Share Manager, the Share Manager will be the one holding the chypc until
    the Share Proposal is ended, in case the Share Proposal is ended, the chypc will be redeemed
    into hypc tokens, in which the share holders will be able to claim the proportional amount
    of share tokens to hypc tokens.

    The Share Proposal will be created with the following data:
        - CHyPC Data: CHyPC Id, CHyPC Owner, CHyPC Level, Initial Revenue Tokens, Initial Wealth Tokens
        - License Data: License Number, License Owner, License Level, Initial Revenue Tokens, Initial Wealth Tokens
        - Operator Data: Operator Revenue, Operator Assigned String, Operator Address
        - Share Token Data: Share Token Number, Revenue Deposit Delay, Revenue Token Id, Wealth Token Id, Valid End Timestamp
        - Status: Pending
    
    The Share Proposal can have the following status in the entire lifecycle of the Share Proposal:
        - Pending: The Share Proposal is created and waiting for the CHyPC NFT to be transfered to the Share Manager
        - Started: The Share Proposal is started and the Share Tokens are created, the CHyPC NFT is transfered to the Share Manager
        - Ended: The Share Proposal is ended and the license is transfered to the License Owner, 
                the CHyPC NFT will be redeem for HyPC tokens and will be claimable by the Share Token Holders.

    The Share Manager contract had a DAO system where share token holderes can be able to create votations to change 
    the hardware operator, the hardware operator revenue, the manager contract and to cancel the share proposal, 
    the votations will be created by the Share Manager and the share token holders will be able to vote.

    The Share Proposal can be ended by the share token holders any time the consensus is reached, for this 100% or 90% (depends on the
    actual `SELECTED_VOTATION_PORCENT`) of the wealth tokens needs to be voted to end the Share Proposal, in case the Share Proposal is 
    ended, the ending process will be executed.

    The Share Manager contract can be changed by the share token holders any time the consensus is reached, for this 100% of the wealth tokens
    needs to be voted to change the Share Manager, in case the Share Manager is changed,  the transfer of the Share Token Ownership will be executed.

    The Hardware Operator can be changed by the share token holders any time the consensus is reached, for this 50% of the wealth tokens
    needs to be voted to change the Hardware Operator, in case the Hardware Operator is changed, the Operator Revenue will be transfered
    to the older operator and the new operator will be set.

    The Hardware Operator Revenue can be changed by the share token holders any time the consensus is reached, 
    for this 50% of the wealth tokens needs to be voted to change the Hardware Operator Revenue, 
    in case the Hardware Operator Revenue is changed, the new operator revenue will be set.

    Another important feature of the Share Manager is the ability to migrate the Share Tokens from the Share Tokens contract
    to the Share Manager, this will allow the Share Manager to be the one holding the Share Tokens and be able to manage the Share
    Proposal and Votations. The Share Manager will be able to claim the Hypc tokens, based in the amount of wealth tokens available, 
    in case the Share Proposal is ended and the CHyPC exists.

    To migrate the Share Tokens to the Share Manager contract, the Share Token owner needs to call `startShareProposalMigration` function,
    this function will start the migration and the Share Manager contract will be able to finish the migration only if the ownership
    of the share token is changed to the Share Manager contract, and the Share Proposal is pending.
*/

contract HyperCycleShareManagerV2 is ERC721Holder, ERC1155Holder, ReentrancyGuard, Context {
    Types.ManagerData private managerData;

    uint256 public sharesProposalsCounter = 1;

    uint256 constant ONE_HUNDRED_PERCENT = 1e18;
    uint256 constant SIX_DECIMALS = 1e6;

    uint256 constant MAX_REVENUE_DELAY = 14 days;

    uint256 public SELECTED_VOTATION_PERCENT;
    uint256 public maxVotationDuration;

    mapping(uint256 shareProposalId => mapping(address user => uint256)) private _votePower;

    mapping(uint256 shareProposalId => mapping(uint256 votationIndex =>mapping(address user => bool))) private _voted;

    
    mapping(uint256 shareProposalId => mapping(address user => uint256)) public _lastVotationCreated;

    mapping(uint256 shareProposalId => mapping(address user => uint256)) private _votedFreeTime;

    mapping(uint256 shareProposalId => Types.Votation[]) private _votations;
  
    mapping(uint256 shareProposalId => Types.ShareProposalData) private _shareProposals;

    mapping(uint256 shareProposalId => bool) private shareCancelled;

    mapping(uint256 shareTokenNumber => uint256) public shareTokenExists;

    modifier onlyVoter(uint256 shareProposalId) {
        if (_votePower[shareProposalId][_msgSender()] == 0) revert Errors.NotEnoughWealthTokensAvailable();   
        _;
    }

    modifier validVoter(uint256 shareProposalId) {
        if (_votePower[shareProposalId][_msgSender()] == 0) revert Errors.NotEnoughWealthTokensAvailable();
        if (_shareProposals[shareProposalId].status != Types.ShareProposalStatus.STARTED) revert Errors.ShareProposalMustBeActive();
        if (_lastVotationCreated[shareProposalId][_msgSender()] > block.timestamp - 2 hours) revert Errors.VotationCreatedTooSoon();
         _;
    }

    modifier validVotation(uint256 shareProposalId, uint256 votationIndex) {
        if (_votations[shareProposalId].length <= votationIndex) {
            revert Errors.InvalidVotation();
        }
        _;
    }

    modifier onlyCHyPCOwner(uint256 shareProposalId) {
        if (_shareProposals[shareProposalId].chypcData.tokenOwner != _msgSender()) revert Errors.InvalidCHYPCOwner();
        _;
    }

    modifier onlyLicenseOwner(uint256 licenseNumber) {
        if (managerData.licenseContract.ownerOf(licenseNumber) != _msgSender()) revert Errors.InvalidLicenseOwner();
        _;
    }

    modifier proposalActive(uint256 shareProposalId) {
        if (_shareProposals[shareProposalId].status != Types.ShareProposalStatus.STARTED) {
            revert Errors.ShareProposalMustBeActive();
        }
        _;
    }

    modifier isHardwareOperator(uint256 shareProposalId) {
        if (_shareProposals[shareProposalId].operatorData.operatorAddress != _msgSender()) {
            revert Errors.MustBeClaimedByHardwareOperatorAddress();
        }
        _;
    }

    modifier validProposedDeadline(uint256 shareProposalId, uint256 deadline) {
        if (deadline <= block.timestamp+1 days) revert Errors.InvalidDeadline();
        if (_votations[shareProposalId].length > 0 && _votations[shareProposalId][_votations[shareProposalId].length-1].deadline > deadline) revert Errors.DeadlineMustBeIncreasing();
        if (deadline - block.timestamp > maxVotationDuration) revert Errors.DeadlineTooLate();
        _;
    }

    /**
    @dev The constructor takes in the contract addresses for the HyPC token, license, cHyPC NFTs and Share Tokens contract.
    @param _consensusOption: The consensus option to be used for the votations.
    @param _hypcToken: The HyPC ERC20 contract address.
    @param _chypcV2: The cHyPC ERC721 contract address.
    @param _licenseContract: The license ERC721 contract address.
    @param _hypcShareTokens: The license ERC721 contract address.
    */
    constructor(Types.ConsensusOptions _consensusOption, address _hypcToken, address _chypcV2, address _licenseContract, 
                address _hypcShareTokens, uint256 _maxVotingTime) {
        if (_hypcToken == address(0)) revert Errors.InvalidHYPCTokenAddress();

        if (_chypcV2 == address(0)) revert Errors.InvalidCHYPCAddress();

        if (_licenseContract == address(0)) revert Errors.InvalidLicenseAddress();

        if (_hypcShareTokens == address(0)) revert Errors.InvalidShareTokenContract();

        if (_maxVotingTime < 1 days || _maxVotingTime > 14 days) revert Errors.InvalidVotingDuration();

        maxVotationDuration = _maxVotingTime;

        _consensusOption == Types.ConsensusOptions.ONE_HUNDRED_PERCENT ?
            SELECTED_VOTATION_PERCENT = ONE_HUNDRED_PERCENT :
            SELECTED_VOTATION_PERCENT = ONE_HUNDRED_PERCENT * 9 / 10;

        managerData = Types.ManagerData({
            hypcToken: IHYPC(_hypcToken),
            chypcV2: IHYPCSwapV2(_chypcV2),
            licenseContract: IHyperCycleLicense(_licenseContract),
            hypcShareTokens: IHyperCycleShareTokensV2(_hypcShareTokens)
       });
    }

    // Share proposal management functions

    /**
    @notice Allows a user to create a new share.
    @param proposalData The encoded data needed to create a new share proposal, should have encoded: 
                        (uint256,uint256,uint256,uint256,uint256,string,address,bool,bool).
    @notice chypcId: should be the license number to be used for the share.
    @notice revenueToAssignToChypc: should be the amount of revenue tokens to be assigned to the chypc owner.
    @notice wealthToAssignToChypc: should be the amount of wealth tokens to be assigned to the chypc owner.
    @notice revenueDepositDelay: should be the amount of time in seconds that the revenue tokens will be locked.
    @notice licenseNumber: the license number to user for the proposal. If 0, then proposal will wait for a license owner to complete it.
    @notice operatorAssignedString: should be the string to be used as the operator assigned string for the share.
    @notice hardwareOperator: should be the address of the hardware operator to be used for the share.
    */
    function createShareProposal(bytes memory proposalData) external nonReentrant {
        (
            uint256 chypcId,
            uint256 revenueToAssignToChypc,
            uint256 wealthToAssignToChypc,
            uint256 revenueDepositDelay,
            uint256 licenseNumber,
            string memory operatorAssignedString,
            address hardwareOperator
        ) = abi.decode(proposalData, (uint256, uint256, uint256, uint256, uint256, string, address));

        uint256 chypcLevel = managerData.chypcV2.getTokenLevel(chypcId);

        if (managerData.chypcV2.ownerOf(chypcId) != _msgSender()) revert Errors.InvalidCHYPCOwner();

        if (hardwareOperator == address(0)) revert Errors.InvalidProposedAddress();

        if (revenueDepositDelay > MAX_REVENUE_DELAY) revert Errors.InvalidDepositRevenueDelay();

        if (
            revenueToAssignToChypc > (1 << chypcLevel) * 7 / 10 ||
            wealthToAssignToChypc > (1 << chypcLevel)
        ) revert Errors.InvalidTokenAmount();

        // @dev We don't want one person to be able to cancel a share themselves off the bat, so
        //      we prevent the creator from getting >= 90% or <= 10% (the acceptor getting 90%),
        //      in the case of 90% consensus.
        // @dev Due to division by ONE_HUNDRED_PERCENT rounds down, the second condition needs + 1.
        //      For example, totalSupply = 524288, 90%, gives 471859.2 -> 471859 as the required
        //      votes to pass. But 524288*1/10 = 52428.8 -> 52428, so if wealthToAssignToChypc is
        //      52429, then this condition would pass, but 524288-52429 = 471859, which would be
        //      enough to pass a cancel share proposal by the other user, which we want to avoid.
        //      Adding 1 to the second condition addresses this.
        if (wealthToAssignToChypc >= (1<<chypcLevel) * SELECTED_VOTATION_PERCENT/ONE_HUNDRED_PERCENT || 
            wealthToAssignToChypc <= (1<<chypcLevel) * (ONE_HUNDRED_PERCENT-SELECTED_VOTATION_PERCENT)/ONE_HUNDRED_PERCENT + 1) {
            revert Errors.InvalidTokenAmount();

        }

        uint256 shareProposalId = sharesProposalsCounter++;

        Types.ShareProposalData storage shareProposal = _shareProposals[shareProposalId];
  
        // @dev  operatorRevenue: (1 << chypcLevel) * 2 * SIX_DECIMALS / 10,
        //       but is simplified to reduce the contract size. 
        shareProposal.operatorData = Types.HardwareOperatorData({
            operatorRevenue: (1 << chypcLevel) * 200000,
            operatorAssignedString: operatorAssignedString,
            operatorAddress: hardwareOperator
        });

        shareProposal.status = Types.ShareProposalStatus.PENDING;

        shareProposal.chypcData = Types.TokenHolderData({
            tokenNumber: chypcId,
            tokenOwner: _msgSender(),
            tokenLevel: chypcLevel,
            initialRevenueTokens: revenueToAssignToChypc,
            initialWealthTokens: wealthToAssignToChypc
        });

        shareProposal.shareTokenData.revenueDepositDelay = revenueDepositDelay;

        managerData.chypcV2.safeTransferFrom(_msgSender(), address(this), chypcId);

        if (licenseNumber != 0) {
            if (managerData.licenseContract.ownerOf(licenseNumber) != _msgSender()) revert Errors.InvalidLicenseOwner();

            _completeProposal(shareProposalId, licenseNumber);
        }

        emit Events.ShareProposalCreated(shareProposalId);
    }

    /// @notice Allows the owner of the cHyPC to cancel a pending share proposal.
    /// @param shareProposalId the share proposal Id to be cancelled.
    function cancelPendingShareProposal(uint256 shareProposalId) external nonReentrant onlyCHyPCOwner(shareProposalId) {
        if (_shareProposals[shareProposalId].status != Types.ShareProposalStatus.PENDING)
            revert Errors.ShareProposalIsNotPending();

        _endShareProposal(shareProposalId);
    }

    /// @notice Allows the owner of the License to complete a pending share proposal.
    /// @param shareProposalId The share proposal Id to be used to complete the share.
    /// @param licenseNumber The License NFT id to be used to start the share.
    function completeShareProposal(uint256 shareProposalId, uint256 licenseNumber) external nonReentrant onlyLicenseOwner(licenseNumber) {
        if (_shareProposals[shareProposalId].status != Types.ShareProposalStatus.PENDING)
            revert Errors.ShareProposalIsNotPending();

        _completeProposal(shareProposalId, licenseNumber);
    }

    /// @notice Internal function to allow the License NFT owner to complete a pending share proposal.
    /// @param shareProposalId The share proposal Id to be used to complete the share.
    /// @param licenseNumber The License NFT id to be used to start the share.
    function _completeProposal(uint256 shareProposalId, uint256 licenseNumber) private {
        Types.ShareProposalData storage shareProposal = _shareProposals[shareProposalId];

        uint256 licenseLevel = managerData.licenseContract.getLicenseHeight(licenseNumber);
        uint256 totalSupply = 1 << shareProposal.chypcData.tokenLevel;

        if (licenseLevel != shareProposal.chypcData.tokenLevel)
            revert Errors.TokenLevelMismatch();

        shareProposal.status = Types.ShareProposalStatus.STARTED;

        shareProposal.licenseData = Types.TokenHolderData({
            tokenNumber: licenseNumber,
            tokenOwner: _msgSender(),
            tokenLevel: licenseLevel,
            initialRevenueTokens: (totalSupply * 7 / 10) - shareProposal.chypcData.initialRevenueTokens,
            initialWealthTokens: totalSupply - shareProposal.chypcData.initialWealthTokens
        });

        uint256 currentShareNumber = managerData.hypcShareTokens.currentShareNumber();
        shareTokenExists[currentShareNumber] = shareProposalId;

        shareProposal.shareTokenData = Types.ShareTokenData({
            shareTokenNumber: currentShareNumber,
            revenueDepositDelay: shareProposal.shareTokenData.revenueDepositDelay,
            rTokenId: currentShareNumber << 1,
            wTokenId: (currentShareNumber << 1) + 1,
            validEndTimestamp: block.timestamp + 1 days
        });

        managerData.licenseContract.safeTransferFrom(_msgSender(), address(this), licenseNumber);

        managerData.licenseContract.approve(
            address(managerData.hypcShareTokens),
            licenseNumber
        );

        managerData.chypcV2.approve(address(managerData.hypcShareTokens), shareProposal.chypcData.tokenNumber);

        managerData.hypcShareTokens.createShareTokens(
            licenseNumber,
            shareProposal.chypcData.tokenNumber,
            true,
            shareProposal.operatorData.operatorAssignedString,
            shareProposal.shareTokenData.revenueDepositDelay
        );

        _sendRevenueAndWealthTokens(
            shareProposal.licenseData.tokenOwner,
            shareProposal.shareTokenData.rTokenId,
            shareProposal.shareTokenData.wTokenId,
            shareProposal.licenseData.initialRevenueTokens,
            shareProposal.licenseData.initialWealthTokens
        );

        _sendRevenueAndWealthTokens(
            shareProposal.chypcData.tokenOwner,
            shareProposal.shareTokenData.rTokenId,
            shareProposal.shareTokenData.wTokenId,
            shareProposal.chypcData.initialRevenueTokens,
            shareProposal.chypcData.initialWealthTokens
        );

        emit Events.ShareProposalStarted(shareProposalId);
    }

    /// @notice Private function to send the share proposal tokens
    /// @param to address to send tokens
    /// @param rTokenId id of the revenue token
    /// @param wTokenId id of the wealth token
    /// @param rTokenAmount amount of revenue to send
    /// @param wTokenAmount amount of wealth to send
    function _sendRevenueAndWealthTokens(
        address to,
        uint256 rTokenId,
        uint256 wTokenId,
        uint256 rTokenAmount,
        uint256 wTokenAmount
    ) private {
        uint256[] memory amounts = new uint256[](2);
        (amounts[0], amounts[1]) = (rTokenAmount, wTokenAmount);
        uint256[] memory tokenIds = new uint256[](2);
        (tokenIds[0], tokenIds[1]) = (rTokenId, wTokenId);

        managerData.hypcShareTokens.safeBatchTransferFrom(address(this), to, tokenIds, amounts, '');
    }
    
    /// @notice This contract will start the migration to the Share Manager contract
    ///         to be able to migrate the share proposal, it needs to be called by the share owner
    /// @param shareTokenNumber share token number to start migration from Share Tokens contract
    /// @param hardwareOperator address of the hardware operator to be used for the share
    function startShareProposalMigration(
        uint256 shareTokenNumber,
        address hardwareOperator,
        string memory operatorAssignedString
    ) external nonReentrant {
        if (managerData.hypcShareTokens.getShareOwner(shareTokenNumber) != _msgSender())
            revert Errors.InvalidShareTokenOwner();

        if (!managerData.hypcShareTokens.isShareActive(shareTokenNumber)) revert Errors.GetShareDataFailed();

        if (shareTokenExists[shareTokenNumber] > 0) revert Errors.ShareTokenAlreadyExists();

        if (hardwareOperator == address(0)) revert Errors.InvalidProposedAddress();

        (uint256 revenueDepositDelay, bool chypcExists) = _getShareDataRevenueDelayAndCHYPCExists(shareTokenNumber);

        if (revenueDepositDelay > MAX_REVENUE_DELAY) revert Errors.InvalidDepositRevenueDelay();

        if (!chypcExists) revert Errors.ChypcIsNotHeld();

        uint256 shareProposalId = sharesProposalsCounter++;

        _shareProposals[shareProposalId].shareTokenData = Types.ShareTokenData({
            shareTokenNumber: shareTokenNumber,
            revenueDepositDelay: revenueDepositDelay,
            rTokenId: shareTokenNumber << 1,
            wTokenId: (shareTokenNumber << 1) + 1,
            validEndTimestamp: block.timestamp + 1 days
        });

        uint256 chypcId = managerData.hypcShareTokens.getShareCHyPCId(shareTokenNumber);
        uint256 licenseId = managerData.hypcShareTokens.getShareLicenseId(shareTokenNumber);
        uint256 chypcLevel = managerData.chypcV2.getTokenLevel(chypcId);
        uint256 licenseLevel = managerData.licenseContract.getLicenseHeight(licenseId);
        uint256 revenueTokensSupply = managerData.hypcShareTokens.getRevenueTokenTotalSupply(shareTokenNumber);

        if (licenseLevel != chypcLevel)
            revert Errors.TokenLevelMismatch();

        _shareProposals[shareProposalId].chypcData = Types.TokenHolderData({
            tokenNumber: chypcId,
            tokenOwner: _msgSender(),
            tokenLevel: chypcLevel,
            initialRevenueTokens: revenueTokensSupply * 7 / 10,
            initialWealthTokens: revenueTokensSupply
        });

        _shareProposals[shareProposalId].licenseData = Types.TokenHolderData({
            tokenNumber: licenseId,
            tokenOwner: _msgSender(),
            tokenLevel: licenseLevel,
            initialRevenueTokens: 0,
            initialWealthTokens: 0
        });

        // @dev operatorRevenue: revenueTokensSupply * 2 * SIX_DECIMALS / 10,
        //      simlipified to reduce contract size.
        _shareProposals[shareProposalId].operatorData = Types.HardwareOperatorData({
            operatorRevenue: revenueTokensSupply * 200000,
            operatorAssignedString: operatorAssignedString,
            operatorAddress: hardwareOperator
        });

        _shareProposals[shareProposalId].status = Types.ShareProposalStatus.MIGRATING;

        managerData.hypcShareTokens.safeTransferFrom(
            _msgSender(), 
            address(this), 
            _shareProposals[shareProposalId].shareTokenData.rTokenId, 
            revenueTokensSupply * 3 / 10, 
            ''
        );
        shareTokenExists[shareTokenNumber] = shareProposalId;

        emit Events.ShareProposalCreated(shareProposalId);
    }

    // @notice Cancels a pending share migration
    // @param  shareProposalId Id of the proposal migration to cancel.
    function cancelShareTokenMigration(uint256 shareProposalId) external nonReentrant {
        Types.ShareProposalData storage shareProposal = _shareProposals[shareProposalId];

        uint256 shareTokenNumber = shareProposal.shareTokenData.shareTokenNumber;

        if (shareProposal.status != Types.ShareProposalStatus.MIGRATING)
            revert Errors.NotMigratingProposal();
        
        // @dev Note that the chypcDat.tokenOwner is the user that started the migration in this case.
        if (_msgSender() != shareProposal.chypcData.tokenOwner) revert Errors.InvalidCHYPCOwner();

        shareProposal.status = Types.ShareProposalStatus.ENDED;
        if (managerData.hypcShareTokens.getShareOwner(shareTokenNumber) == address(this)) {
            // @dev for the case that the user transferred the ownership of the share, but
            //      decided to cancel it instead of finishing the migration.
            managerData.hypcShareTokens.transferShareOwnership(shareTokenNumber, _msgSender());
        }
        uint256 revenueTokensSupply = managerData.hypcShareTokens.getRevenueTokenTotalSupply(shareTokenNumber);

        managerData.hypcShareTokens.safeTransferFrom(
            address(this),
            _msgSender(),
            _shareProposals[shareProposalId].shareTokenData.rTokenId, 
            revenueTokensSupply * 3 / 10, 
            ''
        );
        shareTokenExists[shareTokenNumber] = 0;

        emit Events.ShareProposalEnded(shareProposalId);
    }

    /// @notice This function will finish the migration to the Share Manager contract
    ///         The owner will be able to finish the migration only if the ownership of the share token
    ///         is changed to this contract, and the share proposal is pending
    /// @param shareProposalId Share proposal id to finish migration
    function finishShareTokenMigration(uint256 shareProposalId) external nonReentrant {
        Types.ShareProposalData storage shareProposal = _shareProposals[shareProposalId];

        uint256 shareTokenNumber = shareProposal.shareTokenData.shareTokenNumber;
       
        if (_shareProposals[shareProposalId].status != Types.ShareProposalStatus.MIGRATING) revert Errors.NotMigratingProposal();

        if (_msgSender() != shareProposal.chypcData.tokenOwner) revert Errors.InvalidShareTokenOwner();

        if (managerData.hypcShareTokens.getShareOwner(shareTokenNumber) != address(this)) 
            revert Errors.InvalidShareTokenOwner();

        managerData.hypcShareTokens.setShareMessage(
            shareTokenNumber,
            shareProposal.operatorData.operatorAssignedString
        );

        managerData.hypcShareTokens.changePendingRevenueDelay(
            shareTokenNumber,
            shareProposal.shareTokenData.revenueDepositDelay
        );        

        _shareProposals[shareProposalId].status = Types.ShareProposalStatus.STARTED;
    }

    /// @notice Private function to get the sharde data from the share token contract, 
    ///         and return the revenue deposit delay and if the share is backed by a cHyPC
    ///         Using the specific slot of the `ShareData` struct to initialize the variables
    /// @param shareNumber share number to get the data from
    /// @return revenueDepositDelay delay in seconds to unlock the revenue deposited
    /// @return chypcExists if the share was backed by a HyPC or using a cHyPC NFT
    function _getShareDataRevenueDelayAndCHYPCExists(uint256 shareNumber) private view returns(uint256 revenueDepositDelay, bool chypcExists) {
        (bool success, bytes memory data) = address(managerData.hypcShareTokens).staticcall(abi.encodeWithSelector(managerData.hypcShareTokens.shareData.selector, shareNumber));
        
        if (!success) revert Errors.GetShareDataFailed();

        assembly {
            revenueDepositDelay := mload(add(data, 0x160))
            chypcExists := mload(add(data, 0x1A0))
        }
    }

    /// @notice Private function that returns the revenue deposited into the given share.
    /// @param  shareNumber to get the data from
    /// @return revenueDeposited total revenue deposited into the share.
    function _getShareDataRevenueDeposited(uint256 shareNumber) private view returns (uint256 revenueDeposited) {
        (bool success, bytes memory data) = address(managerData.hypcShareTokens).staticcall(abi.encodeWithSelector(managerData.hypcShareTokens.shareData.selector, shareNumber));
        
        if (!success) revert Errors.GetShareDataFailed();

        assembly {
            revenueDeposited := mload(add(data, 0x140))
        }
    }

    // @notice Returns the amount of deposited revenuf or this share
    // @param  shareNumber the share tokens number
    // @return The total HyPC deposited into this share
    function getShareDataRevenueDeposited(uint256 shareNumber) external view returns(uint256) {
        return _getShareDataRevenueDeposited(shareNumber);
    }

    /// @notice Allows an user to claim Hypc tokens, based in the amount of wealth tokens available,
    ///         and also claim the surplus HyPC revenue based on their revenue tokens.
    ///         The Share Proposal needs to be ended and the user needs to have wTokens or rTokes.
    /// @param shareProposalId The share proposal Id to be used to claim the Hypc.
    /// @param overridePendingDeposits  Bool for whether or not to ignore pending deposits left in the share.
    //          It is generally advised to not override pending revenue deposits and make sure they are unlocked
    //          and claimed before claiming HyPC and surplus.
    function claimHypcPortionAndSurplus(uint256 shareProposalId, bool overridePendingDeposits) external nonReentrant {
        Types.ShareProposalData storage shareProposal = _shareProposals[shareProposalId];
        if (shareProposal.status != Types.ShareProposalStatus.ENDED || shareCancelled[shareProposalId] != true) {
            revert Errors.ShareProposalIsNotEnded();
        }

        uint256 userWealthTokenBalance = managerData.hypcShareTokens.balanceOf(
            _msgSender(),
            shareProposal.shareTokenData.wTokenId
        );
        uint256 userRevenueTokenBalance = managerData.hypcShareTokens.balanceOf(
            _msgSender(),
            shareProposal.shareTokenData.rTokenId
        );
        uint256 shareTokenNumber = shareProposal.shareTokenData.shareTokenNumber;
        uint256 userVotePower = _votePower[shareProposalId][_msgSender()];

        if ( userRevenueTokenBalance == 0 && userVotePower + userWealthTokenBalance == 0 ) {
            revert Errors.NoWealthOrRevenueTokensAvailable();
        }

        uint256 hypcRefundAmount = 0;

        if ( userRevenueTokenBalance > 0 ) {    
            // @dev Suppose there's 1000 HyPC left after share was ended. This is the shareData.hypcSurplus amount.
            //      hardware operator had 10%, so 20% of the last deposit was held (this is the 1000 HyPC).
            //      This 1000 HyPC needs to be distributed amongst the remaining 70% of rTokens in the wild.
            uint256 revenueDeposited = _getShareDataRevenueDeposited(shareTokenNumber);
            if (overridePendingDeposits == false) {
                if (managerData.hypcShareTokens.getPendingDepositsLength(shareTokenNumber) != 0) {
                    revert Errors.MustUnlockRevenueBeforeClaimingSurplus();
                } 
                if (managerData.hypcShareTokens.lastShareClaimRevenue(shareTokenNumber, _msgSender()) != revenueDeposited) {
                    revert Errors.MustClaimRevenueBeforeClaimingSurplus();
                }
            
                if (managerData.hypcShareTokens.withdrawableAmounts(shareTokenNumber, _msgSender()) != 0 ) {
                    revert Errors.MustWithdrawRevenueBeforeClaimingSurplus();
                }
            }  
           
            uint256 surplusAmount = shareProposal.hypcSurplus;
            uint256 revenueTokenTotalSupply = managerData.hypcShareTokens.getRevenueTokenTotalSupply(shareTokenNumber);
            uint256 totalWildRevenueTokens = revenueTokenTotalSupply * 7 / 10;
            uint256 amountToRefund = surplusAmount * userRevenueTokenBalance / totalWildRevenueTokens;

            managerData.hypcShareTokens.safeTransferFrom(
                _msgSender(),
                address(this),
                shareProposal.shareTokenData.rTokenId,
                userRevenueTokenBalance,
                ''
            );
            hypcRefundAmount += amountToRefund;
        }      

        if ( userWealthTokenBalance + userVotePower > 0 ) {
            uint256 wealthTokenTotalSupply = managerData.hypcShareTokens.getWealthTokenTotalSupply(shareTokenNumber);

            uint256 hypcBacked = (1 << shareProposal.chypcData.tokenLevel ) * SIX_DECIMALS;

            uint256 userTransferAmount = (hypcBacked * (userWealthTokenBalance + userVotePower)) / wealthTokenTotalSupply;

            delete _votePower[shareProposalId][_msgSender()];

            if (userWealthTokenBalance > 0) {
                managerData.hypcShareTokens.safeTransferFrom(
                    _msgSender(),
                    address(this),
                    shareProposal.shareTokenData.wTokenId,
                    userWealthTokenBalance,
                    ''
                );
            }
            
            hypcRefundAmount += userTransferAmount;
        }
        if (hypcRefundAmount > 0) {
            managerData.hypcToken.transfer(
                _msgSender(),
                hypcRefundAmount
            );
            emit Events.HypcClaimed(shareProposalId, hypcRefundAmount);
        }

    }

    /// @notice Private function to end the share proposal
    /// @dev It will send the license only if the proposal was started.
    /// @dev It will send the cHyPC only if the token was transfered
    /// @dev It will send the hardware operator revenue only if proposal started
    /// @param shareProposalId The share proposal Id to be used to end the share.
    function _endShareProposal(uint256 shareProposalId) private {
        Types.ShareProposalData storage shareProposal = _shareProposals[shareProposalId];

        bool shareProposalStarted = shareProposal.status == Types.ShareProposalStatus.STARTED;

        shareProposal.status = Types.ShareProposalStatus.ENDED;

        if (!shareProposalStarted) {
            managerData.chypcV2.safeTransferFrom(
                address(this),
                shareProposal.chypcData.tokenOwner,
                shareProposal.chypcData.tokenNumber
            );
        } else {
            managerData.licenseContract.safeTransferFrom(
                address(this),
                shareProposal.licenseData.tokenOwner,
                shareProposal.licenseData.tokenNumber
            );

            _sendRevenueToHardwareOperator(shareProposalId);
            shareCancelled[shareProposalId] = true;
            managerData.chypcV2.redeem(shareProposal.chypcData.tokenNumber);
        }

        emit Events.ShareProposalEnded(shareProposalId);
    }

    /// @notice Public function for the hardware operator to use to claim their revenue 
    /// @param  shareProposalId The share proposal Id to send out the hardware revenue.
    function sendRevenueToHardwareOperator(uint256 shareProposalId) external nonReentrant isHardwareOperator(shareProposalId) proposalActive(shareProposalId) {
        _sendRevenueToHardwareOperator(shareProposalId);
    }

    /// @notice Private function that will send the revenue collected to the hardware operator
    /// @param shareProposalId The share proposal Id to send out the hardware revenue.
    function _sendRevenueToHardwareOperator(uint256 shareProposalId) private {
        Types.ShareProposalData storage shareProposal = _shareProposals[shareProposalId];

        uint256 oldBalance = managerData.hypcToken.balanceOf(address(this));

        try managerData.hypcShareTokens.claimAndWithdraw(shareProposal.shareTokenData.shareTokenNumber) {
            // ...
        } catch (bytes memory err) {
            if (keccak256(abi.encodeWithSignature('NoRevenueToClaim()')) != keccak256(err)) {
                revert(string(err));
                
            }
        }

        uint256 newBalance = managerData.hypcToken.balanceOf(address(this));
        uint256 amountReceived = newBalance - oldBalance;
        if (amountReceived > 0) {
            uint256 hardwareOperatorRevenue = (amountReceived * shareProposal.operatorData.operatorRevenue*10) / ((1 << shareProposal.chypcData.tokenLevel) * 3000000);// 3 * SIX_DECIMALS
        
            // @dev If the hardware operator revenue is 10%, then the 20% surplus will be divide up amongst the rToken holders.
            //      However, if the share is now cancelled (specifically from the cancel share votation), then we can't deposit the revenue anymore, 
            //      so in that case we hold it in the contract so rToken holders can get their share of the final remaining HyPC in the share.
            uint256 hypcSurplus = amountReceived - hardwareOperatorRevenue;
            if ( shareProposal.status != Types.ShareProposalStatus.ENDED ) {
                managerData.hypcToken.approve(address(managerData.hypcShareTokens), hypcSurplus);
                managerData.hypcShareTokens.depositRevenue(shareProposal.shareTokenData.shareTokenNumber, hypcSurplus);
            } else {
                // @dev Add this to the hypcSurplus, that will be claimed on a per-user basis.
                shareProposal.hypcSurplus += hypcSurplus;
            }

            managerData.hypcToken.transfer(shareProposal.operatorData.operatorAddress, hardwareOperatorRevenue);
        }
    }

    // Propose functions

    /// @notice Allows an user to create a new votation and propose to cancel the share.
    /// @param shareProposalId The share proposal Id to be used to create the votation
    /// @param deadline Time to be waited to complete the votation
    function proposeCancelShare(
        uint256 shareProposalId,
        uint256 deadline
    ) external nonReentrant validVoter(shareProposalId) validProposedDeadline(shareProposalId, deadline) {
        uint256 votationId = _votations[shareProposalId].length;
        _lastVotationCreated[shareProposalId][_msgSender()] = block.timestamp;
        _votations[shareProposalId].push(Types.Votation({
            votesFor: 0,
            votesAgainst: 0,
            deadline: deadline,
            proposedData: '',
            option: Types.VotationOptions.CANCEL_SHARE,
            amountReached: false
        }));
        emit Events.VoteStarted(shareProposalId, votationId, Types.VotationOptions.CANCEL_SHARE);
    }

    /// @notice Allows an user to create a new votation and propose a new Hardware Operator.
    /// @param shareProposalId The share proposal Id to be used to create the votation
    /// @param deadline Time to be waited to complete the votation
    /// @param newProposedString the new proposed assigned string for the hardware operator
    /// @param newHardwareOperator the new hardware operator address
    function proposeNewHardwareOperatorAddress(
        uint256 shareProposalId,
        uint256 deadline,
        string memory newProposedString,
        address newHardwareOperator
    ) external nonReentrant validVoter(shareProposalId) validProposedDeadline(shareProposalId, deadline) {
        if (newHardwareOperator == address(0)) revert Errors.InvalidProposedAddress();

        _lastVotationCreated[shareProposalId][_msgSender()] = block.timestamp;
        uint256 votationId = _votations[shareProposalId].length;

        _votations[shareProposalId].push(Types.Votation({
            votesFor: 0,
            votesAgainst: 0,
            deadline: deadline,
            proposedData: abi.encode(newProposedString, newHardwareOperator),
            option: Types.VotationOptions.CHANGE_HARDWARE_OPERATOR_ADDRESS,
            amountReached: false
        }));

        emit Events.VoteStarted(shareProposalId, votationId, Types.VotationOptions.CHANGE_HARDWARE_OPERATOR_ADDRESS);
    }

    /// @notice Allows an user to create a new votation and propose a new Hardware Operator Revenue.
    /// @param shareProposalId The share proposal Id to be used to create the votation
    /// @param deadline Time to be waited to complete the votation
    /// @param newRevenue the new proposed hardware operator revenue
    /// @dev `newRevenue` should be greater or equal than 1/10 of the W Token total supply times 1,000,000
    /// @dev `newRevenue` should be less or equal than 3/10 of the W Token total supply times 1,000,000
    function proposeNewHardwareOperatorRevenue(
        uint256 shareProposalId,
        uint256 deadline,
        uint256 newRevenue
    ) external nonReentrant validVoter(shareProposalId) validProposedDeadline(shareProposalId, deadline) {
        uint256 revenueTotalSupply = managerData.hypcShareTokens.getRevenueTokenTotalSupply(
            _shareProposals[shareProposalId].shareTokenData.shareTokenNumber
        );
        // @dev revenueTotalSupply * 3 * SIX_DECIMALS / 10  but compressed to lower contract size.
        if ( newRevenue > revenueTotalSupply * 300000 ) {
            revert Errors.InvalidTokenAmount();
        }
        _lastVotationCreated[shareProposalId][_msgSender()] = block.timestamp;

        uint256 votationId = _votations[shareProposalId].length;

        _votations[shareProposalId].push(Types.Votation({
            votesFor: 0,
            votesAgainst: 0,
            deadline: deadline,
            proposedData: abi.encode(newRevenue),
            option: Types.VotationOptions.CHANGE_HARDWARE_OPERATOR_REVENUE,
            amountReached: false
        }));
        emit Events.VoteStarted(shareProposalId, votationId, Types.VotationOptions.CHANGE_HARDWARE_OPERATOR_REVENUE);
    }

    /// @notice Allows an user to create a new votation and propose a new share manager
    /// @param shareProposalId The share proposal Id to be used to create the votation
    /// @param deadline Time to be waited to complete the votation
    /// @param newShareManager The new share manager address
    function proposeNewManager(
        uint256 shareProposalId,
        uint256 deadline,
        address newShareManager
    ) external nonReentrant validVoter(shareProposalId) validProposedDeadline(shareProposalId, deadline) {
        if (
            newShareManager == address(0) ||
            newShareManager == address(this)
        ) revert Errors.InvalidProposedAddress();
        _lastVotationCreated[shareProposalId][_msgSender()] = block.timestamp;

        uint256 votationId = _votations[shareProposalId].length;

        _votations[shareProposalId].push(Types.Votation({
            votesFor: 0,
            votesAgainst: 0,
            deadline: deadline,
            proposedData: abi.encode(newShareManager),
            option: Types.VotationOptions.CHANGE_MANAGER_CONTRACT,
            amountReached: false
        }));

        emit Events.VoteStarted(shareProposalId, votationId, Types.VotationOptions.CHANGE_MANAGER_CONTRACT);
    }

    function proposeNewDepositRevenueDelay(
        uint256 shareProposalId,
        uint256 deadline,
        uint256 newDepositRevenueDelay
    ) external nonReentrant validVoter(shareProposalId) validProposedDeadline(shareProposalId, deadline) {
        if (newDepositRevenueDelay > MAX_REVENUE_DELAY) revert Errors.InvalidDepositRevenueDelay();

        uint256 votationId = _votations[shareProposalId].length;
        _lastVotationCreated[shareProposalId][_msgSender()] = block.timestamp;

        _votations[shareProposalId].push(Types.Votation({
            votesFor: 0,
            votesAgainst: 0,
            deadline: deadline,
            proposedData: abi.encode(newDepositRevenueDelay),
            option: Types.VotationOptions.CHANGE_DEPOSIT_REVENUE_DELAY,
            amountReached: false
        }));

        emit Events.VoteStarted(shareProposalId, votationId, Types.VotationOptions.CHANGE_DEPOSIT_REVENUE_DELAY);
    }

    // Votation functions

    /// @notice Function to execute or finish a votation, only able to vote if user increase the vote power
    /// @param shareProposalId Share Proposal Id to get the votations
    /// @param votationIndex Index of the votation to vote
    /// @param voteFor If true will increase the votes to execute the votation, otherwise will increase the votes to finish it.
    function vote(uint256 shareProposalId, uint256 votationIndex, bool voteFor) external nonReentrant onlyVoter(shareProposalId) validVotation(shareProposalId, votationIndex) {
        Types.Votation storage votation = _votations[shareProposalId][votationIndex];

        if (_shareProposals[shareProposalId].status == Types.ShareProposalStatus.ENDED)
            revert Errors.ShareTokenIsNotActive();

        if (votation.amountReached) revert Errors.VotationAmountReached();

        if (block.timestamp > votation.deadline) revert Errors.VotationDeadlineReached();

        if (_voted[shareProposalId][votationIndex][_msgSender()]) revert Errors.ParticipantAlreadyVote();

        _voted[shareProposalId][votationIndex][_msgSender()] = true;

        if (_votedFreeTime[shareProposalId][_msgSender()] < votation.deadline) {
            _votedFreeTime[shareProposalId][_msgSender()] = votation.deadline;
        }

        uint256 votePower = _votePower[shareProposalId][_msgSender()];

        voteFor ? votation.votesFor += votePower : votation.votesAgainst += votePower;

        uint256 wealthTokenSupply = managerData.hypcShareTokens.getWealthTokenTotalSupply(
            _shareProposals[shareProposalId].shareTokenData.shareTokenNumber
        );

        if (
            votation.option == Types.VotationOptions.CANCEL_SHARE ||
            votation.option == Types.VotationOptions.CHANGE_MANAGER_CONTRACT
        ) {
            if (
                (voteFor ? votation.votesFor : votation.votesAgainst ) >= wealthTokenSupply * SELECTED_VOTATION_PERCENT / ONE_HUNDRED_PERCENT
            ) {
                votation.amountReached = true;
            }
        } else {
            if (
                (voteFor ? votation.votesFor : votation.votesAgainst) > (wealthTokenSupply >> 1) 
            ) {
                votation.amountReached = true;
            }
        }

        if (votation.amountReached) {
            if(voteFor) {
                _executeVotationAction(shareProposalId, votationIndex);
            }
            emit Events.VotationEnded(shareProposalId, votationIndex, voteFor);
        }

        emit Events.VoteEmitted(shareProposalId, _msgSender(), votationIndex, voteFor, votePower);
    }

    /// @notice Increase the caller votation power, transfering the wealth tokens from the user to the contract
    /// @param shareProposalId Id of the Share Proposal to increase the vote power
    function increaseVotePower(uint256 shareProposalId, uint256 amount) external nonReentrant proposalActive(shareProposalId) {
        Types.ShareTokenData storage shareTokenData = _shareProposals[shareProposalId].shareTokenData;
        
        uint256 balance = managerData.hypcShareTokens.balanceOf(_msgSender(), shareTokenData.wTokenId);

        if (amount > balance || balance == 0) revert Errors.NotEnoughWealthTokensAvailable();

        managerData.hypcShareTokens.safeTransferFrom(_msgSender(), address(this), shareTokenData.wTokenId, amount, '');

        _votePower[shareProposalId][_msgSender()] += amount;
    }

    /// @notice Decrease the caller votation power, transfering the wealth tokens from the contract to the user
    /// @param shareProposalId Id of the Share Proposal to decrease the vote power
    function decreaseVotePower(uint256 shareProposalId) external nonReentrant {
        if (_shareProposals[shareProposalId].status != Types.ShareProposalStatus.ENDED && _votations[shareProposalId].length > 0 && _votedFreeTime[shareProposalId][_msgSender()] >= block.timestamp)
            revert Errors.VotePowerLockedUntilDeadline();
        Types.ShareTokenData storage shareTokenData = _shareProposals[shareProposalId].shareTokenData;

        uint256 balance = _votePower[shareProposalId][_msgSender()];

        delete _votePower[shareProposalId][_msgSender()];

        managerData.hypcShareTokens.safeTransferFrom(address(this), _msgSender(), shareTokenData.wTokenId, balance, '');
    }

    // Votation Actions

    /// Private function that will execute the votations actions based on the votation type
    /// @param shareProposalId Id of the Share Proposal to execute the action
    /// @param votationIndex Index of the votation to execute the action
    /// @dev If `votationIndex` is zero the proposal will be cancelled
    function _executeVotationAction(uint256 shareProposalId, uint256 votationIndex) private {
        Types.VotationOptions votationOption = _votations[shareProposalId][votationIndex].option;

        if (votationOption == Types.VotationOptions.CANCEL_SHARE) {
            _cancelShareProposal(shareProposalId);
        }

        if (votationOption == Types.VotationOptions.CHANGE_HARDWARE_OPERATOR_ADDRESS) {
            _changeHardwareOperatorAddress(shareProposalId, votationIndex);
        }

        if (votationOption == Types.VotationOptions.CHANGE_HARDWARE_OPERATOR_REVENUE) {
            _changeHardwareOperatorRevenue(shareProposalId, votationIndex);
        }

        if (votationOption == Types.VotationOptions.CHANGE_MANAGER_CONTRACT) {
            _changeShareManagerContract(shareProposalId, votationIndex);
        }

        if (votationOption == Types.VotationOptions.CHANGE_DEPOSIT_REVENUE_DELAY) {
            _changeDepositRevenueDelay(shareProposalId, votationIndex);
        }
    }

    /// Private function that will execute the cancel action
    /// @param shareProposalId Id of the Share Proposal to be cancelled
    function _cancelShareProposal(uint256 shareProposalId) private {
        if (_shareProposals[shareProposalId].shareTokenData.validEndTimestamp > block.timestamp)
            revert Errors.ShareProposalEndTimeNotReached();

        managerData.hypcShareTokens.cancelShareTokens(_shareProposals[shareProposalId].shareTokenData.shareTokenNumber);

        _endShareProposal(shareProposalId);

        emit Events.VoteActionExecuted(shareProposalId, Types.VotationOptions.CANCEL_SHARE);
    }

    /// Private function that will execute the change hardware operator action
    /// @param shareProposalId Id of the Share Proposal to be changed
    /// @param votationIndex Index of the votation to execute
    function _changeHardwareOperatorAddress(uint256 shareProposalId, uint256 votationIndex) private {

        Types.ShareProposalData storage shareProposal = _shareProposals[shareProposalId];
       
        _sendRevenueToHardwareOperator(shareProposalId);

        (string memory newHardwareOperatorString, address newHardwareOperatorAddress) = abi.decode(
            _votations[shareProposalId][votationIndex].proposedData,
            (string, address)
        );

        shareProposal.operatorData.operatorAddress = newHardwareOperatorAddress;
        shareProposal.operatorData.operatorAssignedString = newHardwareOperatorString;

        managerData.hypcShareTokens.setShareMessage(
            shareProposal.shareTokenData.shareTokenNumber,
            shareProposal.operatorData.operatorAssignedString
        );

        emit Events.VoteActionExecuted(shareProposalId, Types.VotationOptions.CHANGE_HARDWARE_OPERATOR_ADDRESS);
    }

    /// Private function that will execute the change hardware operator revenue action
    /// @param shareProposalId Id of the Share Proposal to be changed
    /// @param votationIndex Index of the votation to execute
    function _changeHardwareOperatorRevenue(uint256 shareProposalId, uint256 votationIndex) private{
        _sendRevenueToHardwareOperator(shareProposalId);

        _shareProposals[shareProposalId].operatorData.operatorRevenue = abi.decode(_votations[shareProposalId][votationIndex].proposedData, (uint256));

        emit Events.VoteActionExecuted(shareProposalId, Types.VotationOptions.CHANGE_HARDWARE_OPERATOR_REVENUE);
    }

    /// Private function that will execute the change share manager action
    /// @param shareProposalId Id of the Share Proposal to be changed
    /// @param votationIndex Index of the votation to execute
    /// @dev The share proposal will be ended afterward
    function _changeShareManagerContract(uint256 shareProposalId, uint256 votationIndex) private {
        Types.ShareProposalData storage shareProposal = _shareProposals[shareProposalId];
        uint256 shareTokenNumber = shareProposal.shareTokenData.shareTokenNumber;

        address newManager = abi.decode(_votations[shareProposalId][votationIndex].proposedData, (address));

        managerData.hypcShareTokens.transferShareOwnership(shareTokenNumber, newManager);

        _sendRevenueToHardwareOperator(shareProposalId);

        shareProposal.status = Types.ShareProposalStatus.ENDED;

        _sendRevenueAndWealthTokens(
            newManager,
            shareProposal.shareTokenData.rTokenId,
            shareProposal.shareTokenData.wTokenId,
            managerData.hypcShareTokens.balanceOf(
                address(this),
                shareProposal.shareTokenData.rTokenId
            ),
            0
        );
        shareTokenExists[shareTokenNumber] = 0;

        emit Events.VoteActionExecuted(shareProposalId, Types.VotationOptions.CHANGE_MANAGER_CONTRACT);
    }

    /// Private function that will execute the change deposit revenue delay
    /// @param shareProposalId Id of the Share Proposal to be changed
    /// @param votationIndex Index of the votation to execute
    function _changeDepositRevenueDelay(uint256 shareProposalId, uint256 votationIndex) private {

        _shareProposals[shareProposalId].shareTokenData.revenueDepositDelay = abi.decode(_votations[shareProposalId][votationIndex].proposedData, (uint256));

        managerData.hypcShareTokens.changePendingRevenueDelay(
            _shareProposals[shareProposalId].shareTokenData.shareTokenNumber,
            _shareProposals[shareProposalId].shareTokenData.revenueDepositDelay
        );

        emit Events.VoteActionExecuted(shareProposalId, Types.VotationOptions.CHANGE_DEPOSIT_REVENUE_DELAY);
    }

    // Get functions

    // ManagerData getters

/*   
    /// @notice Get the setted swap V2 contract
    /// @return Swap V2 contract address
    function getCHYPC() external view returns (address) {
        return address(managerData.chypcV2);
    }

    /// @notice Get the setted License contract
    /// @return License contract address
    function getLicenseContract() external view returns (address) {
        return address(managerData.licenseContract);
    }

    /// @notice Get the setted HyperCycle Share Token contract
    /// @return HyperCycle Share Token contract address
    function getHypcShareTokenContract() external view returns (address) {
        return address(managerData.hypcShareTokens);
    }

    /// @notice Get the setted HyperCycle Token contract
    /// @return HyperCycle ERC 20 token
    function getHypcToken() external view returns (address) {
        return address(managerData.hypcToken);
    }
*/
    /// @notice Get the contract addresses used by this contrat
    /// @return addresses of the cHyPC contract, the License contract, the ShareTokens contract, and the HyPC contract.
    function getContracts() external view returns (address,address,address,address) {
        return (address(managerData.chypcV2), address(managerData.licenseContract), address(managerData.hypcShareTokens), address(managerData.hypcToken));
    }

    // ShareProposalData getters

    /// @notice Get the data of a selected share proposal
    /// @param shareProposalId Id of the Share Proposal
    /// @return Share Proposal Data
    function getShareProposalData(uint256 shareProposalId) external view returns (Types.ShareProposalData memory) {
        return _shareProposals[shareProposalId];
    }
/*
    /// @notice Get the status of a selected share proposal
    /// @param shareProposalId Id of the share proposal
    /// @return Share proposal status
    function getShareProposalStatus(uint256 shareProposalId) external view returns (Types.ShareProposalStatus) {
        return _shareProposals[shareProposalId].status;
    }
    
    /// @notice Get the revenue deposit delay of a selected share proposal
    /// @param shareProposalId Id of the share proposal
    /// @return Revenue deposit delay
    function getRevenueDelay(uint256 shareProposalId) external view returns (uint256) {
        return _shareProposals[shareProposalId].shareTokenData.revenueDepositDelay;
    }

    /// @notice Get the actual Hardware Operator Revenue of a selected share proposal
    /// @param shareProposalId Id of the share proposal
    /// @return Hardware Operator Revenue
    function getShareProposalHardwareOperatorRevenue(uint256 shareProposalId) external view returns (uint256) {
        return _shareProposals[shareProposalId].operatorData.operatorRevenue;
    }

    /// @notice Get the License token id
    /// @param shareProposalId Id of the share proposal
    /// @return License token id
    function getShareProposalLicenseNumber(uint256 shareProposalId) external view returns (uint256) {
        return _shareProposals[shareProposalId].licenseData.tokenNumber;
    }

    /// @notice Get the License Owner
    /// @param shareProposalId Id of the share proposal
    /// @return License Owner
    function getShareProposalLicenseOwner(uint256 shareProposalId) external view returns (address) {
        return _shareProposals[shareProposalId].licenseData.tokenOwner;
    }

    /// @notice Get the License Level
    /// @param shareProposalId Id of the share proposal
    /// @return License level
    function getShareProposalLicenseLevel(uint256 shareProposalId) external view returns (uint256) {
        return _shareProposals[shareProposalId].licenseData.tokenLevel;
    }

    /// @notice Get the cHyPc token id
    /// @param shareProposalId Id of the share proposal
    /// @return cHyPc token id
    function getShareProposalCHYPCNumber(uint256 shareProposalId) external view returns (uint256) {
        return _shareProposals[shareProposalId].chypcData.tokenNumber;
    }

    /// @notice Get the cHyPc owner
    /// @param shareProposalId Id of the share proposal
    /// @return cHyPc owner
    function getShareProposalCHYPCOwner(uint256 shareProposalId) external view returns (address) {
        return _shareProposals[shareProposalId].chypcData.tokenOwner;
    }

    /// @notice Get the cHyPc level
    /// @param shareProposalId Id of the share proposal
    /// @return cHyPc level
    function getShareProposalCHYPCLevel(uint256 shareProposalId) external view returns (uint256) {
        return _shareProposals[shareProposalId].chypcData.tokenLevel;
    }

    /// @notice Get the Hardware Operator address
    /// @param shareProposalId Id of the share proposal
    /// @return Hardware Operator address
    function getShareProposalHardwareOperator(uint256 shareProposalId) external view returns (address) {
        return _shareProposals[shareProposalId].operatorData.operatorAddress;
    }

    /// @notice Get the Hardware Operator address
    /// @param shareProposalId Id of the share proposal
    /// @return the share number for this proposal
    function getShareProposalShareNumber(uint256 shareProposalId) external view returns (uint256) {
        return _shareProposals[shareProposalId].shareTokenData.shareTokenNumber;
    }
*/  

    // Votation getters

    /// @notice Get the amount of votes needed to execute or finish the votation
    /// @return Votes needed 
    function getVotationConsensus(uint256 shareProposalId, Types.VotationOptions votationOption) external view returns (uint256) {
        uint256 totalSupply = managerData.hypcShareTokens.getWealthTokenTotalSupply(
            _shareProposals[shareProposalId].shareTokenData.shareTokenNumber
        );
        if (votationOption == Types.VotationOptions.CANCEL_SHARE || votationOption == Types.VotationOptions.CHANGE_MANAGER_CONTRACT) {
            return totalSupply * SELECTED_VOTATION_PERCENT / ONE_HUNDRED_PERCENT;
        } else {
            return (totalSupply >> 1);
        }
    }

    /// @notice Get the voting stats for this user, including the vote power and votedFreeTime. 
    /// @param shareProposalId Id of the share proposal
    /// @param user address of the voter to check
    /// @return votePower of this user.
    ///         votedFreeTime: the timestamp when this user will be able to decrease their votePower
    function getVoteStats(uint256 shareProposalId, address user) external view returns (uint256, uint256) {
        return (_votePower[shareProposalId][user], _votedFreeTime[shareProposalId][user]);
    }

    /// @notice Get if a selected address has voted in a specific votation
    /// @param shareProposalId Id of the share proposal
    /// @param votationIndex Index of the votation
    /// @param voter address of the voter to check
    /// @return If voter has voted
    function getUserVote(uint256 shareProposalId, uint256 votationIndex, address voter) external view returns (bool) {
        return _voted[shareProposalId][votationIndex][voter];
    }


    /// @notice Get the amount of votations a share proposal has
    /// @param shareProposalId Id of the share proposal
    /// @return Amount of votations
    function getVotationsLength(uint256 shareProposalId) external view returns (uint256) {
        return _votations[shareProposalId].length;
    }

    /// @notice Get the votation data
    /// @param shareProposalId Id of the share proposal
    /// @param votationIndex Index of the votation
    /// @return Votation data
    function getVotationData(
        uint256 shareProposalId,
        uint256 votationIndex
    ) external view validVotation(shareProposalId, votationIndex) returns (Types.Votation memory) {
        return _votations[shareProposalId][votationIndex];
    }
}

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

pragma solidity ^0.8.0;

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

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

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

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

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

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

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

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

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

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

File 3 of 22 : IERC721.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (interfaces/IERC721.sol)

pragma solidity ^0.8.0;

import "../token/ERC721/IERC721.sol";

File 4 of 22 : ReentrancyGuard.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.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 5 of 22 : IERC1155.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC1155/IERC1155.sol)

pragma solidity ^0.8.0;

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

/**
 * @dev Required interface of an ERC1155 compliant contract, as defined in the
 * https://eips.ethereum.org/EIPS/eip-1155[EIP].
 *
 * _Available since v3.1._
 */
interface IERC1155 is IERC165 {
    /**
     * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.
     */
    event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);

    /**
     * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all
     * transfers.
     */
    event TransferBatch(
        address indexed operator,
        address indexed from,
        address indexed to,
        uint256[] ids,
        uint256[] values
    );

    /**
     * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to
     * `approved`.
     */
    event ApprovalForAll(address indexed account, address indexed operator, bool approved);

    /**
     * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.
     *
     * If an {URI} event was emitted for `id`, the standard
     * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value
     * returned by {IERC1155MetadataURI-uri}.
     */
    event URI(string value, uint256 indexed id);

    /**
     * @dev Returns the amount of tokens of token type `id` owned by `account`.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     */
    function balanceOf(address account, uint256 id) external view returns (uint256);

    /**
     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.
     *
     * Requirements:
     *
     * - `accounts` and `ids` must have the same length.
     */
    function balanceOfBatch(
        address[] calldata accounts,
        uint256[] calldata ids
    ) external view returns (uint256[] memory);

    /**
     * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,
     *
     * Emits an {ApprovalForAll} event.
     *
     * Requirements:
     *
     * - `operator` cannot be the caller.
     */
    function setApprovalForAll(address operator, bool approved) external;

    /**
     * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.
     *
     * See {setApprovalForAll}.
     */
    function isApprovedForAll(address account, address operator) external view returns (bool);

    /**
     * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.
     *
     * Emits a {TransferSingle} event.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.
     * - `from` must have a balance of tokens of type `id` of at least `amount`.
     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the
     * acceptance magic value.
     */
    function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes calldata data) external;

    /**
     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.
     *
     * Emits a {TransferBatch} event.
     *
     * Requirements:
     *
     * - `ids` and `amounts` must have the same length.
     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the
     * acceptance magic value.
     */
    function safeBatchTransferFrom(
        address from,
        address to,
        uint256[] calldata ids,
        uint256[] calldata amounts,
        bytes calldata data
    ) external;
}

File 6 of 22 : IERC1155Receiver.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)

pragma solidity ^0.8.0;

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

/**
 * @dev _Available since v3.1._
 */
interface IERC1155Receiver is IERC165 {
    /**
     * @dev Handles the receipt of a single ERC1155 token type. This function is
     * called at the end of a `safeTransferFrom` after the balance has been updated.
     *
     * NOTE: To accept the transfer, this must return
     * `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))`
     * (i.e. 0xf23a6e61, or its own function selector).
     *
     * @param operator The address which initiated the transfer (i.e. msg.sender)
     * @param from The address which previously owned the token
     * @param id The ID of the token being transferred
     * @param value The amount of tokens being transferred
     * @param data Additional data with no specified format
     * @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed
     */
    function onERC1155Received(
        address operator,
        address from,
        uint256 id,
        uint256 value,
        bytes calldata data
    ) external returns (bytes4);

    /**
     * @dev Handles the receipt of a multiple ERC1155 token types. This function
     * is called at the end of a `safeBatchTransferFrom` after the balances have
     * been updated.
     *
     * NOTE: To accept the transfer(s), this must return
     * `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))`
     * (i.e. 0xbc197c81, or its own function selector).
     *
     * @param operator The address which initiated the batch transfer (i.e. msg.sender)
     * @param from The address which previously owned the token
     * @param ids An array containing ids of each token being transferred (order and length must match values array)
     * @param values An array containing amounts of each token being transferred (order and length must match ids array)
     * @param data Additional data with no specified format
     * @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed
     */
    function onERC1155BatchReceived(
        address operator,
        address from,
        uint256[] calldata ids,
        uint256[] calldata values,
        bytes calldata data
    ) external returns (bytes4);
}

File 7 of 22 : ERC1155Holder.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/utils/ERC1155Holder.sol)

pragma solidity ^0.8.0;

import "./ERC1155Receiver.sol";

/**
 * Simple implementation of `ERC1155Receiver` that will allow a contract to hold ERC1155 tokens.
 *
 * IMPORTANT: When inheriting this contract, you must include a way to use the received tokens, otherwise they will be
 * stuck.
 *
 * @dev _Available since v3.1._
 */
contract ERC1155Holder is ERC1155Receiver {
    function onERC1155Received(
        address,
        address,
        uint256,
        uint256,
        bytes memory
    ) public virtual override returns (bytes4) {
        return this.onERC1155Received.selector;
    }

    function onERC1155BatchReceived(
        address,
        address,
        uint256[] memory,
        uint256[] memory,
        bytes memory
    ) public virtual override returns (bytes4) {
        return this.onERC1155BatchReceived.selector;
    }
}

File 8 of 22 : ERC1155Receiver.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC1155/utils/ERC1155Receiver.sol)

pragma solidity ^0.8.0;

import "../IERC1155Receiver.sol";
import "../../../utils/introspection/ERC165.sol";

/**
 * @dev _Available since v3.1._
 */
abstract contract ERC1155Receiver is ERC165, IERC1155Receiver {
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
        return interfaceId == type(IERC1155Receiver).interfaceId || super.supportsInterface(interfaceId);
    }
}

File 9 of 22 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.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 10 of 22 : IERC721.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC721/IERC721.sol)

pragma solidity ^0.8.0;

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

/**
 * @dev Required interface of an ERC721 compliant contract.
 */
interface IERC721 is IERC165 {
    /**
     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.
     */
    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
     */
    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
     */
    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    /**
     * @dev Returns the number of tokens in ``owner``'s account.
     */
    function balanceOf(address owner) external view returns (uint256 balance);

    /**
     * @dev Returns the owner of the `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function ownerOf(uint256 tokenId) external view returns (address owner);

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
     * are aware of the ERC721 protocol to prevent tokens from being forever locked.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(address from, address to, uint256 tokenId) external;

    /**
     * @dev Transfers `tokenId` token from `from` to `to`.
     *
     * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721
     * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must
     * understand this adds an external call which potentially creates a reentrancy vulnerability.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address from, address to, uint256 tokenId) external;

    /**
     * @dev Gives permission to `to` to transfer `tokenId` token to another account.
     * The approval is cleared when the token is transferred.
     *
     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.
     *
     * Requirements:
     *
     * - The caller must own the token or be an approved operator.
     * - `tokenId` must exist.
     *
     * Emits an {Approval} event.
     */
    function approve(address to, uint256 tokenId) external;

    /**
     * @dev Approve or remove `operator` as an operator for the caller.
     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
     *
     * Requirements:
     *
     * - The `operator` cannot be the caller.
     *
     * Emits an {ApprovalForAll} event.
     */
    function setApprovalForAll(address operator, bool approved) external;

    /**
     * @dev Returns the account approved for `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function getApproved(uint256 tokenId) external view returns (address operator);

    /**
     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
     *
     * See {setApprovalForAll}
     */
    function isApprovedForAll(address owner, address operator) external view returns (bool);
}

File 11 of 22 : IERC721Receiver.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)

pragma solidity ^0.8.0;

/**
 * @title ERC721 token receiver interface
 * @dev Interface for any contract that wants to support safeTransfers
 * from ERC721 asset contracts.
 */
interface IERC721Receiver {
    /**
     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
     * by `operator` from `from`, this function is called.
     *
     * It must return its Solidity selector to confirm the token transfer.
     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.
     *
     * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.
     */
    function onERC721Received(
        address operator,
        address from,
        uint256 tokenId,
        bytes calldata data
    ) external returns (bytes4);
}

File 12 of 22 : ERC721Holder.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC721/utils/ERC721Holder.sol)

pragma solidity ^0.8.0;

import "../IERC721Receiver.sol";

/**
 * @dev Implementation of the {IERC721Receiver} interface.
 *
 * Accepts all token transfers.
 * Make sure the contract is able to use its token with {IERC721-safeTransferFrom}, {IERC721-approve} or {IERC721-setApprovalForAll}.
 */
contract ERC721Holder is IERC721Receiver {
    /**
     * @dev See {IERC721Receiver-onERC721Received}.
     *
     * Always returns `IERC721Receiver.onERC721Received.selector`.
     */
    function onERC721Received(address, address, uint256, bytes memory) public virtual override returns (bytes4) {
        return this.onERC721Received.selector;
    }
}

File 13 of 22 : 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 14 of 22 : ERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)

pragma solidity ^0.8.0;

import "./IERC165.sol";

/**
 * @dev Implementation of the {IERC165} interface.
 *
 * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
 * for the additional interface id that will be supported. For example:
 *
 * ```solidity
 * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
 *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
 * }
 * ```
 *
 * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
 */
abstract contract ERC165 is IERC165 {
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IERC165).interfaceId;
    }
}

File 15 of 22 : 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 16 of 22 : IHYPC.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

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

/// @notice Interface for the HyperCycleToken.sol contract.
interface IHYPC is IERC20 {
    /*
     * Accesses the ERC20 functions of the HYPC contract. The burn function
     * is also exposed for future contracts.
    */
    /// @notice Burns an amount of the HyPC ERC20.
    function burn(uint256 amount) external;
}

File 17 of 22 : IHYPCSwapV2.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

import "@openzeppelin/contracts/interfaces/IERC721.sol";

/// @notice Interface for the HYPCSwap.sol contract.
interface IHYPCSwapV2 is IERC721 {
    /**
     * Accesses the addNFT function so that the CHYPC contract can
     * add the newly created NFT into this contract.
     */

    function addRootTokens(uint256 tokens) external;

    function splitHeldToken(uint256 level, uint256 skipLevels) external;

    function swapV2(uint256 level) external;

    function redeem(uint256 tokenNumber) external;

    function assignNumber(uint256 tokenNumber, uint256 targetNumber) external;

    function assignString(uint256 tokenNumber, string memory data) external;

    function burn(uint256 tokenNumber, string memory data) external;

    function assign(uint256 tokenNumber, string memory data) external;

    function swap() external;


    function getAssignment(uint256 tokenNumber) external view returns (string memory);
    function getAssignmentNumber(uint256 tokenNumber) external view returns (uint256);
    function getAssignmentString(uint256 tokenNumber) external view returns (string memory);



    function getBurnData(uint256 tokenNumber) external view returns (string memory);

    function getAvailableToken(uint256 level, uint256 index) external view returns (uint256);

    function getTokenLevel(uint256 tokenNumber) external view returns (uint256);

    function getAssignmentTargetNumber(uint256 targetNumber) external view returns (uint256);
}

File 18 of 22 : IHyperCycleLicense.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

import "@openzeppelin/contracts/token/ERC721/IERC721.sol";

/// @notice Interface for the CHYPC.sol contract.
interface IHyperCycleLicense is IERC721 {
    /**
     * Accesses the assignment function of c_HyPC so the swap can remove 
     * the assignment data when a token is redeemed or swapped.
     */
    /// @notice Creates a new root token inside this contract, with a specified licenseID.
    function mint(
        uint256 numTokens
    ) external;

    /// @notice Splits a given token into two new tokens, with corresponding licenseID's.
    function split(
        uint256 tokenId
    ) external;

    /// @notice Burns a given tokenId with a specified burn string.
    function burn(
        uint256 tokenId,
        string memory burnString          
    ) external;

    /// @notice Merges together two child licenses into a parent license.
    function merge(
        uint256 tokenId
    ) external;

    /// @notice Returns the burn data from the given tokenId.
    function getBurnData(
        uint256 tokenId
    ) external view returns (string memory);

    /// @notice Returns the license height of the given tokenId.
    function getLicenseHeight(
        uint256 licenseId
    ) external view returns (uint8);

    /// @notice Returns the license height of the given tokenId.
    function getLicenseStatus(
        uint256 licenseId
    ) external view returns (uint256);
}

File 19 of 22 : IHyperCycleShareTokensV2.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

import '@openzeppelin/contracts/token/ERC1155/IERC1155.sol';

/// @notice Interface for the HyperCycleShareTokens.sol contract.
interface IHyperCycleShareTokensV2 is IERC1155 {
    struct PendingDeposit {
        uint256 availableAtTimestamp;
        uint256 amount;
    }

    function shareData(
        uint256 shareNumber
    )
        external
        pure
        returns (
            uint256 licenseId,
            uint256 chypcId,
            uint256 status,
            address owner,
            uint256 rTokenNumber,
            uint256 wTokenNumber,
            uint256 rTokenSupply,
            uint256 wTokenSupply,
            uint256 startTimestamp,
            uint256 revenueDeposited,
            uint256 revenueDepositDelay,
            string memory message,
            bool chypcTokenHeld
        );

    function currentShareNumber() external returns (uint256);

    function increaseShareLimit(uint256 number) external;

    function createShareTokens(
        uint256 licenseNumber,
        uint256 chypcNumber,
        bool chypcTokenHeld,
        string memory startingMessage,
        uint256 maxRevenueDeposit
    ) external;

    function changePendingRevenueDelay(uint256 shareNumber, uint256 newDelay) external;

    function transferShareOwnership(uint256 shareNumber, address to) external;

    function cancelShareTokens(uint256 shareNumber) external;

    function depositRevenue(uint256 shareNumber, uint256 amt) external;

    function claimRevenue(uint256 shareNumber) external;

    function withdrawEarnings(uint256 shareNumber) external;

    function claimAndWithdraw(uint256 shareNumber) external;

    function setShareMessage(uint256 shareNumber, string memory message) external;

    function burnRevenueTokens(uint256 shareNumber, uint256 amount) external;

    function burnWealthTokens(uint256 shareNumber, uint256 amount) external;

    function getShareLicenseId(uint256 shareNumber) external view returns (uint256);

    function getShareCHyPCId(uint256 shareNumber) external view returns (uint256);

    function getShareOwner(uint256 shareNumber) external view returns (address);

    function getShareRevenueTokenId(uint256 shareNumber) external view returns (uint256);

    function getShareWealthTokenId(uint256 shareNumber) external view returns (uint256);

    function getShareTotalRevenue(uint256 shareNumber) external view returns (uint256);

    function getShareStartTime(uint256 shareNumber) external view returns (uint256);

    function getShareMessage(uint256 shareNumber) external view returns (string memory);

    function isShareActive(uint256 shareNumber) external view returns (bool);

    function shareCreated(uint256 shareNumber) external view returns (bool);

    function getRevenueTokenTotalSupply(uint256 shareNumber) external view returns (uint256);

    function getWealthTokenTotalSupply(uint256 shareNumber) external view returns (uint256);

    function getPendingDeposit(uint256 shareNumber, uint256 index) external view returns (PendingDeposit memory);

    function getPendingDepositsLength(uint256 shareNumber) external view returns (uint256);
    
    function lastShareClaimRevenue(uint256 shareTokenNumber, address user) external view returns (uint256);

    function withdrawableAmounts(uint256 shareTokenNUmber, address user) external view returns (uint256); 
}

File 20 of 22 : ShareManagerErrorsV2.sol
// SPDX-License-Identifier: MIT
/*
    Share Manager Errors
*/

pragma solidity ^0.8.19;

library ShareManagerErrors {
    error NotMigratingProposal();

    error ShareProposalIsNotPending();

    error ShareProposalIsNotEnded();

    error ShareProposalEndTimeNotReached();

    error ShareProposalMustBeActive();

    error InvalidProposedAddress();

    error InvalidHYPCTokenAddress();

    error InvalidCHYPCAddress();

    error InvalidCHYPCOwner();

    error InvalidTokenAmount();

    error InvalidShareTokenContract();

    error VotationCreatedTooSoon();

    error InvalidLicenseAddress();

    error InvalidLicenseOwner();

    error InvalidDeadline();

    error InvalidVotingDuration();
 
    error InvalidVotation();

    error InvalidVotationOption();

    error DeadlineMustBeIncreasing();

    error DeadlineTooLate();

    error VotePowerLockedUntilDeadline();

    error ChypcIsNotHeld();

    error ParticipantAlreadyVote();

    error NotEnoughWealthTokensAvailable();

    error VotationAmountReached();

    error VotationDeadlineReached();

    error TokenLevelMismatch();

    error ShareTokenAlreadyExists();

    error InvalidShareTokenOwner();

    error GetShareDataFailed();

    error ShareTokenIsNotActive();

    error NotEnoughHYPC();

    error InvalidDepositRevenueDelay();

    error NoWealthOrRevenueTokensAvailable();

    error MustUnlockRevenueBeforeClaimingSurplus();

    error MustClaimRevenueBeforeClaimingSurplus();
        
    error MustWithdrawRevenueBeforeClaimingSurplus();

    error MustBeClaimedByHardwareOperatorAddress();
}

File 21 of 22 : ShareManagerEventsV2.sol
// SPDX-License-Identifier: MIT
/*
    Share Manager Events
*/

pragma solidity ^0.8.19;

import {ShareManagerTypes} from './ShareManagerTypesV2.sol';

library ShareManagerEvents {
    event ShareProposalCreated(uint256 shareProposalId);

    event ShareProposalStarted(uint256 shareProposalId);

    event ShareProposalEnded(uint256 shareProposalId);

    event HypcClaimed(uint256 shareProposalId, uint256 hypcClaimed);

    event VoteStarted(uint256 shareProposalId, uint256 votationIndex, ShareManagerTypes.VotationOptions selectedOption);

    event VoteActionExecuted(uint256 shareProposalId, ShareManagerTypes.VotationOptions selectedOption);

    event VoteEmitted(uint256 shareProposalId, address voter, uint256 votationIndex, bool voteFor, uint256 votePower);

    event VotationEnded(uint256 shareProposalId, uint256 votationIndex, bool voteForWinner);
}

File 22 of 22 : ShareManagerTypesV2.sol
// SPDX-License-Identifier: MIT
/*
    Share Manager Types
*/

pragma solidity ^0.8.19;

import {IHYPCSwapV2} from '../interfaces/IHYPCSwapV2.sol';
import {IHyperCycleLicense} from '../interfaces/IHyperCycleLicense.sol';
import {IHyperCycleShareTokensV2} from '../interfaces/IHyperCycleShareTokensV2.sol';
import {IHYPC} from '../interfaces/IHYPC.sol';

library ShareManagerTypes {
    enum ShareProposalStatus {
        NOT_CREATED,
        MIGRATING,
        PENDING,
        STARTED,
        ENDED
    }

    enum VotationOptions {
        NULL_OPTION,
        CANCEL_SHARE,
        CHANGE_HARDWARE_OPERATOR_ADDRESS,
        CHANGE_HARDWARE_OPERATOR_REVENUE,
        CHANGE_MANAGER_CONTRACT,
        CHANGE_DEPOSIT_REVENUE_DELAY
    }

    enum ConsensusOptions {
        ONE_HUNDRED_PERCENT,
        NINETY_PERCENT
    }

    struct ManagerData {
        IHYPC hypcToken;
        IHYPCSwapV2 chypcV2;
        IHyperCycleLicense licenseContract;
        IHyperCycleShareTokensV2 hypcShareTokens;
    }

    struct ShareProposalData {
        ShareTokenData shareTokenData;
        TokenHolderData licenseData;
        TokenHolderData chypcData;
        HardwareOperatorData operatorData;
        ShareProposalStatus status;
        uint256 hypcSurplus;
    }

    struct ShareTokenData {
        uint256 validEndTimestamp;
        uint256 shareTokenNumber;
        uint256 rTokenId;
        uint256 wTokenId;
        uint256 revenueDepositDelay;
    }

    struct TokenHolderData {
        uint256 tokenNumber;
        uint256 tokenLevel;
        uint256 initialRevenueTokens;
        uint256 initialWealthTokens;
        address tokenOwner;
    }

    struct HardwareOperatorData {
        uint256 operatorRevenue;
        string operatorAssignedString;
        address operatorAddress;
    }

    struct Votation {
        uint256 votesFor;
        uint256 votesAgainst;
        uint256 deadline;
        bytes proposedData;
        VotationOptions option;
        bool amountReached;
    }

    struct ShareData {
        uint256 licenseId;
        uint256 chypcId;
        uint256 status;
        address owner;
        uint256 rTokenNumber;
        uint256 wTokenNumber;
        uint256 rTokenSupply;
        uint256 wTokenSupply;
        uint256 startTimestamp;
        uint256 revenueDeposited;
        uint256 revenueDepositDelay;
        string message;
        bool chypcTokenHeld;
    }
}

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

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"enum ShareManagerTypes.ConsensusOptions","name":"_consensusOption","type":"uint8"},{"internalType":"address","name":"_hypcToken","type":"address"},{"internalType":"address","name":"_chypcV2","type":"address"},{"internalType":"address","name":"_licenseContract","type":"address"},{"internalType":"address","name":"_hypcShareTokens","type":"address"},{"internalType":"uint256","name":"_maxVotingTime","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ChypcIsNotHeld","type":"error"},{"inputs":[],"name":"DeadlineMustBeIncreasing","type":"error"},{"inputs":[],"name":"DeadlineTooLate","type":"error"},{"inputs":[],"name":"GetShareDataFailed","type":"error"},{"inputs":[],"name":"InvalidCHYPCAddress","type":"error"},{"inputs":[],"name":"InvalidCHYPCOwner","type":"error"},{"inputs":[],"name":"InvalidDeadline","type":"error"},{"inputs":[],"name":"InvalidDepositRevenueDelay","type":"error"},{"inputs":[],"name":"InvalidHYPCTokenAddress","type":"error"},{"inputs":[],"name":"InvalidLicenseAddress","type":"error"},{"inputs":[],"name":"InvalidLicenseOwner","type":"error"},{"inputs":[],"name":"InvalidProposedAddress","type":"error"},{"inputs":[],"name":"InvalidShareTokenContract","type":"error"},{"inputs":[],"name":"InvalidShareTokenOwner","type":"error"},{"inputs":[],"name":"InvalidTokenAmount","type":"error"},{"inputs":[],"name":"InvalidVotation","type":"error"},{"inputs":[],"name":"InvalidVotingDuration","type":"error"},{"inputs":[],"name":"MustBeClaimedByHardwareOperatorAddress","type":"error"},{"inputs":[],"name":"MustClaimRevenueBeforeClaimingSurplus","type":"error"},{"inputs":[],"name":"MustUnlockRevenueBeforeClaimingSurplus","type":"error"},{"inputs":[],"name":"MustWithdrawRevenueBeforeClaimingSurplus","type":"error"},{"inputs":[],"name":"NoWealthOrRevenueTokensAvailable","type":"error"},{"inputs":[],"name":"NotEnoughWealthTokensAvailable","type":"error"},{"inputs":[],"name":"NotMigratingProposal","type":"error"},{"inputs":[],"name":"ParticipantAlreadyVote","type":"error"},{"inputs":[],"name":"ShareProposalEndTimeNotReached","type":"error"},{"inputs":[],"name":"ShareProposalIsNotEnded","type":"error"},{"inputs":[],"name":"ShareProposalIsNotPending","type":"error"},{"inputs":[],"name":"ShareProposalMustBeActive","type":"error"},{"inputs":[],"name":"ShareTokenAlreadyExists","type":"error"},{"inputs":[],"name":"ShareTokenIsNotActive","type":"error"},{"inputs":[],"name":"TokenLevelMismatch","type":"error"},{"inputs":[],"name":"VotationAmountReached","type":"error"},{"inputs":[],"name":"VotationCreatedTooSoon","type":"error"},{"inputs":[],"name":"VotationDeadlineReached","type":"error"},{"inputs":[],"name":"VotePowerLockedUntilDeadline","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"shareProposalId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"hypcClaimed","type":"uint256"}],"name":"HypcClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"shareProposalId","type":"uint256"}],"name":"ShareProposalCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"shareProposalId","type":"uint256"}],"name":"ShareProposalEnded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"shareProposalId","type":"uint256"}],"name":"ShareProposalStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"shareProposalId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"votationIndex","type":"uint256"},{"indexed":false,"internalType":"bool","name":"voteForWinner","type":"bool"}],"name":"VotationEnded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"shareProposalId","type":"uint256"},{"indexed":false,"internalType":"enum ShareManagerTypes.VotationOptions","name":"selectedOption","type":"uint8"}],"name":"VoteActionExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"shareProposalId","type":"uint256"},{"indexed":false,"internalType":"address","name":"voter","type":"address"},{"indexed":false,"internalType":"uint256","name":"votationIndex","type":"uint256"},{"indexed":false,"internalType":"bool","name":"voteFor","type":"bool"},{"indexed":false,"internalType":"uint256","name":"votePower","type":"uint256"}],"name":"VoteEmitted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"shareProposalId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"votationIndex","type":"uint256"},{"indexed":false,"internalType":"enum ShareManagerTypes.VotationOptions","name":"selectedOption","type":"uint8"}],"name":"VoteStarted","type":"event"},{"inputs":[],"name":"SELECTED_VOTATION_PERCENT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"shareProposalId","type":"uint256"},{"internalType":"address","name":"user","type":"address"}],"name":"_lastVotationCreated","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"shareProposalId","type":"uint256"}],"name":"cancelPendingShareProposal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"shareProposalId","type":"uint256"}],"name":"cancelShareTokenMigration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"shareProposalId","type":"uint256"},{"internalType":"bool","name":"overridePendingDeposits","type":"bool"}],"name":"claimHypcPortionAndSurplus","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"shareProposalId","type":"uint256"},{"internalType":"uint256","name":"licenseNumber","type":"uint256"}],"name":"completeShareProposal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"proposalData","type":"bytes"}],"name":"createShareProposal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"shareProposalId","type":"uint256"}],"name":"decreaseVotePower","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"shareProposalId","type":"uint256"}],"name":"finishShareTokenMigration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getContracts","outputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"shareNumber","type":"uint256"}],"name":"getShareDataRevenueDeposited","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"shareProposalId","type":"uint256"}],"name":"getShareProposalData","outputs":[{"components":[{"components":[{"internalType":"uint256","name":"validEndTimestamp","type":"uint256"},{"internalType":"uint256","name":"shareTokenNumber","type":"uint256"},{"internalType":"uint256","name":"rTokenId","type":"uint256"},{"internalType":"uint256","name":"wTokenId","type":"uint256"},{"internalType":"uint256","name":"revenueDepositDelay","type":"uint256"}],"internalType":"struct ShareManagerTypes.ShareTokenData","name":"shareTokenData","type":"tuple"},{"components":[{"internalType":"uint256","name":"tokenNumber","type":"uint256"},{"internalType":"uint256","name":"tokenLevel","type":"uint256"},{"internalType":"uint256","name":"initialRevenueTokens","type":"uint256"},{"internalType":"uint256","name":"initialWealthTokens","type":"uint256"},{"internalType":"address","name":"tokenOwner","type":"address"}],"internalType":"struct ShareManagerTypes.TokenHolderData","name":"licenseData","type":"tuple"},{"components":[{"internalType":"uint256","name":"tokenNumber","type":"uint256"},{"internalType":"uint256","name":"tokenLevel","type":"uint256"},{"internalType":"uint256","name":"initialRevenueTokens","type":"uint256"},{"internalType":"uint256","name":"initialWealthTokens","type":"uint256"},{"internalType":"address","name":"tokenOwner","type":"address"}],"internalType":"struct ShareManagerTypes.TokenHolderData","name":"chypcData","type":"tuple"},{"components":[{"internalType":"uint256","name":"operatorRevenue","type":"uint256"},{"internalType":"string","name":"operatorAssignedString","type":"string"},{"internalType":"address","name":"operatorAddress","type":"address"}],"internalType":"struct ShareManagerTypes.HardwareOperatorData","name":"operatorData","type":"tuple"},{"internalType":"enum ShareManagerTypes.ShareProposalStatus","name":"status","type":"uint8"},{"internalType":"uint256","name":"hypcSurplus","type":"uint256"}],"internalType":"struct ShareManagerTypes.ShareProposalData","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"shareProposalId","type":"uint256"},{"internalType":"uint256","name":"votationIndex","type":"uint256"},{"internalType":"address","name":"voter","type":"address"}],"name":"getUserVote","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"shareProposalId","type":"uint256"},{"internalType":"enum ShareManagerTypes.VotationOptions","name":"votationOption","type":"uint8"}],"name":"getVotationConsensus","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"shareProposalId","type":"uint256"},{"internalType":"uint256","name":"votationIndex","type":"uint256"}],"name":"getVotationData","outputs":[{"components":[{"internalType":"uint256","name":"votesFor","type":"uint256"},{"internalType":"uint256","name":"votesAgainst","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bytes","name":"proposedData","type":"bytes"},{"internalType":"enum ShareManagerTypes.VotationOptions","name":"option","type":"uint8"},{"internalType":"bool","name":"amountReached","type":"bool"}],"internalType":"struct ShareManagerTypes.Votation","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"shareProposalId","type":"uint256"}],"name":"getVotationsLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"shareProposalId","type":"uint256"},{"internalType":"address","name":"user","type":"address"}],"name":"getVoteStats","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"shareProposalId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"increaseVotePower","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"maxVotationDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155BatchReceived","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"shareProposalId","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"proposeCancelShare","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"shareProposalId","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint256","name":"newDepositRevenueDelay","type":"uint256"}],"name":"proposeNewDepositRevenueDelay","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"shareProposalId","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"string","name":"newProposedString","type":"string"},{"internalType":"address","name":"newHardwareOperator","type":"address"}],"name":"proposeNewHardwareOperatorAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"shareProposalId","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint256","name":"newRevenue","type":"uint256"}],"name":"proposeNewHardwareOperatorRevenue","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"shareProposalId","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"address","name":"newShareManager","type":"address"}],"name":"proposeNewManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"shareProposalId","type":"uint256"}],"name":"sendRevenueToHardwareOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"shareTokenNumber","type":"uint256"}],"name":"shareTokenExists","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"sharesProposalsCounter","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"shareTokenNumber","type":"uint256"},{"internalType":"address","name":"hardwareOperator","type":"address"},{"internalType":"string","name":"operatorAssignedString","type":"string"}],"name":"startShareProposalMigration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"shareProposalId","type":"uint256"},{"internalType":"uint256","name":"votationIndex","type":"uint256"},{"internalType":"bool","name":"voteFor","type":"bool"}],"name":"vote","outputs":[],"stateMutability":"nonpayable","type":"function"}]

6080604052600160055534801561001557600080fd5b5060405161629f38038061629f833981016040819052610034916101f0565b60016000556001600160a01b03851661006057604051635412f96d60e01b815260040160405180910390fd5b6001600160a01b0384166100875760405163a21c5c7f60e01b815260040160405180910390fd5b6001600160a01b0383166100ae576040516373cfb64f60e11b815260040160405180910390fd5b6001600160a01b0382166100d55760405163f7468e4f60e01b815260040160405180910390fd5b620151808110806100e857506212750081115b1561010657604051632be0023160e11b815260040160405180910390fd5b6007819055600086600181111561011f5761011f610263565b1461014d57600a610139670de0b6b3a76400006009610279565b61014391906102a4565b600681905561015c565b670de0b6b3a764000060068190555b5050604080516080810182526001600160a01b0395861680825294861660208201819052938616918101829052919094166060909101819052600180546001600160a01b03199081169094179055600280548416909217909155600380548316909317909255600480549091169091179055506102c6565b80516001600160a01b03811681146101eb57600080fd5b919050565b60008060008060008060c0878903121561020957600080fd5b86516002811061021857600080fd5b9550610226602088016101d4565b9450610234604088016101d4565b9350610242606088016101d4565b9250610250608088016101d4565b915060a087015190509295509295509295565b634e487b7160e01b600052602160045260246000fd5b808202811582820484141761029e57634e487b7160e01b600052601160045260246000fd5b92915050565b6000826102c157634e487b7160e01b600052601260045260246000fd5b500490565b615fca806102d56000396000f3fe608060405234801561001057600080fd5b50600436106101fb5760003560e01c806383d845e21161011a578063c3a2a93a116100ad578063d7b53a0e1161007c578063d7b53a0e146104b9578063ef7ec001146104cc578063f23a6e61146104df578063f482e962146104fe578063f8e261381461051157600080fd5b8063c3a2a93a14610433578063cc5b60f214610473578063cce84c8a14610486578063cf2bd598146104a657600080fd5b8063bb307151116100e9578063bb307151146103e5578063bc197c81146103f8578063c0d700fd14610417578063c1e291ea1461042a57600080fd5b806383d845e2146103ad578063973c96d5146103c05780639eb40277146103c9578063b5348aa9146103dc57600080fd5b80634adc7657116101925780637217ff12116101615780637217ff121461035457806372a127f91461037457806375e02cd9146103875780637d60a1461461039a57600080fd5b80634adc7657146102ee5780635b776c961461030e5780635d02c5e31461032e5780636a18ff7a1461034157600080fd5b80631c0b06ba116101ce5780631c0b06ba1461027c5780633b00b25a1461029d5780633dfebcca146102c857806342f39a3d146102db57600080fd5b806301ffc9a71461020057806310f7c98614610228578063150b7a021461023d578063199789fb14610269575b600080fd5b61021361020e36600461521e565b610571565b60405190151581526020015b60405180910390f35b61023b610236366004615323565b6105a8565b005b61025061024b366004615385565b6108bd565b6040516001600160e01b0319909116815260200161021f565b61023b6102773660046153f0565b6108ce565b61028f61028a36600461541c565b610c50565b60405190815260200161021f565b61028f6102ab366004615435565b600a60209081526000928352604080842090915290825290205481565b61023b6102d6366004615465565b610c5b565b61023b6102e93660046153f0565b610f1f565b6103016102fc366004615465565b611211565b60405161021f9190615501565b61028f61031c36600461541c565b600f6020526000908152604090205481565b61023b61033c366004615566565b611385565b61023b61034f3660046155a8565b611878565b61028f61036236600461541c565b6000908152600c602052604090205490565b6102136103823660046155e1565b611cc0565b61023b610395366004615465565b611cf6565b61023b6103a836600461541c565b611ead565b61023b6103bb36600461541c565b611f4d565b61028f60055481565b61023b6103d736600461560f565b612079565b61028f60065481565b61023b6103f3366004615667565b6127d4565b61025061040636600461570e565b63bc197c8160e01b95945050505050565b61023b61042536600461541c565b612ef3565b61028f60075481565b600254600354600454600154604080516001600160a01b03958616815293851660208501529184169183019190915291909116606082015260800161021f565b61023b61048136600461541c565b613108565b61049961049436600461541c565b6131a6565b60405161021f9190615811565b61023b6104b43660046155e1565b613392565b61023b6104c7366004615465565b61368b565b61028f6104da366004615917565b613788565b6102506104ed366004615940565b63f23a6e6160e01b95945050505050565b61023b61050c36600461541c565b613871565b61055c61051f366004615435565b60008281526008602090815260408083206001600160a01b039490941680845293825280832054948352600b825280832093835292905220549091565b6040805192835260208301919091520161021f565b60006001600160e01b03198216630271189760e51b14806105a257506301ffc9a760e01b6001600160e01b03198316145b92915050565b6105b0613b53565b60008481526008602090815260408083203384529091528120548591036105ea5760405163cf12280d60e01b815260040160405180910390fd5b60036000828152600d602052604090206012015460ff166004811115610612576106126154d7565b1461063057604051634291bdcd60e11b815260040160405180910390fd5b61063c611c20426159b2565b6000828152600a602090815260408083203384529091529020541115610675576040516377b92de560e11b815260040160405180910390fd5b848461068442620151806159c5565b81116106a357604051631da7447960e21b815260040160405180910390fd5b6000828152600c6020526040902054158015906106fe57506000828152600c6020526040902080548291906106da906001906159b2565b815481106106ea576106ea6159d8565b906000526020600020906005020160020154115b1561071c5760405163579e757560e11b815260040160405180910390fd5b60075461072942836159b2565b111561074857604051632b59e68560e11b815260040160405180910390fd5b6001600160a01b03841661076f57604051639792926760e01b815260040160405180910390fd5b6000878152600a602090815260408083203384528252808320429055898352600c82528083208054825160c081018452858152808501959095528483018b9052915191939092909160608301916107ca918b918b91016159ee565b60408051601f1981840301815291905281526020016002815260006020918201819052835460018181018655948252908290208351600590920201908155908201519281019290925560408101516002830155606081015190919060038201906108349082615a99565b50608082015160048201805460ff19166001836005811115610858576108586154d7565b021790555060a08201518160040160016101000a81548160ff0219169083151502179055505050600080516020615f75833981519152888260026040516108a193929190615b57565b60405180910390a1505050506108b76001600055565b50505050565b630a85bd0160e11b5b949350505050565b6108d6613b53565b60008381526008602090815260408083203384529091528120548491036109105760405163cf12280d60e01b815260040160405180910390fd5b60036000828152600d602052604090206012015460ff166004811115610938576109386154d7565b1461095657604051634291bdcd60e11b815260040160405180910390fd5b610962611c20426159b2565b6000828152600a60209081526040808320338452909152902054111561099b576040516377b92de560e11b815260040160405180910390fd5b83836109aa42620151806159c5565b81116109c957604051631da7447960e21b815260040160405180910390fd5b6000828152600c602052604090205415801590610a2457506000828152600c602052604090208054829190610a00906001906159b2565b81548110610a1057610a106159d8565b906000526020600020906005020160020154115b15610a425760405163579e757560e11b815260040160405180910390fd5b600754610a4f42836159b2565b1115610a6e57604051632b59e68560e11b815260040160405180910390fd5b600480546000888152600d60205260408082206001015490516327143fdd60e21b815293840152916001600160a01b0390911690639c50ff7490602401602060405180830381865afa158015610ac8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aec9190615b72565b9050610afb81620493e0615b8b565b851115610b1b57604051632160733960e01b815260040160405180910390fd5b6000878152600a602090815260408083203384528252808320429055898352600c82528083208054825160c0810184528581528085018681528185018d815285518088018e90528651808203890181529087019096526060830195865260036080840181905260a084018990526001808601875595895296909720825160058502909101908155905193810193909355945160028301559151919392909190820190610bc79082615a99565b50608082015160048201805460ff19166001836005811115610beb57610beb6154d7565b021790555060a08201518160040160016101000a81548160ff0219169083151502179055505050600080516020615f7583398151915288826003604051610c3493929190615b57565b60405180910390a15050505050610c4b6001600055565b505050565b60006105a282613bb1565b610c63613b53565b6000828152600860209081526040808320338452909152812054839103610c9d5760405163cf12280d60e01b815260040160405180910390fd5b60036000828152600d602052604090206012015460ff166004811115610cc557610cc56154d7565b14610ce357604051634291bdcd60e11b815260040160405180910390fd5b610cef611c20426159b2565b6000828152600a602090815260408083203384529091529020541115610d28576040516377b92de560e11b815260040160405180910390fd5b8282610d3742620151806159c5565b8111610d5657604051631da7447960e21b815260040160405180910390fd5b6000828152600c602052604090205415801590610db157506000828152600c602052604090208054829190610d8d906001906159b2565b81548110610d9d57610d9d6159d8565b906000526020600020906005020160020154115b15610dcf5760405163579e757560e11b815260040160405180910390fd5b600754610ddc42836159b2565b1115610dfb57604051632b59e68560e11b815260040160405180910390fd5b6000858152600c602081815260408084208054600a84528286203387528452828620429055938352815160c0810183528581528084018681528184018b815284518087019095528785526060830194855260016080840181905260a084018990528454808201865594895295909720825160059094020192835551938201939093559351600285015551919290916003820190610e989082615a99565b50608082015160048201805460ff19166001836005811115610ebc57610ebc6154d7565b021790555060a08201518160040160016101000a81548160ff0219169083151502179055505050600080516020615f7583398151915286826001604051610f0593929190615b57565b60405180910390a150505050610f1b6001600055565b5050565b610f27613b53565b6000838152600860209081526040808320338452909152812054849103610f615760405163cf12280d60e01b815260040160405180910390fd5b60036000828152600d602052604090206012015460ff166004811115610f8957610f896154d7565b14610fa757604051634291bdcd60e11b815260040160405180910390fd5b610fb3611c20426159b2565b6000828152600a602090815260408083203384529091529020541115610fec576040516377b92de560e11b815260040160405180910390fd5b8383610ffb42620151806159c5565b811161101a57604051631da7447960e21b815260040160405180910390fd5b6000828152600c60205260409020541580159061107557506000828152600c602052604090208054829190611051906001906159b2565b81548110611061576110616159d8565b906000526020600020906005020160020154115b156110935760405163579e757560e11b815260040160405180910390fd5b6007546110a042836159b2565b11156110bf57604051632b59e68560e11b815260040160405180910390fd5b621275008411156110e35760405163363d956160e11b815260040160405180910390fd5b6000868152600c602081815260408084208054600a84528286203387528452828620429055938352815160c0810183528581528084018681528184018c815284518087018d90528551808203880181529086019095526060830194855260056080840181905260a08401899052845460018082018755958a529690982083519690980290970194855551918401919091559351600283015551919291600382019061118e9082615a99565b50608082015160048201805460ff191660018360058111156111b2576111b26154d7565b021790555060a08201518160040160016101000a81548160ff0219169083151502179055505050600080516020615f75833981519152878260056040516111fb93929190615b57565b60405180910390a150505050610c4b6001600055565b611219615102565b6000838152600c602052604090205483908390811061124b576040516320d24e3960e21b815260040160405180910390fd5b6000858152600c6020526040902080548590811061126b5761126b6159d8565b90600052602060002090600502016040518060c00160405290816000820154815260200160018201548152602001600282015481526020016003820180546112b290615a18565b80601f01602080910402602001604051908101604052809291908181526020018280546112de90615a18565b801561132b5780601f106113005761010080835404028352916020019161132b565b820191906000526020600020905b81548152906001019060200180831161130e57829003601f168201915b5050509183525050600482015460209091019060ff166005811115611352576113526154d7565b6005811115611363576113636154d7565b815260049190910154610100900460ff16151560209091015295945050505050565b61138d613b53565b6000806000806000806000878060200190518101906113ac9190615be7565b600254604051633404591760e21b815260048101899052979e50959c50939a509198509650945092506000916001600160a01b039091169063d011645c90602401602060405180830381865afa15801561140a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061142e9190615b72565b9050336002546040516331a9108f60e11b8152600481018b90526001600160a01b039283169290911690636352211e90602401602060405180830381865afa15801561147e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114a29190615c6b565b6001600160a01b0316146114c95760405163158980c760e21b815260040160405180910390fd5b6001600160a01b0382166114f057604051639792926760e01b815260040160405180910390fd5b621275008511156115145760405163363d956160e11b815260040160405180910390fd5b600a6115246001831b6007615b8b565b61152e9190615c88565b87118061153d57506001811b86115b1561155b57604051632160733960e01b815260040160405180910390fd5b600654670de0b6b3a764000090611575906001841b615b8b565b61157f9190615c88565b861015806115cd5750670de0b6b3a7640000600654670de0b6b3a76400006115a791906159b2565b6115b4906001841b615b8b565b6115be9190615c88565b6115c99060016159c5565b8611155b156115eb57604051632160733960e01b815260040160405180910390fd5b60058054600091826115fc83615caa565b909155506000818152600d6020526040908190208151606081019092529192508061162d6001861b62030d40615b8b565b8152602001868152602001856001600160a01b031681525081600f016000820151816000015560208201518160010190816116689190615a99565b5060409190910151600291820180546001600160a01b0319166001600160a01b0390921691909117905560128201805460ff191660018302179055506040518060a001604052808b81526020018481526020018a81526020018981526020016116ce3390565b6001600160a01b039081169091528151600a8401556020820151600b8401556040820151600c8401556060820151600d840155608090910151600e830180546001600160a01b03191691831691909117905560048201889055600254166342842e0e33308d6040518463ffffffff1660e01b815260040161175193929190615cc3565b600060405180830381600087803b15801561176b57600080fd5b505af115801561177f573d6000803e3d6000fd5b505050508560001461182e57336003546040516331a9108f60e11b8152600481018990526001600160a01b039283169290911690636352211e90602401602060405180830381865afa1580156117d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117fd9190615c6b565b6001600160a01b03161461182457604051636b0c6fd160e01b815260040160405180910390fd5b61182e8287613c79565b6040518281527fe2d77c4a35bb326277ff28842c7df62528e9dfdf2fbd905b6847260baaa1544f9060200160405180910390a1505050505050505050506118756001600055565b50565b611880613b53565b60008381526008602090815260408083203384529091528120548491036118ba5760405163cf12280d60e01b815260040160405180910390fd5b6000848152600c60205260409020548490849081106118ec576040516320d24e3960e21b815260040160405180910390fd5b6000868152600c6020526040812080548790811061190c5761190c6159d8565b60009182526020909120600590910201905060046000888152600d602052604090206012015460ff166004811115611946576119466154d7565b0361196457604051633cb1a52960e11b815260040160405180910390fd5b6004810154610100900460ff161561198f576040516331b7690560e21b815260040160405180910390fd5b80600201544211156119b45760405163e7110eeb60e01b815260040160405180910390fd5b6000878152600960209081526040808320898452825280832033845290915290205460ff16156119f757604051633526430d60e21b815260040160405180910390fd5b6000878152600960209081526040808320898452825280832033808552908352818420805460ff1916600117905560028501548b8552600b84528285209185529252909120541015611a635760028101546000888152600b602090815260408083203384529091529020555b600087815260086020908152604080832033845290915290205485611aa15780826001016000828254611a9691906159c5565b925050819055611abc565b80826000016000828254611ab591906159c5565b9250508190555b506004805460008a8152600d60205260408082206001015490516314bd9ae160e21b815293840152916001600160a01b03909116906352f66b8490602401602060405180830381865afa158015611b17573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b3b9190615b72565b90506001600484015460ff166005811115611b5857611b586154d7565b1480611b7b575060048084015460ff166005811115611b7957611b796154d7565b145b15611bcf57670de0b6b3a764000060065482611b979190615b8b565b611ba19190615c88565b87611bb0578360010154611bb3565b83545b10611bca5760048301805461ff0019166101001790555b611bfe565b600181901c87611be3578360010154611be6565b83545b1115611bfe5760048301805461ff0019166101001790555b6004830154610100900460ff1615611c62578615611c2057611c20898961411c565b604080518a8152602081018a90528815158183015290517fb8ac4a4d36edbe09a20cdee3233447c1f9f8b2f96df83a710544665a6265c6349181900360600190a15b604080518a81523360208201528082018a905288151560608201526080810184905290517f6f9a5c8fa54dd9373ca24b4ea210568e42186dc9b9aed297349d11f18c1aa11f9181900360a00190a1505050505050610c4b6001600055565b600083815260096020908152604080832085845282528083206001600160a01b038516845290915290205460ff165b9392505050565b611cfe613b53565b8160036000828152600d602052604090206012015460ff166004811115611d2757611d276154d7565b14611d4557604051634291bdcd60e11b815260040160405180910390fd5b6000838152600d602052604081206004549091906001600160a01b031662fdd58e3360038501546040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401602060405180830381865afa158015611db5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dd99190615b72565b905080841180611de7575080155b15611e055760405163cf12280d60e01b815260040160405180910390fd5b600480546003840154604051637921219560e11b81526001600160a01b039092169263f242432a92611e3d92339230928b9101615ce7565b600060405180830381600087803b158015611e5757600080fd5b505af1158015611e6b573d6000803e3d6000fd5b505050600086815260086020908152604080832033845290915281208054879350909190611e9a9084906159c5565b9091555050600160005550610f1b915050565b611eb5613b53565b6000818152600d602052604090206011015481906001600160a01b03163314611ef15760405163786b543160e11b815260040160405180910390fd5b8160036000828152600d602052604090206012015460ff166004811115611f1a57611f1a6154d7565b14611f3857604051634291bdcd60e11b815260040160405180910390fd5b611f4183614203565b50506118756001600055565b611f55613b53565b60046000828152600d602052604090206012015460ff166004811115611f7d57611f7d6154d7565b14158015611f9857506000818152600c602052604090205415155b8015611fbd57506000818152600b602090815260408083203384529091529020544211155b15611fdb5760405163ab1e1f4760e01b815260040160405180910390fd5b6000818152600d602090815260408083206008835281842033808652935281842080549490556004805460038301549351637921219560e11b81529295946001600160a01b039091169363f242432a9361203b9330939291889101615ce7565b600060405180830381600087803b15801561205557600080fd5b505af1158015612069573d6000803e3d6000fd5b5050505050506118756001600055565b612081613b53565b3360048054604051631819659760e01b81529182018690526001600160a01b03928316921690631819659790602401602060405180830381865afa1580156120cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120f19190615c6b565b6001600160a01b0316146121185760405163d47118cb60e01b815260040160405180910390fd5b60048054604051634e8c72a160e11b81529182018590526001600160a01b031690639d18e54290602401602060405180830381865afa15801561215f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121839190615d1f565b6121a057604051633022989960e01b815260040160405180910390fd5b6000838152600f6020526040902054156121cd5760405163bafab1af60e01b815260040160405180910390fd5b6001600160a01b0382166121f457604051639792926760e01b815260040160405180910390fd5b600080612200856145e1565b91509150621275008211156122285760405163363d956160e11b815260040160405180910390fd5b80612246576040516329f38e3f60e21b815260040160405180910390fd5b600580546000918261225783615caa565b9190505590506040518060a00160405280426201518061227791906159c5565b8152602001878152602001600188901b8152602001600188901b600161229d91906159c5565b815260209081018590526000838152600d8252604080822084518155928401516001840155838101516002840155606084015160038401556080909301516004928301558154925163637c77f160e01b8152918201899052916001600160a01b03169063637c77f190602401602060405180830381865afa158015612326573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061234a9190615b72565b60048054604051632cd3581b60e11b81529182018a90529192506000916001600160a01b0316906359a6b03690602401602060405180830381865afa158015612397573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123bb9190615b72565b600254604051633404591760e21b8152600481018590529192506000916001600160a01b039091169063d011645c90602401602060405180830381865afa15801561240a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061242e9190615b72565b6003546040516392680e9560e01b8152600481018590529192506000916001600160a01b03909116906392680e9590602401602060405180830381865afa15801561247d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124a19190615d3c565b600480546040516327143fdd60e21b81529182018d905260ff9290921692506000916001600160a01b031690639c50ff7490602401602060405180830381865afa1580156124f3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125179190615b72565b90508282146125395760405163042c06c160e51b815260040160405180910390fd5b6040518060a00160405280868152602001848152602001600a83600761255f9190615b8b565b6125699190615c88565b815260200182815260200161257b3390565b6001600160a01b039081169091526000888152600d602081815260408084208651600a82015586830151600b82015586820151600c82015560608088015194820194909455608096870151600e90910180546001600160a01b0319169190961617909455835160a081018552898152908101879052928301829052820152908101336001600160a01b039081169091526000888152600d6020908152604091829020845160058201559084015160068201558382015160078201556060808501516008830155608090940151600990910180546001600160a01b031916919093161790915580519182019052806126758362030d40615b8b565b815260208082018c90526001600160a01b038d166040928301526000898152600d8252919091208251600f8201908155918301516010909101906126b99082615a99565b50604091820151600291820180546001600160a01b0319166001600160a01b039283161790556000898152600d6020529290922060128101805460ff1916600117905560045491015491169063f242432a9033903090600a61271c876003615b8b565b6127269190615c88565b6040518563ffffffff1660e01b81526004016127459493929190615ce7565b600060405180830381600087803b15801561275f57600080fd5b505af1158015612773573d6000803e3d6000fd5b50505060008c8152600f602052604090819020889055517fe2d77c4a35bb326277ff28842c7df62528e9dfdf2fbd905b6847260baaa1544f91506127ba9088815260200190565b60405180910390a15050505050505050610c4b6001600055565b6127dc613b53565b6000828152600d602052604090206004601282015460ff166004811115612805576128056154d7565b14158061282657506000838152600e602052604090205460ff161515600114155b1561284457604051637bf390dd60e11b815260040160405180910390fd5b6004546000906001600160a01b031662fdd58e33600385015460405160e084901b6001600160e01b03191681526001600160a01b0390921660048301526024820152604401602060405180830381865afa1580156128a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128ca9190615b72565b6004549091506000906001600160a01b031662fdd58e33600286015460405160e084901b6001600160e01b03191681526001600160a01b0390921660048301526024820152604401602060405180830381865afa15801561292f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129539190615b72565b60018401546000878152600860209081526040808320338452909152902054919250908215801561298b575061298984826159c5565b155b156129a9576040516350114cab60e11b815260040160405180910390fd5b60008315612cbf5760006129bc84613bb1565b9050871515600003612b915760048054604051637e123fa960e11b81529182018690526001600160a01b03169063fc247f5290602401602060405180830381865afa158015612a0f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a339190615b72565b15612a51576040516357e4670f60e01b815260040160405180910390fd5b60045481906001600160a01b0316638a82f24086336040516001600160e01b031960e085901b16815260048101929092526001600160a01b03166024820152604401602060405180830381865afa158015612ab0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ad49190615b72565b14612af257604051630b0c5a4f60e01b815260040160405180910390fd5b6004546001600160a01b03166352aa993285336040516001600160e01b031960e085901b16815260048101929092526001600160a01b03166024820152604401602060405180830381865afa158015612b4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b739190615b72565b15612b9157604051632dd674ab60e21b815260040160405180910390fd5b6013870154600480546040516327143fdd60e21b81529182018790526000916001600160a01b0390911690639c50ff7490602401602060405180830381865afa158015612be2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c069190615b72565b90506000600a612c17836007615b8b565b612c219190615c88565b9050600081612c308a86615b8b565b612c3a9190615c88565b6004549091506001600160a01b031663f242432a3360028e01546040516001600160e01b031960e085901b168152612c79929130918f90600401615ce7565b600060405180830381600087803b158015612c9357600080fd5b505af1158015612ca7573d6000803e3d6000fd5b505050508086612cb791906159c5565b955050505050505b6000612ccb83876159c5565b1115612e1f57600480546040516314bd9ae160e21b81529182018590526000916001600160a01b03909116906352f66b8490602401602060405180830381865afa158015612d1d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d419190615b72565b90506000620f424088600a01600101546001901b612d5f9190615b8b565b9050600082612d6e868a6159c5565b612d789084615b8b565b612d829190615c88565b60008c815260086020908152604080832033845290915281205590508715612e0f576004805460038b0154604051637921219560e11b81526001600160a01b039092169263f242432a92612ddc92339230928f9101615ce7565b600060405180830381600087803b158015612df657600080fd5b505af1158015612e0a573d6000803e3d6000fd5b505050505b612e1981856159c5565b93505050505b8015612ee3576001546001600160a01b031663a9059cbb336040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602481018490526044016020604051808303816000875af1158015612e84573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ea89190615d1f565b5060408051898152602081018390527f4a190041baaa7b7da28a2bb3ad8330bdfb955271be9959517121bfb1c2900f54910160405180910390a15b505050505050610f1b6001600055565b612efb613b53565b6000818152600d60205260409020600180820154601283015490919060ff166004811115612f2b57612f2b6154d7565b14612f49576040516362be612960e01b815260040160405180910390fd5b600e8201546001600160a01b0316336001600160a01b031614612f7f5760405163d47118cb60e01b815260040160405180910390fd5b60048054604051631819659760e01b815291820183905230916001600160a01b0390911690631819659790602401602060405180830381865afa158015612fca573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fee9190615c6b565b6001600160a01b0316146130155760405163d47118cb60e01b815260040160405180910390fd5b60048054604051631d1a064960e11b81526001600160a01b0390911691633a340c9291613049918591601088019101615de2565b600060405180830381600087803b15801561306357600080fd5b505af1158015613077573d6000803e3d6000fd5b5050600480548582015460405163f7ce46b760e01b815292830186905260248301526001600160a01b0316925063f7ce46b79150604401600060405180830381600087803b1580156130c857600080fd5b505af11580156130dc573d6000803e3d6000fd5b5050506000848152600d60205260408120601201805460ff191660031790556001905550611875915050565b613110613b53565b6000818152600d60205260409020600e015481906001600160a01b0316331461314c5760405163158980c760e21b815260040160405180910390fd5b60026000838152600d602052604090206012015460ff166004811115613174576131746154d7565b1461319257604051633949e7c760e21b815260040160405180910390fd5b61319b826146b3565b506118756001600055565b6131ae615149565b6000828152600d6020818152604092839020835161016081018552815460c08201908152600183015460e08301526002830154610100830152600383015461012083015260048301546101408301528152845160a0818101875260058401548252600684015482860152600784015482880152600884015460608084019190915260098501546001600160a01b039081166080808601919091528588019490945288519283018952600a8601548352600b86015483880152600c860154838a01529685015482820152600e85015490961691810191909152818601528451808501909552600f820180548652601083018054929693958701949192918401916132b690615a18565b80601f01602080910402602001604051908101604052809291908181526020018280546132e290615a18565b801561332f5780601f106133045761010080835404028352916020019161332f565b820191906000526020600020905b81548152906001019060200180831161331257829003601f168201915b5050509183525050600291909101546001600160a01b0316602091820152908252601283015491019060ff16600481111561336c5761336c6154d7565b600481111561337d5761337d6154d7565b81526020016013820154815250509050919050565b61339a613b53565b60008381526008602090815260408083203384529091528120548491036133d45760405163cf12280d60e01b815260040160405180910390fd5b60036000828152600d602052604090206012015460ff1660048111156133fc576133fc6154d7565b1461341a57604051634291bdcd60e11b815260040160405180910390fd5b613426611c20426159b2565b6000828152600a60209081526040808320338452909152902054111561345f576040516377b92de560e11b815260040160405180910390fd5b838361346e42620151806159c5565b811161348d57604051631da7447960e21b815260040160405180910390fd5b6000828152600c6020526040902054158015906134e857506000828152600c6020526040902080548291906134c4906001906159b2565b815481106134d4576134d46159d8565b906000526020600020906005020160020154115b156135065760405163579e757560e11b815260040160405180910390fd5b60075461351342836159b2565b111561353257604051632b59e68560e11b815260040160405180910390fd5b6001600160a01b038416158061355057506001600160a01b03841630145b1561356e57604051639792926760e01b815260040160405180910390fd5b6000868152600a602090815260408083203384528252808320429055888352600c82528083208054825160c0810184528581528085018681528185018c815285516001600160a01b038d1681890152865180820389018152908701909652606083019586526004608084015260a0830188905260018085018655948852959096208151600584029091019081559551928601929092559251600285015590519192909160038201906136209082615a99565b50608082015160048201805460ff19166001836005811115613644576136446154d7565b021790555060a09190910151600491820180549115156101000261ff0019909216919091179055604051600080516020615f75833981519152916111fb918a918591615b57565b613693613b53565b80336003546040516331a9108f60e11b8152600481018490526001600160a01b039283169290911690636352211e90602401602060405180830381865afa1580156136e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137069190615c6b565b6001600160a01b03161461372d57604051636b0c6fd160e01b815260040160405180910390fd5b60026000848152600d602052604090206012015460ff166004811115613755576137556154d7565b1461377357604051633949e7c760e21b815260040160405180910390fd5b61377d8383613c79565b50610f1b6001600055565b600480546000848152600d60205260408082206001015490516314bd9ae160e21b8152938401529182916001600160a01b0316906352f66b8490602401602060405180830381865afa1580156137e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138069190615b72565b9050600183600581111561381c5761381c6154d7565b148061383957506004836005811115613837576138376154d7565b145b1561386757670de0b6b3a7640000600654826138559190615b8b565b61385f9190615c88565b9150506105a2565b60011c9392505050565b613879613b53565b6000818152600d6020526040902060018082015490601283015460ff1660048111156138a7576138a76154d7565b146138c5576040516362be612960e01b815260040160405180910390fd5b600e8201546001600160a01b0316336001600160a01b0316146138fb5760405163158980c760e21b815260040160405180910390fd5b60128201805460ff191660049081179091558054604051631819659760e01b815291820183905230916001600160a01b0390911690631819659790602401602060405180830381865afa158015613956573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061397a9190615c6b565b6001600160a01b0316036139fb576004546001600160a01b0316639732d56f82336040516001600160e01b031960e085901b16815260048101929092526001600160a01b03166024820152604401600060405180830381600087803b1580156139e257600080fd5b505af11580156139f6573d6000803e3d6000fd5b505050505b600480546040516327143fdd60e21b81529182018390526000916001600160a01b0390911690639c50ff7490602401602060405180830381865afa158015613a47573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a6b9190615b72565b6004549091506001600160a01b031663f242432a30336000888152600d6020526040902060020154600a613aa0876003615b8b565b613aaa9190615c88565b6040518563ffffffff1660e01b8152600401613ac99493929190615ce7565b600060405180830381600087803b158015613ae357600080fd5b505af1158015613af7573d6000803e3d6000fd5b5050506000838152600f602052604080822091909155517f0b021add1edbb328ed48ca0a1905c666ab931678b4a7602d219c496d174bf0259150613b3e9086815260200190565b60405180910390a15050506118756001600055565b600260005403613baa5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064015b60405180910390fd5b6002600055565b60045460408051602480820185905282518083039091018152604490910182526020810180516001600160e01b03166323f0aa7160e11b1790529051600092839283926001600160a01b0390921691613c0a9190615dfb565b600060405180830381855afa9150503d8060008114613c45576040519150601f19603f3d011682016040523d82523d6000602084013e613c4a565b606091505b509150915081613c6d57604051633022989960e01b815260040160405180910390fd5b61014001519392505050565b6000828152600d602052604080822060035491516392680e9560e01b8152600481018590529092916001600160a01b0316906392680e9590602401602060405180830381865afa158015613cd1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613cf59190615d3c565b600b83015460ff9190911691506001811b908214613d265760405163042c06c160e51b815260040160405180910390fd5b60128301805460ff191660031790556040805160a08101825285815260208101849052600c8501549091820190600a613d60856007615b8b565b613d6a9190615c88565b613d7491906159b2565b815260200184600a016003015483613d8c91906159b2565b815233602091820152815160058601558181015160068601556040808301516007870155606083015160088701556080909201516009860180546001600160a01b0319166001600160a01b03928316179055600480548451636da58de360e01b815294516000959190931693636da58de393828401939192909190829003018187875af1158015613e21573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e459190615b72565b6000818152600f602052604090819020889055805160a0810190915290915080613e7242620151806159c5565b8152602001828152602001600183901b8152602001600183901b6001613e9891906159c5565b8152600486018054602092830152825187559082015160018701556040820151600287015560608201516003808801919091556080909201519055546001600160a01b03166342842e0e3330886040518463ffffffff1660e01b8152600401613f0393929190615cc3565b600060405180830381600087803b158015613f1d57600080fd5b505af1158015613f31573d6000803e3d6000fd5b50506003546004805460405163095ea7b360e01b81526001600160a01b0391821692810192909252602482018a9052909116925063095ea7b39150604401600060405180830381600087803b158015613f8957600080fd5b505af1158015613f9d573d6000803e3d6000fd5b505060025460048054600a89015460405163095ea7b360e01b81526001600160a01b03928316938101939093526024830152909116925063095ea7b39150604401600060405180830381600087803b158015613ff857600080fd5b505af115801561400c573d6000803e3d6000fd5b505060048054600a880154888301546040516306badddb60e21b81526001600160a01b039093169550631aeb776c9450614052938b9360019260108d0192909101615e17565b600060405180830381600087803b15801561406c57600080fd5b505af1158015614080573d6000803e3d6000fd5b505050600985015460028601546003870154600788015460088901546140b295506001600160a01b0390941693614899565b600e84015460028501546003860154600c870154600d8801546140e1946001600160a01b031693929190614899565b6040518681527ff2fb170bc0fd9ce44083044170a7f85cd4887f40565b5439b1886f8f5ec026429060200160405180910390a1505050505050565b6000828152600c6020526040812080548390811061413c5761413c6159d8565b600091825260209091206004600590920201015460ff1690506001816005811115614169576141696154d7565b0361417757614177836149cb565b600281600581111561418b5761418b6154d7565b0361419a5761419a8383614a9b565b60038160058111156141ae576141ae6154d7565b036141bd576141bd8383614c4c565b60048160058111156141d1576141d16154d7565b036141e0576141e08383614d64565b60058160058111156141f4576141f46154d7565b03610c4b57610c4b8383614f90565b6000818152600d602052604080822060015491516370a0823160e01b81523060048201529092916001600160a01b0316906370a0823190602401602060405180830381865afa15801561425a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061427e9190615b72565b60048054600185015460405163f62b46c960e01b8152928301529192506001600160a01b039091169063f62b46c990602401600060405180830381600087803b1580156142ca57600080fd5b505af19250505080156142db575060015b614368573d808015614309576040519150601f19603f3d011682016040523d82523d6000602084013e61430e565b606091505b50805160208083019190912060408051600481526024810190915291820180516001600160e01b03166374d4d10160e11b178152915190912014614366578060405162461bcd60e51b8152600401613ba19190615e50565b505b6001546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa1580156143b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906143d59190615b72565b905060006143e383836159b2565b905080156145da57600b840154600090614404906001901b622dc6c0615b8b565b600f8601546144139084615b8b565b61441e90600a615b8b565b6144289190615c88565b9050600061443682846159b2565b90506004601287015460ff166004811115614453576144536154d7565b14614541576001546004805460405163095ea7b360e01b81526001600160a01b0391821692810192909252602482018490529091169063095ea7b3906044016020604051808303816000875af11580156144b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144d59190615d1f565b5060048054600188015460405163032b9ebf60e21b815292830152602482018390526001600160a01b031690630cae7afc90604401600060405180830381600087803b15801561452457600080fd5b505af1158015614538573d6000803e3d6000fd5b5050505061455b565b8086601301600082825461455591906159c5565b90915550505b600154601187015460405163a9059cbb60e01b81526001600160a01b0391821660048201526024810185905291169063a9059cbb906044016020604051808303816000875af11580156145b2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906145d69190615d1f565b5050505b5050505050565b60045460408051602480820185905282518083039091018152604490910182526020810180516001600160e01b03166323f0aa7160e11b17905290516000928392839283926001600160a01b03169161463991615dfb565b600060405180830381855afa9150503d8060008114614674576040519150601f19603f3d011682016040523d82523d6000602084013e614679565b606091505b50915091508161469c57604051633022989960e01b815260040160405180910390fd5b61016081015193506101a081015192505050915091565b6000818152600d60205260408120906003601283015460ff1660048111156146dd576146dd6154d7565b60128401805460ff191660041790551490508061476a57600254600e830154600a840154604051632142170760e11b81526001600160a01b03938416936342842e0e936147339330939290911691600401615cc3565b600060405180830381600087803b15801561474d57600080fd5b505af1158015614761573d6000803e3d6000fd5b50505050614861565b60035460098301546005840154604051632142170760e11b81526001600160a01b03938416936342842e0e936147a99330939290911691600401615cc3565b600060405180830381600087803b1580156147c357600080fd5b505af11580156147d7573d6000803e3d6000fd5b505050506147e483614203565b6000838152600e602052604090819020805460ff19166001179055600254600a840154915163db006a7560e01b815260048101929092526001600160a01b03169063db006a7590602401600060405180830381600087803b15801561484857600080fd5b505af115801561485c573d6000803e3d6000fd5b505050505b6040518381527f0b021add1edbb328ed48ca0a1905c666ab931678b4a7602d219c496d174bf0259060200160405180910390a1505050565b6040805160028082526060820183526000926020830190803683370190505090508282826000815181106148cf576148cf6159d8565b60200260200101836001815181106148e9576148e96159d8565b60209081029190910101919091525260408051600280825260608201909252600091816020016020820280368337019050509050858582600081518110614932576149326159d8565b602002602001018360018151811061494c5761494c6159d8565b60209081029190910101919091525260048054604051631759616b60e11b81526001600160a01b0390911691632eb2c2d6916149909130918c918791899101615e9f565b600060405180830381600087803b1580156149aa57600080fd5b505af11580156149be573d6000803e3d6000fd5b5050505050505050505050565b6000818152600d60205260409020544210156149fa57604051631b64953f60e11b815260040160405180910390fd5b600480546000838152600d602052604090819020600101549051631444354960e01b8152928301526001600160a01b031690631444354990602401600060405180830381600087803b158015614a4f57600080fd5b505af1158015614a63573d6000803e3d6000fd5b50505050614a70816146b3565b600080516020615f55833981519152816001604051614a90929190615efa565b60405180910390a150565b6000828152600d60205260409020614ab283614203565b6000838152600c60205260408120805482919085908110614ad557614ad56159d8565b90600052602060002090600502016003018054614af190615a18565b80601f0160208091040260200160405190810160405280929190818152602001828054614b1d90615a18565b8015614b6a5780601f10614b3f57610100808354040283529160200191614b6a565b820191906000526020600020905b815481529060010190602001808311614b4d57829003601f168201915b5050505050806020019051810190614b829190615f0e565b6011850180546001600160a01b0319166001600160a01b038316179055909250905060108301614bb28382615a99565b50600480546001850154604051631d1a064960e11b81526001600160a01b0390921692633a340c9292614beb9291601089019101615de2565b600060405180830381600087803b158015614c0557600080fd5b505af1158015614c19573d6000803e3d6000fd5b50505050600080516020615f55833981519152856002604051614c3d929190615efa565b60405180910390a15050505050565b614c5582614203565b6000828152600c60205260409020805482908110614c7557614c756159d8565b90600052602060002090600502016003018054614c9190615a18565b80601f0160208091040260200160405190810160405280929190818152602001828054614cbd90615a18565b8015614d0a5780601f10614cdf57610100808354040283529160200191614d0a565b820191906000526020600020905b815481529060010190602001808311614ced57829003601f168201915b5050505050806020019051810190614d229190615b72565b6000838152600d602052604090819020600f019190915551600080516020615f5583398151915290614d58908490600390615efa565b60405180910390a15050565b6000828152600d602090815260408083206001810154600c909352908320805491939185908110614d9757614d976159d8565b90600052602060002090600502016003018054614db390615a18565b80601f0160208091040260200160405190810160405280929190818152602001828054614ddf90615a18565b8015614e2c5780601f10614e0157610100808354040283529160200191614e2c565b820191906000526020600020905b815481529060010190602001808311614e0f57829003601f168201915b5050505050806020019051810190614e449190615c6b565b60048054604051639732d56f60e01b81529293506001600160a01b031691639732d56f91614e889186918691019182526001600160a01b0316602082015260400190565b600060405180830381600087803b158015614ea257600080fd5b505af1158015614eb6573d6000803e3d6000fd5b50505050614ec385614203565b60128301805460ff19166004908117909155600284015460038501548254604051627eeac760e11b8152309481019490945260248401839052614f5e93859392916001600160a01b03169062fdd58e90604401602060405180830381865afa158015614f33573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614f579190615b72565b6000614899565b6000828152600f60205260408082209190915551600080516020615f5583398151915290614c3d908790600490615efa565b6000828152600c60205260409020805482908110614fb057614fb06159d8565b90600052602060002090600502016003018054614fcc90615a18565b80601f0160208091040260200160405190810160405280929190818152602001828054614ff890615a18565b80156150455780601f1061501a57610100808354040283529160200191615045565b820191906000526020600020905b81548152906001019060200180831161502857829003601f168201915b505050505080602001905181019061505d9190615b72565b6000838152600d60205260409081902060048082018490558054600190920154925163f7ce46b760e01b81526001600160a01b039092169363f7ce46b7936150b093909201918252602082015260400190565b600060405180830381600087803b1580156150ca57600080fd5b505af11580156150de573d6000803e3d6000fd5b50505050600080516020615f55833981519152826005604051614d58929190615efa565b6040518060c00160405280600081526020016000815260200160008152602001606081526020016000600581111561513c5761513c6154d7565b8152600060209091015290565b6040518060c001604052806151866040518060a0016040528060008152602001600081526020016000815260200160008152602001600081525090565b81526020016151936151e6565b81526020016151a06151e6565b81526020016151d26040518060600160405280600081526020016060815260200160006001600160a01b031681525090565b815260200160008152602001600081525090565b6040518060a001604052806000815260200160008152602001600081526020016000815260200160006001600160a01b031681525090565b60006020828403121561523057600080fd5b81356001600160e01b031981168114611cef57600080fd5b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b038111828210171561528657615286615248565b604052919050565b60006001600160401b038211156152a7576152a7615248565b50601f01601f191660200190565b600082601f8301126152c657600080fd5b81356020830160006152df6152da8461528e565b61525e565b90508281528583830111156152f357600080fd5b82826020830137600092810160200192909252509392505050565b6001600160a01b038116811461187557600080fd5b6000806000806080858703121561533957600080fd5b843593506020850135925060408501356001600160401b0381111561535d57600080fd5b615369878288016152b5565b925050606085013561537a8161530e565b939692955090935050565b6000806000806080858703121561539b57600080fd5b84356153a68161530e565b935060208501356153b68161530e565b92506040850135915060608501356001600160401b038111156153d857600080fd5b6153e4878288016152b5565b91505092959194509250565b60008060006060848603121561540557600080fd5b505081359360208301359350604090920135919050565b60006020828403121561542e57600080fd5b5035919050565b6000806040838503121561544857600080fd5b82359150602083013561545a8161530e565b809150509250929050565b6000806040838503121561547857600080fd5b50508035926020909101359150565b60005b838110156154a257818101518382015260200161548a565b50506000910152565b600081518084526154c3816020860160208601615487565b601f01601f19169290920160200192915050565b634e487b7160e01b600052602160045260246000fd5b600681106154fd576154fd6154d7565b9052565b602081528151602082015260208201516040820152604082015160608201526000606083015160c0608084015261553b60e08401826154ab565b9050608084015161554f60a08501826154ed565b5060a0840151151560c08401528091505092915050565b60006020828403121561557857600080fd5b81356001600160401b0381111561558e57600080fd5b6108c6848285016152b5565b801515811461187557600080fd5b6000806000606084860312156155bd57600080fd5b833592506020840135915060408401356155d68161559a565b809150509250925092565b6000806000606084860312156155f657600080fd5b833592506020840135915060408401356155d68161530e565b60008060006060848603121561562457600080fd5b8335925060208401356156368161530e565b915060408401356001600160401b0381111561565157600080fd5b61565d868287016152b5565b9150509250925092565b6000806040838503121561567a57600080fd5b82359150602083013561545a8161559a565b600082601f83011261569d57600080fd5b81356001600160401b038111156156b6576156b6615248565b8060051b6156c66020820161525e565b918252602081850181019290810190868411156156e257600080fd5b6020860192505b838310156157045782358252602092830192909101906156e9565b9695505050505050565b600080600080600060a0868803121561572657600080fd5b85356157318161530e565b945060208601356157418161530e565b935060408601356001600160401b0381111561575c57600080fd5b6157688882890161568c565b93505060608601356001600160401b0381111561578457600080fd5b6157908882890161568c565b92505060808601356001600160401b038111156157ac57600080fd5b6157b8888289016152b5565b9150509295509295909350565b8051825260006020820151606060208501526157e460608501826154ab565b6040938401516001600160a01b0316949093019390935250919050565b600581106154fd576154fd6154d7565b602081526000825180516020840152602081015160408401526040810151606084015260608101516080840152608081015160a084015250602083015161588c60c0840182805182526020808201519083015260408082015190830152606080820151908301526080908101516001600160a01b0316910152565b5060408381015180516101608501526020810151610180850152908101516101a084015260608101516101c084015260808101516001600160a01b03166101e08401525060608301516102406102008401526158ec6102608401826157c5565b90506080840151615901610220850182615801565b5060a08401516102408401528091505092915050565b6000806040838503121561592a57600080fd5b8235915060208301356006811061545a57600080fd5b600080600080600060a0868803121561595857600080fd5b85356159638161530e565b945060208601356159738161530e565b9350604086013592506060860135915060808601356001600160401b038111156157ac57600080fd5b634e487b7160e01b600052601160045260246000fd5b818103818111156105a2576105a261599c565b808201808211156105a2576105a261599c565b634e487b7160e01b600052603260045260246000fd5b604081526000615a0160408301856154ab565b905060018060a01b03831660208301529392505050565b600181811c90821680615a2c57607f821691505b602082108103615a4c57634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115610c4b57806000526020600020601f840160051c81016020851015615a795750805b601f840160051c820191505b818110156145da5760008155600101615a85565b81516001600160401b03811115615ab257615ab2615248565b615ac681615ac08454615a18565b84615a52565b6020601f821160018114615afa5760008315615ae25750848201515b600019600385901b1c1916600184901b1784556145da565b600084815260208120601f198516915b82811015615b2a5787850151825560209485019460019092019101615b0a565b5084821015615b485786840151600019600387901b60f8161c191681555b50505050600190811b01905550565b83815260208101839052606081016108c660408301846154ed565b600060208284031215615b8457600080fd5b5051919050565b80820281158282048414176105a2576105a261599c565b600082601f830112615bb357600080fd5b8151615bc16152da8261528e565b818152846020838601011115615bd657600080fd5b6108c6826020830160208701615487565b600080600080600080600060e0888a031215615c0257600080fd5b8751602089015160408a015160608b015160808c015160a08d0151949b50929950909750955093506001600160401b03811115615c3e57600080fd5b615c4a8a828b01615ba2565b92505060c0880151615c5b8161530e565b8091505092959891949750929550565b600060208284031215615c7d57600080fd5b8151611cef8161530e565b600082615ca557634e487b7160e01b600052601260045260246000fd5b500490565b600060018201615cbc57615cbc61599c565b5060010190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b0394851681529290931660208301526040820152606081019190915260a06080820181905260009082015260c00190565b600060208284031215615d3157600080fd5b8151611cef8161559a565b600060208284031215615d4e57600080fd5b815160ff81168114611cef57600080fd5b60008154615d6c81615a18565b808552600182168015615d865760018114615da257615dd9565b60ff1983166020870152602082151560051b8701019350615dd9565b84600052602060002060005b83811015615dd05781546020828a010152600182019150602081019050615dae565b87016020019450505b50505092915050565b8281526040602082015260006108c66040830184615d5f565b60008251615e0d818460208701615487565b9190910192915050565b858152846020820152831515604082015260a060608201526000615e3e60a0830185615d5f565b90508260808301529695505050505050565b602081526000611cef60208301846154ab565b600081518084526020840193506020830160005b82811015615e95578151865260209586019590910190600101615e77565b5093949350505050565b6001600160a01b0385811682528416602082015260a060408201819052600090615ecb90830185615e63565b8281036060840152615edd8185615e63565b838103608090940193909352505060008152602001949350505050565b82815260408101611cef60208301846154ed565b60008060408385031215615f2157600080fd5b82516001600160401b03811115615f3757600080fd5b615f4385828601615ba2565b925050602083015161545a8161530e56fe0131395fc2023e9f088126b582709c056a327bb71617c4c4eceddafa98a0e2d335f68360d987e6ac1824ca88be7cd548a5e6e7b37ed928147ca1e92ddff1981ba264697066735822122007f78e7ad9c18487d1bc034f76a887a2e19663f77ccadc9b0622e629a193f66f64736f6c634300081a00330000000000000000000000000000000000000000000000000000000000000001000000000000000000000000ea7b7dc089c9a4a916b5a7a37617f59fd54e37e400000000000000000000000021468e63abf3783020750f7b2e57d4b34afafba6000000000000000000000000d32cb5f76989a27782e44c5297aaba728ad616690000000000000000000000004bfba79cf232361a53eddd17c67c6c77a6f003790000000000000000000000000000000000000000000000000000000000127500

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106101fb5760003560e01c806383d845e21161011a578063c3a2a93a116100ad578063d7b53a0e1161007c578063d7b53a0e146104b9578063ef7ec001146104cc578063f23a6e61146104df578063f482e962146104fe578063f8e261381461051157600080fd5b8063c3a2a93a14610433578063cc5b60f214610473578063cce84c8a14610486578063cf2bd598146104a657600080fd5b8063bb307151116100e9578063bb307151146103e5578063bc197c81146103f8578063c0d700fd14610417578063c1e291ea1461042a57600080fd5b806383d845e2146103ad578063973c96d5146103c05780639eb40277146103c9578063b5348aa9146103dc57600080fd5b80634adc7657116101925780637217ff12116101615780637217ff121461035457806372a127f91461037457806375e02cd9146103875780637d60a1461461039a57600080fd5b80634adc7657146102ee5780635b776c961461030e5780635d02c5e31461032e5780636a18ff7a1461034157600080fd5b80631c0b06ba116101ce5780631c0b06ba1461027c5780633b00b25a1461029d5780633dfebcca146102c857806342f39a3d146102db57600080fd5b806301ffc9a71461020057806310f7c98614610228578063150b7a021461023d578063199789fb14610269575b600080fd5b61021361020e36600461521e565b610571565b60405190151581526020015b60405180910390f35b61023b610236366004615323565b6105a8565b005b61025061024b366004615385565b6108bd565b6040516001600160e01b0319909116815260200161021f565b61023b6102773660046153f0565b6108ce565b61028f61028a36600461541c565b610c50565b60405190815260200161021f565b61028f6102ab366004615435565b600a60209081526000928352604080842090915290825290205481565b61023b6102d6366004615465565b610c5b565b61023b6102e93660046153f0565b610f1f565b6103016102fc366004615465565b611211565b60405161021f9190615501565b61028f61031c36600461541c565b600f6020526000908152604090205481565b61023b61033c366004615566565b611385565b61023b61034f3660046155a8565b611878565b61028f61036236600461541c565b6000908152600c602052604090205490565b6102136103823660046155e1565b611cc0565b61023b610395366004615465565b611cf6565b61023b6103a836600461541c565b611ead565b61023b6103bb36600461541c565b611f4d565b61028f60055481565b61023b6103d736600461560f565b612079565b61028f60065481565b61023b6103f3366004615667565b6127d4565b61025061040636600461570e565b63bc197c8160e01b95945050505050565b61023b61042536600461541c565b612ef3565b61028f60075481565b600254600354600454600154604080516001600160a01b03958616815293851660208501529184169183019190915291909116606082015260800161021f565b61023b61048136600461541c565b613108565b61049961049436600461541c565b6131a6565b60405161021f9190615811565b61023b6104b43660046155e1565b613392565b61023b6104c7366004615465565b61368b565b61028f6104da366004615917565b613788565b6102506104ed366004615940565b63f23a6e6160e01b95945050505050565b61023b61050c36600461541c565b613871565b61055c61051f366004615435565b60008281526008602090815260408083206001600160a01b039490941680845293825280832054948352600b825280832093835292905220549091565b6040805192835260208301919091520161021f565b60006001600160e01b03198216630271189760e51b14806105a257506301ffc9a760e01b6001600160e01b03198316145b92915050565b6105b0613b53565b60008481526008602090815260408083203384529091528120548591036105ea5760405163cf12280d60e01b815260040160405180910390fd5b60036000828152600d602052604090206012015460ff166004811115610612576106126154d7565b1461063057604051634291bdcd60e11b815260040160405180910390fd5b61063c611c20426159b2565b6000828152600a602090815260408083203384529091529020541115610675576040516377b92de560e11b815260040160405180910390fd5b848461068442620151806159c5565b81116106a357604051631da7447960e21b815260040160405180910390fd5b6000828152600c6020526040902054158015906106fe57506000828152600c6020526040902080548291906106da906001906159b2565b815481106106ea576106ea6159d8565b906000526020600020906005020160020154115b1561071c5760405163579e757560e11b815260040160405180910390fd5b60075461072942836159b2565b111561074857604051632b59e68560e11b815260040160405180910390fd5b6001600160a01b03841661076f57604051639792926760e01b815260040160405180910390fd5b6000878152600a602090815260408083203384528252808320429055898352600c82528083208054825160c081018452858152808501959095528483018b9052915191939092909160608301916107ca918b918b91016159ee565b60408051601f1981840301815291905281526020016002815260006020918201819052835460018181018655948252908290208351600590920201908155908201519281019290925560408101516002830155606081015190919060038201906108349082615a99565b50608082015160048201805460ff19166001836005811115610858576108586154d7565b021790555060a08201518160040160016101000a81548160ff0219169083151502179055505050600080516020615f75833981519152888260026040516108a193929190615b57565b60405180910390a1505050506108b76001600055565b50505050565b630a85bd0160e11b5b949350505050565b6108d6613b53565b60008381526008602090815260408083203384529091528120548491036109105760405163cf12280d60e01b815260040160405180910390fd5b60036000828152600d602052604090206012015460ff166004811115610938576109386154d7565b1461095657604051634291bdcd60e11b815260040160405180910390fd5b610962611c20426159b2565b6000828152600a60209081526040808320338452909152902054111561099b576040516377b92de560e11b815260040160405180910390fd5b83836109aa42620151806159c5565b81116109c957604051631da7447960e21b815260040160405180910390fd5b6000828152600c602052604090205415801590610a2457506000828152600c602052604090208054829190610a00906001906159b2565b81548110610a1057610a106159d8565b906000526020600020906005020160020154115b15610a425760405163579e757560e11b815260040160405180910390fd5b600754610a4f42836159b2565b1115610a6e57604051632b59e68560e11b815260040160405180910390fd5b600480546000888152600d60205260408082206001015490516327143fdd60e21b815293840152916001600160a01b0390911690639c50ff7490602401602060405180830381865afa158015610ac8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aec9190615b72565b9050610afb81620493e0615b8b565b851115610b1b57604051632160733960e01b815260040160405180910390fd5b6000878152600a602090815260408083203384528252808320429055898352600c82528083208054825160c0810184528581528085018681528185018d815285518088018e90528651808203890181529087019096526060830195865260036080840181905260a084018990526001808601875595895296909720825160058502909101908155905193810193909355945160028301559151919392909190820190610bc79082615a99565b50608082015160048201805460ff19166001836005811115610beb57610beb6154d7565b021790555060a08201518160040160016101000a81548160ff0219169083151502179055505050600080516020615f7583398151915288826003604051610c3493929190615b57565b60405180910390a15050505050610c4b6001600055565b505050565b60006105a282613bb1565b610c63613b53565b6000828152600860209081526040808320338452909152812054839103610c9d5760405163cf12280d60e01b815260040160405180910390fd5b60036000828152600d602052604090206012015460ff166004811115610cc557610cc56154d7565b14610ce357604051634291bdcd60e11b815260040160405180910390fd5b610cef611c20426159b2565b6000828152600a602090815260408083203384529091529020541115610d28576040516377b92de560e11b815260040160405180910390fd5b8282610d3742620151806159c5565b8111610d5657604051631da7447960e21b815260040160405180910390fd5b6000828152600c602052604090205415801590610db157506000828152600c602052604090208054829190610d8d906001906159b2565b81548110610d9d57610d9d6159d8565b906000526020600020906005020160020154115b15610dcf5760405163579e757560e11b815260040160405180910390fd5b600754610ddc42836159b2565b1115610dfb57604051632b59e68560e11b815260040160405180910390fd5b6000858152600c602081815260408084208054600a84528286203387528452828620429055938352815160c0810183528581528084018681528184018b815284518087019095528785526060830194855260016080840181905260a084018990528454808201865594895295909720825160059094020192835551938201939093559351600285015551919290916003820190610e989082615a99565b50608082015160048201805460ff19166001836005811115610ebc57610ebc6154d7565b021790555060a08201518160040160016101000a81548160ff0219169083151502179055505050600080516020615f7583398151915286826001604051610f0593929190615b57565b60405180910390a150505050610f1b6001600055565b5050565b610f27613b53565b6000838152600860209081526040808320338452909152812054849103610f615760405163cf12280d60e01b815260040160405180910390fd5b60036000828152600d602052604090206012015460ff166004811115610f8957610f896154d7565b14610fa757604051634291bdcd60e11b815260040160405180910390fd5b610fb3611c20426159b2565b6000828152600a602090815260408083203384529091529020541115610fec576040516377b92de560e11b815260040160405180910390fd5b8383610ffb42620151806159c5565b811161101a57604051631da7447960e21b815260040160405180910390fd5b6000828152600c60205260409020541580159061107557506000828152600c602052604090208054829190611051906001906159b2565b81548110611061576110616159d8565b906000526020600020906005020160020154115b156110935760405163579e757560e11b815260040160405180910390fd5b6007546110a042836159b2565b11156110bf57604051632b59e68560e11b815260040160405180910390fd5b621275008411156110e35760405163363d956160e11b815260040160405180910390fd5b6000868152600c602081815260408084208054600a84528286203387528452828620429055938352815160c0810183528581528084018681528184018c815284518087018d90528551808203880181529086019095526060830194855260056080840181905260a08401899052845460018082018755958a529690982083519690980290970194855551918401919091559351600283015551919291600382019061118e9082615a99565b50608082015160048201805460ff191660018360058111156111b2576111b26154d7565b021790555060a08201518160040160016101000a81548160ff0219169083151502179055505050600080516020615f75833981519152878260056040516111fb93929190615b57565b60405180910390a150505050610c4b6001600055565b611219615102565b6000838152600c602052604090205483908390811061124b576040516320d24e3960e21b815260040160405180910390fd5b6000858152600c6020526040902080548590811061126b5761126b6159d8565b90600052602060002090600502016040518060c00160405290816000820154815260200160018201548152602001600282015481526020016003820180546112b290615a18565b80601f01602080910402602001604051908101604052809291908181526020018280546112de90615a18565b801561132b5780601f106113005761010080835404028352916020019161132b565b820191906000526020600020905b81548152906001019060200180831161130e57829003601f168201915b5050509183525050600482015460209091019060ff166005811115611352576113526154d7565b6005811115611363576113636154d7565b815260049190910154610100900460ff16151560209091015295945050505050565b61138d613b53565b6000806000806000806000878060200190518101906113ac9190615be7565b600254604051633404591760e21b815260048101899052979e50959c50939a509198509650945092506000916001600160a01b039091169063d011645c90602401602060405180830381865afa15801561140a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061142e9190615b72565b9050336002546040516331a9108f60e11b8152600481018b90526001600160a01b039283169290911690636352211e90602401602060405180830381865afa15801561147e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114a29190615c6b565b6001600160a01b0316146114c95760405163158980c760e21b815260040160405180910390fd5b6001600160a01b0382166114f057604051639792926760e01b815260040160405180910390fd5b621275008511156115145760405163363d956160e11b815260040160405180910390fd5b600a6115246001831b6007615b8b565b61152e9190615c88565b87118061153d57506001811b86115b1561155b57604051632160733960e01b815260040160405180910390fd5b600654670de0b6b3a764000090611575906001841b615b8b565b61157f9190615c88565b861015806115cd5750670de0b6b3a7640000600654670de0b6b3a76400006115a791906159b2565b6115b4906001841b615b8b565b6115be9190615c88565b6115c99060016159c5565b8611155b156115eb57604051632160733960e01b815260040160405180910390fd5b60058054600091826115fc83615caa565b909155506000818152600d6020526040908190208151606081019092529192508061162d6001861b62030d40615b8b565b8152602001868152602001856001600160a01b031681525081600f016000820151816000015560208201518160010190816116689190615a99565b5060409190910151600291820180546001600160a01b0319166001600160a01b0390921691909117905560128201805460ff191660018302179055506040518060a001604052808b81526020018481526020018a81526020018981526020016116ce3390565b6001600160a01b039081169091528151600a8401556020820151600b8401556040820151600c8401556060820151600d840155608090910151600e830180546001600160a01b03191691831691909117905560048201889055600254166342842e0e33308d6040518463ffffffff1660e01b815260040161175193929190615cc3565b600060405180830381600087803b15801561176b57600080fd5b505af115801561177f573d6000803e3d6000fd5b505050508560001461182e57336003546040516331a9108f60e11b8152600481018990526001600160a01b039283169290911690636352211e90602401602060405180830381865afa1580156117d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117fd9190615c6b565b6001600160a01b03161461182457604051636b0c6fd160e01b815260040160405180910390fd5b61182e8287613c79565b6040518281527fe2d77c4a35bb326277ff28842c7df62528e9dfdf2fbd905b6847260baaa1544f9060200160405180910390a1505050505050505050506118756001600055565b50565b611880613b53565b60008381526008602090815260408083203384529091528120548491036118ba5760405163cf12280d60e01b815260040160405180910390fd5b6000848152600c60205260409020548490849081106118ec576040516320d24e3960e21b815260040160405180910390fd5b6000868152600c6020526040812080548790811061190c5761190c6159d8565b60009182526020909120600590910201905060046000888152600d602052604090206012015460ff166004811115611946576119466154d7565b0361196457604051633cb1a52960e11b815260040160405180910390fd5b6004810154610100900460ff161561198f576040516331b7690560e21b815260040160405180910390fd5b80600201544211156119b45760405163e7110eeb60e01b815260040160405180910390fd5b6000878152600960209081526040808320898452825280832033845290915290205460ff16156119f757604051633526430d60e21b815260040160405180910390fd5b6000878152600960209081526040808320898452825280832033808552908352818420805460ff1916600117905560028501548b8552600b84528285209185529252909120541015611a635760028101546000888152600b602090815260408083203384529091529020555b600087815260086020908152604080832033845290915290205485611aa15780826001016000828254611a9691906159c5565b925050819055611abc565b80826000016000828254611ab591906159c5565b9250508190555b506004805460008a8152600d60205260408082206001015490516314bd9ae160e21b815293840152916001600160a01b03909116906352f66b8490602401602060405180830381865afa158015611b17573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b3b9190615b72565b90506001600484015460ff166005811115611b5857611b586154d7565b1480611b7b575060048084015460ff166005811115611b7957611b796154d7565b145b15611bcf57670de0b6b3a764000060065482611b979190615b8b565b611ba19190615c88565b87611bb0578360010154611bb3565b83545b10611bca5760048301805461ff0019166101001790555b611bfe565b600181901c87611be3578360010154611be6565b83545b1115611bfe5760048301805461ff0019166101001790555b6004830154610100900460ff1615611c62578615611c2057611c20898961411c565b604080518a8152602081018a90528815158183015290517fb8ac4a4d36edbe09a20cdee3233447c1f9f8b2f96df83a710544665a6265c6349181900360600190a15b604080518a81523360208201528082018a905288151560608201526080810184905290517f6f9a5c8fa54dd9373ca24b4ea210568e42186dc9b9aed297349d11f18c1aa11f9181900360a00190a1505050505050610c4b6001600055565b600083815260096020908152604080832085845282528083206001600160a01b038516845290915290205460ff165b9392505050565b611cfe613b53565b8160036000828152600d602052604090206012015460ff166004811115611d2757611d276154d7565b14611d4557604051634291bdcd60e11b815260040160405180910390fd5b6000838152600d602052604081206004549091906001600160a01b031662fdd58e3360038501546040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401602060405180830381865afa158015611db5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dd99190615b72565b905080841180611de7575080155b15611e055760405163cf12280d60e01b815260040160405180910390fd5b600480546003840154604051637921219560e11b81526001600160a01b039092169263f242432a92611e3d92339230928b9101615ce7565b600060405180830381600087803b158015611e5757600080fd5b505af1158015611e6b573d6000803e3d6000fd5b505050600086815260086020908152604080832033845290915281208054879350909190611e9a9084906159c5565b9091555050600160005550610f1b915050565b611eb5613b53565b6000818152600d602052604090206011015481906001600160a01b03163314611ef15760405163786b543160e11b815260040160405180910390fd5b8160036000828152600d602052604090206012015460ff166004811115611f1a57611f1a6154d7565b14611f3857604051634291bdcd60e11b815260040160405180910390fd5b611f4183614203565b50506118756001600055565b611f55613b53565b60046000828152600d602052604090206012015460ff166004811115611f7d57611f7d6154d7565b14158015611f9857506000818152600c602052604090205415155b8015611fbd57506000818152600b602090815260408083203384529091529020544211155b15611fdb5760405163ab1e1f4760e01b815260040160405180910390fd5b6000818152600d602090815260408083206008835281842033808652935281842080549490556004805460038301549351637921219560e11b81529295946001600160a01b039091169363f242432a9361203b9330939291889101615ce7565b600060405180830381600087803b15801561205557600080fd5b505af1158015612069573d6000803e3d6000fd5b5050505050506118756001600055565b612081613b53565b3360048054604051631819659760e01b81529182018690526001600160a01b03928316921690631819659790602401602060405180830381865afa1580156120cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120f19190615c6b565b6001600160a01b0316146121185760405163d47118cb60e01b815260040160405180910390fd5b60048054604051634e8c72a160e11b81529182018590526001600160a01b031690639d18e54290602401602060405180830381865afa15801561215f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121839190615d1f565b6121a057604051633022989960e01b815260040160405180910390fd5b6000838152600f6020526040902054156121cd5760405163bafab1af60e01b815260040160405180910390fd5b6001600160a01b0382166121f457604051639792926760e01b815260040160405180910390fd5b600080612200856145e1565b91509150621275008211156122285760405163363d956160e11b815260040160405180910390fd5b80612246576040516329f38e3f60e21b815260040160405180910390fd5b600580546000918261225783615caa565b9190505590506040518060a00160405280426201518061227791906159c5565b8152602001878152602001600188901b8152602001600188901b600161229d91906159c5565b815260209081018590526000838152600d8252604080822084518155928401516001840155838101516002840155606084015160038401556080909301516004928301558154925163637c77f160e01b8152918201899052916001600160a01b03169063637c77f190602401602060405180830381865afa158015612326573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061234a9190615b72565b60048054604051632cd3581b60e11b81529182018a90529192506000916001600160a01b0316906359a6b03690602401602060405180830381865afa158015612397573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123bb9190615b72565b600254604051633404591760e21b8152600481018590529192506000916001600160a01b039091169063d011645c90602401602060405180830381865afa15801561240a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061242e9190615b72565b6003546040516392680e9560e01b8152600481018590529192506000916001600160a01b03909116906392680e9590602401602060405180830381865afa15801561247d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124a19190615d3c565b600480546040516327143fdd60e21b81529182018d905260ff9290921692506000916001600160a01b031690639c50ff7490602401602060405180830381865afa1580156124f3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125179190615b72565b90508282146125395760405163042c06c160e51b815260040160405180910390fd5b6040518060a00160405280868152602001848152602001600a83600761255f9190615b8b565b6125699190615c88565b815260200182815260200161257b3390565b6001600160a01b039081169091526000888152600d602081815260408084208651600a82015586830151600b82015586820151600c82015560608088015194820194909455608096870151600e90910180546001600160a01b0319169190961617909455835160a081018552898152908101879052928301829052820152908101336001600160a01b039081169091526000888152600d6020908152604091829020845160058201559084015160068201558382015160078201556060808501516008830155608090940151600990910180546001600160a01b031916919093161790915580519182019052806126758362030d40615b8b565b815260208082018c90526001600160a01b038d166040928301526000898152600d8252919091208251600f8201908155918301516010909101906126b99082615a99565b50604091820151600291820180546001600160a01b0319166001600160a01b039283161790556000898152600d6020529290922060128101805460ff1916600117905560045491015491169063f242432a9033903090600a61271c876003615b8b565b6127269190615c88565b6040518563ffffffff1660e01b81526004016127459493929190615ce7565b600060405180830381600087803b15801561275f57600080fd5b505af1158015612773573d6000803e3d6000fd5b50505060008c8152600f602052604090819020889055517fe2d77c4a35bb326277ff28842c7df62528e9dfdf2fbd905b6847260baaa1544f91506127ba9088815260200190565b60405180910390a15050505050505050610c4b6001600055565b6127dc613b53565b6000828152600d602052604090206004601282015460ff166004811115612805576128056154d7565b14158061282657506000838152600e602052604090205460ff161515600114155b1561284457604051637bf390dd60e11b815260040160405180910390fd5b6004546000906001600160a01b031662fdd58e33600385015460405160e084901b6001600160e01b03191681526001600160a01b0390921660048301526024820152604401602060405180830381865afa1580156128a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128ca9190615b72565b6004549091506000906001600160a01b031662fdd58e33600286015460405160e084901b6001600160e01b03191681526001600160a01b0390921660048301526024820152604401602060405180830381865afa15801561292f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129539190615b72565b60018401546000878152600860209081526040808320338452909152902054919250908215801561298b575061298984826159c5565b155b156129a9576040516350114cab60e11b815260040160405180910390fd5b60008315612cbf5760006129bc84613bb1565b9050871515600003612b915760048054604051637e123fa960e11b81529182018690526001600160a01b03169063fc247f5290602401602060405180830381865afa158015612a0f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a339190615b72565b15612a51576040516357e4670f60e01b815260040160405180910390fd5b60045481906001600160a01b0316638a82f24086336040516001600160e01b031960e085901b16815260048101929092526001600160a01b03166024820152604401602060405180830381865afa158015612ab0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ad49190615b72565b14612af257604051630b0c5a4f60e01b815260040160405180910390fd5b6004546001600160a01b03166352aa993285336040516001600160e01b031960e085901b16815260048101929092526001600160a01b03166024820152604401602060405180830381865afa158015612b4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b739190615b72565b15612b9157604051632dd674ab60e21b815260040160405180910390fd5b6013870154600480546040516327143fdd60e21b81529182018790526000916001600160a01b0390911690639c50ff7490602401602060405180830381865afa158015612be2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c069190615b72565b90506000600a612c17836007615b8b565b612c219190615c88565b9050600081612c308a86615b8b565b612c3a9190615c88565b6004549091506001600160a01b031663f242432a3360028e01546040516001600160e01b031960e085901b168152612c79929130918f90600401615ce7565b600060405180830381600087803b158015612c9357600080fd5b505af1158015612ca7573d6000803e3d6000fd5b505050508086612cb791906159c5565b955050505050505b6000612ccb83876159c5565b1115612e1f57600480546040516314bd9ae160e21b81529182018590526000916001600160a01b03909116906352f66b8490602401602060405180830381865afa158015612d1d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d419190615b72565b90506000620f424088600a01600101546001901b612d5f9190615b8b565b9050600082612d6e868a6159c5565b612d789084615b8b565b612d829190615c88565b60008c815260086020908152604080832033845290915281205590508715612e0f576004805460038b0154604051637921219560e11b81526001600160a01b039092169263f242432a92612ddc92339230928f9101615ce7565b600060405180830381600087803b158015612df657600080fd5b505af1158015612e0a573d6000803e3d6000fd5b505050505b612e1981856159c5565b93505050505b8015612ee3576001546001600160a01b031663a9059cbb336040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602481018490526044016020604051808303816000875af1158015612e84573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ea89190615d1f565b5060408051898152602081018390527f4a190041baaa7b7da28a2bb3ad8330bdfb955271be9959517121bfb1c2900f54910160405180910390a15b505050505050610f1b6001600055565b612efb613b53565b6000818152600d60205260409020600180820154601283015490919060ff166004811115612f2b57612f2b6154d7565b14612f49576040516362be612960e01b815260040160405180910390fd5b600e8201546001600160a01b0316336001600160a01b031614612f7f5760405163d47118cb60e01b815260040160405180910390fd5b60048054604051631819659760e01b815291820183905230916001600160a01b0390911690631819659790602401602060405180830381865afa158015612fca573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fee9190615c6b565b6001600160a01b0316146130155760405163d47118cb60e01b815260040160405180910390fd5b60048054604051631d1a064960e11b81526001600160a01b0390911691633a340c9291613049918591601088019101615de2565b600060405180830381600087803b15801561306357600080fd5b505af1158015613077573d6000803e3d6000fd5b5050600480548582015460405163f7ce46b760e01b815292830186905260248301526001600160a01b0316925063f7ce46b79150604401600060405180830381600087803b1580156130c857600080fd5b505af11580156130dc573d6000803e3d6000fd5b5050506000848152600d60205260408120601201805460ff191660031790556001905550611875915050565b613110613b53565b6000818152600d60205260409020600e015481906001600160a01b0316331461314c5760405163158980c760e21b815260040160405180910390fd5b60026000838152600d602052604090206012015460ff166004811115613174576131746154d7565b1461319257604051633949e7c760e21b815260040160405180910390fd5b61319b826146b3565b506118756001600055565b6131ae615149565b6000828152600d6020818152604092839020835161016081018552815460c08201908152600183015460e08301526002830154610100830152600383015461012083015260048301546101408301528152845160a0818101875260058401548252600684015482860152600784015482880152600884015460608084019190915260098501546001600160a01b039081166080808601919091528588019490945288519283018952600a8601548352600b86015483880152600c860154838a01529685015482820152600e85015490961691810191909152818601528451808501909552600f820180548652601083018054929693958701949192918401916132b690615a18565b80601f01602080910402602001604051908101604052809291908181526020018280546132e290615a18565b801561332f5780601f106133045761010080835404028352916020019161332f565b820191906000526020600020905b81548152906001019060200180831161331257829003601f168201915b5050509183525050600291909101546001600160a01b0316602091820152908252601283015491019060ff16600481111561336c5761336c6154d7565b600481111561337d5761337d6154d7565b81526020016013820154815250509050919050565b61339a613b53565b60008381526008602090815260408083203384529091528120548491036133d45760405163cf12280d60e01b815260040160405180910390fd5b60036000828152600d602052604090206012015460ff1660048111156133fc576133fc6154d7565b1461341a57604051634291bdcd60e11b815260040160405180910390fd5b613426611c20426159b2565b6000828152600a60209081526040808320338452909152902054111561345f576040516377b92de560e11b815260040160405180910390fd5b838361346e42620151806159c5565b811161348d57604051631da7447960e21b815260040160405180910390fd5b6000828152600c6020526040902054158015906134e857506000828152600c6020526040902080548291906134c4906001906159b2565b815481106134d4576134d46159d8565b906000526020600020906005020160020154115b156135065760405163579e757560e11b815260040160405180910390fd5b60075461351342836159b2565b111561353257604051632b59e68560e11b815260040160405180910390fd5b6001600160a01b038416158061355057506001600160a01b03841630145b1561356e57604051639792926760e01b815260040160405180910390fd5b6000868152600a602090815260408083203384528252808320429055888352600c82528083208054825160c0810184528581528085018681528185018c815285516001600160a01b038d1681890152865180820389018152908701909652606083019586526004608084015260a0830188905260018085018655948852959096208151600584029091019081559551928601929092559251600285015590519192909160038201906136209082615a99565b50608082015160048201805460ff19166001836005811115613644576136446154d7565b021790555060a09190910151600491820180549115156101000261ff0019909216919091179055604051600080516020615f75833981519152916111fb918a918591615b57565b613693613b53565b80336003546040516331a9108f60e11b8152600481018490526001600160a01b039283169290911690636352211e90602401602060405180830381865afa1580156136e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137069190615c6b565b6001600160a01b03161461372d57604051636b0c6fd160e01b815260040160405180910390fd5b60026000848152600d602052604090206012015460ff166004811115613755576137556154d7565b1461377357604051633949e7c760e21b815260040160405180910390fd5b61377d8383613c79565b50610f1b6001600055565b600480546000848152600d60205260408082206001015490516314bd9ae160e21b8152938401529182916001600160a01b0316906352f66b8490602401602060405180830381865afa1580156137e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138069190615b72565b9050600183600581111561381c5761381c6154d7565b148061383957506004836005811115613837576138376154d7565b145b1561386757670de0b6b3a7640000600654826138559190615b8b565b61385f9190615c88565b9150506105a2565b60011c9392505050565b613879613b53565b6000818152600d6020526040902060018082015490601283015460ff1660048111156138a7576138a76154d7565b146138c5576040516362be612960e01b815260040160405180910390fd5b600e8201546001600160a01b0316336001600160a01b0316146138fb5760405163158980c760e21b815260040160405180910390fd5b60128201805460ff191660049081179091558054604051631819659760e01b815291820183905230916001600160a01b0390911690631819659790602401602060405180830381865afa158015613956573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061397a9190615c6b565b6001600160a01b0316036139fb576004546001600160a01b0316639732d56f82336040516001600160e01b031960e085901b16815260048101929092526001600160a01b03166024820152604401600060405180830381600087803b1580156139e257600080fd5b505af11580156139f6573d6000803e3d6000fd5b505050505b600480546040516327143fdd60e21b81529182018390526000916001600160a01b0390911690639c50ff7490602401602060405180830381865afa158015613a47573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a6b9190615b72565b6004549091506001600160a01b031663f242432a30336000888152600d6020526040902060020154600a613aa0876003615b8b565b613aaa9190615c88565b6040518563ffffffff1660e01b8152600401613ac99493929190615ce7565b600060405180830381600087803b158015613ae357600080fd5b505af1158015613af7573d6000803e3d6000fd5b5050506000838152600f602052604080822091909155517f0b021add1edbb328ed48ca0a1905c666ab931678b4a7602d219c496d174bf0259150613b3e9086815260200190565b60405180910390a15050506118756001600055565b600260005403613baa5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064015b60405180910390fd5b6002600055565b60045460408051602480820185905282518083039091018152604490910182526020810180516001600160e01b03166323f0aa7160e11b1790529051600092839283926001600160a01b0390921691613c0a9190615dfb565b600060405180830381855afa9150503d8060008114613c45576040519150601f19603f3d011682016040523d82523d6000602084013e613c4a565b606091505b509150915081613c6d57604051633022989960e01b815260040160405180910390fd5b61014001519392505050565b6000828152600d602052604080822060035491516392680e9560e01b8152600481018590529092916001600160a01b0316906392680e9590602401602060405180830381865afa158015613cd1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613cf59190615d3c565b600b83015460ff9190911691506001811b908214613d265760405163042c06c160e51b815260040160405180910390fd5b60128301805460ff191660031790556040805160a08101825285815260208101849052600c8501549091820190600a613d60856007615b8b565b613d6a9190615c88565b613d7491906159b2565b815260200184600a016003015483613d8c91906159b2565b815233602091820152815160058601558181015160068601556040808301516007870155606083015160088701556080909201516009860180546001600160a01b0319166001600160a01b03928316179055600480548451636da58de360e01b815294516000959190931693636da58de393828401939192909190829003018187875af1158015613e21573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e459190615b72565b6000818152600f602052604090819020889055805160a0810190915290915080613e7242620151806159c5565b8152602001828152602001600183901b8152602001600183901b6001613e9891906159c5565b8152600486018054602092830152825187559082015160018701556040820151600287015560608201516003808801919091556080909201519055546001600160a01b03166342842e0e3330886040518463ffffffff1660e01b8152600401613f0393929190615cc3565b600060405180830381600087803b158015613f1d57600080fd5b505af1158015613f31573d6000803e3d6000fd5b50506003546004805460405163095ea7b360e01b81526001600160a01b0391821692810192909252602482018a9052909116925063095ea7b39150604401600060405180830381600087803b158015613f8957600080fd5b505af1158015613f9d573d6000803e3d6000fd5b505060025460048054600a89015460405163095ea7b360e01b81526001600160a01b03928316938101939093526024830152909116925063095ea7b39150604401600060405180830381600087803b158015613ff857600080fd5b505af115801561400c573d6000803e3d6000fd5b505060048054600a880154888301546040516306badddb60e21b81526001600160a01b039093169550631aeb776c9450614052938b9360019260108d0192909101615e17565b600060405180830381600087803b15801561406c57600080fd5b505af1158015614080573d6000803e3d6000fd5b505050600985015460028601546003870154600788015460088901546140b295506001600160a01b0390941693614899565b600e84015460028501546003860154600c870154600d8801546140e1946001600160a01b031693929190614899565b6040518681527ff2fb170bc0fd9ce44083044170a7f85cd4887f40565b5439b1886f8f5ec026429060200160405180910390a1505050505050565b6000828152600c6020526040812080548390811061413c5761413c6159d8565b600091825260209091206004600590920201015460ff1690506001816005811115614169576141696154d7565b0361417757614177836149cb565b600281600581111561418b5761418b6154d7565b0361419a5761419a8383614a9b565b60038160058111156141ae576141ae6154d7565b036141bd576141bd8383614c4c565b60048160058111156141d1576141d16154d7565b036141e0576141e08383614d64565b60058160058111156141f4576141f46154d7565b03610c4b57610c4b8383614f90565b6000818152600d602052604080822060015491516370a0823160e01b81523060048201529092916001600160a01b0316906370a0823190602401602060405180830381865afa15801561425a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061427e9190615b72565b60048054600185015460405163f62b46c960e01b8152928301529192506001600160a01b039091169063f62b46c990602401600060405180830381600087803b1580156142ca57600080fd5b505af19250505080156142db575060015b614368573d808015614309576040519150601f19603f3d011682016040523d82523d6000602084013e61430e565b606091505b50805160208083019190912060408051600481526024810190915291820180516001600160e01b03166374d4d10160e11b178152915190912014614366578060405162461bcd60e51b8152600401613ba19190615e50565b505b6001546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa1580156143b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906143d59190615b72565b905060006143e383836159b2565b905080156145da57600b840154600090614404906001901b622dc6c0615b8b565b600f8601546144139084615b8b565b61441e90600a615b8b565b6144289190615c88565b9050600061443682846159b2565b90506004601287015460ff166004811115614453576144536154d7565b14614541576001546004805460405163095ea7b360e01b81526001600160a01b0391821692810192909252602482018490529091169063095ea7b3906044016020604051808303816000875af11580156144b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144d59190615d1f565b5060048054600188015460405163032b9ebf60e21b815292830152602482018390526001600160a01b031690630cae7afc90604401600060405180830381600087803b15801561452457600080fd5b505af1158015614538573d6000803e3d6000fd5b5050505061455b565b8086601301600082825461455591906159c5565b90915550505b600154601187015460405163a9059cbb60e01b81526001600160a01b0391821660048201526024810185905291169063a9059cbb906044016020604051808303816000875af11580156145b2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906145d69190615d1f565b5050505b5050505050565b60045460408051602480820185905282518083039091018152604490910182526020810180516001600160e01b03166323f0aa7160e11b17905290516000928392839283926001600160a01b03169161463991615dfb565b600060405180830381855afa9150503d8060008114614674576040519150601f19603f3d011682016040523d82523d6000602084013e614679565b606091505b50915091508161469c57604051633022989960e01b815260040160405180910390fd5b61016081015193506101a081015192505050915091565b6000818152600d60205260408120906003601283015460ff1660048111156146dd576146dd6154d7565b60128401805460ff191660041790551490508061476a57600254600e830154600a840154604051632142170760e11b81526001600160a01b03938416936342842e0e936147339330939290911691600401615cc3565b600060405180830381600087803b15801561474d57600080fd5b505af1158015614761573d6000803e3d6000fd5b50505050614861565b60035460098301546005840154604051632142170760e11b81526001600160a01b03938416936342842e0e936147a99330939290911691600401615cc3565b600060405180830381600087803b1580156147c357600080fd5b505af11580156147d7573d6000803e3d6000fd5b505050506147e483614203565b6000838152600e602052604090819020805460ff19166001179055600254600a840154915163db006a7560e01b815260048101929092526001600160a01b03169063db006a7590602401600060405180830381600087803b15801561484857600080fd5b505af115801561485c573d6000803e3d6000fd5b505050505b6040518381527f0b021add1edbb328ed48ca0a1905c666ab931678b4a7602d219c496d174bf0259060200160405180910390a1505050565b6040805160028082526060820183526000926020830190803683370190505090508282826000815181106148cf576148cf6159d8565b60200260200101836001815181106148e9576148e96159d8565b60209081029190910101919091525260408051600280825260608201909252600091816020016020820280368337019050509050858582600081518110614932576149326159d8565b602002602001018360018151811061494c5761494c6159d8565b60209081029190910101919091525260048054604051631759616b60e11b81526001600160a01b0390911691632eb2c2d6916149909130918c918791899101615e9f565b600060405180830381600087803b1580156149aa57600080fd5b505af11580156149be573d6000803e3d6000fd5b5050505050505050505050565b6000818152600d60205260409020544210156149fa57604051631b64953f60e11b815260040160405180910390fd5b600480546000838152600d602052604090819020600101549051631444354960e01b8152928301526001600160a01b031690631444354990602401600060405180830381600087803b158015614a4f57600080fd5b505af1158015614a63573d6000803e3d6000fd5b50505050614a70816146b3565b600080516020615f55833981519152816001604051614a90929190615efa565b60405180910390a150565b6000828152600d60205260409020614ab283614203565b6000838152600c60205260408120805482919085908110614ad557614ad56159d8565b90600052602060002090600502016003018054614af190615a18565b80601f0160208091040260200160405190810160405280929190818152602001828054614b1d90615a18565b8015614b6a5780601f10614b3f57610100808354040283529160200191614b6a565b820191906000526020600020905b815481529060010190602001808311614b4d57829003601f168201915b5050505050806020019051810190614b829190615f0e565b6011850180546001600160a01b0319166001600160a01b038316179055909250905060108301614bb28382615a99565b50600480546001850154604051631d1a064960e11b81526001600160a01b0390921692633a340c9292614beb9291601089019101615de2565b600060405180830381600087803b158015614c0557600080fd5b505af1158015614c19573d6000803e3d6000fd5b50505050600080516020615f55833981519152856002604051614c3d929190615efa565b60405180910390a15050505050565b614c5582614203565b6000828152600c60205260409020805482908110614c7557614c756159d8565b90600052602060002090600502016003018054614c9190615a18565b80601f0160208091040260200160405190810160405280929190818152602001828054614cbd90615a18565b8015614d0a5780601f10614cdf57610100808354040283529160200191614d0a565b820191906000526020600020905b815481529060010190602001808311614ced57829003601f168201915b5050505050806020019051810190614d229190615b72565b6000838152600d602052604090819020600f019190915551600080516020615f5583398151915290614d58908490600390615efa565b60405180910390a15050565b6000828152600d602090815260408083206001810154600c909352908320805491939185908110614d9757614d976159d8565b90600052602060002090600502016003018054614db390615a18565b80601f0160208091040260200160405190810160405280929190818152602001828054614ddf90615a18565b8015614e2c5780601f10614e0157610100808354040283529160200191614e2c565b820191906000526020600020905b815481529060010190602001808311614e0f57829003601f168201915b5050505050806020019051810190614e449190615c6b565b60048054604051639732d56f60e01b81529293506001600160a01b031691639732d56f91614e889186918691019182526001600160a01b0316602082015260400190565b600060405180830381600087803b158015614ea257600080fd5b505af1158015614eb6573d6000803e3d6000fd5b50505050614ec385614203565b60128301805460ff19166004908117909155600284015460038501548254604051627eeac760e11b8152309481019490945260248401839052614f5e93859392916001600160a01b03169062fdd58e90604401602060405180830381865afa158015614f33573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614f579190615b72565b6000614899565b6000828152600f60205260408082209190915551600080516020615f5583398151915290614c3d908790600490615efa565b6000828152600c60205260409020805482908110614fb057614fb06159d8565b90600052602060002090600502016003018054614fcc90615a18565b80601f0160208091040260200160405190810160405280929190818152602001828054614ff890615a18565b80156150455780601f1061501a57610100808354040283529160200191615045565b820191906000526020600020905b81548152906001019060200180831161502857829003601f168201915b505050505080602001905181019061505d9190615b72565b6000838152600d60205260409081902060048082018490558054600190920154925163f7ce46b760e01b81526001600160a01b039092169363f7ce46b7936150b093909201918252602082015260400190565b600060405180830381600087803b1580156150ca57600080fd5b505af11580156150de573d6000803e3d6000fd5b50505050600080516020615f55833981519152826005604051614d58929190615efa565b6040518060c00160405280600081526020016000815260200160008152602001606081526020016000600581111561513c5761513c6154d7565b8152600060209091015290565b6040518060c001604052806151866040518060a0016040528060008152602001600081526020016000815260200160008152602001600081525090565b81526020016151936151e6565b81526020016151a06151e6565b81526020016151d26040518060600160405280600081526020016060815260200160006001600160a01b031681525090565b815260200160008152602001600081525090565b6040518060a001604052806000815260200160008152602001600081526020016000815260200160006001600160a01b031681525090565b60006020828403121561523057600080fd5b81356001600160e01b031981168114611cef57600080fd5b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b038111828210171561528657615286615248565b604052919050565b60006001600160401b038211156152a7576152a7615248565b50601f01601f191660200190565b600082601f8301126152c657600080fd5b81356020830160006152df6152da8461528e565b61525e565b90508281528583830111156152f357600080fd5b82826020830137600092810160200192909252509392505050565b6001600160a01b038116811461187557600080fd5b6000806000806080858703121561533957600080fd5b843593506020850135925060408501356001600160401b0381111561535d57600080fd5b615369878288016152b5565b925050606085013561537a8161530e565b939692955090935050565b6000806000806080858703121561539b57600080fd5b84356153a68161530e565b935060208501356153b68161530e565b92506040850135915060608501356001600160401b038111156153d857600080fd5b6153e4878288016152b5565b91505092959194509250565b60008060006060848603121561540557600080fd5b505081359360208301359350604090920135919050565b60006020828403121561542e57600080fd5b5035919050565b6000806040838503121561544857600080fd5b82359150602083013561545a8161530e565b809150509250929050565b6000806040838503121561547857600080fd5b50508035926020909101359150565b60005b838110156154a257818101518382015260200161548a565b50506000910152565b600081518084526154c3816020860160208601615487565b601f01601f19169290920160200192915050565b634e487b7160e01b600052602160045260246000fd5b600681106154fd576154fd6154d7565b9052565b602081528151602082015260208201516040820152604082015160608201526000606083015160c0608084015261553b60e08401826154ab565b9050608084015161554f60a08501826154ed565b5060a0840151151560c08401528091505092915050565b60006020828403121561557857600080fd5b81356001600160401b0381111561558e57600080fd5b6108c6848285016152b5565b801515811461187557600080fd5b6000806000606084860312156155bd57600080fd5b833592506020840135915060408401356155d68161559a565b809150509250925092565b6000806000606084860312156155f657600080fd5b833592506020840135915060408401356155d68161530e565b60008060006060848603121561562457600080fd5b8335925060208401356156368161530e565b915060408401356001600160401b0381111561565157600080fd5b61565d868287016152b5565b9150509250925092565b6000806040838503121561567a57600080fd5b82359150602083013561545a8161559a565b600082601f83011261569d57600080fd5b81356001600160401b038111156156b6576156b6615248565b8060051b6156c66020820161525e565b918252602081850181019290810190868411156156e257600080fd5b6020860192505b838310156157045782358252602092830192909101906156e9565b9695505050505050565b600080600080600060a0868803121561572657600080fd5b85356157318161530e565b945060208601356157418161530e565b935060408601356001600160401b0381111561575c57600080fd5b6157688882890161568c565b93505060608601356001600160401b0381111561578457600080fd5b6157908882890161568c565b92505060808601356001600160401b038111156157ac57600080fd5b6157b8888289016152b5565b9150509295509295909350565b8051825260006020820151606060208501526157e460608501826154ab565b6040938401516001600160a01b0316949093019390935250919050565b600581106154fd576154fd6154d7565b602081526000825180516020840152602081015160408401526040810151606084015260608101516080840152608081015160a084015250602083015161588c60c0840182805182526020808201519083015260408082015190830152606080820151908301526080908101516001600160a01b0316910152565b5060408381015180516101608501526020810151610180850152908101516101a084015260608101516101c084015260808101516001600160a01b03166101e08401525060608301516102406102008401526158ec6102608401826157c5565b90506080840151615901610220850182615801565b5060a08401516102408401528091505092915050565b6000806040838503121561592a57600080fd5b8235915060208301356006811061545a57600080fd5b600080600080600060a0868803121561595857600080fd5b85356159638161530e565b945060208601356159738161530e565b9350604086013592506060860135915060808601356001600160401b038111156157ac57600080fd5b634e487b7160e01b600052601160045260246000fd5b818103818111156105a2576105a261599c565b808201808211156105a2576105a261599c565b634e487b7160e01b600052603260045260246000fd5b604081526000615a0160408301856154ab565b905060018060a01b03831660208301529392505050565b600181811c90821680615a2c57607f821691505b602082108103615a4c57634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115610c4b57806000526020600020601f840160051c81016020851015615a795750805b601f840160051c820191505b818110156145da5760008155600101615a85565b81516001600160401b03811115615ab257615ab2615248565b615ac681615ac08454615a18565b84615a52565b6020601f821160018114615afa5760008315615ae25750848201515b600019600385901b1c1916600184901b1784556145da565b600084815260208120601f198516915b82811015615b2a5787850151825560209485019460019092019101615b0a565b5084821015615b485786840151600019600387901b60f8161c191681555b50505050600190811b01905550565b83815260208101839052606081016108c660408301846154ed565b600060208284031215615b8457600080fd5b5051919050565b80820281158282048414176105a2576105a261599c565b600082601f830112615bb357600080fd5b8151615bc16152da8261528e565b818152846020838601011115615bd657600080fd5b6108c6826020830160208701615487565b600080600080600080600060e0888a031215615c0257600080fd5b8751602089015160408a015160608b015160808c015160a08d0151949b50929950909750955093506001600160401b03811115615c3e57600080fd5b615c4a8a828b01615ba2565b92505060c0880151615c5b8161530e565b8091505092959891949750929550565b600060208284031215615c7d57600080fd5b8151611cef8161530e565b600082615ca557634e487b7160e01b600052601260045260246000fd5b500490565b600060018201615cbc57615cbc61599c565b5060010190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b0394851681529290931660208301526040820152606081019190915260a06080820181905260009082015260c00190565b600060208284031215615d3157600080fd5b8151611cef8161559a565b600060208284031215615d4e57600080fd5b815160ff81168114611cef57600080fd5b60008154615d6c81615a18565b808552600182168015615d865760018114615da257615dd9565b60ff1983166020870152602082151560051b8701019350615dd9565b84600052602060002060005b83811015615dd05781546020828a010152600182019150602081019050615dae565b87016020019450505b50505092915050565b8281526040602082015260006108c66040830184615d5f565b60008251615e0d818460208701615487565b9190910192915050565b858152846020820152831515604082015260a060608201526000615e3e60a0830185615d5f565b90508260808301529695505050505050565b602081526000611cef60208301846154ab565b600081518084526020840193506020830160005b82811015615e95578151865260209586019590910190600101615e77565b5093949350505050565b6001600160a01b0385811682528416602082015260a060408201819052600090615ecb90830185615e63565b8281036060840152615edd8185615e63565b838103608090940193909352505060008152602001949350505050565b82815260408101611cef60208301846154ed565b60008060408385031215615f2157600080fd5b82516001600160401b03811115615f3757600080fd5b615f4385828601615ba2565b925050602083015161545a8161530e56fe0131395fc2023e9f088126b582709c056a327bb71617c4c4eceddafa98a0e2d335f68360d987e6ac1824ca88be7cd548a5e6e7b37ed928147ca1e92ddff1981ba264697066735822122007f78e7ad9c18487d1bc034f76a887a2e19663f77ccadc9b0622e629a193f66f64736f6c634300081a0033

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

0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000ea7b7dc089c9a4a916b5a7a37617f59fd54e37e400000000000000000000000021468e63abf3783020750f7b2e57d4b34afafba6000000000000000000000000d32cb5f76989a27782e44c5297aaba728ad616690000000000000000000000004bfba79cf232361a53eddd17c67c6c77a6f003790000000000000000000000000000000000000000000000000000000000127500

-----Decoded View---------------
Arg [0] : _consensusOption (uint8): 1
Arg [1] : _hypcToken (address): 0xeA7B7DC089c9a4A916B5a7a37617f59fD54e37E4
Arg [2] : _chypcV2 (address): 0x21468e63abF3783020750F7b2e57d4B34aFAfba6
Arg [3] : _licenseContract (address): 0xd32CB5f76989A27782e44c5297AAba728Ad61669
Arg [4] : _hypcShareTokens (address): 0x4BFbA79CF232361a53eDdd17C67C6c77A6F00379
Arg [5] : _maxVotingTime (uint256): 1209600

-----Encoded View---------------
6 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [1] : 000000000000000000000000ea7b7dc089c9a4a916b5a7a37617f59fd54e37e4
Arg [2] : 00000000000000000000000021468e63abf3783020750f7b2e57d4b34afafba6
Arg [3] : 000000000000000000000000d32cb5f76989a27782e44c5297aaba728ad61669
Arg [4] : 0000000000000000000000004bfba79cf232361a53eddd17c67c6c77a6f00379
Arg [5] : 0000000000000000000000000000000000000000000000000000000000127500


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.