ETH Price: $3,277.72 (+0.82%)
Gas: 2 Gwei

Contract

0x1767534c0658044E1deD9579214572D3c5c56025
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Renounce Ownersh...162863682022-12-28 22:54:23576 days ago1672268063IN
0x1767534c...3c5c56025
0 ETH0.0004273518.24100197
Unstake135212152021-10-30 22:50:171000 days ago1635634217IN
0x1767534c...3c5c56025
0 ETH0.03439913179.12295812
Unstake133978092021-10-11 14:23:261019 days ago1633962206IN
0x1767534c...3c5c56025
0 ETH0.01337176.42582392
Unstake133348292021-10-01 17:27:581029 days ago1633109278IN
0x1767534c...3c5c56025
0 ETH0.0129377173.95430927
Unstake133347542021-10-01 17:11:511029 days ago1633108311IN
0x1767534c...3c5c56025
0 ETH0.0077300577.30051211
Unstake133347542021-10-01 17:11:511029 days ago1633108311IN
0x1767534c...3c5c56025
0 ETH0.0154062277.10051211
Unstake129856852021-08-08 16:57:101083 days ago1628441830IN
0x1767534c...3c5c56025
0 ETH0.0113416658
Unstake129253072021-07-30 6:04:551093 days ago1627625095IN
0x1767534c...3c5c56025
0 ETH0.0031658523
Stake129252182021-07-30 5:46:141093 days ago1627623974IN
0x1767534c...3c5c56025
0 ETH0.0045742524
Unstake129122712021-07-28 4:12:201095 days ago1627445540IN
0x1767534c...3c5c56025
0 ETH0.0034046722
Stake129122472021-07-28 4:08:191095 days ago1627445299IN
0x1767534c...3c5c56025
0 ETH0.0041933322
Unstake129115462021-07-28 1:37:281095 days ago1627436248IN
0x1767534c...3c5c56025
0 ETH0.003932626
Stake129000212021-07-26 5:39:371097 days ago1627277977IN
0x1767534c...3c5c56025
0 ETH0.0066061129
Unstake128995072021-07-26 3:42:401097 days ago1627270960IN
0x1767534c...3c5c56025
0 ETH0.0033940925.3
Unstake128994702021-07-26 3:32:501097 days ago1627270370IN
0x1767534c...3c5c56025
0 ETH0.0038540828
Unstake128992732021-07-26 2:51:511097 days ago1627267911IN
0x1767534c...3c5c56025
0 ETH0.0116257656
Unstake128983782021-07-25 23:29:061097 days ago1627255746IN
0x1767534c...3c5c56025
0 ETH0.0018841816.1
Unstake128978342021-07-25 21:28:491097 days ago1627248529IN
0x1767534c...3c5c56025
0 ETH0.0022669916.9
Unstake128978292021-07-25 21:27:291097 days ago1627248449IN
0x1767534c...3c5c56025
0 ETH0.0024145518
Unstake128973942021-07-25 19:52:011097 days ago1627242721IN
0x1767534c...3c5c56025
0 ETH0.0018781514
Unstake128959752021-07-25 14:34:211097 days ago1627223661IN
0x1767534c...3c5c56025
0 ETH0.0062277330
Unstake128952902021-07-25 11:58:371097 days ago1627214317IN
0x1767534c...3c5c56025
0 ETH0.0013548310.1
Unstake128892272021-07-24 13:21:001098 days ago1627132860IN
0x1767534c...3c5c56025
0 ETH0.0024912312
Unstake128881432021-07-24 9:17:001099 days ago1627118220IN
0x1767534c...3c5c56025
0 ETH0.0018169213.2
Unstake128863722021-07-24 2:40:011099 days ago1627094401IN
0x1767534c...3c5c56025
0 ETH0.0034879316.8
View all transactions

Latest 3 internal transactions

Advanced mode:
Parent Transaction Hash Block From To
124676922021-05-19 23:11:051164 days ago1621465865
0x1767534c...3c5c56025
 Contract Creation0 ETH
124676922021-05-19 23:11:051164 days ago1621465865
0x1767534c...3c5c56025
 Contract Creation0 ETH
124676922021-05-19 23:11:051164 days ago1621465865
0x1767534c...3c5c56025
 Contract Creation0 ETH
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
TokenGeyser

Compiler Version
v0.5.17+commit.d19bba13

Optimization Enabled:
No with 200 runs

Other Settings:
default evmVersion
File 1 of 6 : TokenGeyser.sol
pragma solidity 0.5.17;
pragma experimental ABIEncoderV2;

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

import "./roles/Ownable.sol";
import "./interfaces/IStaking.sol";
import "./TokenPool.sol";


/**
 * @dev A smart-contract based mechanism to distribute tokens over time, inspired loosely by Compound and Uniswap.
 *
 *  Distribution tokens are added to a locked pool in the contract and become unlocked over time according to a once-configurable unlock schedule. Once unlocked, they are available to be claimed by users.
 *
 *  A user may deposit tokens to accrue ownership share over the unlocked pool. This owner share is a function of the number of tokens deposited as well as the length of time deposited.
 *
 *  Specifically, a user's share of the currently-unlocked pool equals their "deposit-seconds" divided by the global "deposit-seconds". This aligns the new token distribution with long term supporters of the project, addressing one of the major drawbacks of simple airdrops.
 *
 *  More background and motivation available at:
 *  https://github.com/ampleforth/RFCs/blob/master/RFCs/rfc-1.md
 */
contract TokenGeyser is IStaking, Ownable
{
  using SafeMath for uint;


  // single stake for user; user may have multiple.
  struct Stake
  {
    uint stakingShares;
    uint timestampSec;
  }

  // caches aggregated values from the User->Stake[] map to save computation.
  // if lastAccountingTimestampSec is 0, there's no entry for that user.
  struct UserTotals
  {
    uint stakingShares;
    uint stakingShareSeconds;
    uint lastAccountingTimestampSec;
  }

  // locked/unlocked state
  struct UnlockSchedule
  {
    uint initialLockedShares;
    uint unlockedShares;
    uint lastUnlockTimestampSec;
    uint endAtSec;
    uint durationSec;
  }


  TokenPool private _lockedPool;
  TokenPool private _unlockedPool;
  TokenPool private _stakingPool;

  UnlockSchedule[] public unlockSchedules;


  // time-bonus params
  uint public startBonus = 0;
  uint public bonusPeriodSec = 0;
  uint public constant BONUS_DECIMALS = 2;


  // global accounting state
  uint public totalLockedShares = 0;
  uint public totalStakingShares = 0;
  uint private _maxUnlockSchedules = 0;
  uint private _initialSharesPerToken = 0;
  uint private _totalStakingShareSeconds = 0;
  uint private _lastAccountingTimestampSec = now;


  // timestamp ordered stakes for each user, earliest to latest.
  mapping(address => Stake[]) private _userStakes;

  // staking values per user
  mapping(address => UserTotals) private _userTotals;

  mapping(address => uint) public initStakeTimestamps;


  event Staked(address indexed user, uint amount, uint total, bytes data);
  event Unstaked(address indexed user, uint amount, uint total, bytes data);

  event TokensClaimed(address indexed user, uint amount);
  event TokensLocked(uint amount, uint durationSec, uint total);
  event TokensUnlocked(uint amount, uint remainingLocked);


  /**
   * @param stakingToken The token users deposit as stake.
   * @param distributionToken The token users receive as they unstake.
   * @param maxUnlockSchedules Max number of unlock stages, to guard against hitting gas limit.
   * @param startBonus_ Starting time bonus, BONUS_DECIMALS fixed point. e.g. 25% means user gets 25% of max distribution tokens.
   * @param bonusPeriodSec_ Length of time for bonus to increase linearly to max.
   * @param initialSharesPerToken Number of shares to mint per staking token on first stake.
   */
  constructor(IERC20 stakingToken, IERC20 distributionToken, uint maxUnlockSchedules, uint startBonus_, uint bonusPeriodSec_, uint initialSharesPerToken) public
  {
    // start bonus must be <= 100%
    require(startBonus_ <= 10 ** BONUS_DECIMALS, "Garden: bonus too high");
    // if no period is desired, set startBonus = 100% & bonusPeriod to small val like 1sec.
    require(bonusPeriodSec_ != 0, "Garden: bonus period 0");
    require(initialSharesPerToken > 0, "Garden: 0");

    _stakingPool = new TokenPool(stakingToken);
    _lockedPool = new TokenPool(distributionToken);
    _unlockedPool = new TokenPool(distributionToken);

    startBonus = startBonus_;
    bonusPeriodSec = bonusPeriodSec_;
    _maxUnlockSchedules = maxUnlockSchedules;
    _initialSharesPerToken = initialSharesPerToken;
  }


  /**
   * @dev Returns the number of unlockable shares from a given schedule. The returned value depends on the time since the last unlock. This function updates schedule accounting, but does not actually transfer any tokens.
   *
   * @param s Index of the unlock schedule.
   *
   * @return The number of unlocked shares.
   */
  function unlockScheduleShares(uint s) private returns (uint)
  {
    UnlockSchedule storage schedule = unlockSchedules[s];

    if (schedule.unlockedShares >= schedule.initialLockedShares)
    {
      return 0;
    }

    uint sharesToUnlock = 0;

    // Special case to handle any leftover dust from integer division
    if (now >= schedule.endAtSec)
    {
      sharesToUnlock = (schedule.initialLockedShares.sub(schedule.unlockedShares));
      schedule.lastUnlockTimestampSec = schedule.endAtSec;
    }
    else
    {
      sharesToUnlock = now.sub(schedule.lastUnlockTimestampSec).mul(schedule.initialLockedShares).div(schedule.durationSec);

      schedule.lastUnlockTimestampSec = now;
    }

    schedule.unlockedShares = schedule.unlockedShares.add(sharesToUnlock);

    return sharesToUnlock;
  }

  /**
   * @dev Moves distribution tokens from the locked pool to the unlocked pool, according to the previously defined unlock schedules. Publicly callable.
   *
   * @return Number of newly unlocked distribution tokens.
   */
  function unlockTokens() public returns (uint)
  {
    uint unlockedTokens = 0;
    uint lockedTokens = totalLocked();

    if (totalLockedShares == 0)
    {
      unlockedTokens = lockedTokens;
    }
    else
    {
      uint unlockedShares = 0;

      for (uint s = 0; s < unlockSchedules.length; s++)
      {
        unlockedShares = unlockedShares.add(unlockScheduleShares(s));
      }

      unlockedTokens = unlockedShares.mul(lockedTokens).div(totalLockedShares);
      totalLockedShares = totalLockedShares.sub(unlockedShares);
    }

    if (unlockedTokens > 0)
    {
      require(_lockedPool.transfer(address(_unlockedPool), unlockedTokens), "Garden: tx out of locked pool err");

      emit TokensUnlocked(unlockedTokens, totalLocked());
    }

    return unlockedTokens;
  }

  /**
   * @dev A globally callable function to update the accounting state of the system.
   *      Global state and state for the caller are updated.
   *
   * @return [0] balance of the locked pool
   * @return [1] balance of the unlocked pool
   * @return [2] caller's staking share seconds
   * @return [3] global staking share seconds
   * @return [4] Rewards caller has accumulated, optimistically assumes max time-bonus.
   *
   * @return [5] block timestamp
   */
  function updateAccounting() public returns (uint, uint, uint, uint, uint, uint)
  {
    unlockTokens();


    uint newStakingShareSeconds = now.sub(_lastAccountingTimestampSec).mul(totalStakingShares);

    _totalStakingShareSeconds = _totalStakingShareSeconds.add(newStakingShareSeconds);
    _lastAccountingTimestampSec = now;


    UserTotals storage totals = _userTotals[msg.sender];

    uint newUserStakingShareSeconds = now.sub(totals.lastAccountingTimestampSec).mul(totals.stakingShares);

    totals.stakingShareSeconds = totals.stakingShareSeconds.add(newUserStakingShareSeconds);
    totals.lastAccountingTimestampSec = now;

    uint totalUserRewards = (_totalStakingShareSeconds > 0) ? totalUnlocked().mul(totals.stakingShareSeconds).div(_totalStakingShareSeconds) : 0;

    return (totalLocked(), totalUnlocked(), totals.stakingShareSeconds, _totalStakingShareSeconds, totalUserRewards, now);
  }

  /**
   * @dev allows the contract owner to add more locked distribution tokens, along with the associated "unlock schedule". These locked tokens immediately begin unlocking linearly over the duration of durationSec timeframe.
   *
   * @param amount Number of distribution tokens to lock. These are transferred from the caller.
   *
   * @param durationSec Length of time to linear unlock the tokens.
   */
  function lockTokens(uint amount, uint durationSec) external onlyOwner
  {
    require(unlockSchedules.length < _maxUnlockSchedules, "Garden: reached max unlock schedules");

    // update lockedTokens amount before using it in computations after.
    updateAccounting();

    UnlockSchedule memory schedule;

    uint lockedTokens = totalLocked();
    uint mintedLockedShares = (lockedTokens > 0) ? totalLockedShares.mul(amount).div(lockedTokens) : amount.mul(_initialSharesPerToken);


    schedule.initialLockedShares = mintedLockedShares;
    schedule.lastUnlockTimestampSec = now;
    schedule.endAtSec = now.add(durationSec);
    schedule.durationSec = durationSec;
    unlockSchedules.push(schedule);

    totalLockedShares = totalLockedShares.add(mintedLockedShares);

    require(_lockedPool.token().transferFrom(msg.sender, address(_lockedPool), amount), "Garden: tx into locked pool err");

    emit TokensLocked(amount, durationSec, totalLocked());
  }


  /**
   * @dev Transfers amount of deposit tokens from the user.
   * @param amount Number of deposit tokens to stake.
   * @param data Not used.
   */
  function stake(uint amount, bytes calldata data) external
  {
    _stakeFor(msg.sender, msg.sender, amount);
  }

  /**
   * @dev Transfers amount of deposit tokens from the caller on behalf of user.
   * @param user User address who gains credit for this stake operation.
   * @param amount Number of deposit tokens to stake.
   * @param data Not used.
   */
  function stakeFor(address user, uint amount, bytes calldata data) external onlyOwner
  {
    _stakeFor(msg.sender, user, amount);
  }

  /**
   * @dev Private implementation of staking methods.
   * @param staker User address who deposits tokens to stake.
   * @param beneficiary User address who gains credit for this stake operation.
   * @param amount Number of deposit tokens to stake.
   */
  function _stakeFor(address staker, address beneficiary, uint amount) private
  {
    require(amount > 0, "Garden: stake amt is 0");
    require(beneficiary != address(0), "Garden: ben is 0 addr");
    require(totalStakingShares == 0 || totalStaked() > 0, "Garden: !valid state, staking shares but no tokens");


    if (initStakeTimestamps[beneficiary] == 0)
    {
      initStakeTimestamps[beneficiary] = now;
    }


    uint mintedStakingShares = (totalStakingShares > 0) ? totalStakingShares.mul(amount).div(totalStaked()) : amount.mul(_initialSharesPerToken);


    require(mintedStakingShares > 0, "Garden: Stake too small");

    updateAccounting();


    UserTotals storage totals = _userTotals[beneficiary];

    totals.stakingShares = totals.stakingShares.add(mintedStakingShares);
    totals.lastAccountingTimestampSec = now;


    Stake memory newStake = Stake(mintedStakingShares, now);

    _userStakes[beneficiary].push(newStake);
    totalStakingShares = totalStakingShares.add(mintedStakingShares);

    require(_stakingPool.token().transferFrom(staker, address(_stakingPool), amount), "Garden: tx into staking pool failed");

    emit Staked(beneficiary, amount, totalStakedFor(beneficiary), "");
  }


  /**
   * @dev Applies an additional time-bonus to a distribution amount. This is necessary to encourage long-term deposits instead of constant unstake/restakes.
   * The bonus-multiplier is the result of a linear function that starts at startBonus and ends at 100% over bonusPeriodSec, then stays at 100% thereafter.

   * @param currentRewardTokens The current number of distribution tokens already allotted for this unstake op. Any bonuses are already applied.

   * @param stakingShareSeconds The stakingShare-seconds that are being burned for new distribution tokens.

   * @param stakeTimeSec Length of time for which the tokens were staked. Needed to calculate the time-bonus.

   * @return Updated amount of distribution tokens to award, with any bonus included on the newly added tokens.
   */
  function computeNewReward(uint currentRewardTokens, uint stakingShareSeconds, uint stakeTimeSec) private view returns (uint)
  {
    uint newRewardTokens = totalUnlocked().mul(stakingShareSeconds).div(_totalStakingShareSeconds);

    if (stakeTimeSec >= bonusPeriodSec)
    {
      return currentRewardTokens.add(newRewardTokens);
    }

    uint oneHundredPct = 10 ** BONUS_DECIMALS;
    uint bonusedReward = startBonus.add(oneHundredPct.sub(startBonus).mul(stakeTimeSec).div(bonusPeriodSec)).mul(newRewardTokens).div(oneHundredPct);

    return currentRewardTokens.add(bonusedReward);
  }

  /**
   * @dev Unstakes a certain amount of previously deposited tokens. User also receives their allotted number of distribution tokens.
   * @param amount Number of deposit tokens to unstake / withdraw.
   * @param data Not used.
   */
  function unstake(uint amount, bytes calldata data) external
  {
    _unstake(amount);
  }

  /**
   * @param amount Number of deposit tokens to unstake / withdraw.
   * @return The total number of distribution tokens that would be rewarded.
   */
  function unstakeQuery(uint amount) public returns (uint)
  {
    return _unstake(amount);
  }

  /**
   * @dev Unstakes a certain amount of previously deposited tokens. User also receives their allotted number of distribution tokens.
   * @param amount Number of deposit tokens to unstake / withdraw.

   * @return The total number of distribution tokens rewarded.
   */
  function _unstake(uint amount) private returns (uint)
  {
    uint initStakeTimestamp = initStakeTimestamps[msg.sender];

    require(now > initStakeTimestamp.add(10 days), "Garden: in cooldown");

    updateAccounting();

    require(amount > 0, "Garden: unstake amt 0");
    require(totalStakedFor(msg.sender) >= amount, "Garden: unstake amt > total user stake");

    uint stakingSharesToBurn = totalStakingShares.mul(amount).div(totalStaked());

    require(stakingSharesToBurn > 0, "Garden: unstake too small");


    UserTotals storage totals = _userTotals[msg.sender];
    Stake[] storage accountStakes = _userStakes[msg.sender];

    // redeem from most recent stake and go backwards in time.
    uint rewardAmount = 0;
    uint stakingShareSecondsToBurn = 0;
    uint sharesLeftToBurn = stakingSharesToBurn;

    while (sharesLeftToBurn > 0)
    {
      Stake storage lastStake = accountStakes[accountStakes.length - 1];
      uint stakeTimeSec = now.sub(lastStake.timestampSec);
      uint newStakingShareSecondsToBurn = 0;

      if (lastStake.stakingShares <= sharesLeftToBurn)
      {
        // fully redeem a past stake
        newStakingShareSecondsToBurn = lastStake.stakingShares.mul(stakeTimeSec);
        rewardAmount = computeNewReward(rewardAmount, newStakingShareSecondsToBurn, stakeTimeSec);
        stakingShareSecondsToBurn = stakingShareSecondsToBurn.add(newStakingShareSecondsToBurn);
        sharesLeftToBurn = sharesLeftToBurn.sub(lastStake.stakingShares);
        accountStakes.length--;
      }
      else
      {
        // partially redeem a past stake
        newStakingShareSecondsToBurn = sharesLeftToBurn.mul(stakeTimeSec);
        rewardAmount = computeNewReward(rewardAmount, newStakingShareSecondsToBurn, stakeTimeSec);
        stakingShareSecondsToBurn = stakingShareSecondsToBurn.add(newStakingShareSecondsToBurn);
        lastStake.stakingShares = lastStake.stakingShares.sub(sharesLeftToBurn);
        sharesLeftToBurn = 0;
      }
    }

    totals.stakingShareSeconds = totals.stakingShareSeconds.sub(stakingShareSecondsToBurn);
    totals.stakingShares = totals.stakingShares.sub(stakingSharesToBurn);


    _totalStakingShareSeconds = _totalStakingShareSeconds.sub(stakingShareSecondsToBurn);
    totalStakingShares = totalStakingShares.sub(stakingSharesToBurn);


    uint unstakeFee = amount.mul(100).div(10000);

    require(_stakingPool.transfer(owner(), unstakeFee), "Garden: err tx fee");

    require(_stakingPool.transfer(msg.sender, amount.sub(unstakeFee)), "Garden: tx out of staking pool err");
    require(_unlockedPool.transfer(msg.sender, rewardAmount), "Garden: tx out of unlocked pool err");

    emit Unstaked(msg.sender, amount, totalStakedFor(msg.sender), "");
    emit TokensClaimed(msg.sender, rewardAmount);

    require(totalStakingShares == 0 || totalStaked() > 0, "Garden: Err unstake. Staking shares but no tokens");

    return rewardAmount;
  }


  /**
   * @param addr  user to look up staking information for.
   * @return The number of staking tokens deposited for addr.
   */
  function totalStakedFor(address addr) public view returns (uint)
  {
    return totalStakingShares > 0 ? totalStaked().mul(_userTotals[addr].stakingShares).div(totalStakingShares) : 0;
  }

  /**
   * @return The total number of deposit tokens staked globally, by all users.
   */
  function totalStaked() public view returns (uint)
  {
    return _stakingPool.balance();
  }

  /**
   * @return Total number of locked distribution tokens.
   */
  function totalLocked() public view returns (uint)
  {
    return _lockedPool.balance();
  }

  /**
   * @return Total number of unlocked distribution tokens.
   */
  function totalUnlocked() public view returns (uint)
  {
    return _unlockedPool.balance();
  }

  /**
   * @return Number of unlock schedules.
   */
  function unlockScheduleCount() public view returns (uint)
  {
    return unlockSchedules.length;
  }


  // getUserTotals, getTotalStakingShareSeconds, getLastAccountingTimestamp functions added for Yield

  /**
   * @param addr  user to look up staking information for

   * @return The UserStakes for this address
   */
  function getUserStakes(address addr) public view returns (Stake[] memory)
  {
    Stake[] memory userStakes = _userStakes[addr];

    return userStakes;
  }

  /**
   * @param addr user to look up staking information for

   * @return The UserTotals for this address.
   */
  function getUserTotals(address addr) public view returns (UserTotals memory)
  {
    UserTotals memory userTotals = _userTotals[addr];

    return userTotals;
  }

  /**
   * @return The total staking share seconds
   */
  function getTotalStakingShareSeconds() public view returns (uint256)
  {
    return _totalStakingShareSeconds;
  }

  /**
   * @return The last global accounting timestamp.
   */
  function getLastAccountingTimestamp() public view returns (uint256)
  {
    return _lastAccountingTimestampSec;
  }

  /**
   * @return The token users receive as they unstake.
   */
  function getDistributionToken() public view returns (IERC20)
  {
    assert(_unlockedPool.token() == _lockedPool.token());

    return _unlockedPool.token();
  }

  /**
   * @return The token users deposit as stake.
   */
  function getStakingToken() public view returns (IERC20)
  {
    return _stakingPool.token();
  }

  /**
   * @dev Note that this application has a staking token as well as a distribution token, which may be different. This function is required by EIP-900.

   * @return The deposit token used for staking.
   */
  function token() external view returns (address)
  {
    return address(getStakingToken());
  }
}

File 2 of 6 : SafeMath.sol
pragma solidity ^0.5.0;

/**
 * @dev Wrappers over Solidity's arithmetic operations with added overflow
 * checks.
 *
 * Arithmetic operations in Solidity wrap on overflow. This can easily result
 * in bugs, because programmers usually assume that an overflow raises an
 * error, which is the standard behavior in high level programming languages.
 * `SafeMath` restores this intuition by reverting the transaction when an
 * operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 */
library SafeMath {
    /**
     * @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) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");

        return c;
    }

    /**
     * @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 sub(a, b, "SafeMath: subtraction overflow");
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     * - Subtraction cannot overflow.
     *
     * _Available since v2.4.0._
     */
    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b <= a, errorMessage);
        uint256 c = a - b;

        return c;
    }

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

        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");

        return c;
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts 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) internal pure returns (uint256) {
        return div(a, b, "SafeMath: division by zero");
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts 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.
     *
     * _Available since v2.4.0._
     */
    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        // Solidity only automatically asserts when dividing by 0
        require(b > 0, errorMessage);
        uint256 c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold

        return c;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts 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 mod(a, b, "SafeMath: modulo by zero");
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts with custom message 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.
     *
     * _Available since v2.4.0._
     */
    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b != 0, errorMessage);
        return a % b;
    }
}

File 3 of 6 : IERC20.sol
pragma solidity ^0.5.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP. Does not include
 * the optional functions; to access them see {ERC20Detailed}.
 */
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 4 of 6 : Ownable.sol
pragma solidity 0.5.17;


contract Ownable
{
  address private _owner;

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


  modifier onlyOwner()
  {
    require(isOwner(), "!owner");
    _;
  }

  constructor () internal
  {
    _owner = msg.sender;
    emit OwnershipTransferred(address(0), msg.sender);
  }

  function owner() public view returns (address)
  {
    return _owner;
  }

  function isOwner() public view returns (bool)
  {
    return msg.sender == _owner;
  }

  function renounceOwnership() public onlyOwner
  {
    emit OwnershipTransferred(_owner, address(0));

    _owner = address(0);
  }

  function transferOwnership(address _newOwner) public onlyOwner
  {
    require(_newOwner != address(0), "0 addy");

    emit OwnershipTransferred(_owner, _newOwner);

    _owner = _newOwner;
  }
}

File 5 of 6 : IStaking.sol
pragma solidity 0.5.17;


/**
 * @title Staking interface, as defined by EIP-900.
 * @dev https://github.com/ethereum/EIPs/blob/master/EIPS/eip-900.md
 */
contract IStaking
{
  event Staked(address indexed user, uint amount, uint total, bytes data);
  event Unstaked(address indexed user, uint amount, uint total, bytes data);

  function stake(uint amount, bytes calldata data) external;

  function stakeFor(address user, uint amount, bytes calldata data) external;

  function unstake(uint amount, bytes calldata data) external;

  function totalStakedFor(address addr) public view returns (uint);

  function totalStaked() public view returns (uint);

  function token() external view returns (address);

  /**
   * @return false. This application does not support staking history.
   */
  function supportsHistory() external pure returns (bool)
  {
    return false;
  }
}

File 6 of 6 : TokenPool.sol
pragma solidity 0.5.17;

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

import "./roles/Ownable.sol";


/**
 * @title A simple holder of tokens.
 * This is a simple contract to hold tokens. It's useful in the case where a separate contract needs to hold multiple distinct pools of the same token.
 */
contract TokenPool is Ownable
{
  IERC20 public token;


  constructor(IERC20 _token) public
  {
    token = _token;
  }

  function balance() public view returns (uint)
  {
    return token.balanceOf(address(this));
  }

  function transfer(address _to, uint _value) external onlyOwner returns (bool)
  {
    return token.transfer(_to, _value);
  }
}

Settings
{
  "optimizer": {
    "enabled": false,
    "runs": 200
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "abi"
      ]
    }
  },
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"contract IERC20","name":"stakingToken","type":"address"},{"internalType":"contract IERC20","name":"distributionToken","type":"address"},{"internalType":"uint256","name":"maxUnlockSchedules","type":"uint256"},{"internalType":"uint256","name":"startBonus_","type":"uint256"},{"internalType":"uint256","name":"bonusPeriodSec_","type":"uint256"},{"internalType":"uint256","name":"initialSharesPerToken","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"total","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"}],"name":"Staked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"TokensClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"durationSec","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"total","type":"uint256"}],"name":"TokensLocked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"remainingLocked","type":"uint256"}],"name":"TokensUnlocked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"total","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"}],"name":"Unstaked","type":"event"},{"constant":true,"inputs":[],"name":"BONUS_DECIMALS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"bonusPeriodSec","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getDistributionToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getLastAccountingTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getStakingToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getTotalStakingShareSeconds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"getUserStakes","outputs":[{"components":[{"internalType":"uint256","name":"stakingShares","type":"uint256"},{"internalType":"uint256","name":"timestampSec","type":"uint256"}],"internalType":"struct TokenGeyser.Stake[]","name":"","type":"tuple[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"getUserTotals","outputs":[{"components":[{"internalType":"uint256","name":"stakingShares","type":"uint256"},{"internalType":"uint256","name":"stakingShareSeconds","type":"uint256"},{"internalType":"uint256","name":"lastAccountingTimestampSec","type":"uint256"}],"internalType":"struct TokenGeyser.UserTotals","name":"","type":"tuple"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"initStakeTimestamps","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isOwner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"durationSec","type":"uint256"}],"name":"lockTokens","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"renounceOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"stake","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"stakeFor","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"startBonus","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"supportsHistory","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"token","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalLocked","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalLockedShares","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalStaked","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"totalStakedFor","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalStakingShares","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalUnlocked","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"unlockScheduleCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"unlockSchedules","outputs":[{"internalType":"uint256","name":"initialLockedShares","type":"uint256"},{"internalType":"uint256","name":"unlockedShares","type":"uint256"},{"internalType":"uint256","name":"lastUnlockTimestampSec","type":"uint256"},{"internalType":"uint256","name":"endAtSec","type":"uint256"},{"internalType":"uint256","name":"durationSec","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"unlockTokens","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"unstake","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"unstakeQuery","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"updateAccounting","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"}]

6080604052600060055560006006556000600755600060085560006009556000600a556000600b5542600c553480156200003857600080fd5b5060405162004b5238038062004b5283398181016040526200005e91908101906200039f565b336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055503373ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a36002600a0a83111562000143576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200013a9062000529565b60405180910390fd5b60008214156200018a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040162000181906200054b565b60405180910390fd5b60008111620001d0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620001c7906200056d565b60405180910390fd5b85604051620001df9062000363565b620001eb91906200050c565b604051809103906000f08015801562000208573d6000803e3d6000fd5b50600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555084604051620002589062000363565b6200026491906200050c565b604051809103906000f08015801562000281573d6000803e3d6000fd5b50600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555084604051620002d19062000363565b620002dd91906200050c565b604051809103906000f080158015620002fa573d6000803e3d6000fd5b50600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555082600581905550816006819055508360098190555080600a819055505050505050506200064e565b61097280620041e083390190565b60008151905062000382816200061a565b92915050565b600081519050620003998162000634565b92915050565b60008060008060008060c08789031215620003b957600080fd5b6000620003c989828a0162000371565b9650506020620003dc89828a0162000371565b9550506040620003ef89828a0162000388565b94505060606200040289828a0162000388565b93505060806200041589828a0162000388565b92505060a06200042889828a0162000388565b9150509295509295509295565b6200044081620005f2565b82525050565b6000620004556016836200058f565b91507f47617264656e3a20626f6e757320746f6f2068696768000000000000000000006000830152602082019050919050565b6000620004976016836200058f565b91507f47617264656e3a20626f6e757320706572696f642030000000000000000000006000830152602082019050919050565b6000620004d96009836200058f565b91507f47617264656e3a203000000000000000000000000000000000000000000000006000830152602082019050919050565b600060208201905062000523600083018462000435565b92915050565b60006020820190508181036000830152620005448162000446565b9050919050565b60006020820190508181036000830152620005668162000488565b9050919050565b600060208201905081810360008301526200058881620004ca565b9050919050565b600082825260208201905092915050565b6000620005ad82620005c8565b9050919050565b6000620005c182620005a0565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b6000620005ff8262000606565b9050919050565b60006200061382620005c8565b9050919050565b6200062581620005b4565b81146200063157600080fd5b50565b6200063f81620005e8565b81146200064b57600080fd5b50565b613b82806200065e6000396000f3fe608060405234801561001057600080fd5b50600436106101e55760003560e01c806381c39bec1161010f578063a779d080116100a2578063dc24ffee11610071578063dc24ffee1461056d578063f2fde38b1461058b578063f968f493146105a7578063fc0c546a146105c5576101e5565b8063a779d080146104e5578063adbe60cb14610503578063c7ae200714610533578063c8fd6ed014610551576101e5565b80638da5cb5b116100de5780638da5cb5b1461045b5780638f32d59b1461047957806399044f7c146104975780639f9106d1146104c7576101e5565b806381c39bec146103c1578063842e2981146103df57806386805dd11461040f57806389158d8e1461043f576101e5565b80634b341aed1161018757806370c6a17e1161015657806370c6a17e1461035d578063715018a61461037b5780637c6aa6f414610385578063817b1cd2146103a3576101e5565b80634b341aed146102bd57806356891412146102ed5780635c94bcb21461030b5780637033e4a61461033f576101e5565b806322c12b84116101c357806322c12b84146102405780632f58aba21461025e57806338b45fde1461027c578063494347e71461029a576101e5565b80630e89439b146101ea5780630ef96356146102065780631dc27fde14610222575b600080fd5b61020460048036036101ff9190810190612bac565b6105e3565b005b610220600480360361021b9190810190612a9c565b6105f3565b005b61022a61064b565b604051610237919061381a565b60405180910390f35b610248610650565b6040516102559190613542565b60405180910390f35b61026661086a565b604051610273919061381a565b60405180910390f35b610284610874565b604051610291919061381a565b60405180910390f35b6102a261087a565b6040516102b496959493929190613924565b60405180910390f35b6102d760048036036102d29190810190612a73565b6109f0565b6040516102e4919061381a565b60405180910390f35b6102f5610a7a565b604051610302919061381a565b60405180910390f35b61032560048036036103209190810190612b5a565b610b21565b6040516103369594939291906138d1565b60405180910390f35b610347610b64565b6040516103549190613527565b60405180910390f35b610365610b6c565b604051610372919061381a565b60405180910390f35b610383610b72565b005b61038d610c78565b60405161039a919061381a565b60405180910390f35b6103ab610c7e565b6040516103b8919061381a565b60405180910390f35b6103c9610d25565b6040516103d6919061381a565b60405180910390f35b6103f960048036036103f49190810190612a73565b610d2b565b6040516104069190613505565b60405180910390f35b61042960048036036104249190810190612b5a565b610de2565b604051610436919061381a565b60405180910390f35b61045960048036036104549190810190612c04565b610df4565b005b610463611183565b604051610470919061342a565b60405180910390f35b6104816111ac565b60405161048e9190613527565b60405180910390f35b6104b160048036036104ac9190810190612a73565b611203565b6040516104be91906137ff565b60405180910390f35b6104cf611286565b6040516104dc9190613542565b60405180910390f35b6104ed61132d565b6040516104fa919061381a565b60405180910390f35b61051d60048036036105189190810190612a73565b6113d4565b60405161052a919061381a565b60405180910390f35b61053b6113ec565b604051610548919061381a565b60405180910390f35b61056b60048036036105669190810190612bac565b6113f9565b005b610575611408565b604051610582919061381a565b60405180910390f35b6105a560048036036105a09190810190612a73565b611412565b005b6105af611587565b6040516105bc919061381a565b60405180910390f35b6105cd611798565b6040516105da919061342a565b60405180910390f35b6105ee3333856117a7565b505050565b6105fb6111ac565b61063a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610631906137df565b60405180910390fd5b6106453385856117a7565b50505050565b600281565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663fc0c546a6040518163ffffffff1660e01b815260040160206040518083038186803b1580156106ba57600080fd5b505afa1580156106ce573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506106f29190810190612b31565b73ffffffffffffffffffffffffffffffffffffffff16600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663fc0c546a6040518163ffffffff1660e01b815260040160206040518083038186803b15801561077057600080fd5b505afa158015610784573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506107a89190810190612b31565b73ffffffffffffffffffffffffffffffffffffffff16146107c557fe5b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663fc0c546a6040518163ffffffff1660e01b815260040160206040518083038186803b15801561082d57600080fd5b505afa158015610841573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506108659190810190612b31565b905090565b6000600c54905090565b60055481565b60008060008060008061088b611587565b5060006108b76008546108a9600c5442611cfb90919063ffffffff16565b611d4590919063ffffffff16565b90506108ce81600b54611db590919063ffffffff16565b600b8190555042600c819055506000600e60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050600061094d826000015461093f846002015442611cfb90919063ffffffff16565b611d4590919063ffffffff16565b9050610966818360010154611db590919063ffffffff16565b8260010181905550428260020181905550600080600b54116109895760006109bc565b6109bb600b546109ad856001015461099f61132d565b611d4590919063ffffffff16565b611e0a90919063ffffffff16565b5b90506109c6610a7a565b6109ce61132d565b8460010154600b54844299509950995099509950995050505050909192939495565b60008060085411610a02576000610a73565b610a72600854610a64600e60008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000154610a56610c7e565b611d4590919063ffffffff16565b611e0a90919063ffffffff16565b5b9050919050565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663b69ef8a86040518163ffffffff1660e01b815260040160206040518083038186803b158015610ae457600080fd5b505afa158015610af8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610b1c9190810190612b83565b905090565b60048181548110610b2e57fe5b90600052602060002090600502016000915090508060000154908060010154908060020154908060030154908060040154905085565b600080905090565b60085481565b610b7a6111ac565b610bb9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bb0906137df565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b60065481565b6000600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663b69ef8a86040518163ffffffff1660e01b815260040160206040518083038186803b158015610ce857600080fd5b505afa158015610cfc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610d209190810190612b83565b905090565b60075481565b606080600d60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b82821015610dd357838290600052602060002090600202016040518060400160405290816000820154815260200160018201548152505081526020019060010190610d8d565b50505050905080915050919050565b6000610ded82611e54565b9050919050565b610dfc6111ac565b610e3b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e32906137df565b60405180910390fd5b60095460048054905010610e84576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e7b9061363f565b60405180910390fd5b610e8c61087a565b505050505050610e9a6128f5565b6000610ea4610a7a565b90506000808211610ec957610ec4600a5486611d4590919063ffffffff16565b610ef1565b610ef082610ee287600754611d4590919063ffffffff16565b611e0a90919063ffffffff16565b5b90508083600001818152505042836040018181525050610f1a8442611db590919063ffffffff16565b83606001818152505083836080018181525050600483908060018154018082558091505090600182039060005260206000209060050201600090919290919091506000820151816000015560208201518160010155604082015181600201556060820151816003015560808201518160040155505050610fa581600754611db590919063ffffffff16565b600781905550600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663fc0c546a6040518163ffffffff1660e01b815260040160206040518083038186803b15801561101357600080fd5b505afa158015611027573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061104b9190810190612b31565b73ffffffffffffffffffffffffffffffffffffffff166323b872dd33600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16886040518463ffffffff1660e01b81526004016110a993929190613445565b602060405180830381600087803b1580156110c357600080fd5b505af11580156110d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506110fb9190810190612b08565b61113a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111319061365f565b60405180910390fd5b7ff346961af4c52f314df1b45964746280fe409abb959d4a2458d58f79408b1fe88585611165610a7a565b6040516111749392919061389a565b60405180910390a15050505050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614905090565b61120b612924565b611213612924565b600e60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206040518060600160405290816000820154815260200160018201548152602001600282015481525050905080915050919050565b6000600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663fc0c546a6040518163ffffffff1660e01b815260040160206040518083038186803b1580156112f057600080fd5b505afa158015611304573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506113289190810190612b31565b905090565b6000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663b69ef8a86040518163ffffffff1660e01b815260040160206040518083038186803b15801561139757600080fd5b505afa1580156113ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506113cf9190810190612b83565b905090565b600f6020528060005260406000206000915090505481565b6000600480549050905090565b61140283611e54565b50505050565b6000600b54905090565b61141a6111ac565b611459576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611450906137df565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156114c9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114c0906137bf565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600080600090506000611598610a7a565b9050600060075414156115ad57809150611636565b600080905060008090505b6004805490508110156115ef576115e06115d182612651565b83611db590919063ffffffff16565b915080806001019150506115b8565b506116176007546116098484611d4590919063ffffffff16565b611e0a90919063ffffffff16565b925061162e81600754611cfb90919063ffffffff16565b600781905550505b600082111561179057600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16846040518363ffffffff1660e01b81526004016116be9291906134dc565b602060405180830381600087803b1580156116d857600080fd5b505af11580156116ec573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506117109190810190612b08565b61174f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611746906135df565b60405180910390fd5b7f2e444eb379b177e88ce0649c6110a3b01099f03e297127919dd5e3b63a761a9c82611779610a7a565b604051611787929190613835565b60405180910390a15b819250505090565b60006117a2611286565b905090565b600081116117ea576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117e19061371f565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141561185a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611851906135ff565b60405180910390fd5b6000600854148061187257506000611870610c7e565b115b6118b1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118a8906136ff565b60405180910390fd5b6000600f60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054141561193e5742600f60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505b600080600854116119635761195e600a5483611d4590919063ffffffff16565b611992565b61199161196e610c7e565b61198384600854611d4590919063ffffffff16565b611e0a90919063ffffffff16565b5b9050600081116119d7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119ce9061369f565b60405180910390fd5b6119df61087a565b5050505050506000600e60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050611a3f828260000154611db590919063ffffffff16565b8160000181905550428160020181905550611a58612945565b6040518060400160405280848152602001428152509050600d60008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081908060018154018082558091505090600182039060005260206000209060020201600090919290919091506000820151816000015560208201518160010155505050611b0683600854611db590919063ffffffff16565b600881905550600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663fc0c546a6040518163ffffffff1660e01b815260040160206040518083038186803b158015611b7457600080fd5b505afa158015611b88573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611bac9190810190612b31565b73ffffffffffffffffffffffffffffffffffffffff166323b872dd87600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16876040518463ffffffff1660e01b8152600401611c0a939291906134a5565b602060405180830381600087803b158015611c2457600080fd5b505af1158015611c38573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611c5c9190810190612b08565b611c9b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c929061379f565b60405180910390fd5b8473ffffffffffffffffffffffffffffffffffffffff167fc65e53b88159e7d2c0fc12a0600072e28ae53ff73b4c1715369c30f16093514285611cdd886109f0565b604051611ceb92919061385e565b60405180910390a2505050505050565b6000611d3d83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250612742565b905092915050565b600080831415611d585760009050611daf565b6000828402905082848281611d6957fe5b0414611daa576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611da1906136df565b60405180910390fd5b809150505b92915050565b600080828401905083811015611e00576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611df79061361f565b60405180910390fd5b8091505092915050565b6000611e4c83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f00000000000081525061279d565b905092915050565b600080600f60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050611eaf620d2f0082611db590919063ffffffff16565b4211611ef0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ee7906136bf565b60405180910390fd5b611ef861087a565b50505050505060008311611f41576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f389061373f565b60405180910390fd5b82611f4b336109f0565b1015611f8c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f83906135bf565b60405180910390fd5b6000611fbc611f99610c7e565b611fae86600854611d4590919063ffffffff16565b611e0a90919063ffffffff16565b905060008111612001576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ff89061357f565b60405180910390fd5b6000600e60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090506000600d60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090506000809050600080905060008590505b60008111156121c1576000846001868054905003815481106120b557fe5b9060005260206000209060020201905060006120de826001015442611cfb90919063ffffffff16565b905060008090508383600001541161215e57612107828460000154611d4590919063ffffffff16565b90506121148682846127fe565b95506121298186611db590919063ffffffff16565b9450612142836000015485611cfb90919063ffffffff16565b935086805480919060019003612158919061295f565b506121b9565b6121718285611d4590919063ffffffff16565b905061217e8682846127fe565b95506121938186611db590919063ffffffff16565b94506121ac848460000154611cfb90919063ffffffff16565b8360000181905550600093505b505050612097565b6121d8828660010154611cfb90919063ffffffff16565b85600101819055506121f7868660000154611cfb90919063ffffffff16565b856000018190555061221482600b54611cfb90919063ffffffff16565b600b8190555061222f86600854611cfb90919063ffffffff16565b600881905550600061225f61271061225160648d611d4590919063ffffffff16565b611e0a90919063ffffffff16565b9050600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb6122a7611183565b836040518363ffffffff1660e01b81526004016122c59291906134dc565b602060405180830381600087803b1580156122df57600080fd5b505af11580156122f3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506123179190810190612b08565b612356576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161234d9061367f565b60405180910390fd5b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb336123a8848e611cfb90919063ffffffff16565b6040518363ffffffff1660e01b81526004016123c592919061347c565b602060405180830381600087803b1580156123df57600080fd5b505af11580156123f3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506124179190810190612b08565b612456576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161244d9061359f565b60405180910390fd5b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb33866040518363ffffffff1660e01b81526004016124b392919061347c565b602060405180830381600087803b1580156124cd57600080fd5b505af11580156124e1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506125059190810190612b08565b612544576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161253b9061375f565b60405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff167faf01bfc8475df280aca00b578c4a948e6d95700f0db8c13365240f7f973c87548b612586336109f0565b60405161259492919061385e565b60405180910390a23373ffffffffffffffffffffffffffffffffffffffff167f896e034966eaaf1adc54acc0f257056febbd300c9e47182cf761982cf1f5e430856040516125e2919061381a565b60405180910390a26000600854148061260257506000612600610c7e565b115b612641576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016126389061377f565b60405180910390fd5b8398505050505050505050919050565b6000806004838154811061266157fe5b90600052602060002090600502019050806000015481600101541061268a57600091505061273d565b6000809050816003015442106126c9576126b582600101548360000154611cfb90919063ffffffff16565b905081600301548260020181905550612718565b61270c82600401546126fe84600001546126f0866002015442611cfb90919063ffffffff16565b611d4590919063ffffffff16565b611e0a90919063ffffffff16565b90504282600201819055505b61272f818360010154611db590919063ffffffff16565b826001018190555080925050505b919050565b600083831115829061278a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612781919061355d565b60405180910390fd5b5060008385039050809150509392505050565b600080831182906127e4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016127db919061355d565b60405180910390fd5b5060008385816127f057fe5b049050809150509392505050565b60008061282f600b546128218661281361132d565b611d4590919063ffffffff16565b611e0a90919063ffffffff16565b905060065483106128555761284d8186611db590919063ffffffff16565b9150506128ee565b60006002600a0a905060006128d3826128c5856128b76128a66006546128988c61288a6005548c611cfb90919063ffffffff16565b611d4590919063ffffffff16565b611e0a90919063ffffffff16565b600554611db590919063ffffffff16565b611d4590919063ffffffff16565b611e0a90919063ffffffff16565b90506128e88188611db590919063ffffffff16565b93505050505b9392505050565b6040518060a0016040528060008152602001600081526020016000815260200160008152602001600081525090565b60405180606001604052806000815260200160008152602001600081525090565b604051806040016040528060008152602001600081525090565b81548183558181111561298c5760020281600202836000526020600020918201910161298b9190612991565b5b505050565b6129bd91905b808211156129b957600080820160009055600182016000905550600201612997565b5090565b90565b6000813590506129cf81613ae3565b92915050565b6000815190506129e481613afa565b92915050565b60008083601f8401126129fc57600080fd5b8235905067ffffffffffffffff811115612a1557600080fd5b602083019150836001820283011115612a2d57600080fd5b9250929050565b600081519050612a4381613b11565b92915050565b600081359050612a5881613b28565b92915050565b600081519050612a6d81613b28565b92915050565b600060208284031215612a8557600080fd5b6000612a93848285016129c0565b91505092915050565b60008060008060608587031215612ab257600080fd5b6000612ac0878288016129c0565b9450506020612ad187828801612a49565b935050604085013567ffffffffffffffff811115612aee57600080fd5b612afa878288016129ea565b925092505092959194509250565b600060208284031215612b1a57600080fd5b6000612b28848285016129d5565b91505092915050565b600060208284031215612b4357600080fd5b6000612b5184828501612a34565b91505092915050565b600060208284031215612b6c57600080fd5b6000612b7a84828501612a49565b91505092915050565b600060208284031215612b9557600080fd5b6000612ba384828501612a5e565b91505092915050565b600080600060408486031215612bc157600080fd5b6000612bcf86828701612a49565b935050602084013567ffffffffffffffff811115612bec57600080fd5b612bf8868287016129ea565b92509250509250925092565b60008060408385031215612c1757600080fd5b6000612c2585828601612a49565b9250506020612c3685828601612a49565b9150509250929050565b6000612c4c838361339b565b60408301905092915050565b612c6181613a45565b82525050565b612c70816139eb565b82525050565b6000612c8182613995565b612c8b81856139b8565b9350612c9683613985565b8060005b83811015612cc7578151612cae8882612c40565b9750612cb9836139ab565b925050600181019050612c9a565b5085935050505092915050565b612cdd816139fd565b82525050565b612cec81613a57565b82525050565b6000612cfd826139a0565b612d0781856139da565b9350612d17818560208601613a9f565b612d2081613ad2565b840191505092915050565b6000612d386019836139da565b91507f47617264656e3a20756e7374616b6520746f6f20736d616c6c000000000000006000830152602082019050919050565b6000612d786022836139da565b91507f47617264656e3a207478206f7574206f66207374616b696e6720706f6f6c206560008301527f72720000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000612dde6026836139da565b91507f47617264656e3a20756e7374616b6520616d74203e20746f74616c207573657260008301527f207374616b6500000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000612e446021836139da565b91507f47617264656e3a207478206f7574206f66206c6f636b656420706f6f6c20657260008301527f72000000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000612eaa6015836139da565b91507f47617264656e3a2062656e2069732030206164647200000000000000000000006000830152602082019050919050565b6000612eea601b836139da565b91507f536166654d6174683a206164646974696f6e206f766572666c6f7700000000006000830152602082019050919050565b6000612f2a6024836139da565b91507f47617264656e3a2072656163686564206d617820756e6c6f636b20736368656460008301527f756c6573000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000612f90601f836139da565b91507f47617264656e3a20747820696e746f206c6f636b656420706f6f6c20657272006000830152602082019050919050565b6000612fd06012836139da565b91507f47617264656e3a206572722074782066656500000000000000000000000000006000830152602082019050919050565b60006130106017836139da565b91507f47617264656e3a205374616b6520746f6f20736d616c6c0000000000000000006000830152602082019050919050565b60006130506013836139da565b91507f47617264656e3a20696e20636f6f6c646f776e000000000000000000000000006000830152602082019050919050565b60006130906021836139da565b91507f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f60008301527f77000000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006130f66032836139da565b91507f47617264656e3a202176616c69642073746174652c207374616b696e6720736860008301527f6172657320627574206e6f20746f6b656e7300000000000000000000000000006020830152604082019050919050565b600061315c6016836139da565b91507f47617264656e3a207374616b6520616d742069732030000000000000000000006000830152602082019050919050565b600061319c6015836139da565b91507f47617264656e3a20756e7374616b6520616d74203000000000000000000000006000830152602082019050919050565b60006131dc6000836139c9565b9150600082019050919050565b60006131f66023836139da565b91507f47617264656e3a207478206f7574206f6620756e6c6f636b656420706f6f6c2060008301527f65727200000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b600061325c6031836139da565b91507f47617264656e3a2045727220756e7374616b652e205374616b696e672073686160008301527f72657320627574206e6f20746f6b656e730000000000000000000000000000006020830152604082019050919050565b60006132c26023836139da565b91507f47617264656e3a20747820696e746f207374616b696e6720706f6f6c2066616960008301527f6c656400000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006133286006836139da565b91507f30206164647900000000000000000000000000000000000000000000000000006000830152602082019050919050565b60006133686006836139da565b91507f216f776e657200000000000000000000000000000000000000000000000000006000830152602082019050919050565b6040820160008201516133b1600085018261340c565b5060208201516133c4602085018261340c565b50505050565b6060820160008201516133e0600085018261340c565b5060208201516133f3602085018261340c565b506040820151613406604085018261340c565b50505050565b61341581613a3b565b82525050565b61342481613a3b565b82525050565b600060208201905061343f6000830184612c67565b92915050565b600060608201905061345a6000830186612c58565b6134676020830185612c67565b613474604083018461341b565b949350505050565b60006040820190506134916000830185612c58565b61349e602083018461341b565b9392505050565b60006060820190506134ba6000830186612c67565b6134c76020830185612c67565b6134d4604083018461341b565b949350505050565b60006040820190506134f16000830185612c67565b6134fe602083018461341b565b9392505050565b6000602082019050818103600083015261351f8184612c76565b905092915050565b600060208201905061353c6000830184612cd4565b92915050565b60006020820190506135576000830184612ce3565b92915050565b600060208201905081810360008301526135778184612cf2565b905092915050565b6000602082019050818103600083015261359881612d2b565b9050919050565b600060208201905081810360008301526135b881612d6b565b9050919050565b600060208201905081810360008301526135d881612dd1565b9050919050565b600060208201905081810360008301526135f881612e37565b9050919050565b6000602082019050818103600083015261361881612e9d565b9050919050565b6000602082019050818103600083015261363881612edd565b9050919050565b6000602082019050818103600083015261365881612f1d565b9050919050565b6000602082019050818103600083015261367881612f83565b9050919050565b6000602082019050818103600083015261369881612fc3565b9050919050565b600060208201905081810360008301526136b881613003565b9050919050565b600060208201905081810360008301526136d881613043565b9050919050565b600060208201905081810360008301526136f881613083565b9050919050565b60006020820190508181036000830152613718816130e9565b9050919050565b600060208201905081810360008301526137388161314f565b9050919050565b600060208201905081810360008301526137588161318f565b9050919050565b60006020820190508181036000830152613778816131e9565b9050919050565b600060208201905081810360008301526137988161324f565b9050919050565b600060208201905081810360008301526137b8816132b5565b9050919050565b600060208201905081810360008301526137d88161331b565b9050919050565b600060208201905081810360008301526137f88161335b565b9050919050565b600060608201905061381460008301846133ca565b92915050565b600060208201905061382f600083018461341b565b92915050565b600060408201905061384a600083018561341b565b613857602083018461341b565b9392505050565b6000606082019050613873600083018561341b565b613880602083018461341b565b8181036040830152613891816131cf565b90509392505050565b60006060820190506138af600083018661341b565b6138bc602083018561341b565b6138c9604083018461341b565b949350505050565b600060a0820190506138e6600083018861341b565b6138f3602083018761341b565b613900604083018661341b565b61390d606083018561341b565b61391a608083018461341b565b9695505050505050565b600060c082019050613939600083018961341b565b613946602083018861341b565b613953604083018761341b565b613960606083018661341b565b61396d608083018561341b565b61397a60a083018461341b565b979650505050505050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b600082825260208201905092915050565b600082825260208201905092915050565b600082825260208201905092915050565b60006139f682613a1b565b9050919050565b60008115159050919050565b6000613a14826139eb565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b6000613a5082613a7b565b9050919050565b6000613a6282613a69565b9050919050565b6000613a7482613a1b565b9050919050565b6000613a8682613a8d565b9050919050565b6000613a9882613a1b565b9050919050565b60005b83811015613abd578082015181840152602081019050613aa2565b83811115613acc576000848401525b50505050565b6000601f19601f8301169050919050565b613aec816139eb565b8114613af757600080fd5b50565b613b03816139fd565b8114613b0e57600080fd5b50565b613b1a81613a09565b8114613b2557600080fd5b50565b613b3181613a3b565b8114613b3c57600080fd5b5056fea365627a7a723158204619459f0ef9e009779b36573b9311d46c7d78a223f21157967db037d6eb994e6c6578706572696d656e74616cf564736f6c63430005110040608060405234801561001057600080fd5b506040516109723803806109728339818101604052602081101561003357600080fd5b8101908080519060200190929190505050336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055503373ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a380600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050610842806101306000396000f3fe608060405234801561001057600080fd5b506004361061007d5760003560e01c8063a9059cbb1161005b578063a9059cbb146100f8578063b69ef8a81461015e578063f2fde38b1461017c578063fc0c546a146101c05761007d565b8063715018a6146100825780638da5cb5b1461008c5780638f32d59b146100d6575b600080fd5b61008a61020a565b005b610094610343565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6100de61036c565b604051808215151515815260200191505060405180910390f35b6101446004803603604081101561010e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506103c3565b604051808215151515815260200191505060405180910390f35b61016661052b565b6040518082815260200191505060405180910390f35b6101be6004803603602081101561019257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061060c565b005b6101c86107e7565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b61021261036c565b610284576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260068152602001807f216f776e6572000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614905090565b60006103cd61036c565b61043f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260068152602001807f216f776e6572000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb84846040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b1580156104e857600080fd5b505af11580156104fc573d6000803e3d6000fd5b505050506040513d602081101561051257600080fd5b8101908080519060200190929190505050905092915050565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156105cc57600080fd5b505afa1580156105e0573d6000803e3d6000fd5b505050506040513d60208110156105f657600080fd5b8101908080519060200190929190505050905090565b61061461036c565b610686576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260068152602001807f216f776e6572000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610729576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260068152602001807f302061646479000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168156fea265627a7a72315820d57cc0d7b39dbf42dabfef7fc4753b1b1d935e037dca42ddd38df5874f85a66064736f6c63430005110032000000000000000000000000bbfd9b37ec6ea1ca612ab4adef6d8c6ece1a4134000000000000000000000000dcb01cc464238396e213a6fdd933e36796eaff9f0000000000000000000000000000000000000000000000000000000000002710000000000000000000000000000000000000000000000000000000000000002100000000000000000000000000000000000000000000000000000000003b538000000000000000000000000000000000000000000000000000000000000f4240

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106101e55760003560e01c806381c39bec1161010f578063a779d080116100a2578063dc24ffee11610071578063dc24ffee1461056d578063f2fde38b1461058b578063f968f493146105a7578063fc0c546a146105c5576101e5565b8063a779d080146104e5578063adbe60cb14610503578063c7ae200714610533578063c8fd6ed014610551576101e5565b80638da5cb5b116100de5780638da5cb5b1461045b5780638f32d59b1461047957806399044f7c146104975780639f9106d1146104c7576101e5565b806381c39bec146103c1578063842e2981146103df57806386805dd11461040f57806389158d8e1461043f576101e5565b80634b341aed1161018757806370c6a17e1161015657806370c6a17e1461035d578063715018a61461037b5780637c6aa6f414610385578063817b1cd2146103a3576101e5565b80634b341aed146102bd57806356891412146102ed5780635c94bcb21461030b5780637033e4a61461033f576101e5565b806322c12b84116101c357806322c12b84146102405780632f58aba21461025e57806338b45fde1461027c578063494347e71461029a576101e5565b80630e89439b146101ea5780630ef96356146102065780631dc27fde14610222575b600080fd5b61020460048036036101ff9190810190612bac565b6105e3565b005b610220600480360361021b9190810190612a9c565b6105f3565b005b61022a61064b565b604051610237919061381a565b60405180910390f35b610248610650565b6040516102559190613542565b60405180910390f35b61026661086a565b604051610273919061381a565b60405180910390f35b610284610874565b604051610291919061381a565b60405180910390f35b6102a261087a565b6040516102b496959493929190613924565b60405180910390f35b6102d760048036036102d29190810190612a73565b6109f0565b6040516102e4919061381a565b60405180910390f35b6102f5610a7a565b604051610302919061381a565b60405180910390f35b61032560048036036103209190810190612b5a565b610b21565b6040516103369594939291906138d1565b60405180910390f35b610347610b64565b6040516103549190613527565b60405180910390f35b610365610b6c565b604051610372919061381a565b60405180910390f35b610383610b72565b005b61038d610c78565b60405161039a919061381a565b60405180910390f35b6103ab610c7e565b6040516103b8919061381a565b60405180910390f35b6103c9610d25565b6040516103d6919061381a565b60405180910390f35b6103f960048036036103f49190810190612a73565b610d2b565b6040516104069190613505565b60405180910390f35b61042960048036036104249190810190612b5a565b610de2565b604051610436919061381a565b60405180910390f35b61045960048036036104549190810190612c04565b610df4565b005b610463611183565b604051610470919061342a565b60405180910390f35b6104816111ac565b60405161048e9190613527565b60405180910390f35b6104b160048036036104ac9190810190612a73565b611203565b6040516104be91906137ff565b60405180910390f35b6104cf611286565b6040516104dc9190613542565b60405180910390f35b6104ed61132d565b6040516104fa919061381a565b60405180910390f35b61051d60048036036105189190810190612a73565b6113d4565b60405161052a919061381a565b60405180910390f35b61053b6113ec565b604051610548919061381a565b60405180910390f35b61056b60048036036105669190810190612bac565b6113f9565b005b610575611408565b604051610582919061381a565b60405180910390f35b6105a560048036036105a09190810190612a73565b611412565b005b6105af611587565b6040516105bc919061381a565b60405180910390f35b6105cd611798565b6040516105da919061342a565b60405180910390f35b6105ee3333856117a7565b505050565b6105fb6111ac565b61063a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610631906137df565b60405180910390fd5b6106453385856117a7565b50505050565b600281565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663fc0c546a6040518163ffffffff1660e01b815260040160206040518083038186803b1580156106ba57600080fd5b505afa1580156106ce573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506106f29190810190612b31565b73ffffffffffffffffffffffffffffffffffffffff16600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663fc0c546a6040518163ffffffff1660e01b815260040160206040518083038186803b15801561077057600080fd5b505afa158015610784573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506107a89190810190612b31565b73ffffffffffffffffffffffffffffffffffffffff16146107c557fe5b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663fc0c546a6040518163ffffffff1660e01b815260040160206040518083038186803b15801561082d57600080fd5b505afa158015610841573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506108659190810190612b31565b905090565b6000600c54905090565b60055481565b60008060008060008061088b611587565b5060006108b76008546108a9600c5442611cfb90919063ffffffff16565b611d4590919063ffffffff16565b90506108ce81600b54611db590919063ffffffff16565b600b8190555042600c819055506000600e60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050600061094d826000015461093f846002015442611cfb90919063ffffffff16565b611d4590919063ffffffff16565b9050610966818360010154611db590919063ffffffff16565b8260010181905550428260020181905550600080600b54116109895760006109bc565b6109bb600b546109ad856001015461099f61132d565b611d4590919063ffffffff16565b611e0a90919063ffffffff16565b5b90506109c6610a7a565b6109ce61132d565b8460010154600b54844299509950995099509950995050505050909192939495565b60008060085411610a02576000610a73565b610a72600854610a64600e60008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000154610a56610c7e565b611d4590919063ffffffff16565b611e0a90919063ffffffff16565b5b9050919050565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663b69ef8a86040518163ffffffff1660e01b815260040160206040518083038186803b158015610ae457600080fd5b505afa158015610af8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610b1c9190810190612b83565b905090565b60048181548110610b2e57fe5b90600052602060002090600502016000915090508060000154908060010154908060020154908060030154908060040154905085565b600080905090565b60085481565b610b7a6111ac565b610bb9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bb0906137df565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b60065481565b6000600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663b69ef8a86040518163ffffffff1660e01b815260040160206040518083038186803b158015610ce857600080fd5b505afa158015610cfc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610d209190810190612b83565b905090565b60075481565b606080600d60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b82821015610dd357838290600052602060002090600202016040518060400160405290816000820154815260200160018201548152505081526020019060010190610d8d565b50505050905080915050919050565b6000610ded82611e54565b9050919050565b610dfc6111ac565b610e3b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e32906137df565b60405180910390fd5b60095460048054905010610e84576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e7b9061363f565b60405180910390fd5b610e8c61087a565b505050505050610e9a6128f5565b6000610ea4610a7a565b90506000808211610ec957610ec4600a5486611d4590919063ffffffff16565b610ef1565b610ef082610ee287600754611d4590919063ffffffff16565b611e0a90919063ffffffff16565b5b90508083600001818152505042836040018181525050610f1a8442611db590919063ffffffff16565b83606001818152505083836080018181525050600483908060018154018082558091505090600182039060005260206000209060050201600090919290919091506000820151816000015560208201518160010155604082015181600201556060820151816003015560808201518160040155505050610fa581600754611db590919063ffffffff16565b600781905550600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663fc0c546a6040518163ffffffff1660e01b815260040160206040518083038186803b15801561101357600080fd5b505afa158015611027573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061104b9190810190612b31565b73ffffffffffffffffffffffffffffffffffffffff166323b872dd33600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16886040518463ffffffff1660e01b81526004016110a993929190613445565b602060405180830381600087803b1580156110c357600080fd5b505af11580156110d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506110fb9190810190612b08565b61113a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111319061365f565b60405180910390fd5b7ff346961af4c52f314df1b45964746280fe409abb959d4a2458d58f79408b1fe88585611165610a7a565b6040516111749392919061389a565b60405180910390a15050505050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614905090565b61120b612924565b611213612924565b600e60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206040518060600160405290816000820154815260200160018201548152602001600282015481525050905080915050919050565b6000600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663fc0c546a6040518163ffffffff1660e01b815260040160206040518083038186803b1580156112f057600080fd5b505afa158015611304573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506113289190810190612b31565b905090565b6000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663b69ef8a86040518163ffffffff1660e01b815260040160206040518083038186803b15801561139757600080fd5b505afa1580156113ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506113cf9190810190612b83565b905090565b600f6020528060005260406000206000915090505481565b6000600480549050905090565b61140283611e54565b50505050565b6000600b54905090565b61141a6111ac565b611459576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611450906137df565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156114c9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114c0906137bf565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600080600090506000611598610a7a565b9050600060075414156115ad57809150611636565b600080905060008090505b6004805490508110156115ef576115e06115d182612651565b83611db590919063ffffffff16565b915080806001019150506115b8565b506116176007546116098484611d4590919063ffffffff16565b611e0a90919063ffffffff16565b925061162e81600754611cfb90919063ffffffff16565b600781905550505b600082111561179057600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16846040518363ffffffff1660e01b81526004016116be9291906134dc565b602060405180830381600087803b1580156116d857600080fd5b505af11580156116ec573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506117109190810190612b08565b61174f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611746906135df565b60405180910390fd5b7f2e444eb379b177e88ce0649c6110a3b01099f03e297127919dd5e3b63a761a9c82611779610a7a565b604051611787929190613835565b60405180910390a15b819250505090565b60006117a2611286565b905090565b600081116117ea576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117e19061371f565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141561185a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611851906135ff565b60405180910390fd5b6000600854148061187257506000611870610c7e565b115b6118b1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118a8906136ff565b60405180910390fd5b6000600f60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054141561193e5742600f60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505b600080600854116119635761195e600a5483611d4590919063ffffffff16565b611992565b61199161196e610c7e565b61198384600854611d4590919063ffffffff16565b611e0a90919063ffffffff16565b5b9050600081116119d7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119ce9061369f565b60405180910390fd5b6119df61087a565b5050505050506000600e60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050611a3f828260000154611db590919063ffffffff16565b8160000181905550428160020181905550611a58612945565b6040518060400160405280848152602001428152509050600d60008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081908060018154018082558091505090600182039060005260206000209060020201600090919290919091506000820151816000015560208201518160010155505050611b0683600854611db590919063ffffffff16565b600881905550600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663fc0c546a6040518163ffffffff1660e01b815260040160206040518083038186803b158015611b7457600080fd5b505afa158015611b88573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611bac9190810190612b31565b73ffffffffffffffffffffffffffffffffffffffff166323b872dd87600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16876040518463ffffffff1660e01b8152600401611c0a939291906134a5565b602060405180830381600087803b158015611c2457600080fd5b505af1158015611c38573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611c5c9190810190612b08565b611c9b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c929061379f565b60405180910390fd5b8473ffffffffffffffffffffffffffffffffffffffff167fc65e53b88159e7d2c0fc12a0600072e28ae53ff73b4c1715369c30f16093514285611cdd886109f0565b604051611ceb92919061385e565b60405180910390a2505050505050565b6000611d3d83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250612742565b905092915050565b600080831415611d585760009050611daf565b6000828402905082848281611d6957fe5b0414611daa576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611da1906136df565b60405180910390fd5b809150505b92915050565b600080828401905083811015611e00576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611df79061361f565b60405180910390fd5b8091505092915050565b6000611e4c83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f00000000000081525061279d565b905092915050565b600080600f60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050611eaf620d2f0082611db590919063ffffffff16565b4211611ef0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ee7906136bf565b60405180910390fd5b611ef861087a565b50505050505060008311611f41576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f389061373f565b60405180910390fd5b82611f4b336109f0565b1015611f8c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f83906135bf565b60405180910390fd5b6000611fbc611f99610c7e565b611fae86600854611d4590919063ffffffff16565b611e0a90919063ffffffff16565b905060008111612001576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ff89061357f565b60405180910390fd5b6000600e60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090506000600d60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090506000809050600080905060008590505b60008111156121c1576000846001868054905003815481106120b557fe5b9060005260206000209060020201905060006120de826001015442611cfb90919063ffffffff16565b905060008090508383600001541161215e57612107828460000154611d4590919063ffffffff16565b90506121148682846127fe565b95506121298186611db590919063ffffffff16565b9450612142836000015485611cfb90919063ffffffff16565b935086805480919060019003612158919061295f565b506121b9565b6121718285611d4590919063ffffffff16565b905061217e8682846127fe565b95506121938186611db590919063ffffffff16565b94506121ac848460000154611cfb90919063ffffffff16565b8360000181905550600093505b505050612097565b6121d8828660010154611cfb90919063ffffffff16565b85600101819055506121f7868660000154611cfb90919063ffffffff16565b856000018190555061221482600b54611cfb90919063ffffffff16565b600b8190555061222f86600854611cfb90919063ffffffff16565b600881905550600061225f61271061225160648d611d4590919063ffffffff16565b611e0a90919063ffffffff16565b9050600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb6122a7611183565b836040518363ffffffff1660e01b81526004016122c59291906134dc565b602060405180830381600087803b1580156122df57600080fd5b505af11580156122f3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506123179190810190612b08565b612356576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161234d9061367f565b60405180910390fd5b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb336123a8848e611cfb90919063ffffffff16565b6040518363ffffffff1660e01b81526004016123c592919061347c565b602060405180830381600087803b1580156123df57600080fd5b505af11580156123f3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506124179190810190612b08565b612456576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161244d9061359f565b60405180910390fd5b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb33866040518363ffffffff1660e01b81526004016124b392919061347c565b602060405180830381600087803b1580156124cd57600080fd5b505af11580156124e1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506125059190810190612b08565b612544576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161253b9061375f565b60405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff167faf01bfc8475df280aca00b578c4a948e6d95700f0db8c13365240f7f973c87548b612586336109f0565b60405161259492919061385e565b60405180910390a23373ffffffffffffffffffffffffffffffffffffffff167f896e034966eaaf1adc54acc0f257056febbd300c9e47182cf761982cf1f5e430856040516125e2919061381a565b60405180910390a26000600854148061260257506000612600610c7e565b115b612641576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016126389061377f565b60405180910390fd5b8398505050505050505050919050565b6000806004838154811061266157fe5b90600052602060002090600502019050806000015481600101541061268a57600091505061273d565b6000809050816003015442106126c9576126b582600101548360000154611cfb90919063ffffffff16565b905081600301548260020181905550612718565b61270c82600401546126fe84600001546126f0866002015442611cfb90919063ffffffff16565b611d4590919063ffffffff16565b611e0a90919063ffffffff16565b90504282600201819055505b61272f818360010154611db590919063ffffffff16565b826001018190555080925050505b919050565b600083831115829061278a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612781919061355d565b60405180910390fd5b5060008385039050809150509392505050565b600080831182906127e4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016127db919061355d565b60405180910390fd5b5060008385816127f057fe5b049050809150509392505050565b60008061282f600b546128218661281361132d565b611d4590919063ffffffff16565b611e0a90919063ffffffff16565b905060065483106128555761284d8186611db590919063ffffffff16565b9150506128ee565b60006002600a0a905060006128d3826128c5856128b76128a66006546128988c61288a6005548c611cfb90919063ffffffff16565b611d4590919063ffffffff16565b611e0a90919063ffffffff16565b600554611db590919063ffffffff16565b611d4590919063ffffffff16565b611e0a90919063ffffffff16565b90506128e88188611db590919063ffffffff16565b93505050505b9392505050565b6040518060a0016040528060008152602001600081526020016000815260200160008152602001600081525090565b60405180606001604052806000815260200160008152602001600081525090565b604051806040016040528060008152602001600081525090565b81548183558181111561298c5760020281600202836000526020600020918201910161298b9190612991565b5b505050565b6129bd91905b808211156129b957600080820160009055600182016000905550600201612997565b5090565b90565b6000813590506129cf81613ae3565b92915050565b6000815190506129e481613afa565b92915050565b60008083601f8401126129fc57600080fd5b8235905067ffffffffffffffff811115612a1557600080fd5b602083019150836001820283011115612a2d57600080fd5b9250929050565b600081519050612a4381613b11565b92915050565b600081359050612a5881613b28565b92915050565b600081519050612a6d81613b28565b92915050565b600060208284031215612a8557600080fd5b6000612a93848285016129c0565b91505092915050565b60008060008060608587031215612ab257600080fd5b6000612ac0878288016129c0565b9450506020612ad187828801612a49565b935050604085013567ffffffffffffffff811115612aee57600080fd5b612afa878288016129ea565b925092505092959194509250565b600060208284031215612b1a57600080fd5b6000612b28848285016129d5565b91505092915050565b600060208284031215612b4357600080fd5b6000612b5184828501612a34565b91505092915050565b600060208284031215612b6c57600080fd5b6000612b7a84828501612a49565b91505092915050565b600060208284031215612b9557600080fd5b6000612ba384828501612a5e565b91505092915050565b600080600060408486031215612bc157600080fd5b6000612bcf86828701612a49565b935050602084013567ffffffffffffffff811115612bec57600080fd5b612bf8868287016129ea565b92509250509250925092565b60008060408385031215612c1757600080fd5b6000612c2585828601612a49565b9250506020612c3685828601612a49565b9150509250929050565b6000612c4c838361339b565b60408301905092915050565b612c6181613a45565b82525050565b612c70816139eb565b82525050565b6000612c8182613995565b612c8b81856139b8565b9350612c9683613985565b8060005b83811015612cc7578151612cae8882612c40565b9750612cb9836139ab565b925050600181019050612c9a565b5085935050505092915050565b612cdd816139fd565b82525050565b612cec81613a57565b82525050565b6000612cfd826139a0565b612d0781856139da565b9350612d17818560208601613a9f565b612d2081613ad2565b840191505092915050565b6000612d386019836139da565b91507f47617264656e3a20756e7374616b6520746f6f20736d616c6c000000000000006000830152602082019050919050565b6000612d786022836139da565b91507f47617264656e3a207478206f7574206f66207374616b696e6720706f6f6c206560008301527f72720000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000612dde6026836139da565b91507f47617264656e3a20756e7374616b6520616d74203e20746f74616c207573657260008301527f207374616b6500000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000612e446021836139da565b91507f47617264656e3a207478206f7574206f66206c6f636b656420706f6f6c20657260008301527f72000000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000612eaa6015836139da565b91507f47617264656e3a2062656e2069732030206164647200000000000000000000006000830152602082019050919050565b6000612eea601b836139da565b91507f536166654d6174683a206164646974696f6e206f766572666c6f7700000000006000830152602082019050919050565b6000612f2a6024836139da565b91507f47617264656e3a2072656163686564206d617820756e6c6f636b20736368656460008301527f756c6573000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000612f90601f836139da565b91507f47617264656e3a20747820696e746f206c6f636b656420706f6f6c20657272006000830152602082019050919050565b6000612fd06012836139da565b91507f47617264656e3a206572722074782066656500000000000000000000000000006000830152602082019050919050565b60006130106017836139da565b91507f47617264656e3a205374616b6520746f6f20736d616c6c0000000000000000006000830152602082019050919050565b60006130506013836139da565b91507f47617264656e3a20696e20636f6f6c646f776e000000000000000000000000006000830152602082019050919050565b60006130906021836139da565b91507f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f60008301527f77000000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006130f66032836139da565b91507f47617264656e3a202176616c69642073746174652c207374616b696e6720736860008301527f6172657320627574206e6f20746f6b656e7300000000000000000000000000006020830152604082019050919050565b600061315c6016836139da565b91507f47617264656e3a207374616b6520616d742069732030000000000000000000006000830152602082019050919050565b600061319c6015836139da565b91507f47617264656e3a20756e7374616b6520616d74203000000000000000000000006000830152602082019050919050565b60006131dc6000836139c9565b9150600082019050919050565b60006131f66023836139da565b91507f47617264656e3a207478206f7574206f6620756e6c6f636b656420706f6f6c2060008301527f65727200000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b600061325c6031836139da565b91507f47617264656e3a2045727220756e7374616b652e205374616b696e672073686160008301527f72657320627574206e6f20746f6b656e730000000000000000000000000000006020830152604082019050919050565b60006132c26023836139da565b91507f47617264656e3a20747820696e746f207374616b696e6720706f6f6c2066616960008301527f6c656400000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006133286006836139da565b91507f30206164647900000000000000000000000000000000000000000000000000006000830152602082019050919050565b60006133686006836139da565b91507f216f776e657200000000000000000000000000000000000000000000000000006000830152602082019050919050565b6040820160008201516133b1600085018261340c565b5060208201516133c4602085018261340c565b50505050565b6060820160008201516133e0600085018261340c565b5060208201516133f3602085018261340c565b506040820151613406604085018261340c565b50505050565b61341581613a3b565b82525050565b61342481613a3b565b82525050565b600060208201905061343f6000830184612c67565b92915050565b600060608201905061345a6000830186612c58565b6134676020830185612c67565b613474604083018461341b565b949350505050565b60006040820190506134916000830185612c58565b61349e602083018461341b565b9392505050565b60006060820190506134ba6000830186612c67565b6134c76020830185612c67565b6134d4604083018461341b565b949350505050565b60006040820190506134f16000830185612c67565b6134fe602083018461341b565b9392505050565b6000602082019050818103600083015261351f8184612c76565b905092915050565b600060208201905061353c6000830184612cd4565b92915050565b60006020820190506135576000830184612ce3565b92915050565b600060208201905081810360008301526135778184612cf2565b905092915050565b6000602082019050818103600083015261359881612d2b565b9050919050565b600060208201905081810360008301526135b881612d6b565b9050919050565b600060208201905081810360008301526135d881612dd1565b9050919050565b600060208201905081810360008301526135f881612e37565b9050919050565b6000602082019050818103600083015261361881612e9d565b9050919050565b6000602082019050818103600083015261363881612edd565b9050919050565b6000602082019050818103600083015261365881612f1d565b9050919050565b6000602082019050818103600083015261367881612f83565b9050919050565b6000602082019050818103600083015261369881612fc3565b9050919050565b600060208201905081810360008301526136b881613003565b9050919050565b600060208201905081810360008301526136d881613043565b9050919050565b600060208201905081810360008301526136f881613083565b9050919050565b60006020820190508181036000830152613718816130e9565b9050919050565b600060208201905081810360008301526137388161314f565b9050919050565b600060208201905081810360008301526137588161318f565b9050919050565b60006020820190508181036000830152613778816131e9565b9050919050565b600060208201905081810360008301526137988161324f565b9050919050565b600060208201905081810360008301526137b8816132b5565b9050919050565b600060208201905081810360008301526137d88161331b565b9050919050565b600060208201905081810360008301526137f88161335b565b9050919050565b600060608201905061381460008301846133ca565b92915050565b600060208201905061382f600083018461341b565b92915050565b600060408201905061384a600083018561341b565b613857602083018461341b565b9392505050565b6000606082019050613873600083018561341b565b613880602083018461341b565b8181036040830152613891816131cf565b90509392505050565b60006060820190506138af600083018661341b565b6138bc602083018561341b565b6138c9604083018461341b565b949350505050565b600060a0820190506138e6600083018861341b565b6138f3602083018761341b565b613900604083018661341b565b61390d606083018561341b565b61391a608083018461341b565b9695505050505050565b600060c082019050613939600083018961341b565b613946602083018861341b565b613953604083018761341b565b613960606083018661341b565b61396d608083018561341b565b61397a60a083018461341b565b979650505050505050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b600082825260208201905092915050565b600082825260208201905092915050565b600082825260208201905092915050565b60006139f682613a1b565b9050919050565b60008115159050919050565b6000613a14826139eb565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b6000613a5082613a7b565b9050919050565b6000613a6282613a69565b9050919050565b6000613a7482613a1b565b9050919050565b6000613a8682613a8d565b9050919050565b6000613a9882613a1b565b9050919050565b60005b83811015613abd578082015181840152602081019050613aa2565b83811115613acc576000848401525b50505050565b6000601f19601f8301169050919050565b613aec816139eb565b8114613af757600080fd5b50565b613b03816139fd565b8114613b0e57600080fd5b50565b613b1a81613a09565b8114613b2557600080fd5b50565b613b3181613a3b565b8114613b3c57600080fd5b5056fea365627a7a723158204619459f0ef9e009779b36573b9311d46c7d78a223f21157967db037d6eb994e6c6578706572696d656e74616cf564736f6c63430005110040

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

000000000000000000000000bbfd9b37ec6ea1ca612ab4adef6d8c6ece1a4134000000000000000000000000dcb01cc464238396e213a6fdd933e36796eaff9f0000000000000000000000000000000000000000000000000000000000002710000000000000000000000000000000000000000000000000000000000000002100000000000000000000000000000000000000000000000000000000003b538000000000000000000000000000000000000000000000000000000000000f4240

-----Decoded View---------------
Arg [0] : stakingToken (address): 0xBbfd9B37ec6ea1cA612AB4ADef6d8c6ece1a4134
Arg [1] : distributionToken (address): 0xDcB01cc464238396E213a6fDd933E36796eAfF9f
Arg [2] : maxUnlockSchedules (uint256): 10000
Arg [3] : startBonus_ (uint256): 33
Arg [4] : bonusPeriodSec_ (uint256): 3888000
Arg [5] : initialSharesPerToken (uint256): 1000000

-----Encoded View---------------
6 Constructor Arguments found :
Arg [0] : 000000000000000000000000bbfd9b37ec6ea1ca612ab4adef6d8c6ece1a4134
Arg [1] : 000000000000000000000000dcb01cc464238396e213a6fdd933e36796eaff9f
Arg [2] : 0000000000000000000000000000000000000000000000000000000000002710
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000021
Arg [4] : 00000000000000000000000000000000000000000000000000000000003b5380
Arg [5] : 00000000000000000000000000000000000000000000000000000000000f4240


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

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

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