ETH Price: $2,407.37 (+1.41%)

Token

STAKA Token (STAKA)
 

Overview

Max Total Supply

15,444,726.470730523202934596 STAKA

Holders

72

Total Transfers

-

Market

Onchain Market Cap

$0.00

Circulating Supply Market Cap

-

Other Info

Token Contract (WITH 18 Decimals)

Loading...
Loading
Loading...
Loading
Loading...
Loading

Click here to update the token information / general information
# Exchange Pair Price  24H Volume % Volume
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.

Contract Source Code Verified (Exact Match)

Contract Name:
KatanaInuStakingContract

Compiler Version
v0.8.0+commit.c7dfd78e

Optimization Enabled:
No with 200 runs

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

import "@openzeppelin/contracts/utils/Context.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import "@openzeppelin/contracts/utils/math/SafeMath.sol";
import "@openzeppelin/contracts/security/Pausable.sol";
import "./Ownable.sol";

/**
 * @notice
 * A stake struct is used to represent the way we store stakes,
 * A Stake will contain the users address, the duration (0 for imediate withdrawal or 1 / 2 / 3 years), the amount staked and a timestamp,
 * Since which is when the stake was made
 * _stakeCheckPointIndex: The index in the checkpoints array of the current stake
 */
struct Stake {
    uint256 _amount;
    uint256 _since;
    IERC20 _stakingToken;
    uint256 _stakaAmount;
    uint256 _estimatedReward;
    APY _estimatedAPY;
    uint256 _rewardStartDate; //This date will change as the amount staked increases
    bool _exists;
}

/***@notice Struct to store Staking Contract Parameters */
struct StakingContractParameters {
    uint256 _minimumStake;
    uint256 _maxSupply;
    uint256 _totalReward;
    IERC20 _stakingToken;
    uint256 _stakingDuration;
    uint256 _maximumStake;
    //staking starting parameters
    uint256 _minimumNumberStakeHoldersBeforeStart;
    uint256 _minimumTotalStakeBeforeStart;
    uint256 _startDate;
    uint256 _endDate;
    //vesting parameters
    Percentage _immediateRewardPercentage;
    uint256 _cliffDuration;
    Percentage _cliffRewardPercentage;
    uint256 _linearDuration;
}

struct Percentage {
    uint256 _percentage;
    uint256 _percentageBase;
}

struct StakingContractParametersUpdate {
    uint256 _minimumStake;
    uint256 _maxSupply;
    uint256 _totalReward;
    IERC20 _stakingToken;
    uint256 _stakingDuration;
    uint256 _maximumStake;
    uint256 _minimumNumberStakeHoldersBeforeStart;
    uint256 _minimumTotalStakeBeforeStart;
    Percentage _immediateRewardPercentage;
    uint256 _cliffDuration;
    Percentage _cliffRewardPercentage;
    uint256 _linearDuration;
}

struct APY {
    uint256 _apy;
    uint256 _base;
}

/**
 * @dev Implementation of the {IERC20} interface.
 *
 */
contract KatanaInuStakingContract is
    ERC20("STAKA Token", "STAKA"),
    Ownable,
    Pausable
{
    using SafeMath for uint256;

    ///////////// Events ///////////////////
    /**
     * @dev Emitted when a user stakes tokens
     */
    event Staked(
        address indexed stakeholder,
        uint256 amountStaked,
        IERC20 stakingToken,
        uint256 xKataAmount
    );

    /**
     * @dev Emitted when a user withdraw stake
     */
    event Withdrawn(
        address indexed stakeholder,
        uint256 amountStaked,
        uint256 amountReceived,
        IERC20 stakingToken
    );

    /**
     * @dev Emitted when a user withdraw stake
     */
    event EmergencyWithdraw(
        address indexed stakeholder,
        uint256 amountSKataBurned,
        uint256 amountReceived
    );

    ///////////////////////////////////////

    ///// Fields //////////
    /*** @notice Stakes by stakeholder address */
    mapping(address => Stake) public _stakeholdersMapping;
    uint256 _currentNumberOfStakeholders;

    /*** @notice Staking contract parameters */
    StakingContractParameters private _stakingParameters;

    /***@notice Total Kata Staked */
    uint256 private _totalKataStaked;

    /***@notice Total Kata rewards claimed */
    uint256 private _totalKataRewardsClaimed;

    bool private _stakingStarted;

    ////////////////////////////////////////

    constructor(address stakingTokenAddress) {
        _stakingParameters._stakingToken = IERC20(stakingTokenAddress);
        _stakingParameters._minimumNumberStakeHoldersBeforeStart = 1;
    }

    /***@notice Update Staking Parameters: _startDate can't be updated, it is automatically set when the first stake is created */
    function updateStakingParameters(
        StakingContractParametersUpdate calldata stakingParameters
    ) external onlyOwner {
        _stakingParameters._minimumStake = stakingParameters._minimumStake;
        _stakingParameters._maxSupply = stakingParameters._maxSupply;
        _stakingParameters._totalReward = stakingParameters._totalReward;
        _stakingParameters._stakingToken = IERC20(
            stakingParameters._stakingToken
        );
        _stakingParameters._stakingDuration = stakingParameters
            ._stakingDuration;
        if (_stakingStarted) {
            _stakingParameters._endDate =
                _stakingParameters._startDate +
                _stakingParameters._stakingDuration;
        }
        if (!_stakingStarted) {
            // No need to update these paraeter if the staking has already started
            _stakingParameters
                ._minimumNumberStakeHoldersBeforeStart = stakingParameters
                ._minimumNumberStakeHoldersBeforeStart;
            _stakingParameters._minimumTotalStakeBeforeStart = stakingParameters
                ._minimumTotalStakeBeforeStart;
            if (
                (_stakingParameters._minimumTotalStakeBeforeStart == 0 ||
                    _totalKataStaked >=
                    _stakingParameters._minimumTotalStakeBeforeStart) &&
                (_stakingParameters._minimumNumberStakeHoldersBeforeStart ==
                    0 ||
                    _currentNumberOfStakeholders >=
                    _stakingParameters._minimumNumberStakeHoldersBeforeStart)
            ) {
                _stakingStarted = true;
                _stakingParameters._startDate = block.timestamp;
                _stakingParameters._endDate =
                    _stakingParameters._startDate +
                    _stakingParameters._stakingDuration;
            }
        }
        _stakingParameters._maximumStake = stakingParameters._maximumStake;

        //Update reward schedule array
        _stakingParameters._immediateRewardPercentage = stakingParameters
            ._immediateRewardPercentage;
        _stakingParameters._cliffDuration = stakingParameters._cliffDuration;
        _stakingParameters._cliffRewardPercentage = stakingParameters
            ._cliffRewardPercentage;
        _stakingParameters._linearDuration = stakingParameters._linearDuration;
    }

    /***@notice Stake Kata coins in exchange for xKata coins to earn a share of the rewards */
    function stake(uint256 amount) external onlyUser whenNotPaused {
        //Check the amount is >= _minimumStake
        require(
            amount >= _stakingParameters._minimumStake,
            "Amount below the minimum stake"
        );
        //Check the amount is <= _maximumStake
        require(
            _stakingParameters._maximumStake == 0 ||
                amount <= _stakingParameters._maximumStake,
            "amount exceeds maximum stake"
        );
        //Check if the new stake will exceed the maximum supply for this pool
        require(
            (_totalKataStaked + amount) <= _stakingParameters._maxSupply,
            "You can not exceeed maximum supply for staking"
        );

        require(
            !_stakingStarted || block.timestamp < _stakingParameters._endDate,
            "The staking period has ended"
        );
        //Check if the totalReward have been already claimed, in theory this should always be true,
        //but added the extra check for additional safety
        require(
            _totalKataRewardsClaimed < _stakingParameters._totalReward,
            "All rewards have been distributed"
        );

        Stake memory newStake = createStake(amount);
        _totalKataStaked += amount;
        if (!_stakeholdersMapping[msg.sender]._exists) {
            _currentNumberOfStakeholders += 1;
        }
        //Check if the staking period did not end
        if (
            !_stakingStarted &&
            (_stakingParameters._minimumTotalStakeBeforeStart == 0 ||
                _totalKataStaked >=
                _stakingParameters._minimumTotalStakeBeforeStart) &&
            (_stakingParameters._minimumNumberStakeHoldersBeforeStart == 0 ||
                _currentNumberOfStakeholders >=
                _stakingParameters._minimumNumberStakeHoldersBeforeStart)
        ) {
            _stakingStarted = true;
            _stakingParameters._startDate = block.timestamp;
            _stakingParameters._endDate =
                _stakingParameters._startDate +
                _stakingParameters._stakingDuration;
        }
        //Transfer amount to contract (this)
        if (
            !_stakingParameters._stakingToken.transferFrom(
                msg.sender,
                address(this),
                amount
            )
        ) {
            revert("couldn 't transfer tokens from sender to contract");
        }

        _mint(msg.sender, newStake._stakaAmount);

        //Update stakeholders

        if (!_stakeholdersMapping[msg.sender]._exists) {
            _stakeholdersMapping[msg.sender] = newStake;
            _stakeholdersMapping[msg.sender]._exists = true;
        } else {
            _stakeholdersMapping[msg.sender]
                ._rewardStartDate = calculateNewRewardStartDate(
                _stakeholdersMapping[msg.sender],
                newStake
            );
            _stakeholdersMapping[msg.sender]._amount += newStake._amount;
            _stakeholdersMapping[msg.sender]._stakaAmount += newStake
                ._stakaAmount;
        }
        //Emit event
        emit Staked(
            msg.sender,
            amount,
            _stakingParameters._stakingToken,
            newStake._stakaAmount
        );
    }

    function calculateNewRewardStartDate(
        Stake memory existingStake,
        Stake memory newStake
    ) private pure returns (uint256) {
        uint256 multiplier = (
            existingStake._rewardStartDate.mul(existingStake._stakaAmount)
        ).add(newStake._rewardStartDate.mul(newStake._stakaAmount));
        uint256 divider = existingStake._stakaAmount.add(newStake._stakaAmount);
        return multiplier.div(divider);
    }

    /*** @notice Withdraw stake and get initial amount staked + share of the reward */
    function withdrawStake(uint256 amount) external onlyUser whenNotPaused {
        require(
            _stakeholdersMapping[msg.sender]._exists,
            "Can not find stake for sender"
        );
        require(
            _stakeholdersMapping[msg.sender]._amount >= amount,
            "Can not withdraw more than actual stake"
        );
        Stake memory stakeToWithdraw = _stakeholdersMapping[msg.sender];
        require(stakeToWithdraw._amount > 0, "Stake alreday withdrawn");
        //Reward proportional to amount withdrawn
        uint256 reward = (
            computeRewardForStake(block.timestamp, stakeToWithdraw, true).mul(
                amount
            )
        ).div(stakeToWithdraw._amount);
        //Check if there is enough reward tokens, this is to avoid paying rewards with other stakeholders stake
        uint256 currentRewardBalance = getRewardBalance();
        require(
            reward <= currentRewardBalance,
            "The contract does not have enough reward tokens"
        );
        uint256 totalAmoutToWithdraw = reward + amount;
        //Calculate nb STAKA to burn:
        uint256 nbStakaToBurn = (stakeToWithdraw._stakaAmount.mul(amount)).div(
            stakeToWithdraw._amount
        );

        _stakeholdersMapping[msg.sender]._amount -= amount;
        _stakeholdersMapping[msg.sender]._stakaAmount -= nbStakaToBurn;

        _totalKataStaked = _totalKataStaked - amount;
        _totalKataRewardsClaimed += reward;
        //Transfer amount to contract (this)
        if (
            !stakeToWithdraw._stakingToken.transfer(
                msg.sender,
                totalAmoutToWithdraw
            )
        ) {
            revert("couldn 't transfer tokens from sender to contract");
        }
        _burn(msg.sender, nbStakaToBurn);
        emit Withdrawn(
            msg.sender,
            stakeToWithdraw._amount,
            totalAmoutToWithdraw,
            stakeToWithdraw._stakingToken
        );
    }

    /***@notice withdraw all stakes of a given user without including rewards */
    function emergencyWithdraw(address stakeHolderAddress) external onlyOwner {
        require(
            _stakeholdersMapping[stakeHolderAddress]._exists,
            "Can not find stake for sender"
        );
        require(
            _stakeholdersMapping[stakeHolderAddress]._amount > 0,
            "Can not any stake for supplied address"
        );

        uint256 totalAmoutTowithdraw;
        uint256 totalSKataToBurn;
        totalAmoutTowithdraw = _stakeholdersMapping[stakeHolderAddress]._amount;
        totalSKataToBurn = _stakeholdersMapping[stakeHolderAddress]
            ._stakaAmount;
        if (
            !_stakeholdersMapping[stakeHolderAddress]._stakingToken.transfer(
                stakeHolderAddress,
                _stakeholdersMapping[stakeHolderAddress]._amount
            )
        ) {
            revert("couldn 't transfer tokens from sender to contract");
        }
        _stakeholdersMapping[stakeHolderAddress]._amount = 0;
        _stakeholdersMapping[stakeHolderAddress]._exists = false;
        _stakeholdersMapping[stakeHolderAddress]._stakaAmount = 0;

        _totalKataStaked = _totalKataStaked - totalAmoutTowithdraw;
        _burn(stakeHolderAddress, totalSKataToBurn);
        emit EmergencyWithdraw(
            stakeHolderAddress,
            totalSKataToBurn,
            totalAmoutTowithdraw
        );
    }

    /***@notice Get an estimate of the reward  */
    function getStakeReward(uint256 targetTime)
        external
        view
        onlyUser
        returns (uint256)
    {
        require(
            _stakeholdersMapping[msg.sender]._exists,
            "Can not find stake for sender"
        );
        Stake memory targetStake = _stakeholdersMapping[msg.sender];
        return computeRewardForStake(targetTime, targetStake, true);
    }

    /***@notice Get an estimate of the reward  */
    function getEstimationOfReward(uint256 targetTime, uint256 amountToStake)
        external
        view
        returns (uint256)
    {
        Stake memory targetStake = createStake(amountToStake);
        return computeRewardForStake(targetTime, targetStake, false);
    }

    function getAPY() external view returns (APY memory) {
        if (
            !_stakingStarted ||
            _stakingParameters._endDate == _stakingParameters._startDate ||
            _totalKataStaked == 0
        ) return APY(0, 1);

        uint256 targetTime = 365 days;
        if (
            _stakingParameters._immediateRewardPercentage._percentage == 0 &&
            _stakingParameters._cliffRewardPercentage._percentage == 0 &&
            _stakingParameters._cliffDuration == 0 &&
            _stakingParameters._linearDuration == 0
        ) {
            uint256 reward = _stakingParameters
                ._totalReward
                .mul(targetTime)
                .div(
                    _stakingParameters._endDate.sub(
                        _stakingParameters._startDate
                    )
                );
            return APY(reward.mul(100000).div(_totalKataStaked), 100000);
        }
        return getAPYWithVesting();
    }

    function getAPYWithVesting() private view returns (APY memory) {
        uint256 targetTime = 365 days;
        Stake memory syntheticStake = Stake(
            _totalKataStaked,
            block.timestamp,
            _stakingParameters._stakingToken,
            totalSupply(),
            0,
            APY(0, 1),
            block.timestamp,
            true
        );
        uint256 reward = computeRewardForStakeWithVesting(
            block.timestamp + targetTime,
            syntheticStake,
            true
        );
        return APY(reward.mul(100000).div(_totalKataStaked), 100000);
    }

    /***@notice Create a new stake by taking into account accrued rewards when estimating the number of xKata tokens in exchange for Kata tokens */
    function createStake(uint256 amount) private view returns (Stake memory) {
        uint256 xKataAmountToMint;
        uint256 currentTimeStanp = block.timestamp;
        if (_totalKataStaked == 0 || totalSupply() == 0) {
            xKataAmountToMint = amount;
        } else {
            //Add multiplication by 1 + time to maturity ratio
            uint256 multiplier = amount
                .mul(
                    _stakingParameters._endDate.sub(
                        _stakingParameters._startDate
                    )
                )
                .div(
                    _stakingParameters._endDate.add(currentTimeStanp).sub(
                        2 * _stakingParameters._startDate
                    )
                );
            xKataAmountToMint = multiplier.mul(totalSupply()).div(
                _totalKataStaked
            );
        }
        return
            Stake(
                amount,
                currentTimeStanp,
                _stakingParameters._stakingToken,
                xKataAmountToMint,
                0,
                APY(0, 1),
                currentTimeStanp,
                true
            );
    }

    /*** Stats functions */

    /***@notice returns the amount of Kata tokens available for rewards */
    function getRewardBalance() public view returns (uint256) {
        uint256 stakingTokenBalance = _stakingParameters
            ._stakingToken
            .balanceOf(address(this));
        uint256 rewardBalance = stakingTokenBalance.sub(_totalKataStaked);
        return rewardBalance;
    }

    /***@notice returns the amount of Kata tokens withdrawn as rewards */
    function getTotalRewardsClaimed() public view returns (uint256) {
        return _totalKataRewardsClaimed;
    }

    function getRequiredRewardAmountForPerdiod(uint256 endPeriod)
        external
        view
        onlyOwner
        returns (uint256)
    {
        return caluclateRequiredRewardAmountForPerdiod(endPeriod);
    }

    function getRequiredRewardAmount() external view returns (uint256) {
        return caluclateRequiredRewardAmountForPerdiod(block.timestamp);
    }

    ///////////////////////////////////////////////////////////////

    function caluclateRequiredRewardAmountForPerdiod(uint256 endPeriod)
        private
        view
        returns (uint256)
    {
        if (
            !_stakingStarted ||
            _stakingParameters._endDate == _stakingParameters._startDate ||
            _totalKataStaked == 0
        ) return 0;
        uint256 requiredReward = _stakingParameters
            ._totalReward
            .mul(endPeriod.sub(_stakingParameters._startDate))
            .div(_stakingParameters._endDate.sub(_stakingParameters._startDate))
            .sub(_totalKataRewardsClaimed);
        return requiredReward;
    }

    /***@notice Calculate the reward for a give stake if withdrawn at 'targetTime' */
    function computeRewardForStake(
        uint256 targetTime,
        Stake memory targetStake,
        bool existingStake
    ) private view returns (uint256) {
        if (
            _stakingParameters._immediateRewardPercentage._percentage == 0 &&
            _stakingParameters._cliffRewardPercentage._percentage == 0 &&
            _stakingParameters._cliffDuration == 0 &&
            _stakingParameters._linearDuration == 0
        ) {
            return
                computeReward(
                    _stakingParameters._totalReward,
                    targetTime,
                    targetStake._stakaAmount,
                    targetStake._rewardStartDate,
                    existingStake
                );
        }
        return
            computeRewardForStakeWithVesting(
                targetTime,
                targetStake,
                existingStake
            );
    }

    function computeRewardForStakeWithVesting(
        uint256 targetTime,
        Stake memory targetStake,
        bool existingStake
    ) private view returns (uint256) {
        uint256 accumulatedReward;
        uint256 currentStartTime = targetStake._rewardStartDate;
        uint256 currentTotalRewardAmount = (
            _stakingParameters._totalReward.mul(
                _stakingParameters._immediateRewardPercentage._percentage
            )
        ).div(_stakingParameters._immediateRewardPercentage._percentageBase);

        if (
            (currentStartTime + _stakingParameters._cliffDuration) >= targetTime
        ) {
            return
                computeReward(
                    currentTotalRewardAmount,
                    targetTime,
                    targetStake._stakaAmount,
                    currentStartTime,
                    existingStake
                );
        }

        accumulatedReward += computeReward(
            currentTotalRewardAmount,
            currentStartTime + _stakingParameters._cliffDuration,
            targetStake._stakaAmount,
            currentStartTime,
            existingStake
        );

        currentStartTime = currentStartTime + _stakingParameters._cliffDuration;
        currentTotalRewardAmount += (
            _stakingParameters._totalReward.mul(
                _stakingParameters._cliffRewardPercentage._percentage
            )
        ).div(_stakingParameters._cliffRewardPercentage._percentageBase);

        if (
            _stakingParameters._linearDuration == 0 ||
            (currentStartTime + _stakingParameters._linearDuration) <=
            targetTime
        ) {
            // 100% percent of the reward vested
            currentTotalRewardAmount = _stakingParameters._totalReward;

            return (
                accumulatedReward.add(
                    computeReward(
                        currentTotalRewardAmount,
                        targetTime,
                        targetStake._stakaAmount,
                        currentStartTime,
                        existingStake
                    )
                )
            );
        }
        // immediate + cliff + linear proportion of the reward
        currentTotalRewardAmount += (
            _stakingParameters._totalReward.sub(currentTotalRewardAmount)
        ).mul(targetTime - currentStartTime).div(
                _stakingParameters._linearDuration
            );
        accumulatedReward += computeReward(
            currentTotalRewardAmount,
            targetTime,
            targetStake._stakaAmount,
            currentStartTime,
            existingStake
        );
        return accumulatedReward;
    }

    /***@notice Calculate the reward for a give stake if withdrawn at 'targetTime' */
    function computeReward(
        uint256 applicableReward,
        uint256 targetTime,
        uint256 stakaAmount,
        uint256 rewardStartDate,
        bool existingStake
    ) private view returns (uint256) {
        uint256 mulltiplier = stakaAmount
            .mul(applicableReward)
            .mul(targetTime.sub(rewardStartDate))
            .div(
                _stakingParameters._endDate.sub(_stakingParameters._startDate)
            );

        uint256 divider = existingStake
            ? totalSupply()
            : totalSupply().add(stakaAmount);
        return mulltiplier.div(divider);
    }

    /**
     * @notice
     * Update Staking Token
     */
    function setStakingToken(address stakingTokenAddress) external onlyOwner {
        _stakingParameters._stakingToken = IERC20(stakingTokenAddress);
    }

    /*** @notice Withdraw reward */
    function withdrawFromReward(uint256 amount) external onlyOwner {
        //Check if there is enough reward tokens, this is to avoid paying rewards with other stakeholders stake
        require(
            amount <= getRewardBalance(),
            "The contract does not have enough reward tokens"
        );
        //Transfer amount to contract (this)
        if (!_stakingParameters._stakingToken.transfer(msg.sender, amount)) {
            revert("couldn 't transfer tokens from sender to contract");
        }
    }

    /**
     * @notice
     * Return the total amount staked
     */
    function getTotalStaked() external view returns (uint256) {
        return _totalKataStaked;
    }

    /**
     * @notice
     * Return the value of the penalty for early exit
     */
    function getContractParameters()
        external
        view
        returns (StakingContractParameters memory)
    {
        return _stakingParameters;
    }

    /**
     * @notice
     * Return stakes for msg.sender
     */
    function getStake() external view returns (Stake memory) {
        Stake memory currentStake = _stakeholdersMapping[msg.sender];
        if (!currentStake._exists) {
            // Return empty stake
            return
                Stake(
                    0,
                    0,
                    _stakingParameters._stakingToken,
                    0,
                    0,
                    APY(0, 1),
                    0,
                    false
                );
        }
        if (_stakingStarted) {
            currentStake._estimatedReward = computeRewardForStake(
                block.timestamp,
                currentStake,
                true
            );
            currentStake._estimatedAPY = APY(
                computeRewardForStake(
                    currentStake._rewardStartDate + 365 days,
                    currentStake,
                    true
                ).mul(100000).div(currentStake._amount),
                100000
            );
        }
        return currentStake;
    }

    function shouldStartContract(
        uint256 newTotalKataStaked,
        uint256 newCurrentNumberOfStakeHolders
    ) private view returns (bool) {
        if (
            _stakingParameters._minimumTotalStakeBeforeStart > 0 &&
            newTotalKataStaked <
            _stakingParameters._minimumTotalStakeBeforeStart
        ) {
            return false;
        }
        if (
            _stakingParameters._minimumNumberStakeHoldersBeforeStart > 0 &&
            newCurrentNumberOfStakeHolders <
            _stakingParameters._minimumNumberStakeHoldersBeforeStart
        ) {
            return false;
        }
        return true;
    }

    function _afterTokenTransfer(
        address from,
        address to,
        uint256 amount
    ) internal override {
        if (from == address(0))
            //Nothing to do when _mint is called
            return;
        if (to == address(0))
            //Nothing to do when _burn is called
            return;

        Stake memory fromStake = _stakeholdersMapping[from];
        uint256 amountOfKataToTransfer = (
            _stakeholdersMapping[from]._amount.mul(amount)
        ).div(_stakeholdersMapping[from]._stakaAmount);

        fromStake._exists = true;
        fromStake._stakaAmount = amount;
        fromStake._amount = amountOfKataToTransfer;
        if (!_stakeholdersMapping[to]._exists) {
            _stakeholdersMapping[to] = fromStake;
            _stakeholdersMapping[from]._stakaAmount -= amount;
            _stakeholdersMapping[from]._amount -= amountOfKataToTransfer;
        } else {
            _stakeholdersMapping[to]
                ._rewardStartDate = calculateNewRewardStartDate(
                _stakeholdersMapping[to],
                fromStake
            );
            _stakeholdersMapping[to]._stakaAmount += amount;
            _stakeholdersMapping[to]._amount += amountOfKataToTransfer;
            _stakeholdersMapping[from]._stakaAmount -= amount;
            _stakeholdersMapping[from]._amount -= amountOfKataToTransfer;
        }
    }

    function pause() external onlyOwner {
        _pause();
    }

    function unpause() external onlyOwner {
        _unpause();
    }

    /**
     * onlyUser
     * @dev guard contracts from calling method
     **/
    modifier onlyUser() {
        require(msg.sender == tx.origin);
        _;
    }
}

File 2 of 8 : Ownable.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

/**
 * @title Ownable
 * @dev Ownable has an owner address to simplify "user permissions".
 */
contract Ownable {
  address payable public owner;

  /**
   * Ownable
   * @dev Ownable constructor sets the `owner` of the contract to sender
   */
  constructor() {  owner = payable(msg.sender);  }

  /**
   * ownerOnly
   * @dev Throws an error if called by any account other than the owner.
   */
  modifier onlyOwner() {
    require(msg.sender == owner);
    _;
  }

  /**
   * transferOwnership
   * @dev Allows the current owner to transfer control of the contract to a newOwner.
   * @param newOwner The address to transfer ownership to.
   */
  function transferOwnership(address payable newOwner) public onlyOwner {
    require(newOwner != address(0));
    owner = newOwner;
  }
}

File 3 of 8 : SafeMath.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/math/SafeMath.sol)

pragma solidity ^0.8.0;

// CAUTION
// This version of SafeMath should only be used with Solidity 0.8 or later,
// because it relies on the compiler's built in overflow checks.

/**
 * @dev Wrappers over Solidity's arithmetic operations.
 *
 * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler
 * now has built in overflow checking.
 */
library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            uint256 c = a + b;
            if (c < a) return (false, 0);
            return (true, c);
        }
    }

    /**
     * @dev Returns the substraction of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b > a) return (false, 0);
            return (true, a - b);
        }
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
            // benefit is lost if 'b' is also tested.
            // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
            if (a == 0) return (true, 0);
            uint256 c = a * b;
            if (c / a != b) return (false, 0);
            return (true, c);
        }
    }

    /**
     * @dev Returns the division of two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a / b);
        }
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a % b);
        }
    }

    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     *
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        return a + b;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        return a - b;
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     *
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        return a * b;
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator.
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return a / b;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        return a % b;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {trySub}.
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        unchecked {
            require(b <= a, errorMessage);
            return a - b;
        }
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting with custom message on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        unchecked {
            require(b > 0, errorMessage);
            return a / b;
        }
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting with custom message when dividing by zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryMod}.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        unchecked {
            require(b > 0, errorMessage);
            return a % b;
        }
    }
}

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

pragma solidity ^0.8.0;

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

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

File 5 of 8 : IERC20Metadata.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)

pragma solidity ^0.8.0;

import "../IERC20.sol";

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

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

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

File 6 of 8 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @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 `recipient`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address recipient, 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 `sender` to `recipient` 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 sender,
        address recipient,
        uint256 amount
    ) external returns (bool);

    /**
     * @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);
}

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

pragma solidity ^0.8.0;

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

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

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

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;

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

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

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

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

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

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

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

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

    /**
     * @dev See {IERC20-approve}.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function approve(address spender, uint256 amount) public virtual override returns (bool) {
        _approve(_msgSender(), spender, amount);
        return true;
    }

    /**
     * @dev See {IERC20-transferFrom}.
     *
     * Emits an {Approval} event indicating the updated allowance. This is not
     * required by the EIP. See the note at the beginning of {ERC20}.
     *
     * Requirements:
     *
     * - `sender` and `recipient` cannot be the zero address.
     * - `sender` must have a balance of at least `amount`.
     * - the caller must have allowance for ``sender``'s tokens of at least
     * `amount`.
     */
    function transferFrom(
        address sender,
        address recipient,
        uint256 amount
    ) public virtual override returns (bool) {
        _transfer(sender, recipient, amount);

        uint256 currentAllowance = _allowances[sender][_msgSender()];
        require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance");
        unchecked {
            _approve(sender, _msgSender(), currentAllowance - amount);
        }

        return true;
    }

    /**
     * @dev Atomically increases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
        _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue);
        return true;
    }

    /**
     * @dev Atomically decreases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `spender` must have allowance for the caller of at least
     * `subtractedValue`.
     */
    function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
        uint256 currentAllowance = _allowances[_msgSender()][spender];
        require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
        unchecked {
            _approve(_msgSender(), spender, currentAllowance - subtractedValue);
        }

        return true;
    }

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

        _beforeTokenTransfer(sender, recipient, amount);

        uint256 senderBalance = _balances[sender];
        require(senderBalance >= amount, "ERC20: transfer amount exceeds balance");
        unchecked {
            _balances[sender] = senderBalance - amount;
        }
        _balances[recipient] += amount;

        emit Transfer(sender, recipient, amount);

        _afterTokenTransfer(sender, recipient, amount);
    }

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

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

        _totalSupply += amount;
        _balances[account] += amount;
        emit Transfer(address(0), account, amount);

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

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

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

        uint256 accountBalance = _balances[account];
        require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
        unchecked {
            _balances[account] = accountBalance - amount;
        }
        _totalSupply -= amount;

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

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

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

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

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

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

File 8 of 8 : Pausable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (security/Pausable.sol)

pragma solidity ^0.8.0;

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

/**
 * @dev Contract module which allows children to implement an emergency stop
 * mechanism that can be triggered by an authorized account.
 *
 * This module is used through inheritance. It will make available the
 * modifiers `whenNotPaused` and `whenPaused`, which can be applied to
 * the functions of your contract. Note that they will not be pausable by
 * simply including this module, only once the modifiers are put in place.
 */
abstract contract Pausable is Context {
    /**
     * @dev Emitted when the pause is triggered by `account`.
     */
    event Paused(address account);

    /**
     * @dev Emitted when the pause is lifted by `account`.
     */
    event Unpaused(address account);

    bool private _paused;

    /**
     * @dev Initializes the contract in unpaused state.
     */
    constructor() {
        _paused = false;
    }

    /**
     * @dev Returns true if the contract is paused, and false otherwise.
     */
    function paused() public view virtual returns (bool) {
        return _paused;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is not paused.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    modifier whenNotPaused() {
        require(!paused(), "Pausable: paused");
        _;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is paused.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    modifier whenPaused() {
        require(paused(), "Pausable: not paused");
        _;
    }

    /**
     * @dev Triggers stopped state.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    function _pause() internal virtual whenNotPaused {
        _paused = true;
        emit Paused(_msgSender());
    }

    /**
     * @dev Returns to normal state.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    function _unpause() internal virtual whenPaused {
        _paused = false;
        emit Unpaused(_msgSender());
    }
}

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

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"stakingTokenAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"stakeholder","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountSKataBurned","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountReceived","type":"uint256"}],"name":"EmergencyWithdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"stakeholder","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountStaked","type":"uint256"},{"indexed":false,"internalType":"contract IERC20","name":"stakingToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"xKataAmount","type":"uint256"}],"name":"Staked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"stakeholder","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountStaked","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountReceived","type":"uint256"},{"indexed":false,"internalType":"contract IERC20","name":"stakingToken","type":"address"}],"name":"Withdrawn","type":"event"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"_stakeholdersMapping","outputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_since","type":"uint256"},{"internalType":"contract IERC20","name":"_stakingToken","type":"address"},{"internalType":"uint256","name":"_stakaAmount","type":"uint256"},{"internalType":"uint256","name":"_estimatedReward","type":"uint256"},{"components":[{"internalType":"uint256","name":"_apy","type":"uint256"},{"internalType":"uint256","name":"_base","type":"uint256"}],"internalType":"struct APY","name":"_estimatedAPY","type":"tuple"},{"internalType":"uint256","name":"_rewardStartDate","type":"uint256"},{"internalType":"bool","name":"_exists","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"stakeHolderAddress","type":"address"}],"name":"emergencyWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getAPY","outputs":[{"components":[{"internalType":"uint256","name":"_apy","type":"uint256"},{"internalType":"uint256","name":"_base","type":"uint256"}],"internalType":"struct APY","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getContractParameters","outputs":[{"components":[{"internalType":"uint256","name":"_minimumStake","type":"uint256"},{"internalType":"uint256","name":"_maxSupply","type":"uint256"},{"internalType":"uint256","name":"_totalReward","type":"uint256"},{"internalType":"contract IERC20","name":"_stakingToken","type":"address"},{"internalType":"uint256","name":"_stakingDuration","type":"uint256"},{"internalType":"uint256","name":"_maximumStake","type":"uint256"},{"internalType":"uint256","name":"_minimumNumberStakeHoldersBeforeStart","type":"uint256"},{"internalType":"uint256","name":"_minimumTotalStakeBeforeStart","type":"uint256"},{"internalType":"uint256","name":"_startDate","type":"uint256"},{"internalType":"uint256","name":"_endDate","type":"uint256"},{"components":[{"internalType":"uint256","name":"_percentage","type":"uint256"},{"internalType":"uint256","name":"_percentageBase","type":"uint256"}],"internalType":"struct Percentage","name":"_immediateRewardPercentage","type":"tuple"},{"internalType":"uint256","name":"_cliffDuration","type":"uint256"},{"components":[{"internalType":"uint256","name":"_percentage","type":"uint256"},{"internalType":"uint256","name":"_percentageBase","type":"uint256"}],"internalType":"struct Percentage","name":"_cliffRewardPercentage","type":"tuple"},{"internalType":"uint256","name":"_linearDuration","type":"uint256"}],"internalType":"struct StakingContractParameters","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"targetTime","type":"uint256"},{"internalType":"uint256","name":"amountToStake","type":"uint256"}],"name":"getEstimationOfReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getRequiredRewardAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"endPeriod","type":"uint256"}],"name":"getRequiredRewardAmountForPerdiod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getRewardBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStake","outputs":[{"components":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_since","type":"uint256"},{"internalType":"contract IERC20","name":"_stakingToken","type":"address"},{"internalType":"uint256","name":"_stakaAmount","type":"uint256"},{"internalType":"uint256","name":"_estimatedReward","type":"uint256"},{"components":[{"internalType":"uint256","name":"_apy","type":"uint256"},{"internalType":"uint256","name":"_base","type":"uint256"}],"internalType":"struct APY","name":"_estimatedAPY","type":"tuple"},{"internalType":"uint256","name":"_rewardStartDate","type":"uint256"},{"internalType":"bool","name":"_exists","type":"bool"}],"internalType":"struct Stake","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"targetTime","type":"uint256"}],"name":"getStakeReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalRewardsClaimed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalStaked","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address payable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"stakingTokenAddress","type":"address"}],"name":"setStakingToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"stake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"_minimumStake","type":"uint256"},{"internalType":"uint256","name":"_maxSupply","type":"uint256"},{"internalType":"uint256","name":"_totalReward","type":"uint256"},{"internalType":"contract IERC20","name":"_stakingToken","type":"address"},{"internalType":"uint256","name":"_stakingDuration","type":"uint256"},{"internalType":"uint256","name":"_maximumStake","type":"uint256"},{"internalType":"uint256","name":"_minimumNumberStakeHoldersBeforeStart","type":"uint256"},{"internalType":"uint256","name":"_minimumTotalStakeBeforeStart","type":"uint256"},{"components":[{"internalType":"uint256","name":"_percentage","type":"uint256"},{"internalType":"uint256","name":"_percentageBase","type":"uint256"}],"internalType":"struct Percentage","name":"_immediateRewardPercentage","type":"tuple"},{"internalType":"uint256","name":"_cliffDuration","type":"uint256"},{"components":[{"internalType":"uint256","name":"_percentage","type":"uint256"},{"internalType":"uint256","name":"_percentageBase","type":"uint256"}],"internalType":"struct Percentage","name":"_cliffRewardPercentage","type":"tuple"},{"internalType":"uint256","name":"_linearDuration","type":"uint256"}],"internalType":"struct StakingContractParametersUpdate","name":"stakingParameters","type":"tuple"}],"name":"updateStakingParameters","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawFromReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawStake","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60806040523480156200001157600080fd5b50604051620060fa380380620060fa833981810160405281019062000037919062000250565b6040518060400160405280600b81526020017f5354414b4120546f6b656e0000000000000000000000000000000000000000008152506040518060400160405280600581526020017f5354414b410000000000000000000000000000000000000000000000000000008152508160039080519060200190620000bb92919062000189565b508060049080519060200190620000d492919062000189565b50505033600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000600560146101000a81548160ff02191690831515021790555080600860030160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506001600860060181905550506200032f565b8280546200019790620002b0565b90600052602060002090601f016020900481019282620001bb576000855562000207565b82601f10620001d657805160ff191683800117855562000207565b8280016001018555821562000207579182015b8281111562000206578251825591602001919060010190620001e9565b5b5090506200021691906200021a565b5090565b5b80821115620002355760008160009055506001016200021b565b5090565b6000815190506200024a8162000315565b92915050565b6000602082840312156200026357600080fd5b6000620002738482850162000239565b91505092915050565b6000620002898262000290565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006002820490506001821680620002c957607f821691505b60208210811415620002e057620002df620002e6565b5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b62000320816200027c565b81146200032c57600080fd5b50565b615dbb806200033f6000396000f3fe608060405234801561001057600080fd5b50600436106101fb5760003560e01c80636ff1c9bc1161011a578063a694fc3a116100ad578063d2cbf7ad1161007c578063d2cbf7ad146105bd578063dd62ed3e146105db578063ea4405001461060b578063f2fde38b1461063b578063fc0e3d9014610657576101fb565b8063a694fc3a14610537578063a9059cbb14610553578063b0b5529e14610583578063bfacd9ed1461059f576101fb565b80638da5cb5b116100e95780638da5cb5b146104af57806395d89b41146104cd5780639d836bd2146104eb578063a457c2d714610507576101fb565b80636ff1c9bc1461042257806370a082311461043e578063758035661461046e5780638456cb59146104a5576101fb565b80632ff7cfc61161019257806348f9ead41161016157806348f9ead4146103865780635931b24e146103b65780635c975abb146103e65780635e42b45514610404576101fb565b80632ff7cfc614610310578063313ce5671461032e578063395093511461034c5780633f4ba83a1461037c576101fb565b80631e9b12ef116101ce5780631e9b12ef1461028a57806323b872dd146102a657806325d5971f146102d65780632f861449146102f2576101fb565b806306fdde03146102005780630917e7761461021e578063095ea7b31461023c57806318160ddd1461026c575b600080fd5b610208610675565b60405161021591906154b6565b60405180910390f35b610226610707565b604051610233919061580b565b60405180910390f35b610256600480360381019061025191906147b5565b610711565b604051610263919061549b565b60405180910390f35b61027461072f565b604051610281919061580b565b60405180910390f35b6102a4600480360381019061029f91906146d8565b610739565b005b6102c060048036038101906102bb9190614766565b6107da565b6040516102cd919061549b565b60405180910390f35b6102f060048036038101906102eb919061486d565b6108d2565b005b6102fa610eaa565b604051610307919061580b565b60405180910390f35b610318610eb4565b604051610325919061580b565b60405180910390f35b610336610ec4565b604051610343919061593c565b60405180910390f35b610366600480360381019061036191906147b5565b610ecd565b604051610373919061549b565b60405180910390f35b610384610f79565b005b6103a0600480360381019061039b919061486d565b610fdd565b6040516103ad919061580b565b60405180910390f35b6103d060048036038101906103cb91906148bf565b611049565b6040516103dd919061580b565b60405180910390f35b6103ee61106c565b6040516103fb919061549b565b60405180910390f35b61040c611083565b604051610419919061580b565b60405180910390f35b61043c600480360381019061043791906146d8565b611157565b005b610458600480360381019061045391906146d8565b611620565b604051610465919061580b565b60405180910390f35b610488600480360381019061048391906146d8565b611668565b60405161049c9897969594939291906158bd565b60405180910390f35b6104ad6116fb565b005b6104b761175f565b6040516104c49190615420565b60405180910390f35b6104d5611785565b6040516104e291906154b6565b60405180910390f35b61050560048036038101906105009190614843565b611817565b005b610521600480360381019061051c91906147b5565b611a4b565b60405161052e919061549b565b60405180910390f35b610551600480360381019061054c919061486d565b611b36565b005b61056d600480360381019061056891906147b5565b6123d6565b60405161057a919061549b565b60405180910390f35b61059d6004803603810190610598919061486d565b6123f4565b005b6105a761258c565b6040516105b491906157ef565b60405180910390f35b6105c56126bb565b6040516105d291906157b8565b60405180910390f35b6105f560048036038101906105f0919061472a565b612809565b604051610602919061580b565b60405180910390f35b6106256004803603810190610620919061486d565b612890565b604051610632919061580b565b60405180910390f35b61065560048036038101906106509190614701565b612a87565b005b61065f612b5f565b60405161066c91906157d3565b60405180910390f35b60606003805461068490615b6a565b80601f01602080910402602001604051908101604052809291908181526020018280546106b090615b6a565b80156106fd5780601f106106d2576101008083540402835291602001916106fd565b820191906000526020600020905b8154815290600101906020018083116106e057829003601f168201915b5050505050905090565b6000601854905090565b600061072561071e612dc1565b8484612dc9565b6001905092915050565b6000600254905090565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461079357600080fd5b80600860030160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60006107e7848484612f94565b6000600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000610832612dc1565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050828110156108b2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108a990615678565b60405180910390fd5b6108c6856108be612dc1565b858403612dc9565b60019150509392505050565b3273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461090a57600080fd5b61091261106c565b15610952576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610949906155f8565b60405180910390fd5b600660003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060080160009054906101000a900460ff166109e1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109d890615658565b60405180910390fd5b80600660003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001541015610a66576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a5d906155d8565b60405180910390fd5b6000600660003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206040518061010001604052908160008201548152602001600182015481526020016002820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600382015481526020016004820154815260200160058201604051806040016040529081600082015481526020016001820154815250508152602001600782015481526020016008820160009054906101000a900460ff16151515158152505090506000816000015111610bc7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bbe906156d8565b60405180910390fd5b6000610bfd8260000151610bef85610be142876001613215565b61329390919063ffffffff16565b6132a990919063ffffffff16565b90506000610c09611083565b905080821115610c4e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c4590615618565b60405180910390fd5b60008483610c5c9190615973565b90506000610c8d8560000151610c7f88886060015161329390919063ffffffff16565b6132a990919063ffffffff16565b905085600660003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000016000828254610ce19190615a54565b9250508190555080600660003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206003016000828254610d3a9190615a54565b9250508190555085601854610d4f9190615a54565b6018819055508360196000828254610d679190615973565b92505081905550846040015173ffffffffffffffffffffffffffffffffffffffff1663a9059cbb33846040518363ffffffff1660e01b8152600401610dad929190615472565b602060405180830381600087803b158015610dc757600080fd5b505af1158015610ddb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dff91906147f1565b610e3e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e3590615718565b60405180910390fd5b610e4833826132bf565b3373ffffffffffffffffffffffffffffffffffffffff167fbc0fb706d03a6cb96fbe31862998338850cd01d239a360045dbe469d548e42188660000151848860400151604051610e9a93929190615886565b60405180910390a2505050505050565b6000601954905090565b6000610ebf42613496565b905090565b60006012905090565b6000610f6f610eda612dc1565b848460016000610ee8612dc1565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f6a9190615973565b612dc9565b6001905092915050565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610fd357600080fd5b610fdb613554565b565b6000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461103957600080fd5b61104282613496565b9050919050565b600080611055836135f6565b905061106384826000613215565b91505092915050565b6000600560149054906101000a900460ff16905090565b600080600860030160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016110e49190615405565b60206040518083038186803b1580156110fc57600080fd5b505afa158015611110573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111349190614896565b9050600061114d6018548361377090919063ffffffff16565b9050809250505090565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146111b157600080fd5b600660008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060080160009054906101000a900460ff16611240576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161123790615658565b60405180910390fd5b6000600660008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000154116112c5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112bc90615558565b60405180910390fd5b600080600660008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001549150600660008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600301549050600660008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb84600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001546040518363ffffffff1660e01b8152600401611431929190615472565b602060405180830381600087803b15801561144b57600080fd5b505af115801561145f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061148391906147f1565b6114c2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114b990615718565b60405180910390fd5b6000600660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001819055506000600660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060080160006101000a81548160ff0219169083151502179055506000600660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060030181905550816018546115bb9190615a54565b6018819055506115cb83826132bf565b8273ffffffffffffffffffffffffffffffffffffffff167fbb757047c2b5f3974fe26b7c10f732e7bce710b0952a71082702781e62ae0595828460405161161392919061585d565b60405180910390a2505050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b60066020528060005260406000206000915090508060000154908060010154908060020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060030154908060040154908060050160405180604001604052908160008201548152602001600182015481525050908060070154908060080160009054906101000a900460ff16905088565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461175557600080fd5b61175d613786565b565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60606004805461179490615b6a565b80601f01602080910402602001604051908101604052809291908181526020018280546117c090615b6a565b801561180d5780601f106117e25761010080835404028352916020019161180d565b820191906000526020600020905b8154815290600101906020018083116117f057829003601f168201915b5050505050905090565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461187157600080fd5b8060000135600860000181905550806020013560086001018190555080604001356008600201819055508060600160208101906118ae919061481a565b600860030160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508060800135600860040181905550601a60009054906101000a900460ff16156119335760086004015460088001546119299190615973565b6008600901819055505b601a60009054906101000a900460ff166119ea578060c001356008600601819055508060e001356008600701819055506000600860070154148061197e575060086007015460185410155b80156119a15750600060086006015414806119a0575060086006015460075410155b5b156119e9576001601a60006101000a81548160ff02191690831515021790555042600880018190555060086004015460088001546119df9190615973565b6008600901819055505b5b8060a0013560086005018190555080610100016008600a018181611a0e9190615ca9565b9050508061014001356008600c018190555080610160016008600d018181611a369190615ca9565b905050806101a001356008600f018190555050565b60008060016000611a5a612dc1565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905082811015611b17576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b0e90615778565b60405180910390fd5b611b2b611b22612dc1565b85858403612dc9565b600191505092915050565b3273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611b6e57600080fd5b611b7661106c565b15611bb6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611bad906155f8565b60405180910390fd5b600860000154811015611bfe576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611bf590615598565b60405180910390fd5b60006008600501541480611c1757506008600501548111155b611c56576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c4d906156f8565b60405180910390fd5b60086001015481601854611c6a9190615973565b1115611cab576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ca290615638565b60405180910390fd5b601a60009054906101000a900460ff161580611ccb575060086009015442105b611d0a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d0190615538565b60405180910390fd5b60086002015460195410611d53576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d4a90615758565b60405180910390fd5b6000611d5e826135f6565b90508160186000828254611d729190615973565b92505081905550600660003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060080160009054906101000a900460ff16611de857600160076000828254611de09190615973565b925050819055505b601a60009054906101000a900460ff16158015611e1c575060006008600701541480611e1b575060086007015460185410155b5b8015611e3f575060006008600601541480611e3e575060086006015460075410155b5b15611e87576001601a60006101000a81548160ff0219169083151502179055504260088001819055506008600401546008800154611e7d9190615973565b6008600901819055505b600860030160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd3330856040518463ffffffff1660e01b8152600401611ee99392919061543b565b602060405180830381600087803b158015611f0357600080fd5b505af1158015611f17573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f3b91906147f1565b611f7a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f7190615718565b60405180910390fd5b611f88338260600151613829565b600660003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060080160009054906101000a900460ff166121375780600660003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082015181600001556020820151816001015560408201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550606082015181600301556080820151816004015560a0820151816005016000820151816000015560208201518160010155505060c0820151816007015560e08201518160080160006101000a81548160ff0219169083151502179055509050506001600660003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060080160006101000a81548160ff021916908315150217905550612357565b612256600660003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206040518061010001604052908160008201548152602001600182015481526020016002820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600382015481526020016004820154815260200160058201604051806040016040529081600082015481526020016001820154815250508152602001600782015481526020016008820160009054906101000a900460ff16151515158152505082613989565b600660003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600701819055508060000151600660003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160008282546122f29190615973565b925050819055508060600151600660003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600301600082825461234f9190615973565b925050819055505b3373ffffffffffffffffffffffffffffffffffffffff167ff65271afc35201e83c229b7b581d7fde59bfe7b7dd943e8719fc8c5f5ada63f683600860030160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1684606001516040516123ca93929190615826565b60405180910390a25050565b60006123ea6123e3612dc1565b8484612f94565b6001905092915050565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461244e57600080fd5b612456611083565b811115612498576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161248f90615618565b60405180910390fd5b600860030160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb33836040518363ffffffff1660e01b81526004016124f8929190615472565b602060405180830381600087803b15801561251257600080fd5b505af1158015612526573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061254a91906147f1565b612589576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161258090615718565b60405180910390fd5b50565b612594614516565b6008604051806101c00160405290816000820154815260200160018201548152602001600282015481526020016003820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600482015481526020016005820154815260200160068201548152602001600782015481526020016008820154815260200160098201548152602001600a8201604051806040016040529081600082015481526020016001820154815250508152602001600c8201548152602001600d8201604051806040016040529081600082015481526020016001820154815250508152602001600f82015481525050905090565b6126c36145a7565b601a60009054906101000a900460ff1615806126e757506008800154600860090154145b806126f457506000601854145b156127175760405180604001604052806000815260200160018152509050612806565b60006301e13380905060006008600a0160000154148015612740575060006008600d0160000154145b8015612751575060006008600c0154145b8015612762575060006008600f0154145b156127fa5760006127ae612788600880015460086009015461377090919063ffffffff16565b6127a08460086002015461329390919063ffffffff16565b6132a990919063ffffffff16565b905060405180604001604052806127e56018546127d7620186a08661329390919063ffffffff16565b6132a990919063ffffffff16565b8152602001620186a081525092505050612806565b612802613a11565b9150505b90565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b60003273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146128ca57600080fd5b600660003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060080160009054906101000a900460ff16612959576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161295090615658565b60405180910390fd5b6000600660003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206040518061010001604052908160008201548152602001600182015481526020016002820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600382015481526020016004820154815260200160058201604051806040016040529081600082015481526020016001820154815250508152602001600782015481526020016008820160009054906101000a900460ff1615151515815250509050612a7f83826001613215565b915050919050565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614612ae157600080fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415612b1b57600080fd5b80600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b612b676145c1565b6000600660003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206040518061010001604052908160008201548152602001600182015481526020016002820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600382015481526020016004820154815260200160058201604051806040016040529081600082015481526020016001820154815250508152602001600782015481526020016008820160009054906101000a900460ff16151515158152505090508060e00151612d25576040518061010001604052806000815260200160008152602001600860030160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016000815260200160008152602001604051806040016040528060008152602001600181525081526020016000815260200160001515815250915050612dbe565b601a60009054906101000a900460ff1615612db957612d4642826001613215565b8160800181815250506040518060400160405280612da48360000151612d96620186a0612d886301e133808860c00151612d809190615973565b886001613215565b61329390919063ffffffff16565b6132a990919063ffffffff16565b8152602001620186a08152508160a001819052505b809150505b90565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415612e39576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612e3090615738565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415612ea9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612ea090615578565b60405180910390fd5b80600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92583604051612f87919061580b565b60405180910390a3505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415613004576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612ffb906156b8565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415613074576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161306b906154d8565b60405180910390fd5b61307f838383613b22565b60008060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905081811015613105576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016130fc906155b8565b60405180910390fd5b8181036000808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546131989190615973565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516131fc919061580b565b60405180910390a361320f848484613b27565b50505050565b6000806008600a0160000154148015613236575060006008600d0160000154145b8015613247575060006008600c0154145b8015613258575060006008600f0154145b1561327e576132776008600201548585606001518660c001518661425f565b905061328c565b613289848484614319565b90505b9392505050565b600081836132a191906159fa565b905092915050565b600081836132b791906159c9565b905092915050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141561332f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161332690615698565b60405180910390fd5b61333b82600083613b22565b60008060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050818110156133c1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016133b890615518565b60405180910390fd5b8181036000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555081600260008282546134189190615a54565b92505081905550600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161347d919061580b565b60405180910390a361349183600084613b27565b505050565b6000601a60009054906101000a900460ff1615806134bc57506008800154600860090154145b806134c957506000601854145b156134d7576000905061354f565b600061354860195461353a6134fe600880015460086009015461377090919063ffffffff16565b61352c61351860088001548961377090919063ffffffff16565b60086002015461329390919063ffffffff16565b6132a990919063ffffffff16565b61377090919063ffffffff16565b9050809150505b919050565b61355c61106c565b61359b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613592906154f8565b60405180910390fd5b6000600560146101000a81548160ff0219169083151502179055507f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa6135df612dc1565b6040516135ec9190615405565b60405180910390a1565b6135fe6145c1565b6000804290506000601854148061361c5750600061361a61072f565b145b15613629578391506136d8565b60006136a46136686008800154600261364291906159fa565b61365a8560086009015461450090919063ffffffff16565b61377090919063ffffffff16565b613696613687600880015460086009015461377090919063ffffffff16565b8861329390919063ffffffff16565b6132a990919063ffffffff16565b90506136d46018546136c66136b761072f565b8461329390919063ffffffff16565b6132a990919063ffffffff16565b9250505b604051806101000160405280858152602001828152602001600860030160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200183815260200160008152602001604051806040016040528060008152602001600181525081526020018281526020016001151581525092505050919050565b6000818361377e9190615a54565b905092915050565b61378e61106c565b156137ce576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016137c5906155f8565b60405180910390fd5b6001600560146101000a81548160ff0219169083151502179055507f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258613812612dc1565b60405161381f9190615405565b60405180910390a1565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415613899576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161389090615798565b60405180910390fd5b6138a560008383613b22565b80600260008282546138b79190615973565b92505081905550806000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825461390c9190615973565b925050819055508173ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051613971919061580b565b60405180910390a361398560008383613b27565b5050565b6000806139d36139aa84606001518560c0015161329390919063ffffffff16565b6139c586606001518760c0015161329390919063ffffffff16565b61450090919063ffffffff16565b905060006139f28460600151866060015161450090919063ffffffff16565b9050613a0781836132a990919063ffffffff16565b9250505092915050565b613a196145a7565b60006301e13380905060006040518061010001604052806018548152602001428152602001600860030160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001613a8761072f565b815260200160008152602001604051806040016040528060008152602001600181525081526020014281526020016001151581525090506000613ad78342613acf9190615973565b836001614319565b90506040518060400160405280613b0e601854613b00620186a08661329390919063ffffffff16565b6132a990919063ffffffff16565b8152602001620186a0815250935050505090565b505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415613b615761425a565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415613b9b5761425a565b6000600660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206040518061010001604052908160008201548152602001600182015481526020016002820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600382015481526020016004820154815260200160058201604051806040016040529081600082015481526020016001820154815250508152602001600782015481526020016008820160009054906101000a900460ff16151515158152505090506000613d60600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060030154613d5285600660008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000015461329390919063ffffffff16565b6132a990919063ffffffff16565b905060018260e00190151590811515815250508282606001818152505080826000018181525050600660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060080160009054906101000a900460ff16613f8d5781600660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082015181600001556020820151816001015560408201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550606082015181600301556080820151816004015560a0820151816005016000820151816000015560208201518160010155505060c0820151816007015560e08201518160080160006101000a81548160ff02191690831515021790555090505082600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206003016000828254613f289190615a54565b9250508190555080600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000016000828254613f819190615a54565b92505081905550614257565b6140ac600660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206040518061010001604052908160008201548152602001600182015481526020016002820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600382015481526020016004820154815260200160058201604051806040016040529081600082015481526020016001820154815250508152602001600782015481526020016008820160009054906101000a900460ff16151515158152505083613989565b600660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206007018190555082600660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060030160008282546141449190615973565b9250508190555080600660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001600082825461419d9190615973565b9250508190555082600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060030160008282546141f69190615a54565b9250508190555080600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001600082825461424f9190615a54565b925050819055505b50505b505050565b6000806142c6614281600880015460086009015461377090919063ffffffff16565b6142b8614297878a61377090919063ffffffff16565b6142aa8b8a61329390919063ffffffff16565b61329390919063ffffffff16565b6132a990919063ffffffff16565b90506000836142ee576142e9866142db61072f565b61450090919063ffffffff16565b6142f7565b6142f661072f565b5b905061430c81836132a990919063ffffffff16565b9250505095945050505050565b60008060008460c00151905060006143616008600a01600101546143536008600a016000015460086002015461329390919063ffffffff16565b6132a990919063ffffffff16565b9050866008600c0154836143759190615973565b106143955761438b81888860600151858961425f565b93505050506144f9565b6143b6816008600c0154846143aa9190615973565b8860600151858961425f565b836143c19190615973565b92506008600c0154826143d49190615973565b91506144106008600d01600101546144026008600d016000015460086002015461329390919063ffffffff16565b6132a990919063ffffffff16565b8161441b9190615973565b905060006008600f015414806144415750866008600f01548361443e9190615973565b11155b1561447b57600860020154905061447161446282898960600151868a61425f565b8461450090919063ffffffff16565b93505050506144f9565b6144c76008600f01546144b9848a6144939190615a54565b6144ab8560086002015461377090919063ffffffff16565b61329390919063ffffffff16565b6132a990919063ffffffff16565b816144d29190615973565b90506144e581888860600151858961425f565b836144f09190615973565b92508293505050505b9392505050565b6000818361450e9190615973565b905092915050565b604051806101c00160405280600081526020016000815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001614586614624565b81526020016000815260200161459a614624565b8152602001600081525090565b604051806040016040528060008152602001600081525090565b6040518061010001604052806000815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600081526020016000815260200161460e6145a7565b8152602001600081526020016000151581525090565b604051806040016040528060008152602001600081525090565b60008135905061464d81615d12565b92915050565b60008135905061466281615d29565b92915050565b60008151905061467781615d40565b92915050565b60008135905061468c81615d57565b92915050565b60006101c082840312156146a557600080fd5b81905092915050565b6000813590506146bd81615d6e565b92915050565b6000815190506146d281615d6e565b92915050565b6000602082840312156146ea57600080fd5b60006146f88482850161463e565b91505092915050565b60006020828403121561471357600080fd5b600061472184828501614653565b91505092915050565b6000806040838503121561473d57600080fd5b600061474b8582860161463e565b925050602061475c8582860161463e565b9150509250929050565b60008060006060848603121561477b57600080fd5b60006147898682870161463e565b935050602061479a8682870161463e565b92505060406147ab868287016146ae565b9150509250925092565b600080604083850312156147c857600080fd5b60006147d68582860161463e565b92505060206147e7858286016146ae565b9150509250929050565b60006020828403121561480357600080fd5b600061481184828501614668565b91505092915050565b60006020828403121561482c57600080fd5b600061483a8482850161467d565b91505092915050565b60006101c0828403121561485657600080fd5b600061486484828501614692565b91505092915050565b60006020828403121561487f57600080fd5b600061488d848285016146ae565b91505092915050565b6000602082840312156148a857600080fd5b60006148b6848285016146c3565b91505092915050565b600080604083850312156148d257600080fd5b60006148e0858286016146ae565b92505060206148f1858286016146ae565b9150509250929050565b61490481615a9a565b82525050565b61491381615a88565b82525050565b61492281615aac565b82525050565b61493181615aac565b82525050565b61494081615b01565b82525050565b61494f81615b01565b82525050565b600061496082615957565b61496a8185615962565b935061497a818560208601615b37565b61498381615c49565b840191505092915050565b600061499b602383615962565b91507f45524332303a207472616e7366657220746f20746865207a65726f206164647260008301527f65737300000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000614a01601483615962565b91507f5061757361626c653a206e6f74207061757365640000000000000000000000006000830152602082019050919050565b6000614a41602283615962565b91507f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60008301527f63650000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000614aa7601c83615962565b91507f546865207374616b696e6720706572696f642068617320656e646564000000006000830152602082019050919050565b6000614ae7602683615962565b91507f43616e206e6f7420616e79207374616b6520666f7220737570706c696564206160008301527f64647265737300000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000614b4d602283615962565b91507f45524332303a20617070726f766520746f20746865207a65726f20616464726560008301527f73730000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000614bb3601e83615962565b91507f416d6f756e742062656c6f7720746865206d696e696d756d207374616b6500006000830152602082019050919050565b6000614bf3602683615962565b91507f45524332303a207472616e7366657220616d6f756e742065786365656473206260008301527f616c616e636500000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000614c59602783615962565b91507f43616e206e6f74207769746864726177206d6f7265207468616e20616374756160008301527f6c207374616b65000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000614cbf601083615962565b91507f5061757361626c653a20706175736564000000000000000000000000000000006000830152602082019050919050565b6000614cff602f83615962565b91507f54686520636f6e747261637420646f6573206e6f74206861766520656e6f756760008301527f682072657761726420746f6b656e7300000000000000000000000000000000006020830152604082019050919050565b6000614d65602e83615962565b91507f596f752063616e206e6f742065786365656564206d6178696d756d207375707060008301527f6c7920666f72207374616b696e670000000000000000000000000000000000006020830152604082019050919050565b6000614dcb601d83615962565b91507f43616e206e6f742066696e64207374616b6520666f722073656e6465720000006000830152602082019050919050565b6000614e0b602883615962565b91507f45524332303a207472616e7366657220616d6f756e742065786365656473206160008301527f6c6c6f77616e63650000000000000000000000000000000000000000000000006020830152604082019050919050565b6000614e71602183615962565b91507f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360008301527f73000000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000614ed7602583615962565b91507f45524332303a207472616e736665722066726f6d20746865207a65726f20616460008301527f64726573730000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000614f3d601783615962565b91507f5374616b6520616c72656461792077697468647261776e0000000000000000006000830152602082019050919050565b6000614f7d601c83615962565b91507f616d6f756e742065786365656473206d6178696d756d207374616b65000000006000830152602082019050919050565b6000614fbd603183615962565b91507f636f756c646e202774207472616e7366657220746f6b656e732066726f6d207360008301527f656e64657220746f20636f6e74726163740000000000000000000000000000006020830152604082019050919050565b6000615023602483615962565b91507f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460008301527f72657373000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000615089602183615962565b91507f416c6c20726577617264732068617665206265656e206469737472696275746560008301527f64000000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006150ef602583615962565b91507f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760008301527f207a65726f0000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000615155601f83615962565b91507f45524332303a206d696e7420746f20746865207a65726f2061646472657373006000830152602082019050919050565b60408201600082015161519e60008501826153d8565b5060208201516151b160208501826153d8565b50505050565b6040820160008201516151cd60008501826153d8565b5060208201516151e060208501826153d8565b50505050565b6040820160008201516151fc60008501826153d8565b50602082015161520f60208501826153d8565b50505050565b6101208201600082015161522c60008501826153d8565b50602082015161523f60208501826153d8565b5060408201516152526040850182614937565b50606082015161526560608501826153d8565b50608082015161527860808501826153d8565b5060a082015161528b60a0850182615188565b5060c082015161529e60e08501826153d8565b5060e08201516152b2610100850182614919565b50505050565b610200820160008201516152cf60008501826153d8565b5060208201516152e260208501826153d8565b5060408201516152f560408501826153d8565b5060608201516153086060850182614937565b50608082015161531b60808501826153d8565b5060a082015161532e60a08501826153d8565b5060c082015161534160c08501826153d8565b5060e082015161535460e08501826153d8565b506101008201516153696101008501826153d8565b5061012082015161537e6101208501826153d8565b506101408201516153936101408501826151e6565b506101608201516153a86101808501826153d8565b506101808201516153bd6101a08501826151e6565b506101a08201516153d26101e08501826153d8565b50505050565b6153e181615aea565b82525050565b6153f081615aea565b82525050565b6153ff81615af4565b82525050565b600060208201905061541a600083018461490a565b92915050565b600060208201905061543560008301846148fb565b92915050565b6000606082019050615450600083018661490a565b61545d602083018561490a565b61546a60408301846153e7565b949350505050565b6000604082019050615487600083018561490a565b61549460208301846153e7565b9392505050565b60006020820190506154b06000830184614928565b92915050565b600060208201905081810360008301526154d08184614955565b905092915050565b600060208201905081810360008301526154f18161498e565b9050919050565b60006020820190508181036000830152615511816149f4565b9050919050565b6000602082019050818103600083015261553181614a34565b9050919050565b6000602082019050818103600083015261555181614a9a565b9050919050565b6000602082019050818103600083015261557181614ada565b9050919050565b6000602082019050818103600083015261559181614b40565b9050919050565b600060208201905081810360008301526155b181614ba6565b9050919050565b600060208201905081810360008301526155d181614be6565b9050919050565b600060208201905081810360008301526155f181614c4c565b9050919050565b6000602082019050818103600083015261561181614cb2565b9050919050565b6000602082019050818103600083015261563181614cf2565b9050919050565b6000602082019050818103600083015261565181614d58565b9050919050565b6000602082019050818103600083015261567181614dbe565b9050919050565b6000602082019050818103600083015261569181614dfe565b9050919050565b600060208201905081810360008301526156b181614e64565b9050919050565b600060208201905081810360008301526156d181614eca565b9050919050565b600060208201905081810360008301526156f181614f30565b9050919050565b6000602082019050818103600083015261571181614f70565b9050919050565b6000602082019050818103600083015261573181614fb0565b9050919050565b6000602082019050818103600083015261575181615016565b9050919050565b600060208201905081810360008301526157718161507c565b9050919050565b60006020820190508181036000830152615791816150e2565b9050919050565b600060208201905081810360008301526157b181615148565b9050919050565b60006040820190506157cd60008301846151b7565b92915050565b6000610120820190506157e96000830184615215565b92915050565b60006102008201905061580560008301846152b8565b92915050565b600060208201905061582060008301846153e7565b92915050565b600060608201905061583b60008301866153e7565b6158486020830185614946565b61585560408301846153e7565b949350505050565b600060408201905061587260008301856153e7565b61587f60208301846153e7565b9392505050565b600060608201905061589b60008301866153e7565b6158a860208301856153e7565b6158b56040830184614946565b949350505050565b6000610120820190506158d3600083018b6153e7565b6158e0602083018a6153e7565b6158ed6040830189614946565b6158fa60608301886153e7565b61590760808301876153e7565b61591460a08301866151b7565b61592160e08301856153e7565b61592f610100830184614928565b9998505050505050505050565b600060208201905061595160008301846153f6565b92915050565b600081519050919050565b600082825260208201905092915050565b600061597e82615aea565b915061598983615aea565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038211156159be576159bd615b9c565b5b828201905092915050565b60006159d482615aea565b91506159df83615aea565b9250826159ef576159ee615bcb565b5b828204905092915050565b6000615a0582615aea565b9150615a1083615aea565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615615a4957615a48615b9c565b5b828202905092915050565b6000615a5f82615aea565b9150615a6a83615aea565b925082821015615a7d57615a7c615b9c565b5b828203905092915050565b6000615a9382615aca565b9050919050565b6000615aa582615aca565b9050919050565b60008115159050919050565b6000615ac382615a88565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600060ff82169050919050565b6000615b0c82615b13565b9050919050565b6000615b1e82615aca565b9050919050565b6000615b3082615aea565b9050919050565b60005b83811015615b55578082015181840152602081019050615b3a565b83811115615b64576000848401525b50505050565b60006002820490506001821680615b8257607f821691505b60208210811415615b9657615b95615bfa565b5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000819050919050565b60008135615c4081615d6e565b80915050919050565b6000601f19601f8301169050919050565b60008160001b9050919050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff615c9384615c5a565b9350801983169250808416831791505092915050565b600081016000830180615cbb81615c33565b9050615cc78184615cef565b505050600181016020830180615cdc81615c33565b9050615ce88184615cef565b5050505050565b615cf882615b25565b615d0b615d0482615c29565b8354615c67565b8255505050565b615d1b81615a88565b8114615d2657600080fd5b50565b615d3281615a9a565b8114615d3d57600080fd5b50565b615d4981615aac565b8114615d5457600080fd5b50565b615d6081615ab8565b8114615d6b57600080fd5b50565b615d7781615aea565b8114615d8257600080fd5b5056fea2646970667358221220afecb0b0dd0e73ee4bd971c9bbd3ae530612cceed388cf838f1f5eb5cdbfdbb964736f6c634300080000330000000000000000000000002e85ae1c47602f7927bcabc2ff99c40aa222ae15

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106101fb5760003560e01c80636ff1c9bc1161011a578063a694fc3a116100ad578063d2cbf7ad1161007c578063d2cbf7ad146105bd578063dd62ed3e146105db578063ea4405001461060b578063f2fde38b1461063b578063fc0e3d9014610657576101fb565b8063a694fc3a14610537578063a9059cbb14610553578063b0b5529e14610583578063bfacd9ed1461059f576101fb565b80638da5cb5b116100e95780638da5cb5b146104af57806395d89b41146104cd5780639d836bd2146104eb578063a457c2d714610507576101fb565b80636ff1c9bc1461042257806370a082311461043e578063758035661461046e5780638456cb59146104a5576101fb565b80632ff7cfc61161019257806348f9ead41161016157806348f9ead4146103865780635931b24e146103b65780635c975abb146103e65780635e42b45514610404576101fb565b80632ff7cfc614610310578063313ce5671461032e578063395093511461034c5780633f4ba83a1461037c576101fb565b80631e9b12ef116101ce5780631e9b12ef1461028a57806323b872dd146102a657806325d5971f146102d65780632f861449146102f2576101fb565b806306fdde03146102005780630917e7761461021e578063095ea7b31461023c57806318160ddd1461026c575b600080fd5b610208610675565b60405161021591906154b6565b60405180910390f35b610226610707565b604051610233919061580b565b60405180910390f35b610256600480360381019061025191906147b5565b610711565b604051610263919061549b565b60405180910390f35b61027461072f565b604051610281919061580b565b60405180910390f35b6102a4600480360381019061029f91906146d8565b610739565b005b6102c060048036038101906102bb9190614766565b6107da565b6040516102cd919061549b565b60405180910390f35b6102f060048036038101906102eb919061486d565b6108d2565b005b6102fa610eaa565b604051610307919061580b565b60405180910390f35b610318610eb4565b604051610325919061580b565b60405180910390f35b610336610ec4565b604051610343919061593c565b60405180910390f35b610366600480360381019061036191906147b5565b610ecd565b604051610373919061549b565b60405180910390f35b610384610f79565b005b6103a0600480360381019061039b919061486d565b610fdd565b6040516103ad919061580b565b60405180910390f35b6103d060048036038101906103cb91906148bf565b611049565b6040516103dd919061580b565b60405180910390f35b6103ee61106c565b6040516103fb919061549b565b60405180910390f35b61040c611083565b604051610419919061580b565b60405180910390f35b61043c600480360381019061043791906146d8565b611157565b005b610458600480360381019061045391906146d8565b611620565b604051610465919061580b565b60405180910390f35b610488600480360381019061048391906146d8565b611668565b60405161049c9897969594939291906158bd565b60405180910390f35b6104ad6116fb565b005b6104b761175f565b6040516104c49190615420565b60405180910390f35b6104d5611785565b6040516104e291906154b6565b60405180910390f35b61050560048036038101906105009190614843565b611817565b005b610521600480360381019061051c91906147b5565b611a4b565b60405161052e919061549b565b60405180910390f35b610551600480360381019061054c919061486d565b611b36565b005b61056d600480360381019061056891906147b5565b6123d6565b60405161057a919061549b565b60405180910390f35b61059d6004803603810190610598919061486d565b6123f4565b005b6105a761258c565b6040516105b491906157ef565b60405180910390f35b6105c56126bb565b6040516105d291906157b8565b60405180910390f35b6105f560048036038101906105f0919061472a565b612809565b604051610602919061580b565b60405180910390f35b6106256004803603810190610620919061486d565b612890565b604051610632919061580b565b60405180910390f35b61065560048036038101906106509190614701565b612a87565b005b61065f612b5f565b60405161066c91906157d3565b60405180910390f35b60606003805461068490615b6a565b80601f01602080910402602001604051908101604052809291908181526020018280546106b090615b6a565b80156106fd5780601f106106d2576101008083540402835291602001916106fd565b820191906000526020600020905b8154815290600101906020018083116106e057829003601f168201915b5050505050905090565b6000601854905090565b600061072561071e612dc1565b8484612dc9565b6001905092915050565b6000600254905090565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461079357600080fd5b80600860030160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60006107e7848484612f94565b6000600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000610832612dc1565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050828110156108b2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108a990615678565b60405180910390fd5b6108c6856108be612dc1565b858403612dc9565b60019150509392505050565b3273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461090a57600080fd5b61091261106c565b15610952576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610949906155f8565b60405180910390fd5b600660003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060080160009054906101000a900460ff166109e1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109d890615658565b60405180910390fd5b80600660003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001541015610a66576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a5d906155d8565b60405180910390fd5b6000600660003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206040518061010001604052908160008201548152602001600182015481526020016002820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600382015481526020016004820154815260200160058201604051806040016040529081600082015481526020016001820154815250508152602001600782015481526020016008820160009054906101000a900460ff16151515158152505090506000816000015111610bc7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bbe906156d8565b60405180910390fd5b6000610bfd8260000151610bef85610be142876001613215565b61329390919063ffffffff16565b6132a990919063ffffffff16565b90506000610c09611083565b905080821115610c4e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c4590615618565b60405180910390fd5b60008483610c5c9190615973565b90506000610c8d8560000151610c7f88886060015161329390919063ffffffff16565b6132a990919063ffffffff16565b905085600660003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000016000828254610ce19190615a54565b9250508190555080600660003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206003016000828254610d3a9190615a54565b9250508190555085601854610d4f9190615a54565b6018819055508360196000828254610d679190615973565b92505081905550846040015173ffffffffffffffffffffffffffffffffffffffff1663a9059cbb33846040518363ffffffff1660e01b8152600401610dad929190615472565b602060405180830381600087803b158015610dc757600080fd5b505af1158015610ddb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dff91906147f1565b610e3e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e3590615718565b60405180910390fd5b610e4833826132bf565b3373ffffffffffffffffffffffffffffffffffffffff167fbc0fb706d03a6cb96fbe31862998338850cd01d239a360045dbe469d548e42188660000151848860400151604051610e9a93929190615886565b60405180910390a2505050505050565b6000601954905090565b6000610ebf42613496565b905090565b60006012905090565b6000610f6f610eda612dc1565b848460016000610ee8612dc1565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f6a9190615973565b612dc9565b6001905092915050565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610fd357600080fd5b610fdb613554565b565b6000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461103957600080fd5b61104282613496565b9050919050565b600080611055836135f6565b905061106384826000613215565b91505092915050565b6000600560149054906101000a900460ff16905090565b600080600860030160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016110e49190615405565b60206040518083038186803b1580156110fc57600080fd5b505afa158015611110573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111349190614896565b9050600061114d6018548361377090919063ffffffff16565b9050809250505090565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146111b157600080fd5b600660008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060080160009054906101000a900460ff16611240576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161123790615658565b60405180910390fd5b6000600660008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000154116112c5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112bc90615558565b60405180910390fd5b600080600660008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001549150600660008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600301549050600660008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb84600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001546040518363ffffffff1660e01b8152600401611431929190615472565b602060405180830381600087803b15801561144b57600080fd5b505af115801561145f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061148391906147f1565b6114c2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114b990615718565b60405180910390fd5b6000600660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001819055506000600660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060080160006101000a81548160ff0219169083151502179055506000600660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060030181905550816018546115bb9190615a54565b6018819055506115cb83826132bf565b8273ffffffffffffffffffffffffffffffffffffffff167fbb757047c2b5f3974fe26b7c10f732e7bce710b0952a71082702781e62ae0595828460405161161392919061585d565b60405180910390a2505050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b60066020528060005260406000206000915090508060000154908060010154908060020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060030154908060040154908060050160405180604001604052908160008201548152602001600182015481525050908060070154908060080160009054906101000a900460ff16905088565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461175557600080fd5b61175d613786565b565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60606004805461179490615b6a565b80601f01602080910402602001604051908101604052809291908181526020018280546117c090615b6a565b801561180d5780601f106117e25761010080835404028352916020019161180d565b820191906000526020600020905b8154815290600101906020018083116117f057829003601f168201915b5050505050905090565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461187157600080fd5b8060000135600860000181905550806020013560086001018190555080604001356008600201819055508060600160208101906118ae919061481a565b600860030160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508060800135600860040181905550601a60009054906101000a900460ff16156119335760086004015460088001546119299190615973565b6008600901819055505b601a60009054906101000a900460ff166119ea578060c001356008600601819055508060e001356008600701819055506000600860070154148061197e575060086007015460185410155b80156119a15750600060086006015414806119a0575060086006015460075410155b5b156119e9576001601a60006101000a81548160ff02191690831515021790555042600880018190555060086004015460088001546119df9190615973565b6008600901819055505b5b8060a0013560086005018190555080610100016008600a018181611a0e9190615ca9565b9050508061014001356008600c018190555080610160016008600d018181611a369190615ca9565b905050806101a001356008600f018190555050565b60008060016000611a5a612dc1565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905082811015611b17576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b0e90615778565b60405180910390fd5b611b2b611b22612dc1565b85858403612dc9565b600191505092915050565b3273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611b6e57600080fd5b611b7661106c565b15611bb6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611bad906155f8565b60405180910390fd5b600860000154811015611bfe576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611bf590615598565b60405180910390fd5b60006008600501541480611c1757506008600501548111155b611c56576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c4d906156f8565b60405180910390fd5b60086001015481601854611c6a9190615973565b1115611cab576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ca290615638565b60405180910390fd5b601a60009054906101000a900460ff161580611ccb575060086009015442105b611d0a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d0190615538565b60405180910390fd5b60086002015460195410611d53576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d4a90615758565b60405180910390fd5b6000611d5e826135f6565b90508160186000828254611d729190615973565b92505081905550600660003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060080160009054906101000a900460ff16611de857600160076000828254611de09190615973565b925050819055505b601a60009054906101000a900460ff16158015611e1c575060006008600701541480611e1b575060086007015460185410155b5b8015611e3f575060006008600601541480611e3e575060086006015460075410155b5b15611e87576001601a60006101000a81548160ff0219169083151502179055504260088001819055506008600401546008800154611e7d9190615973565b6008600901819055505b600860030160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd3330856040518463ffffffff1660e01b8152600401611ee99392919061543b565b602060405180830381600087803b158015611f0357600080fd5b505af1158015611f17573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f3b91906147f1565b611f7a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f7190615718565b60405180910390fd5b611f88338260600151613829565b600660003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060080160009054906101000a900460ff166121375780600660003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082015181600001556020820151816001015560408201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550606082015181600301556080820151816004015560a0820151816005016000820151816000015560208201518160010155505060c0820151816007015560e08201518160080160006101000a81548160ff0219169083151502179055509050506001600660003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060080160006101000a81548160ff021916908315150217905550612357565b612256600660003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206040518061010001604052908160008201548152602001600182015481526020016002820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600382015481526020016004820154815260200160058201604051806040016040529081600082015481526020016001820154815250508152602001600782015481526020016008820160009054906101000a900460ff16151515158152505082613989565b600660003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600701819055508060000151600660003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160008282546122f29190615973565b925050819055508060600151600660003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600301600082825461234f9190615973565b925050819055505b3373ffffffffffffffffffffffffffffffffffffffff167ff65271afc35201e83c229b7b581d7fde59bfe7b7dd943e8719fc8c5f5ada63f683600860030160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1684606001516040516123ca93929190615826565b60405180910390a25050565b60006123ea6123e3612dc1565b8484612f94565b6001905092915050565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461244e57600080fd5b612456611083565b811115612498576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161248f90615618565b60405180910390fd5b600860030160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb33836040518363ffffffff1660e01b81526004016124f8929190615472565b602060405180830381600087803b15801561251257600080fd5b505af1158015612526573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061254a91906147f1565b612589576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161258090615718565b60405180910390fd5b50565b612594614516565b6008604051806101c00160405290816000820154815260200160018201548152602001600282015481526020016003820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600482015481526020016005820154815260200160068201548152602001600782015481526020016008820154815260200160098201548152602001600a8201604051806040016040529081600082015481526020016001820154815250508152602001600c8201548152602001600d8201604051806040016040529081600082015481526020016001820154815250508152602001600f82015481525050905090565b6126c36145a7565b601a60009054906101000a900460ff1615806126e757506008800154600860090154145b806126f457506000601854145b156127175760405180604001604052806000815260200160018152509050612806565b60006301e13380905060006008600a0160000154148015612740575060006008600d0160000154145b8015612751575060006008600c0154145b8015612762575060006008600f0154145b156127fa5760006127ae612788600880015460086009015461377090919063ffffffff16565b6127a08460086002015461329390919063ffffffff16565b6132a990919063ffffffff16565b905060405180604001604052806127e56018546127d7620186a08661329390919063ffffffff16565b6132a990919063ffffffff16565b8152602001620186a081525092505050612806565b612802613a11565b9150505b90565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b60003273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146128ca57600080fd5b600660003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060080160009054906101000a900460ff16612959576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161295090615658565b60405180910390fd5b6000600660003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206040518061010001604052908160008201548152602001600182015481526020016002820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600382015481526020016004820154815260200160058201604051806040016040529081600082015481526020016001820154815250508152602001600782015481526020016008820160009054906101000a900460ff1615151515815250509050612a7f83826001613215565b915050919050565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614612ae157600080fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415612b1b57600080fd5b80600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b612b676145c1565b6000600660003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206040518061010001604052908160008201548152602001600182015481526020016002820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600382015481526020016004820154815260200160058201604051806040016040529081600082015481526020016001820154815250508152602001600782015481526020016008820160009054906101000a900460ff16151515158152505090508060e00151612d25576040518061010001604052806000815260200160008152602001600860030160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016000815260200160008152602001604051806040016040528060008152602001600181525081526020016000815260200160001515815250915050612dbe565b601a60009054906101000a900460ff1615612db957612d4642826001613215565b8160800181815250506040518060400160405280612da48360000151612d96620186a0612d886301e133808860c00151612d809190615973565b886001613215565b61329390919063ffffffff16565b6132a990919063ffffffff16565b8152602001620186a08152508160a001819052505b809150505b90565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415612e39576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612e3090615738565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415612ea9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612ea090615578565b60405180910390fd5b80600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92583604051612f87919061580b565b60405180910390a3505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415613004576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612ffb906156b8565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415613074576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161306b906154d8565b60405180910390fd5b61307f838383613b22565b60008060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905081811015613105576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016130fc906155b8565b60405180910390fd5b8181036000808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546131989190615973565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516131fc919061580b565b60405180910390a361320f848484613b27565b50505050565b6000806008600a0160000154148015613236575060006008600d0160000154145b8015613247575060006008600c0154145b8015613258575060006008600f0154145b1561327e576132776008600201548585606001518660c001518661425f565b905061328c565b613289848484614319565b90505b9392505050565b600081836132a191906159fa565b905092915050565b600081836132b791906159c9565b905092915050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141561332f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161332690615698565b60405180910390fd5b61333b82600083613b22565b60008060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050818110156133c1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016133b890615518565b60405180910390fd5b8181036000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555081600260008282546134189190615a54565b92505081905550600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161347d919061580b565b60405180910390a361349183600084613b27565b505050565b6000601a60009054906101000a900460ff1615806134bc57506008800154600860090154145b806134c957506000601854145b156134d7576000905061354f565b600061354860195461353a6134fe600880015460086009015461377090919063ffffffff16565b61352c61351860088001548961377090919063ffffffff16565b60086002015461329390919063ffffffff16565b6132a990919063ffffffff16565b61377090919063ffffffff16565b9050809150505b919050565b61355c61106c565b61359b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613592906154f8565b60405180910390fd5b6000600560146101000a81548160ff0219169083151502179055507f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa6135df612dc1565b6040516135ec9190615405565b60405180910390a1565b6135fe6145c1565b6000804290506000601854148061361c5750600061361a61072f565b145b15613629578391506136d8565b60006136a46136686008800154600261364291906159fa565b61365a8560086009015461450090919063ffffffff16565b61377090919063ffffffff16565b613696613687600880015460086009015461377090919063ffffffff16565b8861329390919063ffffffff16565b6132a990919063ffffffff16565b90506136d46018546136c66136b761072f565b8461329390919063ffffffff16565b6132a990919063ffffffff16565b9250505b604051806101000160405280858152602001828152602001600860030160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200183815260200160008152602001604051806040016040528060008152602001600181525081526020018281526020016001151581525092505050919050565b6000818361377e9190615a54565b905092915050565b61378e61106c565b156137ce576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016137c5906155f8565b60405180910390fd5b6001600560146101000a81548160ff0219169083151502179055507f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258613812612dc1565b60405161381f9190615405565b60405180910390a1565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415613899576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161389090615798565b60405180910390fd5b6138a560008383613b22565b80600260008282546138b79190615973565b92505081905550806000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825461390c9190615973565b925050819055508173ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051613971919061580b565b60405180910390a361398560008383613b27565b5050565b6000806139d36139aa84606001518560c0015161329390919063ffffffff16565b6139c586606001518760c0015161329390919063ffffffff16565b61450090919063ffffffff16565b905060006139f28460600151866060015161450090919063ffffffff16565b9050613a0781836132a990919063ffffffff16565b9250505092915050565b613a196145a7565b60006301e13380905060006040518061010001604052806018548152602001428152602001600860030160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001613a8761072f565b815260200160008152602001604051806040016040528060008152602001600181525081526020014281526020016001151581525090506000613ad78342613acf9190615973565b836001614319565b90506040518060400160405280613b0e601854613b00620186a08661329390919063ffffffff16565b6132a990919063ffffffff16565b8152602001620186a0815250935050505090565b505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415613b615761425a565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415613b9b5761425a565b6000600660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206040518061010001604052908160008201548152602001600182015481526020016002820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600382015481526020016004820154815260200160058201604051806040016040529081600082015481526020016001820154815250508152602001600782015481526020016008820160009054906101000a900460ff16151515158152505090506000613d60600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060030154613d5285600660008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000015461329390919063ffffffff16565b6132a990919063ffffffff16565b905060018260e00190151590811515815250508282606001818152505080826000018181525050600660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060080160009054906101000a900460ff16613f8d5781600660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082015181600001556020820151816001015560408201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550606082015181600301556080820151816004015560a0820151816005016000820151816000015560208201518160010155505060c0820151816007015560e08201518160080160006101000a81548160ff02191690831515021790555090505082600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206003016000828254613f289190615a54565b9250508190555080600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000016000828254613f819190615a54565b92505081905550614257565b6140ac600660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206040518061010001604052908160008201548152602001600182015481526020016002820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600382015481526020016004820154815260200160058201604051806040016040529081600082015481526020016001820154815250508152602001600782015481526020016008820160009054906101000a900460ff16151515158152505083613989565b600660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206007018190555082600660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060030160008282546141449190615973565b9250508190555080600660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001600082825461419d9190615973565b9250508190555082600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060030160008282546141f69190615a54565b9250508190555080600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001600082825461424f9190615a54565b925050819055505b50505b505050565b6000806142c6614281600880015460086009015461377090919063ffffffff16565b6142b8614297878a61377090919063ffffffff16565b6142aa8b8a61329390919063ffffffff16565b61329390919063ffffffff16565b6132a990919063ffffffff16565b90506000836142ee576142e9866142db61072f565b61450090919063ffffffff16565b6142f7565b6142f661072f565b5b905061430c81836132a990919063ffffffff16565b9250505095945050505050565b60008060008460c00151905060006143616008600a01600101546143536008600a016000015460086002015461329390919063ffffffff16565b6132a990919063ffffffff16565b9050866008600c0154836143759190615973565b106143955761438b81888860600151858961425f565b93505050506144f9565b6143b6816008600c0154846143aa9190615973565b8860600151858961425f565b836143c19190615973565b92506008600c0154826143d49190615973565b91506144106008600d01600101546144026008600d016000015460086002015461329390919063ffffffff16565b6132a990919063ffffffff16565b8161441b9190615973565b905060006008600f015414806144415750866008600f01548361443e9190615973565b11155b1561447b57600860020154905061447161446282898960600151868a61425f565b8461450090919063ffffffff16565b93505050506144f9565b6144c76008600f01546144b9848a6144939190615a54565b6144ab8560086002015461377090919063ffffffff16565b61329390919063ffffffff16565b6132a990919063ffffffff16565b816144d29190615973565b90506144e581888860600151858961425f565b836144f09190615973565b92508293505050505b9392505050565b6000818361450e9190615973565b905092915050565b604051806101c00160405280600081526020016000815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001614586614624565b81526020016000815260200161459a614624565b8152602001600081525090565b604051806040016040528060008152602001600081525090565b6040518061010001604052806000815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600081526020016000815260200161460e6145a7565b8152602001600081526020016000151581525090565b604051806040016040528060008152602001600081525090565b60008135905061464d81615d12565b92915050565b60008135905061466281615d29565b92915050565b60008151905061467781615d40565b92915050565b60008135905061468c81615d57565b92915050565b60006101c082840312156146a557600080fd5b81905092915050565b6000813590506146bd81615d6e565b92915050565b6000815190506146d281615d6e565b92915050565b6000602082840312156146ea57600080fd5b60006146f88482850161463e565b91505092915050565b60006020828403121561471357600080fd5b600061472184828501614653565b91505092915050565b6000806040838503121561473d57600080fd5b600061474b8582860161463e565b925050602061475c8582860161463e565b9150509250929050565b60008060006060848603121561477b57600080fd5b60006147898682870161463e565b935050602061479a8682870161463e565b92505060406147ab868287016146ae565b9150509250925092565b600080604083850312156147c857600080fd5b60006147d68582860161463e565b92505060206147e7858286016146ae565b9150509250929050565b60006020828403121561480357600080fd5b600061481184828501614668565b91505092915050565b60006020828403121561482c57600080fd5b600061483a8482850161467d565b91505092915050565b60006101c0828403121561485657600080fd5b600061486484828501614692565b91505092915050565b60006020828403121561487f57600080fd5b600061488d848285016146ae565b91505092915050565b6000602082840312156148a857600080fd5b60006148b6848285016146c3565b91505092915050565b600080604083850312156148d257600080fd5b60006148e0858286016146ae565b92505060206148f1858286016146ae565b9150509250929050565b61490481615a9a565b82525050565b61491381615a88565b82525050565b61492281615aac565b82525050565b61493181615aac565b82525050565b61494081615b01565b82525050565b61494f81615b01565b82525050565b600061496082615957565b61496a8185615962565b935061497a818560208601615b37565b61498381615c49565b840191505092915050565b600061499b602383615962565b91507f45524332303a207472616e7366657220746f20746865207a65726f206164647260008301527f65737300000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000614a01601483615962565b91507f5061757361626c653a206e6f74207061757365640000000000000000000000006000830152602082019050919050565b6000614a41602283615962565b91507f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60008301527f63650000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000614aa7601c83615962565b91507f546865207374616b696e6720706572696f642068617320656e646564000000006000830152602082019050919050565b6000614ae7602683615962565b91507f43616e206e6f7420616e79207374616b6520666f7220737570706c696564206160008301527f64647265737300000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000614b4d602283615962565b91507f45524332303a20617070726f766520746f20746865207a65726f20616464726560008301527f73730000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000614bb3601e83615962565b91507f416d6f756e742062656c6f7720746865206d696e696d756d207374616b6500006000830152602082019050919050565b6000614bf3602683615962565b91507f45524332303a207472616e7366657220616d6f756e742065786365656473206260008301527f616c616e636500000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000614c59602783615962565b91507f43616e206e6f74207769746864726177206d6f7265207468616e20616374756160008301527f6c207374616b65000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000614cbf601083615962565b91507f5061757361626c653a20706175736564000000000000000000000000000000006000830152602082019050919050565b6000614cff602f83615962565b91507f54686520636f6e747261637420646f6573206e6f74206861766520656e6f756760008301527f682072657761726420746f6b656e7300000000000000000000000000000000006020830152604082019050919050565b6000614d65602e83615962565b91507f596f752063616e206e6f742065786365656564206d6178696d756d207375707060008301527f6c7920666f72207374616b696e670000000000000000000000000000000000006020830152604082019050919050565b6000614dcb601d83615962565b91507f43616e206e6f742066696e64207374616b6520666f722073656e6465720000006000830152602082019050919050565b6000614e0b602883615962565b91507f45524332303a207472616e7366657220616d6f756e742065786365656473206160008301527f6c6c6f77616e63650000000000000000000000000000000000000000000000006020830152604082019050919050565b6000614e71602183615962565b91507f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360008301527f73000000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000614ed7602583615962565b91507f45524332303a207472616e736665722066726f6d20746865207a65726f20616460008301527f64726573730000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000614f3d601783615962565b91507f5374616b6520616c72656461792077697468647261776e0000000000000000006000830152602082019050919050565b6000614f7d601c83615962565b91507f616d6f756e742065786365656473206d6178696d756d207374616b65000000006000830152602082019050919050565b6000614fbd603183615962565b91507f636f756c646e202774207472616e7366657220746f6b656e732066726f6d207360008301527f656e64657220746f20636f6e74726163740000000000000000000000000000006020830152604082019050919050565b6000615023602483615962565b91507f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460008301527f72657373000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000615089602183615962565b91507f416c6c20726577617264732068617665206265656e206469737472696275746560008301527f64000000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006150ef602583615962565b91507f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760008301527f207a65726f0000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000615155601f83615962565b91507f45524332303a206d696e7420746f20746865207a65726f2061646472657373006000830152602082019050919050565b60408201600082015161519e60008501826153d8565b5060208201516151b160208501826153d8565b50505050565b6040820160008201516151cd60008501826153d8565b5060208201516151e060208501826153d8565b50505050565b6040820160008201516151fc60008501826153d8565b50602082015161520f60208501826153d8565b50505050565b6101208201600082015161522c60008501826153d8565b50602082015161523f60208501826153d8565b5060408201516152526040850182614937565b50606082015161526560608501826153d8565b50608082015161527860808501826153d8565b5060a082015161528b60a0850182615188565b5060c082015161529e60e08501826153d8565b5060e08201516152b2610100850182614919565b50505050565b610200820160008201516152cf60008501826153d8565b5060208201516152e260208501826153d8565b5060408201516152f560408501826153d8565b5060608201516153086060850182614937565b50608082015161531b60808501826153d8565b5060a082015161532e60a08501826153d8565b5060c082015161534160c08501826153d8565b5060e082015161535460e08501826153d8565b506101008201516153696101008501826153d8565b5061012082015161537e6101208501826153d8565b506101408201516153936101408501826151e6565b506101608201516153a86101808501826153d8565b506101808201516153bd6101a08501826151e6565b506101a08201516153d26101e08501826153d8565b50505050565b6153e181615aea565b82525050565b6153f081615aea565b82525050565b6153ff81615af4565b82525050565b600060208201905061541a600083018461490a565b92915050565b600060208201905061543560008301846148fb565b92915050565b6000606082019050615450600083018661490a565b61545d602083018561490a565b61546a60408301846153e7565b949350505050565b6000604082019050615487600083018561490a565b61549460208301846153e7565b9392505050565b60006020820190506154b06000830184614928565b92915050565b600060208201905081810360008301526154d08184614955565b905092915050565b600060208201905081810360008301526154f18161498e565b9050919050565b60006020820190508181036000830152615511816149f4565b9050919050565b6000602082019050818103600083015261553181614a34565b9050919050565b6000602082019050818103600083015261555181614a9a565b9050919050565b6000602082019050818103600083015261557181614ada565b9050919050565b6000602082019050818103600083015261559181614b40565b9050919050565b600060208201905081810360008301526155b181614ba6565b9050919050565b600060208201905081810360008301526155d181614be6565b9050919050565b600060208201905081810360008301526155f181614c4c565b9050919050565b6000602082019050818103600083015261561181614cb2565b9050919050565b6000602082019050818103600083015261563181614cf2565b9050919050565b6000602082019050818103600083015261565181614d58565b9050919050565b6000602082019050818103600083015261567181614dbe565b9050919050565b6000602082019050818103600083015261569181614dfe565b9050919050565b600060208201905081810360008301526156b181614e64565b9050919050565b600060208201905081810360008301526156d181614eca565b9050919050565b600060208201905081810360008301526156f181614f30565b9050919050565b6000602082019050818103600083015261571181614f70565b9050919050565b6000602082019050818103600083015261573181614fb0565b9050919050565b6000602082019050818103600083015261575181615016565b9050919050565b600060208201905081810360008301526157718161507c565b9050919050565b60006020820190508181036000830152615791816150e2565b9050919050565b600060208201905081810360008301526157b181615148565b9050919050565b60006040820190506157cd60008301846151b7565b92915050565b6000610120820190506157e96000830184615215565b92915050565b60006102008201905061580560008301846152b8565b92915050565b600060208201905061582060008301846153e7565b92915050565b600060608201905061583b60008301866153e7565b6158486020830185614946565b61585560408301846153e7565b949350505050565b600060408201905061587260008301856153e7565b61587f60208301846153e7565b9392505050565b600060608201905061589b60008301866153e7565b6158a860208301856153e7565b6158b56040830184614946565b949350505050565b6000610120820190506158d3600083018b6153e7565b6158e0602083018a6153e7565b6158ed6040830189614946565b6158fa60608301886153e7565b61590760808301876153e7565b61591460a08301866151b7565b61592160e08301856153e7565b61592f610100830184614928565b9998505050505050505050565b600060208201905061595160008301846153f6565b92915050565b600081519050919050565b600082825260208201905092915050565b600061597e82615aea565b915061598983615aea565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038211156159be576159bd615b9c565b5b828201905092915050565b60006159d482615aea565b91506159df83615aea565b9250826159ef576159ee615bcb565b5b828204905092915050565b6000615a0582615aea565b9150615a1083615aea565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615615a4957615a48615b9c565b5b828202905092915050565b6000615a5f82615aea565b9150615a6a83615aea565b925082821015615a7d57615a7c615b9c565b5b828203905092915050565b6000615a9382615aca565b9050919050565b6000615aa582615aca565b9050919050565b60008115159050919050565b6000615ac382615a88565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600060ff82169050919050565b6000615b0c82615b13565b9050919050565b6000615b1e82615aca565b9050919050565b6000615b3082615aea565b9050919050565b60005b83811015615b55578082015181840152602081019050615b3a565b83811115615b64576000848401525b50505050565b60006002820490506001821680615b8257607f821691505b60208210811415615b9657615b95615bfa565b5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000819050919050565b60008135615c4081615d6e565b80915050919050565b6000601f19601f8301169050919050565b60008160001b9050919050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff615c9384615c5a565b9350801983169250808416831791505092915050565b600081016000830180615cbb81615c33565b9050615cc78184615cef565b505050600181016020830180615cdc81615c33565b9050615ce88184615cef565b5050505050565b615cf882615b25565b615d0b615d0482615c29565b8354615c67565b8255505050565b615d1b81615a88565b8114615d2657600080fd5b50565b615d3281615a9a565b8114615d3d57600080fd5b50565b615d4981615aac565b8114615d5457600080fd5b50565b615d6081615ab8565b8114615d6b57600080fd5b50565b615d7781615aea565b8114615d8257600080fd5b5056fea2646970667358221220afecb0b0dd0e73ee4bd971c9bbd3ae530612cceed388cf838f1f5eb5cdbfdbb964736f6c63430008000033

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

0000000000000000000000002e85ae1c47602f7927bcabc2ff99c40aa222ae15

-----Decoded View---------------
Arg [0] : stakingTokenAddress (address): 0x2e85ae1C47602f7927bCabc2Ff99C40aA222aE15

-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 0000000000000000000000002e85ae1c47602f7927bcabc2ff99c40aa222ae15


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

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