ETH Price: $2,319.06 (+3.11%)
Gas: 0.08 Gwei

Contract

0x7Ec8FcC26bE7e9E85B57E73083E5Fe0550d8A7fE
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

More Info

Private Name Tags

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Submit Vote190647232024-01-22 20:46:47784 days ago1705956407IN
Kyber Network: Governance
0 ETH0.0030042416.60135129
Submit Vote190590352024-01-22 1:31:11785 days ago1705887071IN
Kyber Network: Governance
0 ETH0.002007411.09286786
Submit Vote190525542024-01-21 3:29:11786 days ago1705807751IN
Kyber Network: Governance
0 ETH0.0019320610.67651365
Submit Vote190471772024-01-20 9:27:35786 days ago1705742855IN
Kyber Network: Governance
0 ETH0.0028942914.6129148
Submit Vote190466282024-01-20 7:37:47786 days ago1705736267IN
Kyber Network: Governance
0 ETH0.0027496115.19424363
Submit Vote190466252024-01-20 7:37:11786 days ago1705736231IN
Kyber Network: Governance
0 ETH0.0029208216.14036955
Submit Vote190463342024-01-20 6:38:59787 days ago1705732739IN
Kyber Network: Governance
0 ETH0.0029721516.42403732
Submit Vote190425202024-01-19 17:51:59787 days ago1705686719IN
Kyber Network: Governance
0 ETH0.0062250534.39939516
Submit Vote190371552024-01-18 23:53:59788 days ago1705622039IN
Kyber Network: Governance
0 ETH0.0050048427.65658089
Submit Vote190316632024-01-18 5:28:11789 days ago1705555691IN
Kyber Network: Governance
0 ETH0.0042998923.76107763
Submit Vote190315222024-01-18 4:59:59789 days ago1705553999IN
Kyber Network: Governance
0 ETH0.0044194424.42166896
Submit Vote190300292024-01-17 23:59:23789 days ago1705535963IN
Kyber Network: Governance
0 ETH0.0062375234.46832454
Submit Vote190264782024-01-17 12:01:59789 days ago1705492919IN
Kyber Network: Governance
0 ETH0.0063783735.24663497
Submit Vote190247652024-01-17 6:17:59790 days ago1705472279IN
Kyber Network: Governance
0 ETH0.0050387827.84415252
Submit Vote190243942024-01-17 5:03:23790 days ago1705467803IN
Kyber Network: Governance
0 ETH0.0043392330.94191804
Submit Vote190182342024-01-16 8:23:47790 days ago1705393427IN
Kyber Network: Governance
0 ETH0.0053161224.7073332
Execute188683102023-12-26 7:14:23811 days ago1703574863IN
Kyber Network: Governance
0 ETH0.0038179614.79131885
Queue188184452023-12-19 7:13:35818 days ago1702970015IN
Kyber Network: Governance
0 ETH0.0087243143
Submit Vote188174992023-12-19 4:01:35819 days ago1702958495IN
Kyber Network: Governance
0 ETH0.008420846.55004408
Submit Vote188114492023-12-18 7:39:47819 days ago1702885187IN
Kyber Network: Governance
0 ETH0.005647431.21874979
Submit Vote188107842023-12-18 5:25:35820 days ago1702877135IN
Kyber Network: Governance
0 ETH0.0031986932.82223785
Submit Vote188107502023-12-18 5:18:47820 days ago1702876727IN
Kyber Network: Governance
0 ETH0.0066857336.95856302
Submit Vote188107372023-12-18 5:16:11820 days ago1702876571IN
Kyber Network: Governance
0 ETH0.0076473242.27421079
Submit Vote188024882023-12-17 1:29:23821 days ago1702776563IN
Kyber Network: Governance
0 ETH0.0057668531.87902785
Submit Vote187917812023-12-15 13:21:35822 days ago1702646495IN
Kyber Network: Governance
0 ETH0.005347154.86738096
View all transactions

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
KyberGovernance

Compiler Version
v0.7.6+commit.7338295f

Optimization Enabled:
Yes with 1000 runs

Other Settings:
default evmVersion
// SPDX-License-Identifier: agpl-3.0
pragma solidity 0.7.6;
pragma abicoder v2;

import {SafeMath} from '@openzeppelin/contracts/math/SafeMath.sol';
import {PermissionAdmin} from '@kyber.network/utils-sc/contracts/PermissionAdmin.sol';
import {IKyberGovernance} from '../interfaces/governance/IKyberGovernance.sol';
import {IExecutorWithTimelock} from '../interfaces/governance/IExecutorWithTimelock.sol';
import {IVotingPowerStrategy} from '../interfaces/governance/IVotingPowerStrategy.sol';
import {IProposalValidator} from '../interfaces/governance/IProposalValidator.sol';
import {getChainId} from '../misc/Helpers.sol';

/**
 * @title Kyber Governance contract for Kyber 3.0
 * - Create a Proposal
 * - Cancel a Proposal
 * - Queue a Proposal
 * - Execute a Proposal
 * - Submit Vote to a Proposal
 * Proposal States : Pending => Active => Succeeded(/Failed/Finalized)
 *                   => Queued => Executed(/Expired)
 *                   The transition to "Canceled" can appear in multiple states
 **/
contract KyberGovernance is IKyberGovernance, PermissionAdmin {
  using SafeMath for uint256;

  bytes32 public constant DOMAIN_TYPEHASH = keccak256(
    'EIP712Domain(string name,uint256 chainId,address verifyingContract)'
  );
  bytes32 public constant VOTE_EMITTED_TYPEHASH = keccak256(
    'VoteEmitted(uint256 id,uint256 optionBitMask)'
  );
  string public constant NAME = 'Kyber Governance';

  address private _daoOperator;
  uint256 private _proposalsCount;
  mapping(uint256 => Proposal) private _proposals;
  mapping(address => bool) private _authorizedExecutors;
  mapping(address => bool) private _authorizedVotingPowerStrategies;

  constructor(
    address admin,
    address daoOperator,
    address[] memory executors,
    address[] memory votingPowerStrategies
  ) PermissionAdmin(admin) {
    require(daoOperator != address(0), 'invalid dao operator');
    _daoOperator = daoOperator;

    _authorizeExecutors(executors);
    _authorizeVotingPowerStrategies(votingPowerStrategies);
  }

  /**
   * @dev Creates a Binary Proposal (needs to be validated by the Proposal Validator)
   * @param executor The ExecutorWithTimelock contract that will execute the proposal
   * @param strategy voting power strategy of the proposal
   * @param executionParams data for execution, includes
   *   targets list of contracts called by proposal's associated transactions
   *   weiValues list of value in wei for each proposal's associated transaction
   *   signatures list of function signatures (can be empty) to be used when created the callData
   *   calldatas list of calldatas: if associated signature empty,
   *        calldata ready, else calldata is arguments
   *   withDelegatecalls boolean, true = transaction delegatecalls the taget,
   *         else calls the target
   * @param startTime start timestamp to allow vote
   * @param endTime end timestamp of the proposal
   * @param link link to the proposal description
   **/
  function createBinaryProposal(
    IExecutorWithTimelock executor,
    IVotingPowerStrategy strategy,
    BinaryProposalParams memory executionParams,
    uint256 startTime,
    uint256 endTime,
    string memory link
  ) external override returns (uint256 proposalId) {
    require(executionParams.targets.length != 0, 'create binary invalid empty targets');
    require(
      executionParams.targets.length == executionParams.weiValues.length &&
        executionParams.targets.length == executionParams.signatures.length &&
        executionParams.targets.length == executionParams.calldatas.length &&
        executionParams.targets.length == executionParams.withDelegatecalls.length,
      'create binary inconsistent params length'
    );

    require(isExecutorAuthorized(address(executor)), 'create binary executor not authorized');
    require(
      isVotingPowerStrategyAuthorized(address(strategy)),
      'create binary strategy not authorized'
    );

    proposalId = _proposalsCount;
    require(
      IProposalValidator(address(executor)).validateBinaryProposalCreation(
        strategy,
        msg.sender,
        startTime,
        endTime,
        _daoOperator
      ),
      'validate proposal creation invalid'
    );

    ProposalWithoutVote storage newProposalData = _proposals[proposalId].proposalData;
    newProposalData.id = proposalId;
    newProposalData.proposalType = ProposalType.Binary;
    newProposalData.creator = msg.sender;
    newProposalData.executor = executor;
    newProposalData.targets = executionParams.targets;
    newProposalData.weiValues = executionParams.weiValues;
    newProposalData.signatures = executionParams.signatures;
    newProposalData.calldatas = executionParams.calldatas;
    newProposalData.withDelegatecalls = executionParams.withDelegatecalls;
    newProposalData.startTime = startTime;
    newProposalData.endTime = endTime;
    newProposalData.strategy = strategy;
    newProposalData.link = link;

    // only 2 options, YES and NO
    newProposalData.options.push('YES');
    newProposalData.options.push('NO');
    newProposalData.voteCounts.push(0);
    newProposalData.voteCounts.push(0);
    // use max voting power to finalise the proposal
    newProposalData.maxVotingPower = strategy.getMaxVotingPower();

    _proposalsCount++;
    // call strategy to record data if needed
    strategy.handleProposalCreation(proposalId, startTime, endTime);

    emit BinaryProposalCreated(
      proposalId,
      msg.sender,
      executor,
      strategy,
      executionParams.targets,
      executionParams.weiValues,
      executionParams.signatures,
      executionParams.calldatas,
      executionParams.withDelegatecalls,
      startTime,
      endTime,
      link,
      newProposalData.maxVotingPower
    );
  }

  /**
   * @dev Creates a Generic Proposal (needs to be validated by the Proposal Validator)
   *    It only gets the winning option without any executions
   * @param executor The ExecutorWithTimelock contract that will execute the proposal
   * @param strategy voting power strategy of the proposal
   * @param options list of options to vote for
   * @param startTime start timestamp to allow vote
   * @param endTime end timestamp of the proposal
   * @param link link to the proposal description
   **/
  function createGenericProposal(
    IExecutorWithTimelock executor,
    IVotingPowerStrategy strategy,
    string[] memory options,
    uint256 startTime,
    uint256 endTime,
    string memory link
  )
    external override returns (uint256 proposalId)
  {
    require(
      isExecutorAuthorized(address(executor)),
      'create generic executor not authorized'
    );
    require(
      isVotingPowerStrategyAuthorized(address(strategy)),
      'create generic strategy not authorized'
    );
    proposalId = _proposalsCount;
    require(
      IProposalValidator(address(executor)).validateGenericProposalCreation(
        strategy,
        msg.sender,
        startTime,
        endTime,
        options,
        _daoOperator
      ),
      'validate proposal creation invalid'
    );
    Proposal storage newProposal = _proposals[proposalId];
    ProposalWithoutVote storage newProposalData = newProposal.proposalData;
    newProposalData.id = proposalId;
    newProposalData.proposalType = ProposalType.Generic;
    newProposalData.creator = msg.sender;
    newProposalData.executor = executor;
    newProposalData.startTime = startTime;
    newProposalData.endTime = endTime;
    newProposalData.strategy = strategy;
    newProposalData.link = link;
    newProposalData.options = options;
    newProposalData.voteCounts = new uint256[](options.length);
    // use max voting power to finalise the proposal
    newProposalData.maxVotingPower = strategy.getMaxVotingPower();

    _proposalsCount++;
    // call strategy to record data if needed
    strategy.handleProposalCreation(proposalId, startTime, endTime);

    emit GenericProposalCreated(
      proposalId,
      msg.sender,
      executor,
      strategy,
      options,
      startTime,
      endTime,
      link,
      newProposalData.maxVotingPower
    );
  }

  /**
   * @dev Cancels a Proposal.
   * - Callable by the _daoOperator with relaxed conditions,
   *   or by anybody if the conditions of cancellation on the executor are fulfilled
   * @param proposalId id of the proposal
   **/
  function cancel(uint256 proposalId) external override {
    require(proposalId < _proposalsCount, 'invalid proposal id');
    ProposalState state = getProposalState(proposalId);
    require(
      state != ProposalState.Executed &&
        state != ProposalState.Canceled &&
        state != ProposalState.Expired &&
        state != ProposalState.Finalized,
      'invalid state to cancel'
    );

    ProposalWithoutVote storage proposal = _proposals[proposalId].proposalData;
    require(
      msg.sender == _daoOperator ||
        IProposalValidator(address(proposal.executor)).validateProposalCancellation(
          IKyberGovernance(this),
          proposalId,
          proposal.creator
        ),
      'validate proposal cancellation failed'
    );
    proposal.canceled = true;
    if (proposal.proposalType == ProposalType.Binary) {
      for (uint256 i = 0; i < proposal.targets.length; i++) {
        proposal.executor.cancelTransaction(
          proposal.targets[i],
          proposal.weiValues[i],
          proposal.signatures[i],
          proposal.calldatas[i],
          proposal.executionTime,
          proposal.withDelegatecalls[i]
        );
      }
    }
    // notify voting power strategy about the cancellation
    proposal.strategy.handleProposalCancellation(proposalId);

    emit ProposalCanceled(proposalId);
  }

  /**
   * @dev Queue the proposal (If Proposal Succeeded), only for Binary proposals
   * @param proposalId id of the proposal to queue
   **/
  function queue(uint256 proposalId) external override {
    require(proposalId < _proposalsCount, 'invalid proposal id');
    require(
      getProposalState(proposalId) == ProposalState.Succeeded,
      'invalid state to queue'
    );
    ProposalWithoutVote storage proposal = _proposals[proposalId].proposalData;
    // generic proposal does not have Succeeded state
    assert(proposal.proposalType == ProposalType.Binary);
    uint256 executionTime = block.timestamp.add(proposal.executor.getDelay());
    for (uint256 i = 0; i < proposal.targets.length; i++) {
      _queueOrRevert(
        proposal.executor,
        proposal.targets[i],
        proposal.weiValues[i],
        proposal.signatures[i],
        proposal.calldatas[i],
        executionTime,
        proposal.withDelegatecalls[i]
      );
    }
    proposal.executionTime = executionTime;

    emit ProposalQueued(proposalId, executionTime, msg.sender);
  }

  /**
   * @dev Execute the proposal (If Proposal Queued), only for Binary proposals
   * @param proposalId id of the proposal to execute
   **/
  function execute(uint256 proposalId) external override payable {
    require(proposalId < _proposalsCount, 'invalid proposal id');
    require(getProposalState(proposalId) == ProposalState.Queued, 'only queued proposals');
    ProposalWithoutVote storage proposal = _proposals[proposalId].proposalData;
    // generic proposal does not have Queued state
    assert(proposal.proposalType == ProposalType.Binary);
    proposal.executed = true;
    for (uint256 i = 0; i < proposal.targets.length; i++) {
      proposal.executor.executeTransaction{value: proposal.weiValues[i]}(
        proposal.targets[i],
        proposal.weiValues[i],
        proposal.signatures[i],
        proposal.calldatas[i],
        proposal.executionTime,
        proposal.withDelegatecalls[i]
      );
    }
    emit ProposalExecuted(proposalId, msg.sender);
  }

  /**
   * @dev Function allowing msg.sender to vote for/against a proposal
   * @param proposalId id of the proposal
   * @param optionBitMask bitmask optionBitMask of voter
   *  for Binary Proposal, optionBitMask should be either 1 or 2 (Accept/Reject)
   *  for Generic Proposal, optionBitMask is the bitmask of voted options
   **/
  function submitVote(uint256 proposalId, uint256 optionBitMask) external override {
    return _submitVote(msg.sender, proposalId, optionBitMask);
  }

  /**
   * @dev Function to register the vote of user that has voted offchain via signature
   * @param proposalId id of the proposal
   * @param optionBitMask the bit mask of voted options
   * @param v v part of the voter signature
   * @param r r part of the voter signature
   * @param s s part of the voter signature
   **/
  function submitVoteBySignature(
    uint256 proposalId,
    uint256 optionBitMask,
    uint8 v,
    bytes32 r,
    bytes32 s
  ) external override {
    bytes32 digest = keccak256(
      abi.encodePacked(
        '\x19\x01',
        keccak256(
          abi.encode(DOMAIN_TYPEHASH, keccak256(bytes(NAME)), getChainId(), address(this))
        ),
        keccak256(abi.encode(VOTE_EMITTED_TYPEHASH, proposalId, optionBitMask))
      )
    );
    address signer = ecrecover(digest, v, r, s);
    require(signer != address(0), 'invalid signature');
    return _submitVote(signer, proposalId, optionBitMask);
  }

  /**
   * @dev Function to handle voting power changed for a voter
   *  caller must be the voting power strategy of the proposal
   * @param voter address that has changed the voting power
   * @param newVotingPower new voting power of that address,
   *   old voting power can be taken from records
   * @param proposalIds list proposal ids that belongs to this voting power strategy
   *   should update the voteCound of the active proposals in the list
   **/
  function handleVotingPowerChanged(
    address voter,
    uint256 newVotingPower,
    uint256[] calldata proposalIds
  ) external override {
    uint224 safeNewVotingPower = _safeUint224(newVotingPower);
    for (uint256 i = 0; i < proposalIds.length; i++) {
      // only update for active proposals
      if (getProposalState(proposalIds[i]) != ProposalState.Active) continue;
      ProposalWithoutVote storage proposal = _proposals[proposalIds[i]].proposalData;
      require(address(proposal.strategy) == msg.sender, 'invalid voting power strategy');
      Vote memory vote = _proposals[proposalIds[i]].votes[voter];
      if (vote.optionBitMask == 0) continue; // not voted yet
      uint256 oldVotingPower = uint256(vote.votingPower);
      // update totalVotes of the proposal
      proposal.totalVotes = proposal.totalVotes.add(newVotingPower).sub(oldVotingPower);
      for (uint256 j = 0; j < proposal.options.length; j++) {
        if (vote.optionBitMask & (2**j) == 2**j) {
          // update voteCounts for each voted option
          proposal.voteCounts[j] = proposal.voteCounts[j].add(newVotingPower).sub(oldVotingPower);
        }
      }
      // update voting power of the voter
      _proposals[proposalIds[i]].votes[voter].votingPower = safeNewVotingPower;
      emit VotingPowerChanged(
        proposalIds[i],
        voter,
        vote.optionBitMask,
        vote.votingPower,
        safeNewVotingPower
      );
    }
  }

  /**
  * @dev Transfer dao operator
  * @param newDaoOperator new dao operator
  **/
  function transferDaoOperator(address newDaoOperator) external {
    require(msg.sender == _daoOperator, 'only dao operator');
    require(newDaoOperator != address(0), 'invalid dao operator');
    _daoOperator = newDaoOperator;
    emit DaoOperatorTransferred(newDaoOperator);
  }

  /**
   * @dev Add new addresses to the list of authorized executors
   * @param executors list of new addresses to be authorized executors
   **/
  function authorizeExecutors(address[] memory executors)
    public override onlyAdmin
  {
    _authorizeExecutors(executors);
  }

  /**
   * @dev Remove addresses to the list of authorized executors
   * @param executors list of addresses to be removed as authorized executors
   **/
  function unauthorizeExecutors(address[] memory executors)
    public override onlyAdmin
  {
    _unauthorizeExecutors(executors);
  }

  /**
   * @dev Add new addresses to the list of authorized strategies
   * @param strategies list of new addresses to be authorized strategies
   **/
  function authorizeVotingPowerStrategies(address[] memory strategies)
    public override onlyAdmin
  {
    _authorizeVotingPowerStrategies(strategies);
  }

  /**
   * @dev Remove addresses to the list of authorized strategies
   * @param strategies list of addresses to be removed as authorized strategies
   **/
  function unauthorizeVotingPowerStrategies(address[] memory strategies)
    public
    override
    onlyAdmin
  {
    _unauthorizedVotingPowerStrategies(strategies);
  }

  /**
   * @dev Returns whether an address is an authorized executor
   * @param executor address to evaluate as authorized executor
   * @return true if authorized
   **/
  function isExecutorAuthorized(address executor) public override view returns (bool) {
    return _authorizedExecutors[executor];
  }

  /**
   * @dev Returns whether an address is an authorized strategy
   * @param strategy address to evaluate as authorized strategy
   * @return true if authorized
   **/
  function isVotingPowerStrategyAuthorized(address strategy) public override view returns (bool) {
    return _authorizedVotingPowerStrategies[strategy];
  }

  /**
   * @dev Getter the address of the daoOperator, that can mainly cancel proposals
   * @return The address of the daoOperator
   **/
  function getDaoOperator() external override view returns (address) {
    return _daoOperator;
  }

  /**
   * @dev Getter of the proposal count (the current number of proposals ever created)
   * @return the proposal count
   **/
  function getProposalsCount() external override view returns (uint256) {
    return _proposalsCount;
  }

  /**
   * @dev Getter of a proposal by id
   * @param proposalId id of the proposal to get
   * @return the proposal as ProposalWithoutVote memory object
   **/
  function getProposalById(uint256 proposalId)
    external
    override
    view
    returns (ProposalWithoutVote memory)
  {
    return _proposals[proposalId].proposalData;
  }

  /**
   * @dev Getter of the vote data of a proposal by id
   * including totalVotes, voteCounts and options
   * @param proposalId id of the proposal
   * @return (totalVotes, voteCounts, options)
   **/
  function getProposalVoteDataById(uint256 proposalId)
    external
    override
    view
    returns (
      uint256,
      uint256[] memory,
      string[] memory
    )
  {
    ProposalWithoutVote storage proposal = _proposals[proposalId].proposalData;
    return (proposal.totalVotes, proposal.voteCounts, proposal.options);
  }

  /**
   * @dev Getter of the Vote of a voter about a proposal
   * Note: Vote is a struct: ({uint32 bitOptionMask, uint224 votingPower})
   * @param proposalId id of the proposal
   * @param voter address of the voter
   * @return The associated Vote memory object
   **/
  function getVoteOnProposal(uint256 proposalId, address voter)
    external
    override
    view
    returns (Vote memory)
  {
    return _proposals[proposalId].votes[voter];
  }

  /**
   * @dev Get the current state of a proposal
   * @param proposalId id of the proposal
   * @return The current state if the proposal
   **/
  function getProposalState(uint256 proposalId) public override view returns (ProposalState) {
    require(proposalId < _proposalsCount, 'invalid proposal id');
    ProposalWithoutVote storage proposal = _proposals[proposalId].proposalData;
    if (proposal.canceled) {
      return ProposalState.Canceled;
    } else if (block.timestamp < proposal.startTime) {
      return ProposalState.Pending;
    } else if (block.timestamp <= proposal.endTime) {
      return ProposalState.Active;
    } else if (proposal.proposalType == ProposalType.Generic) {
      return ProposalState.Finalized;
    } else if (
      !IProposalValidator(address(proposal.executor)).isBinaryProposalPassed(
        IKyberGovernance(this),
        proposalId
      )
    ) {
      return ProposalState.Failed;
    } else if (proposal.executionTime == 0) {
      return ProposalState.Succeeded;
    } else if (proposal.executed) {
      return ProposalState.Executed;
    } else if (proposal.executor.isProposalOverGracePeriod(this, proposalId)) {
      return ProposalState.Expired;
    } else {
      return ProposalState.Queued;
    }
  }

  function _queueOrRevert(
    IExecutorWithTimelock executor,
    address target,
    uint256 value,
    string memory signature,
    bytes memory callData,
    uint256 executionTime,
    bool withDelegatecall
  ) internal {
    require(
      !executor.isActionQueued(
        keccak256(abi.encode(target, value, signature, callData, executionTime, withDelegatecall))
      ),
      'duplicated action'
    );
    executor.queueTransaction(target, value, signature, callData, executionTime, withDelegatecall);
  }

  function _submitVote(
    address voter,
    uint256 proposalId,
    uint256 optionBitMask
  ) internal {
    require(proposalId < _proposalsCount, 'invalid proposal id');
    require(getProposalState(proposalId) == ProposalState.Active, 'voting closed');
    ProposalWithoutVote storage proposal = _proposals[proposalId].proposalData;
    uint256 numOptions = proposal.options.length;
    if (proposal.proposalType == ProposalType.Binary) {
      // either Yes (1) or No (2)
      require(optionBitMask == 1 || optionBitMask == 2, 'wrong vote for binary proposal');
    } else {
      require(
        optionBitMask > 0 && optionBitMask < 2**numOptions,
        'invalid options for generic proposal'
      );
    }

    Vote memory vote = _proposals[proposalId].votes[voter];
    uint256 votingPower = proposal.strategy.handleVote(voter, proposalId, optionBitMask);
    if (vote.optionBitMask == 0) {
      // first time vote, increase the totalVotes of the proposal
      proposal.totalVotes = proposal.totalVotes.add(votingPower);
    }
    for (uint256 i = 0; i < proposal.options.length; i++) {
      bool hasVoted = (vote.optionBitMask & (2**i)) == 2**i;
      bool isVoting = (optionBitMask & (2**i)) == 2**i;
      if (hasVoted && !isVoting) {
        proposal.voteCounts[i] = proposal.voteCounts[i].sub(votingPower);
      } else if (!hasVoted && isVoting) {
        proposal.voteCounts[i] = proposal.voteCounts[i].add(votingPower);
      }
    }

    _proposals[proposalId].votes[voter] = Vote({
      optionBitMask: _safeUint32(optionBitMask),
      votingPower: _safeUint224(votingPower)
    });
    emit VoteEmitted(proposalId, voter, _safeUint32(optionBitMask), _safeUint224(votingPower));
  }

  function _authorizeExecutors(address[] memory executors) internal {
    for(uint256 i = 0; i < executors.length; i++) {
      _authorizedExecutors[executors[i]] = true;
      emit ExecutorAuthorized(executors[i]);
    }
  }

  function _unauthorizeExecutors(address[] memory executors) internal {
    for(uint256 i = 0; i < executors.length; i++) {
      _authorizedExecutors[executors[i]] = false;
      emit ExecutorUnauthorized(executors[i]);
    }
  }

  function _authorizeVotingPowerStrategies(address[] memory strategies) internal {
    for(uint256 i = 0; i < strategies.length; i++) {
      _authorizedVotingPowerStrategies[strategies[i]] = true;
      emit VotingPowerStrategyAuthorized(strategies[i]);
    }
  }

  function _unauthorizedVotingPowerStrategies(address[] memory strategies) internal {
    for(uint256 i = 0; i < strategies.length; i++) {
      _authorizedVotingPowerStrategies[strategies[i]] = false;
      emit VotingPowerStrategyUnauthorized(strategies[i]);
    }
  }

  function _safeUint224(uint256 value) internal pure returns (uint224) {
    require(value < 2**224 - 1, 'value is too big (uint224)');
    return uint224(value);
  }

  function _safeUint32(uint256 value) internal pure returns (uint32) {
    require(value < 2**32 - 1, 'value is too big (uint32)');
    return uint32(value);
  }
}

// SPDX-License-Identifier: MIT

pragma solidity ^0.7.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, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        uint256 c = a + b;
        if (c < a) return (false, 0);
        return (true, c);
    }

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

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

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

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

    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     *
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        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) {
        require(b <= a, "SafeMath: subtraction overflow");
        return a - b;
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     *
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        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, reverting 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) {
        require(b > 0, "SafeMath: division by zero");
        return a / b;
    }

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

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

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

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

// SPDX-License-Identifier: MIT
pragma solidity 0.7.6;


abstract contract PermissionAdmin {
    address public admin;
    address public pendingAdmin;

    event AdminClaimed(address newAdmin, address previousAdmin);

    event TransferAdminPending(address pendingAdmin);

    constructor(address _admin) {
        require(_admin != address(0), "admin 0");
        admin = _admin;
    }

    modifier onlyAdmin() {
        require(msg.sender == admin, "only admin");
        _;
    }

    /**
     * @dev Allows the current admin to set the pendingAdmin address.
     * @param newAdmin The address to transfer ownership to.
     */
    function transferAdmin(address newAdmin) public onlyAdmin {
        require(newAdmin != address(0), "new admin 0");
        emit TransferAdminPending(newAdmin);
        pendingAdmin = newAdmin;
    }

    /**
     * @dev Allows the current admin to set the admin in one tx. Useful initial deployment.
     * @param newAdmin The address to transfer ownership to.
     */
    function transferAdminQuickly(address newAdmin) public onlyAdmin {
        require(newAdmin != address(0), "admin 0");
        emit TransferAdminPending(newAdmin);
        emit AdminClaimed(newAdmin, admin);
        admin = newAdmin;
    }

    /**
     * @dev Allows the pendingAdmin address to finalize the change admin process.
     */
    function claimAdmin() public {
        require(pendingAdmin == msg.sender, "not pending");
        emit AdminClaimed(pendingAdmin, admin);
        admin = pendingAdmin;
        pendingAdmin = address(0);
    }
}

// SPDX-License-Identifier: agpl-3.0
pragma solidity 0.7.6;
pragma abicoder v2;

import {IExecutorWithTimelock} from './IExecutorWithTimelock.sol';
import {IVotingPowerStrategy} from './IVotingPowerStrategy.sol';

interface IKyberGovernance {
  enum ProposalState {
    Pending,
    Canceled,
    Active,
    Failed,
    Succeeded,
    Queued,
    Expired,
    Executed,
    Finalized
  }
  enum ProposalType {Generic, Binary}

  /// For Binary proposal, optionBitMask is 0/1/2
  /// For Generic proposal, optionBitMask is bitmask of voted options
  struct Vote {
    uint32 optionBitMask;
    uint224 votingPower;
  }

  struct ProposalWithoutVote {
    uint256 id;
    ProposalType proposalType;
    address creator;
    IExecutorWithTimelock executor;
    IVotingPowerStrategy strategy;
    address[] targets;
    uint256[] weiValues;
    string[] signatures;
    bytes[] calldatas;
    bool[] withDelegatecalls;
    string[] options;
    uint256[] voteCounts;
    uint256 totalVotes;
    uint256 maxVotingPower;
    uint256 startTime;
    uint256 endTime;
    uint256 executionTime;
    string link;
    bool executed;
    bool canceled;
  }

  struct Proposal {
    ProposalWithoutVote proposalData;
    mapping(address => Vote) votes;
  }

  struct BinaryProposalParams {
    address[] targets;
    uint256[] weiValues;
    string[] signatures;
    bytes[] calldatas;
    bool[] withDelegatecalls;
  }

  /**
   * @dev emitted when a new binary proposal is created
   * @param proposalId id of the binary proposal
   * @param creator address of the creator
   * @param executor ExecutorWithTimelock contract that will execute the proposal
   * @param strategy votingPowerStrategy contract to calculate voting power
   * @param targets list of contracts called by proposal's associated transactions
   * @param weiValues list of value in wei for each propoposal's associated transaction
   * @param signatures list of function signatures (can be empty) to be used
   *     when created the callData
   * @param calldatas list of calldatas: if associated signature empty,
   *     calldata ready, else calldata is arguments
   * @param withDelegatecalls boolean, true = transaction delegatecalls the taget,
   *    else calls the target
   * @param startTime timestamp when vote starts
   * @param endTime timestamp when vote ends
   * @param link URL link of the proposal
   * @param maxVotingPower max voting power for this proposal
   **/
  event BinaryProposalCreated(
    uint256 proposalId,
    address indexed creator,
    IExecutorWithTimelock indexed executor,
    IVotingPowerStrategy indexed strategy,
    address[] targets,
    uint256[] weiValues,
    string[] signatures,
    bytes[] calldatas,
    bool[] withDelegatecalls,
    uint256 startTime,
    uint256 endTime,
    string link,
    uint256 maxVotingPower
  );

  /**
   * @dev emitted when a new generic proposal is created
   * @param proposalId id of the generic proposal
   * @param creator address of the creator
   * @param executor ExecutorWithTimelock contract that will execute the proposal
   * @param strategy votingPowerStrategy contract to calculate voting power
   * @param options list of proposal vote options
   * @param startTime timestamp when vote starts
   * @param endTime timestamp when vote ends
   * @param link URL link of the proposal
   * @param maxVotingPower max voting power for this proposal
   **/
  event GenericProposalCreated(
    uint256 proposalId,
    address indexed creator,
    IExecutorWithTimelock indexed executor,
    IVotingPowerStrategy indexed strategy,
    string[] options,
    uint256 startTime,
    uint256 endTime,
    string link,
    uint256 maxVotingPower
  );

  /**
   * @dev emitted when a proposal is canceled
   * @param proposalId id of the proposal
   **/
  event ProposalCanceled(uint256 proposalId);

  /**
   * @dev emitted when a proposal is queued
   * @param proposalId id of the proposal
   * @param executionTime time when proposal underlying transactions can be executed
   * @param initiatorQueueing address of the initiator of the queuing transaction
   **/
  event ProposalQueued(
    uint256 indexed proposalId,
    uint256 executionTime,
    address indexed initiatorQueueing
  );
  /**
   * @dev emitted when a proposal is executed
   * @param proposalId id of the proposal
   * @param initiatorExecution address of the initiator of the execution transaction
   **/
  event ProposalExecuted(uint256 proposalId, address indexed initiatorExecution);
  /**
   * @dev emitted when a vote is registered
   * @param proposalId id of the proposal
   * @param voter address of the voter
   * @param voteOptions vote options selected by voter
   * @param votingPower Power of the voter/vote
   **/
  event VoteEmitted(
    uint256 indexed proposalId,
    address indexed voter,
    uint32 indexed voteOptions,
    uint224 votingPower
  );

  /**
   * @dev emitted when a vote is registered
   * @param proposalId id of the proposal
   * @param voter address of the voter
   * @param voteOptions vote options selected by voter
   * @param oldVotingPower Old power of the voter/vote
   * @param newVotingPower New power of the voter/vote
   **/
  event VotingPowerChanged(
    uint256 indexed proposalId,
    address indexed voter,
    uint32 indexed voteOptions,
    uint224 oldVotingPower,
    uint224 newVotingPower
  );

  event DaoOperatorTransferred(address indexed newDaoOperator);

  event ExecutorAuthorized(address indexed executor);

  event ExecutorUnauthorized(address indexed executor);

  event VotingPowerStrategyAuthorized(address indexed strategy);

  event VotingPowerStrategyUnauthorized(address indexed strategy);

  /**
   * @dev Function is triggered when users withdraw from staking and change voting power
   */
  function handleVotingPowerChanged(
    address staker,
    uint256 newVotingPower,
    uint256[] calldata proposalIds
  ) external;

  /**
   * @dev Creates a Binary Proposal (needs to be validated by the Proposal Validator)
   * @param executor The ExecutorWithTimelock contract that will execute the proposal
   * @param strategy voting power strategy of the proposal
   * @param executionParams data for execution, includes
   *   targets list of contracts called by proposal's associated transactions
   *   weiValues list of value in wei for each proposal's associated transaction
   *   signatures list of function signatures (can be empty)
   *        to be used when created the callData
   *   calldatas list of calldatas: if associated signature empty,
   *        calldata ready, else calldata is arguments
   *   withDelegatecalls boolean, true = transaction delegatecalls the taget,
   *        else calls the target
   * @param startTime start timestamp to allow vote
   * @param endTime end timestamp of the proposal
   * @param link link to the proposal description
   **/
  function createBinaryProposal(
    IExecutorWithTimelock executor,
    IVotingPowerStrategy strategy,
    BinaryProposalParams memory executionParams,
    uint256 startTime,
    uint256 endTime,
    string memory link
  ) external returns (uint256 proposalId);

  /**
   * @dev Creates a Generic Proposal
   * @param executor ExecutorWithTimelock contract that will execute the proposal
   * @param strategy votingPowerStrategy contract to calculate voting power
   * @param options list of proposal vote options
   * @param startTime timestamp when vote starts
   * @param endTime timestamp when vote ends
   * @param link URL link of the proposal
   **/
  function createGenericProposal(
    IExecutorWithTimelock executor,
    IVotingPowerStrategy strategy,
    string[] memory options,
    uint256 startTime,
    uint256 endTime,
    string memory link
  ) external returns (uint256 proposalId);

  /**
   * @dev Cancels a Proposal,
   * either at anytime by guardian
   * or when proposal is Pending/Active and threshold no longer reached
   * @param proposalId id of the proposal
   **/
  function cancel(uint256 proposalId) external;

  /**
   * @dev Queue the proposal (If Proposal Succeeded)
   * @param proposalId id of the proposal to queue
   **/
  function queue(uint256 proposalId) external;

  /**
   * @dev Execute the proposal (If Proposal Queued)
   * @param proposalId id of the proposal to execute
   **/
  function execute(uint256 proposalId) external payable;

  /**
   * @dev Function allowing msg.sender to vote for/against a proposal
   * @param proposalId id of the proposal
   * @param optionBitMask vote option(s) selected
   **/
  function submitVote(uint256 proposalId, uint256 optionBitMask) external;

  /**
   * @dev Function to register the vote of user that has voted offchain via signature
   * @param proposalId id of the proposal
   * @param choice the bit mask of voted options
   * @param v v part of the voter signature
   * @param r r part of the voter signature
   * @param s s part of the voter signature
   **/
  function submitVoteBySignature(
    uint256 proposalId,
    uint256 choice,
    uint8 v,
    bytes32 r,
    bytes32 s
  ) external;

  /**
   * @dev Add new addresses to the list of authorized executors
   * @param executors list of new addresses to be authorized executors
   **/
  function authorizeExecutors(address[] calldata executors) external;

  /**
   * @dev Remove addresses to the list of authorized executors
   * @param executors list of addresses to be removed as authorized executors
   **/
  function unauthorizeExecutors(address[] calldata executors) external;

  /**
   * @dev Add new addresses to the list of authorized strategies
   * @param strategies list of new addresses to be authorized strategies
   **/
  function authorizeVotingPowerStrategies(address[] calldata strategies) external;

  /**
   * @dev Remove addresses to the list of authorized strategies
   * @param strategies list of addresses to be removed as authorized strategies
   **/
  function unauthorizeVotingPowerStrategies(address[] calldata strategies) external;

  /**
   * @dev Returns whether an address is an authorized executor
   * @param executor address to evaluate as authorized executor
   * @return true if authorized
   **/
  function isExecutorAuthorized(address executor) external view returns (bool);

  /**
   * @dev Returns whether an address is an authorized strategy
   * @param strategy address to evaluate as authorized strategy
   * @return true if authorized
   **/
  function isVotingPowerStrategyAuthorized(address strategy) external view returns (bool);

  /**
   * @dev Getter the address of the guardian, that can mainly cancel proposals
   * @return The address of the guardian
   **/
  function getDaoOperator() external view returns (address);

  /**
   * @dev Getter of the proposal count (the current number of proposals ever created)
   * @return the proposal count
   **/
  function getProposalsCount() external view returns (uint256);

  /**
   * @dev Getter of a proposal by id
   * @param proposalId id of the proposal to get
   * @return the proposal as ProposalWithoutVote memory object
   **/
  function getProposalById(uint256 proposalId) external view returns (ProposalWithoutVote memory);

  /**
   * @dev Getter of the vote data of a proposal by id
   * including totalVotes, voteCounts and options
   * @param proposalId id of the proposal
   * @return (totalVotes, voteCounts, options)
   **/
  function getProposalVoteDataById(uint256 proposalId)
    external
    view
    returns (
      uint256,
      uint256[] memory,
      string[] memory
    );

  /**
   * @dev Getter of the Vote of a voter about a proposal
   * Note: Vote is a struct: ({uint32 bitOptionMask, uint224 votingPower})
   * @param proposalId id of the proposal
   * @param voter address of the voter
   * @return The associated Vote memory object
   **/
  function getVoteOnProposal(uint256 proposalId, address voter)
    external
    view
    returns (Vote memory);

  /**
   * @dev Get the current state of a proposal
   * @param proposalId id of the proposal
   * @return The current state if the proposal
   **/
  function getProposalState(uint256 proposalId) external view returns (ProposalState);
}

// SPDX-License-Identifier: agpl-3.0
pragma solidity 0.7.6;
pragma abicoder v2;

import {IKyberGovernance} from './IKyberGovernance.sol';

interface IExecutorWithTimelock {
  /**
   * @dev emitted when a new pending admin is set
   * @param newPendingAdmin address of the new pending admin
   **/
  event NewPendingAdmin(address newPendingAdmin);

  /**
   * @dev emitted when a new admin is set
   * @param newAdmin address of the new admin
   **/
  event NewAdmin(address newAdmin);

  /**
   * @dev emitted when a new delay (between queueing and execution) is set
   * @param delay new delay
   **/
  event NewDelay(uint256 delay);

  /**
   * @dev emitted when a new (trans)action is Queued.
   * @param actionHash hash of the action
   * @param target address of the targeted contract
   * @param value wei value of the transaction
   * @param signature function signature of the transaction
   * @param data function arguments of the transaction or callData if signature empty
   * @param executionTime time at which to execute the transaction
   * @param withDelegatecall boolean, true = transaction delegatecalls the target, else calls the target
   **/
  event QueuedAction(
    bytes32 actionHash,
    address indexed target,
    uint256 value,
    string signature,
    bytes data,
    uint256 executionTime,
    bool withDelegatecall
  );

  /**
   * @dev emitted when an action is Cancelled
   * @param actionHash hash of the action
   * @param target address of the targeted contract
   * @param value wei value of the transaction
   * @param signature function signature of the transaction
   * @param data function arguments of the transaction or callData if signature empty
   * @param executionTime time at which to execute the transaction
   * @param withDelegatecall boolean, true = transaction delegatecalls the target, else calls the target
   **/
  event CancelledAction(
    bytes32 actionHash,
    address indexed target,
    uint256 value,
    string signature,
    bytes data,
    uint256 executionTime,
    bool withDelegatecall
  );

  /**
   * @dev emitted when an action is Cancelled
   * @param actionHash hash of the action
   * @param target address of the targeted contract
   * @param value wei value of the transaction
   * @param signature function signature of the transaction
   * @param data function arguments of the transaction or callData if signature empty
   * @param executionTime time at which to execute the transaction
   * @param withDelegatecall boolean, true = transaction delegatecalls the target, else calls the target
   * @param resultData the actual callData used on the target
   **/
  event ExecutedAction(
    bytes32 actionHash,
    address indexed target,
    uint256 value,
    string signature,
    bytes data,
    uint256 executionTime,
    bool withDelegatecall,
    bytes resultData
  );

  /**
   * @dev Function, called by Governance, that queue a transaction, returns action hash
   * @param target smart contract target
   * @param value wei value of the transaction
   * @param signature function signature of the transaction
   * @param data function arguments of the transaction or callData if signature empty
   * @param executionTime time at which to execute the transaction
   * @param withDelegatecall boolean, true = transaction delegatecalls the target, else calls the target
   **/
  function queueTransaction(
    address target,
    uint256 value,
    string memory signature,
    bytes memory data,
    uint256 executionTime,
    bool withDelegatecall
  ) external returns (bytes32);

  /**
   * @dev Function, called by Governance, that cancels a transaction, returns the callData executed
   * @param target smart contract target
   * @param value wei value of the transaction
   * @param signature function signature of the transaction
   * @param data function arguments of the transaction or callData if signature empty
   * @param executionTime time at which to execute the transaction
   * @param withDelegatecall boolean, true = transaction delegatecalls the target, else calls the target
   **/
  function executeTransaction(
    address target,
    uint256 value,
    string memory signature,
    bytes memory data,
    uint256 executionTime,
    bool withDelegatecall
  ) external payable returns (bytes memory);

  /**
   * @dev Function, called by Governance, that cancels a transaction, returns action hash
   * @param target smart contract target
   * @param value wei value of the transaction
   * @param signature function signature of the transaction
   * @param data function arguments of the transaction or callData if signature empty
   * @param executionTime time at which to execute the transaction
   * @param withDelegatecall boolean, true = transaction delegatecalls the target, else calls the target
   **/
  function cancelTransaction(
    address target,
    uint256 value,
    string memory signature,
    bytes memory data,
    uint256 executionTime,
    bool withDelegatecall
  ) external returns (bytes32);

  /**
   * @dev Getter of the current admin address (should be governance)
   * @return The address of the current admin
   **/
  function getAdmin() external view returns (address);

  /**
   * @dev Getter of the current pending admin address
   * @return The address of the pending admin
   **/
  function getPendingAdmin() external view returns (address);

  /**
   * @dev Getter of the delay between queuing and execution
   * @return The delay in seconds
   **/
  function getDelay() external view returns (uint256);

  /**
   * @dev Returns whether an action (via actionHash) is queued
   * @param actionHash hash of the action to be checked
   * keccak256(abi.encode(target, value, signature, data, executionTime, withDelegatecall))
   * @return true if underlying action of actionHash is queued
   **/
  function isActionQueued(bytes32 actionHash) external view returns (bool);

  /**
   * @dev Checks whether a proposal is over its grace period
   * @param governance Governance contract
   * @param proposalId Id of the proposal against which to test
   * @return true of proposal is over grace period
   **/
  function isProposalOverGracePeriod(IKyberGovernance governance, uint256 proposalId)
    external
    view
    returns (bool);

  /**
   * @dev Getter of grace period constant
   * @return grace period in seconds
   **/
  function GRACE_PERIOD() external view returns (uint256);

  /**
   * @dev Getter of minimum delay constant
   * @return minimum delay in seconds
   **/
  function MINIMUM_DELAY() external view returns (uint256);

  /**
   * @dev Getter of maximum delay constant
   * @return maximum delay in seconds
   **/
  function MAXIMUM_DELAY() external view returns (uint256);
}

// SPDX-License-Identifier: agpl-3.0
pragma solidity 0.7.6;
pragma abicoder v2;

import {IWithdrawHandler} from '../staking/IWithdrawHandler.sol';

interface IVotingPowerStrategy is IWithdrawHandler {
  /**
   * @dev call by governance when create a proposal
   */
  function handleProposalCreation(
    uint256 proposalId,
    uint256 startTime,
    uint256 endTime
  ) external;

  /**
   * @dev call by governance when cancel a proposal
   */
  function handleProposalCancellation(uint256 proposalId) external;

  /**
   * @dev call by governance when submitting a vote
   * @param choice: unused param for future usage
   * @return votingPower of voter
   */
  function handleVote(
    address voter,
    uint256 proposalId,
    uint256 choice
  ) external returns (uint256 votingPower);

  /**
   * @dev get voter's voting power given timestamp
   * @dev for reading purposes and validating voting power for creating/canceling proposal in the furture
   * @dev when submitVote, should call 'handleVote' instead
   */
  function getVotingPower(address voter, uint256 timestamp)
    external
    view
    returns (uint256 votingPower);

  /**
   * @dev validate that startTime and endTime are suitable for calculating voting power
   * @dev with current version, startTime and endTime must be in the sameEpcoh
   */
  function validateProposalCreation(uint256 startTime, uint256 endTime)
    external
    view
    returns (bool);

  /**
   * @dev getMaxVotingPower at current time
   * @dev call by governance when creating a proposal
   */
  function getMaxVotingPower() external view returns (uint256);
}

// SPDX-License-Identifier: agpl-3.0
pragma solidity 0.7.6;
pragma abicoder v2;

import {IKyberGovernance} from './IKyberGovernance.sol';
import {IVotingPowerStrategy} from './IVotingPowerStrategy.sol';

interface IProposalValidator {
  /**
   * @dev Called to validate a binary proposal
   * @param strategy votingPowerStrategy contract to calculate voting power
   * @param creator address of the creator
   * @param startTime timestamp when vote starts
   * @param endTime timestamp when vote ends
   * @param daoOperator address of daoOperator
   * @return boolean, true if can be created
   **/
  function validateBinaryProposalCreation(
    IVotingPowerStrategy strategy,
    address creator,
    uint256 startTime,
    uint256 endTime,
    address daoOperator
  ) external view returns (bool);

  /**
   * @dev Called to validate a generic proposal
   * @param strategy votingPowerStrategy contract to calculate voting power
   * @param creator address of the creator
   * @param startTime timestamp when vote starts
   * @param endTime timestamp when vote ends
   * @param options list of proposal vote options
   * @param daoOperator address of daoOperator
   * @return boolean, true if can be created
   **/
  function validateGenericProposalCreation(
    IVotingPowerStrategy strategy,
    address creator,
    uint256 startTime,
    uint256 endTime,
    string[] calldata options,
    address daoOperator
  ) external view returns (bool);

  /**
   * @dev Called to validate the cancellation of a proposal
   * @param governance governance contract to fetch proposals from
   * @param proposalId Id of the generic proposal
   * @param user entity initiating the cancellation
   * @return boolean, true if can be cancelled
   **/
  function validateProposalCancellation(
    IKyberGovernance governance,
    uint256 proposalId,
    address user
  ) external view returns (bool);

  /**
   * @dev Returns whether a binary proposal passed or not
   * @param governance governance contract to fetch proposals from
   * @param proposalId Id of the proposal to set
   * @return true if proposal passed
   **/
  function isBinaryProposalPassed(IKyberGovernance governance, uint256 proposalId)
    external
    view
    returns (bool);

  /**
   * @dev Check whether a proposal has reached quorum
   * @param governance governance contract to fetch proposals from
   * @param proposalId Id of the proposal to verify
   * @return voting power needed for a proposal to pass
   **/
  function isQuorumValid(IKyberGovernance governance, uint256 proposalId)
    external
    view
    returns (bool);

  /**
   * @dev Check whether a proposal has enough extra FOR-votes than AGAINST-votes
   * @param governance governance contract to fetch proposals from
   * @param proposalId Id of the proposal to verify
   * @return true if enough For-Votes
   **/
  function isVoteDifferentialValid(IKyberGovernance governance, uint256 proposalId)
    external
    view
    returns (bool);

  /**
   * @dev Get maximum vote options for a generic proposal
   * @return the maximum no. of vote options possible for a generic proposal
   **/
  function MAX_VOTING_OPTIONS() external view returns (uint256);

  /**
   * @dev Get minimum voting duration constant value
   * @return the minimum voting duration value in seconds
   **/
  function MIN_VOTING_DURATION() external view returns (uint256);

  /**
   * @dev Get the vote differential threshold constant value
   * to compare with % of for votes/total supply - % of against votes/total supply
   * @return the vote differential threshold value (100 <=> 1%)
   **/
  function VOTE_DIFFERENTIAL() external view returns (uint256);

  /**
   * @dev Get quorum threshold constant value
   * to compare with % of for votes/total supply
   * @return the quorum threshold value (100 <=> 1%)
   **/
  function MINIMUM_QUORUM() external view returns (uint256);
}

// SPDX-License-Identifier: agpl-3.0
pragma solidity 0.7.6;
pragma abicoder v2;

function getChainId() pure returns (uint256) {
  uint256 chainId;
  assembly {
    chainId := chainid()
  }
  return chainId;
}

function isContract(address account) view returns (bool) {
  // According to EIP-1052, 0x0 is the value returned for not-yet created accounts
  // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned
  // for accounts without code, i.e. `keccak256('')`
  bytes32 codehash;
  bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
  // solhint-disable-next-line no-inline-assembly
  assembly {
    codehash := extcodehash(account)
  }
  return (codehash != accountHash && codehash != 0x0);
}

// SPDX-License-Identifier: agpl-3.0
pragma solidity 0.7.6;
pragma abicoder v2;

/**
 * @title Interface for callbacks hooks when user withdraws from staking contract
 */
interface IWithdrawHandler {
  function handleWithdrawal(address staker, uint256 reduceAmount) external;
}

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

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"address","name":"admin","type":"address"},{"internalType":"address","name":"daoOperator","type":"address"},{"internalType":"address[]","name":"executors","type":"address[]"},{"internalType":"address[]","name":"votingPowerStrategies","type":"address[]"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"previousAdmin","type":"address"}],"name":"AdminClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"proposalId","type":"uint256"},{"indexed":true,"internalType":"address","name":"creator","type":"address"},{"indexed":true,"internalType":"contract IExecutorWithTimelock","name":"executor","type":"address"},{"indexed":true,"internalType":"contract IVotingPowerStrategy","name":"strategy","type":"address"},{"indexed":false,"internalType":"address[]","name":"targets","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"weiValues","type":"uint256[]"},{"indexed":false,"internalType":"string[]","name":"signatures","type":"string[]"},{"indexed":false,"internalType":"bytes[]","name":"calldatas","type":"bytes[]"},{"indexed":false,"internalType":"bool[]","name":"withDelegatecalls","type":"bool[]"},{"indexed":false,"internalType":"uint256","name":"startTime","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"endTime","type":"uint256"},{"indexed":false,"internalType":"string","name":"link","type":"string"},{"indexed":false,"internalType":"uint256","name":"maxVotingPower","type":"uint256"}],"name":"BinaryProposalCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"newDaoOperator","type":"address"}],"name":"DaoOperatorTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"executor","type":"address"}],"name":"ExecutorAuthorized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"executor","type":"address"}],"name":"ExecutorUnauthorized","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"proposalId","type":"uint256"},{"indexed":true,"internalType":"address","name":"creator","type":"address"},{"indexed":true,"internalType":"contract IExecutorWithTimelock","name":"executor","type":"address"},{"indexed":true,"internalType":"contract IVotingPowerStrategy","name":"strategy","type":"address"},{"indexed":false,"internalType":"string[]","name":"options","type":"string[]"},{"indexed":false,"internalType":"uint256","name":"startTime","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"endTime","type":"uint256"},{"indexed":false,"internalType":"string","name":"link","type":"string"},{"indexed":false,"internalType":"uint256","name":"maxVotingPower","type":"uint256"}],"name":"GenericProposalCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"ProposalCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"proposalId","type":"uint256"},{"indexed":true,"internalType":"address","name":"initiatorExecution","type":"address"}],"name":"ProposalExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"proposalId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"executionTime","type":"uint256"},{"indexed":true,"internalType":"address","name":"initiatorQueueing","type":"address"}],"name":"ProposalQueued","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"pendingAdmin","type":"address"}],"name":"TransferAdminPending","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"proposalId","type":"uint256"},{"indexed":true,"internalType":"address","name":"voter","type":"address"},{"indexed":true,"internalType":"uint32","name":"voteOptions","type":"uint32"},{"indexed":false,"internalType":"uint224","name":"votingPower","type":"uint224"}],"name":"VoteEmitted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"proposalId","type":"uint256"},{"indexed":true,"internalType":"address","name":"voter","type":"address"},{"indexed":true,"internalType":"uint32","name":"voteOptions","type":"uint32"},{"indexed":false,"internalType":"uint224","name":"oldVotingPower","type":"uint224"},{"indexed":false,"internalType":"uint224","name":"newVotingPower","type":"uint224"}],"name":"VotingPowerChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"strategy","type":"address"}],"name":"VotingPowerStrategyAuthorized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"strategy","type":"address"}],"name":"VotingPowerStrategyUnauthorized","type":"event"},{"inputs":[],"name":"DOMAIN_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"NAME","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"VOTE_EMITTED_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"admin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"executors","type":"address[]"}],"name":"authorizeExecutors","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"strategies","type":"address[]"}],"name":"authorizeVotingPowerStrategies","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"cancel","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IExecutorWithTimelock","name":"executor","type":"address"},{"internalType":"contract IVotingPowerStrategy","name":"strategy","type":"address"},{"components":[{"internalType":"address[]","name":"targets","type":"address[]"},{"internalType":"uint256[]","name":"weiValues","type":"uint256[]"},{"internalType":"string[]","name":"signatures","type":"string[]"},{"internalType":"bytes[]","name":"calldatas","type":"bytes[]"},{"internalType":"bool[]","name":"withDelegatecalls","type":"bool[]"}],"internalType":"struct IKyberGovernance.BinaryProposalParams","name":"executionParams","type":"tuple"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"},{"internalType":"string","name":"link","type":"string"}],"name":"createBinaryProposal","outputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IExecutorWithTimelock","name":"executor","type":"address"},{"internalType":"contract IVotingPowerStrategy","name":"strategy","type":"address"},{"internalType":"string[]","name":"options","type":"string[]"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"},{"internalType":"string","name":"link","type":"string"}],"name":"createGenericProposal","outputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"execute","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"getDaoOperator","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"getProposalById","outputs":[{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"enum IKyberGovernance.ProposalType","name":"proposalType","type":"uint8"},{"internalType":"address","name":"creator","type":"address"},{"internalType":"contract IExecutorWithTimelock","name":"executor","type":"address"},{"internalType":"contract IVotingPowerStrategy","name":"strategy","type":"address"},{"internalType":"address[]","name":"targets","type":"address[]"},{"internalType":"uint256[]","name":"weiValues","type":"uint256[]"},{"internalType":"string[]","name":"signatures","type":"string[]"},{"internalType":"bytes[]","name":"calldatas","type":"bytes[]"},{"internalType":"bool[]","name":"withDelegatecalls","type":"bool[]"},{"internalType":"string[]","name":"options","type":"string[]"},{"internalType":"uint256[]","name":"voteCounts","type":"uint256[]"},{"internalType":"uint256","name":"totalVotes","type":"uint256"},{"internalType":"uint256","name":"maxVotingPower","type":"uint256"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"},{"internalType":"uint256","name":"executionTime","type":"uint256"},{"internalType":"string","name":"link","type":"string"},{"internalType":"bool","name":"executed","type":"bool"},{"internalType":"bool","name":"canceled","type":"bool"}],"internalType":"struct IKyberGovernance.ProposalWithoutVote","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"getProposalState","outputs":[{"internalType":"enum IKyberGovernance.ProposalState","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"getProposalVoteDataById","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"string[]","name":"","type":"string[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getProposalsCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"},{"internalType":"address","name":"voter","type":"address"}],"name":"getVoteOnProposal","outputs":[{"components":[{"internalType":"uint32","name":"optionBitMask","type":"uint32"},{"internalType":"uint224","name":"votingPower","type":"uint224"}],"internalType":"struct IKyberGovernance.Vote","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"voter","type":"address"},{"internalType":"uint256","name":"newVotingPower","type":"uint256"},{"internalType":"uint256[]","name":"proposalIds","type":"uint256[]"}],"name":"handleVotingPowerChanged","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"executor","type":"address"}],"name":"isExecutorAuthorized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"strategy","type":"address"}],"name":"isVotingPowerStrategyAuthorized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingAdmin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"queue","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"},{"internalType":"uint256","name":"optionBitMask","type":"uint256"}],"name":"submitVote","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"},{"internalType":"uint256","name":"optionBitMask","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"submitVoteBySignature","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newAdmin","type":"address"}],"name":"transferAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newAdmin","type":"address"}],"name":"transferAdminQuickly","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newDaoOperator","type":"address"}],"name":"transferDaoOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"executors","type":"address[]"}],"name":"unauthorizeExecutors","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"strategies","type":"address[]"}],"name":"unauthorizeVotingPowerStrategies","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60806040523480156200001157600080fd5b5060405162004ff838038062004ff883398101604081905262000034916200031b565b836001600160a01b0381166200007b576040805162461bcd60e51b8152602060048201526007602482015266061646d696e20360cc1b604482015290519081900360640190fd5b600080546001600160a01b0319166001600160a01b039283161790558316620000c15760405162461bcd60e51b8152600401620000b890620003a8565b60405180910390fd5b600280546001600160a01b0319166001600160a01b038516179055620000e782620000fc565b620000f281620001b2565b50505050620003df565b60005b8151811015620001ae576001600560008484815181106200011c57fe5b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff0219169083151502179055508181815181106200016857fe5b60200260200101516001600160a01b03167f52762435f58790076157ea2a4914a5a4d0aa0eb421588891377692f7fd3bc08260405160405180910390a2600101620000ff565b5050565b60005b8151811015620001ae57600160066000848481518110620001d257fe5b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff0219169083151502179055508181815181106200021e57fe5b60200260200101516001600160a01b03167f35a21f44f4ef215174b9bdf3d74192be42648f0e70dc6c952741a821ba98fa0960405160405180910390a2600101620001b5565b80516001600160a01b03811681146200027c57600080fd5b919050565b600082601f83011262000292578081fd5b815160206001600160401b0380831115620002a957fe5b81830260405183828201018181108482111715620002c357fe5b60405284815283810192508684018288018501891015620002e2578687fd5b8692505b858310156200030f57620002fa8162000264565b845292840192600192909201918401620002e6565b50979650505050505050565b6000806000806080858703121562000331578384fd5b6200033c8562000264565b93506200034c6020860162000264565b60408601519093506001600160401b038082111562000369578384fd5b620003778883890162000281565b935060608701519150808211156200038d578283fd5b506200039c8782880162000281565b91505092959194509250565b60208082526014908201527f696e76616c69642064616f206f70657261746f72000000000000000000000000604082015260600190565b614c0980620003ef6000396000f3fe6080604052600436106101c25760003560e01c80636f93bfb7116100f757806398e527d311610095578063ddf0b00911610064578063ddf0b00914610500578063f851a44014610520578063fbeb406b14610535578063fe0d94c114610564576101c2565b806398e527d314610489578063a02aef341461049e578063a3f4df7e146104be578063bf107270146104e0576101c2565b80637acc8678116100d15780637acc8678146103fc5780638a79cbc11461041c5780638dde84c61461043c5780639080936f1461045c576101c2565b80636f93bfb7146103a757806375829def146103c757806377f50f97146103e7576101c2565b80633656de211161016457806343b4f6e71161013e57806343b4f6e71461031a578063548b514e1461033a57806364c786d91461036757806368e3ba7014610387576101c2565b80633656de21146102a057806340e58ee5146102cd5780634185ff83146102ed576101c2565b806320606b70116101a057806320606b701461023f57806320b8a38614610254578063267822471461027657806334b18c261461028b576101c2565b806302f299db146101c757806313001cc9146101fd5780631a1caf7f1461021f575b600080fd5b3480156101d357600080fd5b506101e76101e2366004613b98565b610577565b6040516101f491906140e0565b60405180910390f35b34801561020957600080fd5b5061021d610218366004613ab6565b6108f1565b005b34801561022b57600080fd5b5061021d61023a366004613ab6565b610949565b34801561024b57600080fd5b506101e761099e565b34801561026057600080fd5b506102696109c2565b6040516101f49190614011565b34801561028257600080fd5b506102696109d1565b34801561029757600080fd5b506101e76109e0565b3480156102ac57600080fd5b506102c06102bb366004613d6a565b610a04565b6040516101f491906147d3565b3480156102d957600080fd5b5061021d6102e8366004613d6a565b610f98565b3480156102f957600080fd5b5061030d610308366004613d82565b611353565b6040516101f49190614998565b34801561032657600080fd5b5061021d610335366004613dd2565b6113b0565b34801561034657600080fd5b5061035a610355366004613a14565b61155d565b6040516101f491906140d5565b34801561037357600080fd5b5061021d610382366004613ab6565b61157b565b34801561039357600080fd5b5061021d6103a2366004613ab6565b6115d0565b3480156103b357600080fd5b5061021d6103c2366004613db1565b611625565b3480156103d357600080fd5b5061021d6103e2366004613a14565b611634565b3480156103f357600080fd5b5061021d611739565b34801561040857600080fd5b5061021d610417366004613a14565b61180b565b34801561042857600080fd5b5061021d610437366004613a14565b611958565b34801561044857600080fd5b5061035a610457366004613a14565b6119f2565b34801561046857600080fd5b5061047c610477366004613d6a565b611a10565b6040516101f491906141fa565b34801561049557600080fd5b506101e7611c38565b3480156104aa57600080fd5b506101e76104b9366004613c30565b611c3e565b3480156104ca57600080fd5b506104d3612169565b6040516101f4919061420e565b3480156104ec57600080fd5b5061021d6104fb366004613a30565b6121a2565b34801561050c57600080fd5b5061021d61051b366004613d6a565b612444565b34801561052c57600080fd5b50610269612786565b34801561054157600080fd5b50610555610550366004613d6a565b612795565b6040516101f493929190614adb565b61021d610572366004613d6a565b6128e5565b60006105828761155d565b6105a75760405162461bcd60e51b815260040161059e906143d6565b60405180910390fd5b6105b0866119f2565b6105cc5760405162461bcd60e51b815260040161059e9061462e565b506003546002546040517f97b734b00000000000000000000000000000000000000000000000000000000081526001600160a01b03808a16926397b734b092610624928b9233928b928b928e929116906004016141ad565b60206040518083038186803b15801561063c57600080fd5b505afa158015610650573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106749190613af1565b6106905760405162461bcd60e51b815260040161059e9061453d565b60008181526004602090815260409091208281556001810180547fffffffffffffffffffffff0000000000000000000000000000000000000000001633610100021790556002810180546001600160a01b03199081166001600160a01b038c811691909117909255600d8301889055600e8301879055600383018054909116918a1691909117905583519091829161073091601084019190870190613403565b50865161074690600983019060208a019061348b565b50865167ffffffffffffffff8111801561075f57600080fd5b50604051908082528060200260200182016040528015610789578160200160208202803683370190505b5080516107a091600a8401916020909101906134e4565b50876001600160a01b0316639f9c30806040518163ffffffff1660e01b815260040160206040518083038186803b1580156107da57600080fd5b505afa1580156107ee573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108129190613b0d565b600c820155600380546001019055604051639f28a85160e01b81526001600160a01b03891690639f28a851906108509086908a908a9060040161410d565b600060405180830381600087803b15801561086a57600080fd5b505af115801561087e573d6000803e3d6000fd5b50505050876001600160a01b0316896001600160a01b0316336001600160a01b03167fcc6472b2c9c107b7776c30a31c7456b2f2b6f0524c585deda5d5f7dc15839dbb868b8b8b8b89600c01546040516108dd96959493929190614a90565b60405180910390a450509695505050505050565b6000546001600160a01b0316331461093d576040805162461bcd60e51b815260206004820152600a60248201526937b7363c9030b236b4b760b11b604482015290519081900360640190fd5b61094681612b20565b50565b6000546001600160a01b03163314610995576040805162461bcd60e51b815260206004820152600a60248201526937b7363c9030b236b4b760b11b604482015290519081900360640190fd5b61094681612bce565b7f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86681565b6002546001600160a01b031690565b6001546001600160a01b031681565b7f56bf7c6a2c05f72fa60205f0f2bbae2fe95a52940f7df12cd3f85c2345a5f33081565b610a0c61351e565b6000828152600460209081526040918290208251610280810190935280548352600180820154919284019160ff1690811115610a4457fe5b6001811115610a4f57fe5b815260018201546001600160a01b03610100909104811660208084019190915260028401548216604080850191909152600385015490921660608401526004840180548351818402810184019094528084526080909401939091830182828015610ae257602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610ac4575b5050505050815260200160058201805480602002602001604051908101604052809291908181526020018280548015610b3a57602002820191906000526020600020905b815481526020019060010190808311610b26575b5050505050815260200160068201805480602002602001604051908101604052809291908181526020016000905b82821015610c135760008481526020908190208301805460408051601f6002600019610100600187161502019094169390930492830185900485028101850190915281815292830182828015610bff5780601f10610bd457610100808354040283529160200191610bff565b820191906000526020600020905b815481529060010190602001808311610be257829003601f168201915b505050505081526020019060010190610b68565b50505050815260200160078201805480602002602001604051908101604052809291908181526020016000905b82821015610ceb5760008481526020908190208301805460408051601f6002600019610100600187161502019094169390930492830185900485028101850190915281815292830182828015610cd75780601f10610cac57610100808354040283529160200191610cd7565b820191906000526020600020905b815481529060010190602001808311610cba57829003601f168201915b505050505081526020019060010190610c40565b50505050815260200160088201805480602002602001604051908101604052809291908181526020018280548015610d6257602002820191906000526020600020906000905b825461010083900a900460ff161515815260206001928301818104948501949093039092029101808411610d315790505b5050505050815260200160098201805480602002602001604051908101604052809291908181526020016000905b82821015610e3b5760008481526020908190208301805460408051601f6002600019610100600187161502019094169390930492830185900485028101850190915281815292830182828015610e275780601f10610dfc57610100808354040283529160200191610e27565b820191906000526020600020905b815481529060010190602001808311610e0a57829003601f168201915b505050505081526020019060010190610d90565b505050508152602001600a8201805480602002602001604051908101604052809291908181526020018280548015610e9257602002820191906000526020600020905b815481526020019060010190808311610e7e575b50505050508152602001600b8201548152602001600c8201548152602001600d8201548152602001600e8201548152602001600f8201548152602001601082018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610f665780601f10610f3b57610100808354040283529160200191610f66565b820191906000526020600020905b815481529060010190602001808311610f4957829003601f168201915b50505091835250506011919091015460ff8082161515602084015261010090910416151560409091015290505b919050565b6003548110610fb95760405162461bcd60e51b815260040161059e90614323565b6000610fc482611a10565b90506007816008811115610fd457fe5b14158015610fee57506001816008811115610feb57fe5b14155b80156110065750600681600881111561100357fe5b14155b801561101e5750600881600881111561101b57fe5b14155b61103a5760405162461bcd60e51b815260040161059e906146d1565b60008281526004602052604090206002546001600160a01b03163314806111055750600281015460018201546040517f2edbdb520000000000000000000000000000000000000000000000000000000081526001600160a01b0392831692632edbdb52926110b592309289926101009004169060040161415a565b60206040518083038186803b1580156110cd57600080fd5b505afa1580156110e1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111059190613af1565b6111215760405162461bcd60e51b815260040161059e90614674565b60118101805461ff0019166101001790556001808083015460ff169081111561114657fe5b141561129a5760005b60048201548110156112985760028201546004830180546001600160a01b0390921691631dc40b5191908490811061118357fe5b6000918252602090912001546005850180546001600160a01b0390921691859081106111ab57fe5b90600052602060002001548560060185815481106111c557fe5b906000526020600020018660070186815481106111de57fe5b9060005260206000200187600f01548860080188815481106111fc57fe5b90600052602060002090602091828204019190069054906101000a900460ff166040518763ffffffff1660e01b815260040161123d9695949392919061407a565b602060405180830381600087803b15801561125757600080fd5b505af115801561126b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061128f9190613b0d565b5060010161114f565b505b60038101546040517f278db7090000000000000000000000000000000000000000000000000000000081526001600160a01b039091169063278db709906112e59086906004016140e0565b600060405180830381600087803b1580156112ff57600080fd5b505af1158015611313573d6000803e3d6000fd5b505050507f789cf55be980739dad1d0699b93b58e806b51c9d96619bfa8fe0a28abaa7b30c8360405161134691906140e0565b60405180910390a1505050565b61135b6135d7565b5060008281526004602090815260408083206001600160a01b038516845260120182529182902082518084019093525463ffffffff811683526001600160e01b03640100000000909104169082015292915050565b60408051808201909152601081527f4b7962657220476f7665726e616e63650000000000000000000000000000000060209091015260007f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a8667f21d5b40092e6c9383d272bba611240515ef31f3b2ca5fb60d81839330b3cdc93611431612c7c565b3060405160200161144594939291906140e9565b604051602081830303815290604052805190602001207f56bf7c6a2c05f72fa60205f0f2bbae2fe95a52940f7df12cd3f85c2345a5f33087876040516020016114909392919061410d565b604051602081830303815290604052805190602001206040516020016114b7929190613fdb565b6040516020818303038152906040528051906020012090506000600182868686604051600081526020016040526040516114f49493929190614123565b6020604051602081039080840390855afa158015611516573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166115495760405162461bcd60e51b815260040161059e906142b5565b611554818888612c80565b50505050505050565b6001600160a01b031660009081526005602052604090205460ff1690565b6000546001600160a01b031633146115c7576040805162461bcd60e51b815260206004820152600a60248201526937b7363c9030b236b4b760b11b604482015290519081900360640190fd5b61094681613024565b6000546001600160a01b0316331461161c576040805162461bcd60e51b815260206004820152600a60248201526937b7363c9030b236b4b760b11b604482015290519081900360640190fd5b610946816130d2565b611630338383612c80565b5050565b6000546001600160a01b03163314611680576040805162461bcd60e51b815260206004820152600a60248201526937b7363c9030b236b4b760b11b604482015290519081900360640190fd5b6001600160a01b0381166116db576040805162461bcd60e51b815260206004820152600b60248201527f6e65772061646d696e2030000000000000000000000000000000000000000000604482015290519081900360640190fd5b604080516001600160a01b038316815290517f3b81caf78fa51ecbc8acb482fd7012a277b428d9b80f9d156e8a54107496cc409181900360200190a1600180546001600160a01b0319166001600160a01b0392909216919091179055565b6001546001600160a01b03163314611798576040805162461bcd60e51b815260206004820152600b60248201527f6e6f742070656e64696e67000000000000000000000000000000000000000000604482015290519081900360640190fd5b600154600054604080516001600160a01b03938416815292909116602083015280517f65da1cfc2c2e81576ad96afb24a581f8e109b7a403b35cbd3243a1c99efdb9ed9281900390910190a160018054600080546001600160a01b03199081166001600160a01b03841617909155169055565b6000546001600160a01b03163314611857576040805162461bcd60e51b815260206004820152600a60248201526937b7363c9030b236b4b760b11b604482015290519081900360640190fd5b6001600160a01b0381166118b2576040805162461bcd60e51b815260206004820152600760248201527f61646d696e203000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b604080516001600160a01b038316815290517f3b81caf78fa51ecbc8acb482fd7012a277b428d9b80f9d156e8a54107496cc409181900360200190a1600054604080516001600160a01b038085168252909216602083015280517f65da1cfc2c2e81576ad96afb24a581f8e109b7a403b35cbd3243a1c99efdb9ed9281900390910190a1600080546001600160a01b0319166001600160a01b0392909216919091179055565b6002546001600160a01b031633146119825760405162461bcd60e51b815260040161059e906144cf565b6001600160a01b0381166119a85760405162461bcd60e51b815260040161059e9061479c565b600280546001600160a01b0319166001600160a01b0383169081179091556040517fedc3bac66c523c022d3f3d92772ca8371588b8952260859eb0e750d2a763593e90600090a250565b6001600160a01b031660009081526006602052604090205460ff1690565b60006003548210611a335760405162461bcd60e51b815260040161059e90614323565b60008281526004602052604090206011810154610100900460ff1615611a5d576001915050610f93565b80600d0154421015611a73576000915050610f93565b80600e01544211611a88576002915050610f93565b600060018083015460ff1690811115611a9d57fe5b1415611aad576008915050610f93565b60028101546040517fa54d87a20000000000000000000000000000000000000000000000000000000081526001600160a01b039091169063a54d87a290611afa9030908790600401614141565b60206040518083038186803b158015611b1257600080fd5b505afa158015611b26573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b4a9190613af1565b611b58576003915050610f93565b600f810154611b6b576004915050610f93565b601181015460ff1615611b82576007915050610f93565b60028101546040517ff670a5f90000000000000000000000000000000000000000000000000000000081526001600160a01b039091169063f670a5f990611bcf9030908790600401614141565b60206040518083038186803b158015611be757600080fd5b505afa158015611bfb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c1f9190613af1565b15611c2e576006915050610f93565b6005915050610f93565b60035490565b835151600090611c605760405162461bcd60e51b815260040161059e90614221565b602085015151855151148015611c7c5750604085015151855151145b8015611c8e5750606085015151855151145b8015611ca05750608085015151855151145b611cbc5760405162461bcd60e51b815260040161059e906145d1565b611cc58761155d565b611ce15760405162461bcd60e51b815260040161059e90614391565b611cea866119f2565b611d065760405162461bcd60e51b815260040161059e9061448a565b506003546002546040517f194f91580000000000000000000000000000000000000000000000000000000081526001600160a01b03808a169263194f915892611d5b928b9233928b928b92169060040161417d565b60206040518083038186803b158015611d7357600080fd5b505afa158015611d87573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dab9190613af1565b611dc75760405162461bcd60e51b815260040161059e9061453d565b60008181526004602052604090208181556001808201805460ff1916828002179055506001810180547fffffffffffffffffffffff0000000000000000000000000000000000000000ff1633610100021790556002810180546001600160a01b0319166001600160a01b038a1617905585518051611e4f9160048401916020909101906135ee565b506020808701518051611e6892600585019201906134e4565b5060408601518051611e8491600684019160209091019061348b565b5060608601518051611ea0916007840191602090910190613643565b5060808601518051611ebc91600884019160209091019061369c565b50600d8101859055600e81018490556003810180546001600160a01b0319166001600160a01b0389161790558251611efd9060108301906020860190613403565b5060098101805460018101825560009182526020918290206040805180820190915260038082527f594553000000000000000000000000000000000000000000000000000000000091909401908152611f5b93919092019190613403565b5060098101805460018101825560009182526020918290206040805180820190915260028082527f4e4f00000000000000000000000000000000000000000000000000000000000091909401908152611fb993919092019190613403565b50600a8101805460018181018355600083815260208082209384018290558454928301909455910155604080517f9f9c308000000000000000000000000000000000000000000000000000000000815290516001600160a01b038a1692639f9c30809260048082019391829003018186803b15801561203757600080fd5b505afa15801561204b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061206f9190613b0d565b600c820155600380546001019055604051639f28a85160e01b81526001600160a01b03881690639f28a851906120ad9085908990899060040161410d565b600060405180830381600087803b1580156120c757600080fd5b505af11580156120db573d6000803e3d6000fd5b50505050866001600160a01b0316886001600160a01b0316336001600160a01b03167f69188e0b1fe29a684d099392c549be47abf36f594eff86a10860aa72892f9d51858a600001518b602001518c604001518d606001518e608001518e8e8e8d600c01546040516121569a999897969594939291906149ec565b60405180910390a4509695505050505050565b6040518060400160405280601081526020017f4b7962657220476f7665726e616e63650000000000000000000000000000000081525081565b60006121ad84613180565b905060005b8281101561243c5760026121d78585848181106121cb57fe5b90506020020135611a10565b60088111156121e257fe5b146121ec57612434565b6000600460008686858181106121fe57fe5b6020908102929092013583525081019190915260400160002060038101549091506001600160a01b031633146122465760405162461bcd60e51b815260040161059e9061441c565b60006004600087878681811061225857fe5b6020908102929092013583525081810192909252604090810160009081206001600160a01b038c168252601201835281902081518083019092525463ffffffff81168083526401000000009091046001600160e01b03169282019290925291506122c3575050612434565b600081602001516001600160e01b031690506122f6816122f08a86600b01546131ac90919063ffffffff16565b9061320d565b600b84015560005b6009840154811015612374578251600282900a90811663ffffffff16141561236c57612350826122f08b87600a01858154811061233757fe5b90600052602060002001546131ac90919063ffffffff16565b84600a01828154811061235f57fe5b6000918252602090912001555b6001016122fe565b50846004600089898881811061238657fe5b6020908102929092013583525081810192909252604090810160009081206001600160a01b038e1680835260129091019093522080546001600160e01b03939093166401000000000263ffffffff9384161790558351909116908888878181106123ec57fe5b905060200201357fd5d8d9cd5fd14f4f0db3033c674546819d762dfdeba3b638fd6da11f2af22a3e8560200151896040516124289291906149d2565b60405180910390a45050505b6001016121b2565b505050505050565b60035481106124655760405162461bcd60e51b815260040161059e90614323565b600461247082611a10565b600881111561247b57fe5b146124985760405162461bcd60e51b815260040161059e90614506565b600081815260046020526040902060018082015460ff16818111156124b957fe5b146124c057fe5b60006125548260020160009054906101000a90046001600160a01b03166001600160a01b031663cebc9a826040518163ffffffff1660e01b815260040160206040518083038186803b15801561251557600080fd5b505afa158015612529573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061254d9190613b0d565b42906131ac565b905060005b600483015481101561273d576002830154600484018054612735926001600160a01b031691908490811061258957fe5b6000918252602090912001546005860180546001600160a01b0390921691859081106125b157fe5b90600052602060002001548660060185815481106125cb57fe5b600091825260209182902001805460408051601f60026000196101006001871615020190941693909304928301859004850281018501909152818152928301828280156126595780601f1061262e57610100808354040283529160200191612659565b820191906000526020600020905b81548152906001019060200180831161263c57829003601f168201915b505050505087600701868154811061266d57fe5b600091825260209182902001805460408051601f60026000196101006001871615020190941693909304928301859004850281018501909152818152928301828280156126fb5780601f106126d0576101008083540402835291602001916126fb565b820191906000526020600020905b8154815290600101906020018083116126de57829003601f168201915b50505050508789600801888154811061271057fe5b90600052602060002090602091828204019190069054906101000a900460ff1661326a565b600101612559565b50600f8201819055604051339084907f11a0b38e70585e4b09b794bd1d9f9b1a51a802eb8ee2101eeee178d0349e73fe906127799085906140e0565b60405180910390a3505050565b6000546001600160a01b031681565b6000818152600460209081526040808320600b810154600a820180548451818702810187019095528085526060958695600986019290918491908301828280156127fe57602002820191906000526020600020905b8154815260200190600101908083116127ea575b5050505050915080805480602002602001604051908101604052809291908181526020016000905b828210156128d15760008481526020908190208301805460408051601f60026000196101006001871615020190941693909304928301859004850281018501909152818152928301828280156128bd5780601f10612892576101008083540402835291602001916128bd565b820191906000526020600020905b8154815290600101906020018083116128a057829003601f168201915b505050505081526020019060010190612826565b505050509050935093509350509193909250565b60035481106129065760405162461bcd60e51b815260040161059e90614323565b600561291182611a10565b600881111561291c57fe5b146129395760405162461bcd60e51b815260040161059e90614453565b600081815260046020526040902060018082015460ff168181111561295a57fe5b1461296157fe5b60118101805460ff1916600117905560005b6004820154811015612ada5760028201546005830180546001600160a01b0390921691638902ab659190849081106129a757fe5b90600052602060002001548460040184815481106129c157fe5b6000918252602090912001546005860180546001600160a01b0390921691869081106129e957fe5b9060005260206000200154866006018681548110612a0357fe5b90600052602060002001876007018781548110612a1c57fe5b9060005260206000200188600f0154896008018981548110612a3a57fe5b90600052602060002090602091828204019190069054906101000a900460ff166040518863ffffffff1660e01b8152600401612a7b9695949392919061407a565b6000604051808303818588803b158015612a9457600080fd5b505af1158015612aa8573d6000803e3d6000fd5b50505050506040513d6000823e601f3d908101601f19168201604052612ad19190810190613b25565b50600101612973565b50336001600160a01b03167f9c85b616f29fca57a17eafe71cf9ff82ffef41766e2cf01ea7f8f7878dd3ec2483604051612b1491906140e0565b60405180910390a25050565b60005b815181101561163057600160066000848481518110612b3e57fe5b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff021916908315150217905550818181518110612b8957fe5b60200260200101516001600160a01b03167f35a21f44f4ef215174b9bdf3d74192be42648f0e70dc6c952741a821ba98fa0960405160405180910390a2600101612b23565b60005b815181101561163057600060056000848481518110612bec57fe5b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff021916908315150217905550818181518110612c3757fe5b60200260200101516001600160a01b03167f5e8105a2af24345971359d2289f43efa80d093f4a7123561b8d63836b98724f460405160405180910390a2600101612bd1565b4690565b6003548210612ca15760405162461bcd60e51b815260040161059e90614323565b6002612cac83611a10565b6008811115612cb757fe5b14612cd45760405162461bcd60e51b815260040161059e9061459a565b6000828152600460205260409020600981015460018083015460ff1681811115612cfa57fe5b1415612d30578260011480612d0f5750826002145b612d2b5760405162461bcd60e51b815260040161059e9061435a565b612d5e565b600083118015612d4257508060020a83105b612d5e5760405162461bcd60e51b815260040161059e90614708565b60008481526004602081815260408084206001600160a01b038a811686526012909101835281852082518084018452905463ffffffff8116825264010000000090046001600160e01b031693810193909352600387015491517f21a6d2600000000000000000000000000000000000000000000000000000000081529294939116916321a6d26091612df6918b918b918b91016140b4565b602060405180830381600087803b158015612e1057600080fd5b505af1158015612e24573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e489190613b0d565b825190915063ffffffff16612e6c57600b840154612e6690826131ac565b600b8501555b60005b6009850154811015612f37578251600282900a90811663ffffffff1681149087811614818015612e9d575080155b15612eee57612ece8488600a018581548110612eb557fe5b906000526020600020015461320d90919063ffffffff16565b87600a018481548110612edd57fe5b600091825260209091200155612f2d565b81158015612ef95750805b15612f2d57612f118488600a01858154811061233757fe5b87600a018481548110612f2057fe5b6000918252602090912001555b5050600101612e6f565b506040518060400160405280612f4c876133de565b63ffffffff168152602001612f6083613180565b6001600160e01b0390811690915260008881526004602090815260408083206001600160a01b038d16845260120182529091208351815494909201519092166401000000000263ffffffff91821663ffffffff199094169390931716919091179055612fcb856133de565b63ffffffff16876001600160a01b0316877f612a68349ed2a41418dc9795d6525cab0c1f41d11b97b3dff2dc55695dfbdec261300685613180565b60405161301391906149be565b60405180910390a450505050505050565b60005b81518110156116305760016005600084848151811061304257fe5b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555081818151811061308d57fe5b60200260200101516001600160a01b03167f52762435f58790076157ea2a4914a5a4d0aa0eb421588891377692f7fd3bc08260405160405180910390a2600101613027565b60005b8151811015611630576000600660008484815181106130f057fe5b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555081818151811061313b57fe5b60200260200101516001600160a01b03167f42eb712815cbb2bbe9607880d05fc79635cf9712f706f41e8c20f02a7f64194160405160405180910390a26001016130d5565b60006001600160e01b0382106131a85760405162461bcd60e51b815260040161059e9061427e565b5090565b600082820183811015613206576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b600082821115613264576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b866001600160a01b031663b1fc879687878787878760405160200161329496959493929190614025565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b81526004016132c691906140e0565b60206040518083038186803b1580156132de57600080fd5b505afa1580156132f2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133169190613af1565b156133335760405162461bcd60e51b815260040161059e90614765565b6040517f8d8fe2e30000000000000000000000000000000000000000000000000000000081526001600160a01b03881690638d8fe2e39061338290899089908990899089908990600401614025565b602060405180830381600087803b15801561339c57600080fd5b505af11580156133b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133d49190613b0d565b5050505050505050565b600063ffffffff82106131a85760405162461bcd60e51b815260040161059e906142ec565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282613439576000855561347f565b82601f1061345257805160ff191683800117855561347f565b8280016001018555821561347f579182015b8281111561347f578251825591602001919060010190613464565b506131a8929150613738565b8280548282559060005260206000209081019282156134d8579160200282015b828111156134d857825180516134c8918491602090910190613403565b50916020019190600101906134ab565b506131a892915061374d565b82805482825590600052602060002090810192821561347f579160200282018281111561347f578251825591602001919060010190613464565b60408051610280810190915260008082526020820190815260200160006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b03168152602001606081526020016060815260200160608152602001606081526020016060815260200160608152602001606081526020016000815260200160008152602001600081526020016000815260200160008152602001606081526020016000151581526020016000151581525090565b604080518082019091526000808252602082015290565b82805482825590600052602060002090810192821561347f579160200282015b8281111561347f57825182546001600160a01b0319166001600160a01b0390911617825560209092019160019091019061360e565b828054828255906000526020600020908101928215613690579160200282015b828111156136905782518051613680918491602090910190613403565b5091602001919060010190613663565b506131a892915061376a565b82805482825590600052602060002090601f0160209004810192821561347f5791602002820160005b8382111561370257835183826101000a81548160ff02191690831515021790555092602001926001016020816000010492830192600103026136c5565b801561372f5782816101000a81549060ff0219169055600101602081600001049283019260010302613702565b50506131a89291505b5b808211156131a85760008155600101613739565b808211156131a85760006137618282613787565b5060010161374d565b808211156131a857600061377e8282613787565b5060010161376a565b50805460018160011615610100020316600290046000825580601f106137ad5750610946565b601f0160209004906000526020600020908101906109469190613738565b60006137de6137d984614b52565b614b10565b90508281528383830111156137f257600080fd5b828260208301376000602084830101529392505050565b600082601f830112613819578081fd5b813560206138296137d983614b34565b8281528181019085830183850287018401881015613845578586fd5b855b8581101561386c57813561385a81614bb0565b84529284019290840190600101613847565b5090979650505050505050565b600082601f830112613889578081fd5b813560206138996137d983614b34565b82815281810190858301838502870184018810156138b5578586fd5b855b8581101561386c5781356138ca81614bc5565b845292840192908401906001016138b7565b600082601f8301126138ec578081fd5b813560206138fc6137d983614b34565b82815281810190858301855b8581101561386c578135880189603f820112613922578788fd5b6139338a87830135604084016137cb565b8552509284019290840190600101613908565b600082601f830112613956578081fd5b813560206139666137d983614b34565b82815281810190858301855b8581101561386c57613989898684358b01016139f5565b84529284019290840190600101613972565b600082601f8301126139ab578081fd5b813560206139bb6137d983614b34565b82815281810190858301838502870184018810156139d7578586fd5b855b8581101561386c578135845292840192908401906001016139d9565b600082601f830112613a05578081fd5b613206838335602085016137cb565b600060208284031215613a25578081fd5b813561320681614bb0565b60008060008060608587031215613a45578283fd5b8435613a5081614bb0565b935060208501359250604085013567ffffffffffffffff80821115613a73578384fd5b818701915087601f830112613a86578384fd5b813581811115613a94578485fd5b8860208083028501011115613aa7578485fd5b95989497505060200194505050565b600060208284031215613ac7578081fd5b813567ffffffffffffffff811115613add578182fd5b613ae984828501613809565b949350505050565b600060208284031215613b02578081fd5b815161320681614bc5565b600060208284031215613b1e578081fd5b5051919050565b600060208284031215613b36578081fd5b815167ffffffffffffffff811115613b4c578182fd5b8201601f81018413613b5c578182fd5b8051613b6a6137d982614b52565b818152856020838501011115613b7e578384fd5b613b8f826020830160208601614b80565b95945050505050565b60008060008060008060c08789031215613bb0578384fd5b8635613bbb81614bb0565b95506020870135613bcb81614bb0565b9450604087013567ffffffffffffffff80821115613be7578586fd5b613bf38a838b01613946565b9550606089013594506080890135935060a0890135915080821115613c16578283fd5b50613c2389828a016139f5565b9150509295509295509295565b60008060008060008060c08789031215613c48578384fd5b8635613c5381614bb0565b95506020870135613c6381614bb0565b9450604087013567ffffffffffffffff80821115613c7f578586fd5b9088019060a0828b031215613c92578586fd5b613c9c60a0614b10565b823582811115613caa578788fd5b613cb68c828601613809565b825250602083013582811115613cca578788fd5b613cd68c82860161399b565b602083015250604083013582811115613ced578788fd5b613cf98c828601613946565b604083015250606083013582811115613d10578788fd5b613d1c8c8286016138dc565b606083015250608083013582811115613d33578788fd5b613d3f8c828601613879565b60808301525080965050606089013594506080890135935060a0890135915080821115613c16578283fd5b600060208284031215613d7b578081fd5b5035919050565b60008060408385031215613d94578182fd5b823591506020830135613da681614bb0565b809150509250929050565b60008060408385031215613dc3578182fd5b50508035926020909101359150565b600080600080600060a08688031215613de9578283fd5b8535945060208601359350604086013560ff81168114613e07578384fd5b94979396509394606081013594506080013592915050565b6001600160a01b03169052565b6000815180845260208085019450808401835b83811015613e645781516001600160a01b031687529582019590820190600101613e3f565b509495945050505050565b6000815180845260208085019450808401835b83811015613e64578151151587529582019590820190600101613e82565b60008282518085526020808601955080818302840101818601855b8481101561386c57601f19868403018952613ed7838351613f1e565b98840198925090830190600101613ebb565b6000815180845260208085019450808401835b83811015613e6457815187529582019590820190600101613efc565b15159052565b60008151808452613f36816020860160208601614b80565b601f01601f19169290920160200192915050565b60008154600180821660008114613f685760018114613f8657613fc4565b60028304607f16865260ff1983166020870152604086019350613fc4565b60028304808752613f9686614b74565b60005b82811015613fba5781546020828b0101528482019150602081019050613f99565b8801602001955050505b50505092915050565b60028110613fd757fe5b9052565b7f190100000000000000000000000000000000000000000000000000000000000081526002810192909252602282015260420190565b6001600160a01b0391909116815260200190565b60006001600160a01b038816825286602083015260c0604083015261404d60c0830187613f1e565b828103606084015261405f8187613f1e565b6080840195909552505090151560a090910152949350505050565b60006001600160a01b038816825286602083015260c060408301526140a260c0830187613f4a565b828103606084015261405f8187613f4a565b6001600160a01b039390931683526020830191909152604082015260600190565b901515815260200190565b90815260200190565b938452602084019290925260408301526001600160a01b0316606082015260800190565b9283526020830191909152604082015260600190565b93845260ff9290921660208401526040830152606082015260800190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b0393841681526020810192909252909116604082015260600190565b6001600160a01b039586168152938516602085015260408401929092526060830152909116608082015260a00190565b60006001600160a01b038089168352808816602084015286604084015285606084015260c060808401526141e460c0840186613ea0565b915080841660a084015250979650505050505050565b602081016009831061420857fe5b91905290565b6000602082526132066020830184613f1e565b60208082526023908201527f6372656174652062696e61727920696e76616c696420656d707479207461726760408201527f6574730000000000000000000000000000000000000000000000000000000000606082015260800190565b6020808252601a908201527f76616c756520697320746f6f20626967202875696e7432323429000000000000604082015260600190565b60208082526011908201527f696e76616c6964207369676e6174757265000000000000000000000000000000604082015260600190565b60208082526019908201527f76616c756520697320746f6f20626967202875696e7433322900000000000000604082015260600190565b60208082526013908201527f696e76616c69642070726f706f73616c20696400000000000000000000000000604082015260600190565b6020808252601e908201527f77726f6e6720766f746520666f722062696e6172792070726f706f73616c0000604082015260600190565b60208082526025908201527f6372656174652062696e617279206578656375746f72206e6f7420617574686f6040820152641c9a5e995960da1b606082015260800190565b60208082526026908201527f6372656174652067656e65726963206578656375746f72206e6f7420617574686040820152651bdc9a5e995960d21b606082015260800190565b6020808252601d908201527f696e76616c696420766f74696e6720706f776572207374726174656779000000604082015260600190565b60208082526015908201527f6f6e6c79207175657565642070726f706f73616c730000000000000000000000604082015260600190565b60208082526025908201527f6372656174652062696e617279207374726174656779206e6f7420617574686f6040820152641c9a5e995960da1b606082015260800190565b60208082526011908201527f6f6e6c792064616f206f70657261746f72000000000000000000000000000000604082015260600190565b60208082526016908201527f696e76616c696420737461746520746f20717565756500000000000000000000604082015260600190565b60208082526022908201527f76616c69646174652070726f706f73616c206372656174696f6e20696e76616c60408201527f6964000000000000000000000000000000000000000000000000000000000000606082015260800190565b6020808252600d908201527f766f74696e6720636c6f73656400000000000000000000000000000000000000604082015260600190565b60208082526028908201527f6372656174652062696e61727920696e636f6e73697374656e7420706172616d60408201527f73206c656e677468000000000000000000000000000000000000000000000000606082015260800190565b60208082526026908201527f6372656174652067656e65726963207374726174656779206e6f7420617574686040820152651bdc9a5e995960d21b606082015260800190565b60208082526025908201527f76616c69646174652070726f706f73616c2063616e63656c6c6174696f6e206660408201527f61696c6564000000000000000000000000000000000000000000000000000000606082015260800190565b60208082526017908201527f696e76616c696420737461746520746f2063616e63656c000000000000000000604082015260600190565b60208082526024908201527f696e76616c6964206f7074696f6e7320666f722067656e657269632070726f7060408201527f6f73616c00000000000000000000000000000000000000000000000000000000606082015260800190565b60208082526011908201527f6475706c69636174656420616374696f6e000000000000000000000000000000604082015260600190565b60208082526014908201527f696e76616c69642064616f206f70657261746f72000000000000000000000000604082015260600190565b6000602082528251602083015260208301516147f26040840182613fcd565b5060408301516148056060840182613e1f565b5060608301516148186080840182613e1f565b50608083015161482b60a0840182613e1f565b5060a08301516102808060c08501526148486102a0850183613e2c565b915060c0850151601f19808685030160e08701526148668483613ee9565b935060e087015191506101008187860301818801526148858584613ea0565b9450808801519250506101208187860301818801526148a48584613ea0565b9450808801519250506101408187860301818801526148c38584613e6f565b9450808801519250506101608187860301818801526148e28584613ea0565b9450808801519250506101808187860301818801526149018584613ee9565b908801516101a0888101919091528801516101c0808901919091528801516101e08089019190915288015161020080890191909152880151610220808901919091528801518782038301610240808a019190915291955092506149648584613f1e565b9450808801519250505061026061497d81870183613f18565b860151905061498e85830182613f18565b5090949350505050565b815163ffffffff1681526020918201516001600160e01b03169181019190915260400190565b6001600160e01b0391909116815260200190565b6001600160e01b0392831681529116602082015260400190565b60006101408c8352806020840152614a068184018d613e2c565b90508281036040840152614a1a818c613ee9565b90508281036060840152614a2e818b613ea0565b90508281036080840152614a42818a613ea0565b905082810360a0840152614a568189613e6f565b90508660c08401528560e0840152828103610100840152614a778186613f1e565b915050826101208301529b9a5050505050505050505050565b600087825260c06020830152614aa960c0830188613ea0565b8660408401528560608401528281036080840152614ac78186613f1e565b9150508260a0830152979650505050505050565b600084825260606020830152614af46060830185613ee9565b8281036040840152614b068185613ea0565b9695505050505050565b60405181810167ffffffffffffffff81118282101715614b2c57fe5b604052919050565b600067ffffffffffffffff821115614b4857fe5b5060209081020190565b600067ffffffffffffffff821115614b6657fe5b50601f01601f191660200190565b60009081526020902090565b60005b83811015614b9b578181015183820152602001614b83565b83811115614baa576000848401525b50505050565b6001600160a01b038116811461094657600080fd5b801515811461094657600080fdfea26469706673582212202797f380f95f7d6c1930f14f37b038e1d1f1f4e6a32e0c8d98e99fd9a648ef2864736f6c63430007060033000000000000000000000000560fb65513a3e9f22df97501393360bf0db448ad000000000000000000000000e6a7338cba0a1070adfb22c07115299605454713000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

Deployed Bytecode

0x6080604052600436106101c25760003560e01c80636f93bfb7116100f757806398e527d311610095578063ddf0b00911610064578063ddf0b00914610500578063f851a44014610520578063fbeb406b14610535578063fe0d94c114610564576101c2565b806398e527d314610489578063a02aef341461049e578063a3f4df7e146104be578063bf107270146104e0576101c2565b80637acc8678116100d15780637acc8678146103fc5780638a79cbc11461041c5780638dde84c61461043c5780639080936f1461045c576101c2565b80636f93bfb7146103a757806375829def146103c757806377f50f97146103e7576101c2565b80633656de211161016457806343b4f6e71161013e57806343b4f6e71461031a578063548b514e1461033a57806364c786d91461036757806368e3ba7014610387576101c2565b80633656de21146102a057806340e58ee5146102cd5780634185ff83146102ed576101c2565b806320606b70116101a057806320606b701461023f57806320b8a38614610254578063267822471461027657806334b18c261461028b576101c2565b806302f299db146101c757806313001cc9146101fd5780631a1caf7f1461021f575b600080fd5b3480156101d357600080fd5b506101e76101e2366004613b98565b610577565b6040516101f491906140e0565b60405180910390f35b34801561020957600080fd5b5061021d610218366004613ab6565b6108f1565b005b34801561022b57600080fd5b5061021d61023a366004613ab6565b610949565b34801561024b57600080fd5b506101e761099e565b34801561026057600080fd5b506102696109c2565b6040516101f49190614011565b34801561028257600080fd5b506102696109d1565b34801561029757600080fd5b506101e76109e0565b3480156102ac57600080fd5b506102c06102bb366004613d6a565b610a04565b6040516101f491906147d3565b3480156102d957600080fd5b5061021d6102e8366004613d6a565b610f98565b3480156102f957600080fd5b5061030d610308366004613d82565b611353565b6040516101f49190614998565b34801561032657600080fd5b5061021d610335366004613dd2565b6113b0565b34801561034657600080fd5b5061035a610355366004613a14565b61155d565b6040516101f491906140d5565b34801561037357600080fd5b5061021d610382366004613ab6565b61157b565b34801561039357600080fd5b5061021d6103a2366004613ab6565b6115d0565b3480156103b357600080fd5b5061021d6103c2366004613db1565b611625565b3480156103d357600080fd5b5061021d6103e2366004613a14565b611634565b3480156103f357600080fd5b5061021d611739565b34801561040857600080fd5b5061021d610417366004613a14565b61180b565b34801561042857600080fd5b5061021d610437366004613a14565b611958565b34801561044857600080fd5b5061035a610457366004613a14565b6119f2565b34801561046857600080fd5b5061047c610477366004613d6a565b611a10565b6040516101f491906141fa565b34801561049557600080fd5b506101e7611c38565b3480156104aa57600080fd5b506101e76104b9366004613c30565b611c3e565b3480156104ca57600080fd5b506104d3612169565b6040516101f4919061420e565b3480156104ec57600080fd5b5061021d6104fb366004613a30565b6121a2565b34801561050c57600080fd5b5061021d61051b366004613d6a565b612444565b34801561052c57600080fd5b50610269612786565b34801561054157600080fd5b50610555610550366004613d6a565b612795565b6040516101f493929190614adb565b61021d610572366004613d6a565b6128e5565b60006105828761155d565b6105a75760405162461bcd60e51b815260040161059e906143d6565b60405180910390fd5b6105b0866119f2565b6105cc5760405162461bcd60e51b815260040161059e9061462e565b506003546002546040517f97b734b00000000000000000000000000000000000000000000000000000000081526001600160a01b03808a16926397b734b092610624928b9233928b928b928e929116906004016141ad565b60206040518083038186803b15801561063c57600080fd5b505afa158015610650573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106749190613af1565b6106905760405162461bcd60e51b815260040161059e9061453d565b60008181526004602090815260409091208281556001810180547fffffffffffffffffffffff0000000000000000000000000000000000000000001633610100021790556002810180546001600160a01b03199081166001600160a01b038c811691909117909255600d8301889055600e8301879055600383018054909116918a1691909117905583519091829161073091601084019190870190613403565b50865161074690600983019060208a019061348b565b50865167ffffffffffffffff8111801561075f57600080fd5b50604051908082528060200260200182016040528015610789578160200160208202803683370190505b5080516107a091600a8401916020909101906134e4565b50876001600160a01b0316639f9c30806040518163ffffffff1660e01b815260040160206040518083038186803b1580156107da57600080fd5b505afa1580156107ee573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108129190613b0d565b600c820155600380546001019055604051639f28a85160e01b81526001600160a01b03891690639f28a851906108509086908a908a9060040161410d565b600060405180830381600087803b15801561086a57600080fd5b505af115801561087e573d6000803e3d6000fd5b50505050876001600160a01b0316896001600160a01b0316336001600160a01b03167fcc6472b2c9c107b7776c30a31c7456b2f2b6f0524c585deda5d5f7dc15839dbb868b8b8b8b89600c01546040516108dd96959493929190614a90565b60405180910390a450509695505050505050565b6000546001600160a01b0316331461093d576040805162461bcd60e51b815260206004820152600a60248201526937b7363c9030b236b4b760b11b604482015290519081900360640190fd5b61094681612b20565b50565b6000546001600160a01b03163314610995576040805162461bcd60e51b815260206004820152600a60248201526937b7363c9030b236b4b760b11b604482015290519081900360640190fd5b61094681612bce565b7f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86681565b6002546001600160a01b031690565b6001546001600160a01b031681565b7f56bf7c6a2c05f72fa60205f0f2bbae2fe95a52940f7df12cd3f85c2345a5f33081565b610a0c61351e565b6000828152600460209081526040918290208251610280810190935280548352600180820154919284019160ff1690811115610a4457fe5b6001811115610a4f57fe5b815260018201546001600160a01b03610100909104811660208084019190915260028401548216604080850191909152600385015490921660608401526004840180548351818402810184019094528084526080909401939091830182828015610ae257602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610ac4575b5050505050815260200160058201805480602002602001604051908101604052809291908181526020018280548015610b3a57602002820191906000526020600020905b815481526020019060010190808311610b26575b5050505050815260200160068201805480602002602001604051908101604052809291908181526020016000905b82821015610c135760008481526020908190208301805460408051601f6002600019610100600187161502019094169390930492830185900485028101850190915281815292830182828015610bff5780601f10610bd457610100808354040283529160200191610bff565b820191906000526020600020905b815481529060010190602001808311610be257829003601f168201915b505050505081526020019060010190610b68565b50505050815260200160078201805480602002602001604051908101604052809291908181526020016000905b82821015610ceb5760008481526020908190208301805460408051601f6002600019610100600187161502019094169390930492830185900485028101850190915281815292830182828015610cd75780601f10610cac57610100808354040283529160200191610cd7565b820191906000526020600020905b815481529060010190602001808311610cba57829003601f168201915b505050505081526020019060010190610c40565b50505050815260200160088201805480602002602001604051908101604052809291908181526020018280548015610d6257602002820191906000526020600020906000905b825461010083900a900460ff161515815260206001928301818104948501949093039092029101808411610d315790505b5050505050815260200160098201805480602002602001604051908101604052809291908181526020016000905b82821015610e3b5760008481526020908190208301805460408051601f6002600019610100600187161502019094169390930492830185900485028101850190915281815292830182828015610e275780601f10610dfc57610100808354040283529160200191610e27565b820191906000526020600020905b815481529060010190602001808311610e0a57829003601f168201915b505050505081526020019060010190610d90565b505050508152602001600a8201805480602002602001604051908101604052809291908181526020018280548015610e9257602002820191906000526020600020905b815481526020019060010190808311610e7e575b50505050508152602001600b8201548152602001600c8201548152602001600d8201548152602001600e8201548152602001600f8201548152602001601082018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610f665780601f10610f3b57610100808354040283529160200191610f66565b820191906000526020600020905b815481529060010190602001808311610f4957829003601f168201915b50505091835250506011919091015460ff8082161515602084015261010090910416151560409091015290505b919050565b6003548110610fb95760405162461bcd60e51b815260040161059e90614323565b6000610fc482611a10565b90506007816008811115610fd457fe5b14158015610fee57506001816008811115610feb57fe5b14155b80156110065750600681600881111561100357fe5b14155b801561101e5750600881600881111561101b57fe5b14155b61103a5760405162461bcd60e51b815260040161059e906146d1565b60008281526004602052604090206002546001600160a01b03163314806111055750600281015460018201546040517f2edbdb520000000000000000000000000000000000000000000000000000000081526001600160a01b0392831692632edbdb52926110b592309289926101009004169060040161415a565b60206040518083038186803b1580156110cd57600080fd5b505afa1580156110e1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111059190613af1565b6111215760405162461bcd60e51b815260040161059e90614674565b60118101805461ff0019166101001790556001808083015460ff169081111561114657fe5b141561129a5760005b60048201548110156112985760028201546004830180546001600160a01b0390921691631dc40b5191908490811061118357fe5b6000918252602090912001546005850180546001600160a01b0390921691859081106111ab57fe5b90600052602060002001548560060185815481106111c557fe5b906000526020600020018660070186815481106111de57fe5b9060005260206000200187600f01548860080188815481106111fc57fe5b90600052602060002090602091828204019190069054906101000a900460ff166040518763ffffffff1660e01b815260040161123d9695949392919061407a565b602060405180830381600087803b15801561125757600080fd5b505af115801561126b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061128f9190613b0d565b5060010161114f565b505b60038101546040517f278db7090000000000000000000000000000000000000000000000000000000081526001600160a01b039091169063278db709906112e59086906004016140e0565b600060405180830381600087803b1580156112ff57600080fd5b505af1158015611313573d6000803e3d6000fd5b505050507f789cf55be980739dad1d0699b93b58e806b51c9d96619bfa8fe0a28abaa7b30c8360405161134691906140e0565b60405180910390a1505050565b61135b6135d7565b5060008281526004602090815260408083206001600160a01b038516845260120182529182902082518084019093525463ffffffff811683526001600160e01b03640100000000909104169082015292915050565b60408051808201909152601081527f4b7962657220476f7665726e616e63650000000000000000000000000000000060209091015260007f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a8667f21d5b40092e6c9383d272bba611240515ef31f3b2ca5fb60d81839330b3cdc93611431612c7c565b3060405160200161144594939291906140e9565b604051602081830303815290604052805190602001207f56bf7c6a2c05f72fa60205f0f2bbae2fe95a52940f7df12cd3f85c2345a5f33087876040516020016114909392919061410d565b604051602081830303815290604052805190602001206040516020016114b7929190613fdb565b6040516020818303038152906040528051906020012090506000600182868686604051600081526020016040526040516114f49493929190614123565b6020604051602081039080840390855afa158015611516573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166115495760405162461bcd60e51b815260040161059e906142b5565b611554818888612c80565b50505050505050565b6001600160a01b031660009081526005602052604090205460ff1690565b6000546001600160a01b031633146115c7576040805162461bcd60e51b815260206004820152600a60248201526937b7363c9030b236b4b760b11b604482015290519081900360640190fd5b61094681613024565b6000546001600160a01b0316331461161c576040805162461bcd60e51b815260206004820152600a60248201526937b7363c9030b236b4b760b11b604482015290519081900360640190fd5b610946816130d2565b611630338383612c80565b5050565b6000546001600160a01b03163314611680576040805162461bcd60e51b815260206004820152600a60248201526937b7363c9030b236b4b760b11b604482015290519081900360640190fd5b6001600160a01b0381166116db576040805162461bcd60e51b815260206004820152600b60248201527f6e65772061646d696e2030000000000000000000000000000000000000000000604482015290519081900360640190fd5b604080516001600160a01b038316815290517f3b81caf78fa51ecbc8acb482fd7012a277b428d9b80f9d156e8a54107496cc409181900360200190a1600180546001600160a01b0319166001600160a01b0392909216919091179055565b6001546001600160a01b03163314611798576040805162461bcd60e51b815260206004820152600b60248201527f6e6f742070656e64696e67000000000000000000000000000000000000000000604482015290519081900360640190fd5b600154600054604080516001600160a01b03938416815292909116602083015280517f65da1cfc2c2e81576ad96afb24a581f8e109b7a403b35cbd3243a1c99efdb9ed9281900390910190a160018054600080546001600160a01b03199081166001600160a01b03841617909155169055565b6000546001600160a01b03163314611857576040805162461bcd60e51b815260206004820152600a60248201526937b7363c9030b236b4b760b11b604482015290519081900360640190fd5b6001600160a01b0381166118b2576040805162461bcd60e51b815260206004820152600760248201527f61646d696e203000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b604080516001600160a01b038316815290517f3b81caf78fa51ecbc8acb482fd7012a277b428d9b80f9d156e8a54107496cc409181900360200190a1600054604080516001600160a01b038085168252909216602083015280517f65da1cfc2c2e81576ad96afb24a581f8e109b7a403b35cbd3243a1c99efdb9ed9281900390910190a1600080546001600160a01b0319166001600160a01b0392909216919091179055565b6002546001600160a01b031633146119825760405162461bcd60e51b815260040161059e906144cf565b6001600160a01b0381166119a85760405162461bcd60e51b815260040161059e9061479c565b600280546001600160a01b0319166001600160a01b0383169081179091556040517fedc3bac66c523c022d3f3d92772ca8371588b8952260859eb0e750d2a763593e90600090a250565b6001600160a01b031660009081526006602052604090205460ff1690565b60006003548210611a335760405162461bcd60e51b815260040161059e90614323565b60008281526004602052604090206011810154610100900460ff1615611a5d576001915050610f93565b80600d0154421015611a73576000915050610f93565b80600e01544211611a88576002915050610f93565b600060018083015460ff1690811115611a9d57fe5b1415611aad576008915050610f93565b60028101546040517fa54d87a20000000000000000000000000000000000000000000000000000000081526001600160a01b039091169063a54d87a290611afa9030908790600401614141565b60206040518083038186803b158015611b1257600080fd5b505afa158015611b26573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b4a9190613af1565b611b58576003915050610f93565b600f810154611b6b576004915050610f93565b601181015460ff1615611b82576007915050610f93565b60028101546040517ff670a5f90000000000000000000000000000000000000000000000000000000081526001600160a01b039091169063f670a5f990611bcf9030908790600401614141565b60206040518083038186803b158015611be757600080fd5b505afa158015611bfb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c1f9190613af1565b15611c2e576006915050610f93565b6005915050610f93565b60035490565b835151600090611c605760405162461bcd60e51b815260040161059e90614221565b602085015151855151148015611c7c5750604085015151855151145b8015611c8e5750606085015151855151145b8015611ca05750608085015151855151145b611cbc5760405162461bcd60e51b815260040161059e906145d1565b611cc58761155d565b611ce15760405162461bcd60e51b815260040161059e90614391565b611cea866119f2565b611d065760405162461bcd60e51b815260040161059e9061448a565b506003546002546040517f194f91580000000000000000000000000000000000000000000000000000000081526001600160a01b03808a169263194f915892611d5b928b9233928b928b92169060040161417d565b60206040518083038186803b158015611d7357600080fd5b505afa158015611d87573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dab9190613af1565b611dc75760405162461bcd60e51b815260040161059e9061453d565b60008181526004602052604090208181556001808201805460ff1916828002179055506001810180547fffffffffffffffffffffff0000000000000000000000000000000000000000ff1633610100021790556002810180546001600160a01b0319166001600160a01b038a1617905585518051611e4f9160048401916020909101906135ee565b506020808701518051611e6892600585019201906134e4565b5060408601518051611e8491600684019160209091019061348b565b5060608601518051611ea0916007840191602090910190613643565b5060808601518051611ebc91600884019160209091019061369c565b50600d8101859055600e81018490556003810180546001600160a01b0319166001600160a01b0389161790558251611efd9060108301906020860190613403565b5060098101805460018101825560009182526020918290206040805180820190915260038082527f594553000000000000000000000000000000000000000000000000000000000091909401908152611f5b93919092019190613403565b5060098101805460018101825560009182526020918290206040805180820190915260028082527f4e4f00000000000000000000000000000000000000000000000000000000000091909401908152611fb993919092019190613403565b50600a8101805460018181018355600083815260208082209384018290558454928301909455910155604080517f9f9c308000000000000000000000000000000000000000000000000000000000815290516001600160a01b038a1692639f9c30809260048082019391829003018186803b15801561203757600080fd5b505afa15801561204b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061206f9190613b0d565b600c820155600380546001019055604051639f28a85160e01b81526001600160a01b03881690639f28a851906120ad9085908990899060040161410d565b600060405180830381600087803b1580156120c757600080fd5b505af11580156120db573d6000803e3d6000fd5b50505050866001600160a01b0316886001600160a01b0316336001600160a01b03167f69188e0b1fe29a684d099392c549be47abf36f594eff86a10860aa72892f9d51858a600001518b602001518c604001518d606001518e608001518e8e8e8d600c01546040516121569a999897969594939291906149ec565b60405180910390a4509695505050505050565b6040518060400160405280601081526020017f4b7962657220476f7665726e616e63650000000000000000000000000000000081525081565b60006121ad84613180565b905060005b8281101561243c5760026121d78585848181106121cb57fe5b90506020020135611a10565b60088111156121e257fe5b146121ec57612434565b6000600460008686858181106121fe57fe5b6020908102929092013583525081019190915260400160002060038101549091506001600160a01b031633146122465760405162461bcd60e51b815260040161059e9061441c565b60006004600087878681811061225857fe5b6020908102929092013583525081810192909252604090810160009081206001600160a01b038c168252601201835281902081518083019092525463ffffffff81168083526401000000009091046001600160e01b03169282019290925291506122c3575050612434565b600081602001516001600160e01b031690506122f6816122f08a86600b01546131ac90919063ffffffff16565b9061320d565b600b84015560005b6009840154811015612374578251600282900a90811663ffffffff16141561236c57612350826122f08b87600a01858154811061233757fe5b90600052602060002001546131ac90919063ffffffff16565b84600a01828154811061235f57fe5b6000918252602090912001555b6001016122fe565b50846004600089898881811061238657fe5b6020908102929092013583525081810192909252604090810160009081206001600160a01b038e1680835260129091019093522080546001600160e01b03939093166401000000000263ffffffff9384161790558351909116908888878181106123ec57fe5b905060200201357fd5d8d9cd5fd14f4f0db3033c674546819d762dfdeba3b638fd6da11f2af22a3e8560200151896040516124289291906149d2565b60405180910390a45050505b6001016121b2565b505050505050565b60035481106124655760405162461bcd60e51b815260040161059e90614323565b600461247082611a10565b600881111561247b57fe5b146124985760405162461bcd60e51b815260040161059e90614506565b600081815260046020526040902060018082015460ff16818111156124b957fe5b146124c057fe5b60006125548260020160009054906101000a90046001600160a01b03166001600160a01b031663cebc9a826040518163ffffffff1660e01b815260040160206040518083038186803b15801561251557600080fd5b505afa158015612529573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061254d9190613b0d565b42906131ac565b905060005b600483015481101561273d576002830154600484018054612735926001600160a01b031691908490811061258957fe5b6000918252602090912001546005860180546001600160a01b0390921691859081106125b157fe5b90600052602060002001548660060185815481106125cb57fe5b600091825260209182902001805460408051601f60026000196101006001871615020190941693909304928301859004850281018501909152818152928301828280156126595780601f1061262e57610100808354040283529160200191612659565b820191906000526020600020905b81548152906001019060200180831161263c57829003601f168201915b505050505087600701868154811061266d57fe5b600091825260209182902001805460408051601f60026000196101006001871615020190941693909304928301859004850281018501909152818152928301828280156126fb5780601f106126d0576101008083540402835291602001916126fb565b820191906000526020600020905b8154815290600101906020018083116126de57829003601f168201915b50505050508789600801888154811061271057fe5b90600052602060002090602091828204019190069054906101000a900460ff1661326a565b600101612559565b50600f8201819055604051339084907f11a0b38e70585e4b09b794bd1d9f9b1a51a802eb8ee2101eeee178d0349e73fe906127799085906140e0565b60405180910390a3505050565b6000546001600160a01b031681565b6000818152600460209081526040808320600b810154600a820180548451818702810187019095528085526060958695600986019290918491908301828280156127fe57602002820191906000526020600020905b8154815260200190600101908083116127ea575b5050505050915080805480602002602001604051908101604052809291908181526020016000905b828210156128d15760008481526020908190208301805460408051601f60026000196101006001871615020190941693909304928301859004850281018501909152818152928301828280156128bd5780601f10612892576101008083540402835291602001916128bd565b820191906000526020600020905b8154815290600101906020018083116128a057829003601f168201915b505050505081526020019060010190612826565b505050509050935093509350509193909250565b60035481106129065760405162461bcd60e51b815260040161059e90614323565b600561291182611a10565b600881111561291c57fe5b146129395760405162461bcd60e51b815260040161059e90614453565b600081815260046020526040902060018082015460ff168181111561295a57fe5b1461296157fe5b60118101805460ff1916600117905560005b6004820154811015612ada5760028201546005830180546001600160a01b0390921691638902ab659190849081106129a757fe5b90600052602060002001548460040184815481106129c157fe5b6000918252602090912001546005860180546001600160a01b0390921691869081106129e957fe5b9060005260206000200154866006018681548110612a0357fe5b90600052602060002001876007018781548110612a1c57fe5b9060005260206000200188600f0154896008018981548110612a3a57fe5b90600052602060002090602091828204019190069054906101000a900460ff166040518863ffffffff1660e01b8152600401612a7b9695949392919061407a565b6000604051808303818588803b158015612a9457600080fd5b505af1158015612aa8573d6000803e3d6000fd5b50505050506040513d6000823e601f3d908101601f19168201604052612ad19190810190613b25565b50600101612973565b50336001600160a01b03167f9c85b616f29fca57a17eafe71cf9ff82ffef41766e2cf01ea7f8f7878dd3ec2483604051612b1491906140e0565b60405180910390a25050565b60005b815181101561163057600160066000848481518110612b3e57fe5b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff021916908315150217905550818181518110612b8957fe5b60200260200101516001600160a01b03167f35a21f44f4ef215174b9bdf3d74192be42648f0e70dc6c952741a821ba98fa0960405160405180910390a2600101612b23565b60005b815181101561163057600060056000848481518110612bec57fe5b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff021916908315150217905550818181518110612c3757fe5b60200260200101516001600160a01b03167f5e8105a2af24345971359d2289f43efa80d093f4a7123561b8d63836b98724f460405160405180910390a2600101612bd1565b4690565b6003548210612ca15760405162461bcd60e51b815260040161059e90614323565b6002612cac83611a10565b6008811115612cb757fe5b14612cd45760405162461bcd60e51b815260040161059e9061459a565b6000828152600460205260409020600981015460018083015460ff1681811115612cfa57fe5b1415612d30578260011480612d0f5750826002145b612d2b5760405162461bcd60e51b815260040161059e9061435a565b612d5e565b600083118015612d4257508060020a83105b612d5e5760405162461bcd60e51b815260040161059e90614708565b60008481526004602081815260408084206001600160a01b038a811686526012909101835281852082518084018452905463ffffffff8116825264010000000090046001600160e01b031693810193909352600387015491517f21a6d2600000000000000000000000000000000000000000000000000000000081529294939116916321a6d26091612df6918b918b918b91016140b4565b602060405180830381600087803b158015612e1057600080fd5b505af1158015612e24573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e489190613b0d565b825190915063ffffffff16612e6c57600b840154612e6690826131ac565b600b8501555b60005b6009850154811015612f37578251600282900a90811663ffffffff1681149087811614818015612e9d575080155b15612eee57612ece8488600a018581548110612eb557fe5b906000526020600020015461320d90919063ffffffff16565b87600a018481548110612edd57fe5b600091825260209091200155612f2d565b81158015612ef95750805b15612f2d57612f118488600a01858154811061233757fe5b87600a018481548110612f2057fe5b6000918252602090912001555b5050600101612e6f565b506040518060400160405280612f4c876133de565b63ffffffff168152602001612f6083613180565b6001600160e01b0390811690915260008881526004602090815260408083206001600160a01b038d16845260120182529091208351815494909201519092166401000000000263ffffffff91821663ffffffff199094169390931716919091179055612fcb856133de565b63ffffffff16876001600160a01b0316877f612a68349ed2a41418dc9795d6525cab0c1f41d11b97b3dff2dc55695dfbdec261300685613180565b60405161301391906149be565b60405180910390a450505050505050565b60005b81518110156116305760016005600084848151811061304257fe5b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555081818151811061308d57fe5b60200260200101516001600160a01b03167f52762435f58790076157ea2a4914a5a4d0aa0eb421588891377692f7fd3bc08260405160405180910390a2600101613027565b60005b8151811015611630576000600660008484815181106130f057fe5b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555081818151811061313b57fe5b60200260200101516001600160a01b03167f42eb712815cbb2bbe9607880d05fc79635cf9712f706f41e8c20f02a7f64194160405160405180910390a26001016130d5565b60006001600160e01b0382106131a85760405162461bcd60e51b815260040161059e9061427e565b5090565b600082820183811015613206576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b600082821115613264576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b866001600160a01b031663b1fc879687878787878760405160200161329496959493929190614025565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b81526004016132c691906140e0565b60206040518083038186803b1580156132de57600080fd5b505afa1580156132f2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133169190613af1565b156133335760405162461bcd60e51b815260040161059e90614765565b6040517f8d8fe2e30000000000000000000000000000000000000000000000000000000081526001600160a01b03881690638d8fe2e39061338290899089908990899089908990600401614025565b602060405180830381600087803b15801561339c57600080fd5b505af11580156133b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133d49190613b0d565b5050505050505050565b600063ffffffff82106131a85760405162461bcd60e51b815260040161059e906142ec565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282613439576000855561347f565b82601f1061345257805160ff191683800117855561347f565b8280016001018555821561347f579182015b8281111561347f578251825591602001919060010190613464565b506131a8929150613738565b8280548282559060005260206000209081019282156134d8579160200282015b828111156134d857825180516134c8918491602090910190613403565b50916020019190600101906134ab565b506131a892915061374d565b82805482825590600052602060002090810192821561347f579160200282018281111561347f578251825591602001919060010190613464565b60408051610280810190915260008082526020820190815260200160006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b03168152602001606081526020016060815260200160608152602001606081526020016060815260200160608152602001606081526020016000815260200160008152602001600081526020016000815260200160008152602001606081526020016000151581526020016000151581525090565b604080518082019091526000808252602082015290565b82805482825590600052602060002090810192821561347f579160200282015b8281111561347f57825182546001600160a01b0319166001600160a01b0390911617825560209092019160019091019061360e565b828054828255906000526020600020908101928215613690579160200282015b828111156136905782518051613680918491602090910190613403565b5091602001919060010190613663565b506131a892915061376a565b82805482825590600052602060002090601f0160209004810192821561347f5791602002820160005b8382111561370257835183826101000a81548160ff02191690831515021790555092602001926001016020816000010492830192600103026136c5565b801561372f5782816101000a81549060ff0219169055600101602081600001049283019260010302613702565b50506131a89291505b5b808211156131a85760008155600101613739565b808211156131a85760006137618282613787565b5060010161374d565b808211156131a857600061377e8282613787565b5060010161376a565b50805460018160011615610100020316600290046000825580601f106137ad5750610946565b601f0160209004906000526020600020908101906109469190613738565b60006137de6137d984614b52565b614b10565b90508281528383830111156137f257600080fd5b828260208301376000602084830101529392505050565b600082601f830112613819578081fd5b813560206138296137d983614b34565b8281528181019085830183850287018401881015613845578586fd5b855b8581101561386c57813561385a81614bb0565b84529284019290840190600101613847565b5090979650505050505050565b600082601f830112613889578081fd5b813560206138996137d983614b34565b82815281810190858301838502870184018810156138b5578586fd5b855b8581101561386c5781356138ca81614bc5565b845292840192908401906001016138b7565b600082601f8301126138ec578081fd5b813560206138fc6137d983614b34565b82815281810190858301855b8581101561386c578135880189603f820112613922578788fd5b6139338a87830135604084016137cb565b8552509284019290840190600101613908565b600082601f830112613956578081fd5b813560206139666137d983614b34565b82815281810190858301855b8581101561386c57613989898684358b01016139f5565b84529284019290840190600101613972565b600082601f8301126139ab578081fd5b813560206139bb6137d983614b34565b82815281810190858301838502870184018810156139d7578586fd5b855b8581101561386c578135845292840192908401906001016139d9565b600082601f830112613a05578081fd5b613206838335602085016137cb565b600060208284031215613a25578081fd5b813561320681614bb0565b60008060008060608587031215613a45578283fd5b8435613a5081614bb0565b935060208501359250604085013567ffffffffffffffff80821115613a73578384fd5b818701915087601f830112613a86578384fd5b813581811115613a94578485fd5b8860208083028501011115613aa7578485fd5b95989497505060200194505050565b600060208284031215613ac7578081fd5b813567ffffffffffffffff811115613add578182fd5b613ae984828501613809565b949350505050565b600060208284031215613b02578081fd5b815161320681614bc5565b600060208284031215613b1e578081fd5b5051919050565b600060208284031215613b36578081fd5b815167ffffffffffffffff811115613b4c578182fd5b8201601f81018413613b5c578182fd5b8051613b6a6137d982614b52565b818152856020838501011115613b7e578384fd5b613b8f826020830160208601614b80565b95945050505050565b60008060008060008060c08789031215613bb0578384fd5b8635613bbb81614bb0565b95506020870135613bcb81614bb0565b9450604087013567ffffffffffffffff80821115613be7578586fd5b613bf38a838b01613946565b9550606089013594506080890135935060a0890135915080821115613c16578283fd5b50613c2389828a016139f5565b9150509295509295509295565b60008060008060008060c08789031215613c48578384fd5b8635613c5381614bb0565b95506020870135613c6381614bb0565b9450604087013567ffffffffffffffff80821115613c7f578586fd5b9088019060a0828b031215613c92578586fd5b613c9c60a0614b10565b823582811115613caa578788fd5b613cb68c828601613809565b825250602083013582811115613cca578788fd5b613cd68c82860161399b565b602083015250604083013582811115613ced578788fd5b613cf98c828601613946565b604083015250606083013582811115613d10578788fd5b613d1c8c8286016138dc565b606083015250608083013582811115613d33578788fd5b613d3f8c828601613879565b60808301525080965050606089013594506080890135935060a0890135915080821115613c16578283fd5b600060208284031215613d7b578081fd5b5035919050565b60008060408385031215613d94578182fd5b823591506020830135613da681614bb0565b809150509250929050565b60008060408385031215613dc3578182fd5b50508035926020909101359150565b600080600080600060a08688031215613de9578283fd5b8535945060208601359350604086013560ff81168114613e07578384fd5b94979396509394606081013594506080013592915050565b6001600160a01b03169052565b6000815180845260208085019450808401835b83811015613e645781516001600160a01b031687529582019590820190600101613e3f565b509495945050505050565b6000815180845260208085019450808401835b83811015613e64578151151587529582019590820190600101613e82565b60008282518085526020808601955080818302840101818601855b8481101561386c57601f19868403018952613ed7838351613f1e565b98840198925090830190600101613ebb565b6000815180845260208085019450808401835b83811015613e6457815187529582019590820190600101613efc565b15159052565b60008151808452613f36816020860160208601614b80565b601f01601f19169290920160200192915050565b60008154600180821660008114613f685760018114613f8657613fc4565b60028304607f16865260ff1983166020870152604086019350613fc4565b60028304808752613f9686614b74565b60005b82811015613fba5781546020828b0101528482019150602081019050613f99565b8801602001955050505b50505092915050565b60028110613fd757fe5b9052565b7f190100000000000000000000000000000000000000000000000000000000000081526002810192909252602282015260420190565b6001600160a01b0391909116815260200190565b60006001600160a01b038816825286602083015260c0604083015261404d60c0830187613f1e565b828103606084015261405f8187613f1e565b6080840195909552505090151560a090910152949350505050565b60006001600160a01b038816825286602083015260c060408301526140a260c0830187613f4a565b828103606084015261405f8187613f4a565b6001600160a01b039390931683526020830191909152604082015260600190565b901515815260200190565b90815260200190565b938452602084019290925260408301526001600160a01b0316606082015260800190565b9283526020830191909152604082015260600190565b93845260ff9290921660208401526040830152606082015260800190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b0393841681526020810192909252909116604082015260600190565b6001600160a01b039586168152938516602085015260408401929092526060830152909116608082015260a00190565b60006001600160a01b038089168352808816602084015286604084015285606084015260c060808401526141e460c0840186613ea0565b915080841660a084015250979650505050505050565b602081016009831061420857fe5b91905290565b6000602082526132066020830184613f1e565b60208082526023908201527f6372656174652062696e61727920696e76616c696420656d707479207461726760408201527f6574730000000000000000000000000000000000000000000000000000000000606082015260800190565b6020808252601a908201527f76616c756520697320746f6f20626967202875696e7432323429000000000000604082015260600190565b60208082526011908201527f696e76616c6964207369676e6174757265000000000000000000000000000000604082015260600190565b60208082526019908201527f76616c756520697320746f6f20626967202875696e7433322900000000000000604082015260600190565b60208082526013908201527f696e76616c69642070726f706f73616c20696400000000000000000000000000604082015260600190565b6020808252601e908201527f77726f6e6720766f746520666f722062696e6172792070726f706f73616c0000604082015260600190565b60208082526025908201527f6372656174652062696e617279206578656375746f72206e6f7420617574686f6040820152641c9a5e995960da1b606082015260800190565b60208082526026908201527f6372656174652067656e65726963206578656375746f72206e6f7420617574686040820152651bdc9a5e995960d21b606082015260800190565b6020808252601d908201527f696e76616c696420766f74696e6720706f776572207374726174656779000000604082015260600190565b60208082526015908201527f6f6e6c79207175657565642070726f706f73616c730000000000000000000000604082015260600190565b60208082526025908201527f6372656174652062696e617279207374726174656779206e6f7420617574686f6040820152641c9a5e995960da1b606082015260800190565b60208082526011908201527f6f6e6c792064616f206f70657261746f72000000000000000000000000000000604082015260600190565b60208082526016908201527f696e76616c696420737461746520746f20717565756500000000000000000000604082015260600190565b60208082526022908201527f76616c69646174652070726f706f73616c206372656174696f6e20696e76616c60408201527f6964000000000000000000000000000000000000000000000000000000000000606082015260800190565b6020808252600d908201527f766f74696e6720636c6f73656400000000000000000000000000000000000000604082015260600190565b60208082526028908201527f6372656174652062696e61727920696e636f6e73697374656e7420706172616d60408201527f73206c656e677468000000000000000000000000000000000000000000000000606082015260800190565b60208082526026908201527f6372656174652067656e65726963207374726174656779206e6f7420617574686040820152651bdc9a5e995960d21b606082015260800190565b60208082526025908201527f76616c69646174652070726f706f73616c2063616e63656c6c6174696f6e206660408201527f61696c6564000000000000000000000000000000000000000000000000000000606082015260800190565b60208082526017908201527f696e76616c696420737461746520746f2063616e63656c000000000000000000604082015260600190565b60208082526024908201527f696e76616c6964206f7074696f6e7320666f722067656e657269632070726f7060408201527f6f73616c00000000000000000000000000000000000000000000000000000000606082015260800190565b60208082526011908201527f6475706c69636174656420616374696f6e000000000000000000000000000000604082015260600190565b60208082526014908201527f696e76616c69642064616f206f70657261746f72000000000000000000000000604082015260600190565b6000602082528251602083015260208301516147f26040840182613fcd565b5060408301516148056060840182613e1f565b5060608301516148186080840182613e1f565b50608083015161482b60a0840182613e1f565b5060a08301516102808060c08501526148486102a0850183613e2c565b915060c0850151601f19808685030160e08701526148668483613ee9565b935060e087015191506101008187860301818801526148858584613ea0565b9450808801519250506101208187860301818801526148a48584613ea0565b9450808801519250506101408187860301818801526148c38584613e6f565b9450808801519250506101608187860301818801526148e28584613ea0565b9450808801519250506101808187860301818801526149018584613ee9565b908801516101a0888101919091528801516101c0808901919091528801516101e08089019190915288015161020080890191909152880151610220808901919091528801518782038301610240808a019190915291955092506149648584613f1e565b9450808801519250505061026061497d81870183613f18565b860151905061498e85830182613f18565b5090949350505050565b815163ffffffff1681526020918201516001600160e01b03169181019190915260400190565b6001600160e01b0391909116815260200190565b6001600160e01b0392831681529116602082015260400190565b60006101408c8352806020840152614a068184018d613e2c565b90508281036040840152614a1a818c613ee9565b90508281036060840152614a2e818b613ea0565b90508281036080840152614a42818a613ea0565b905082810360a0840152614a568189613e6f565b90508660c08401528560e0840152828103610100840152614a778186613f1e565b915050826101208301529b9a5050505050505050505050565b600087825260c06020830152614aa960c0830188613ea0565b8660408401528560608401528281036080840152614ac78186613f1e565b9150508260a0830152979650505050505050565b600084825260606020830152614af46060830185613ee9565b8281036040840152614b068185613ea0565b9695505050505050565b60405181810167ffffffffffffffff81118282101715614b2c57fe5b604052919050565b600067ffffffffffffffff821115614b4857fe5b5060209081020190565b600067ffffffffffffffff821115614b6657fe5b50601f01601f191660200190565b60009081526020902090565b60005b83811015614b9b578181015183820152602001614b83565b83811115614baa576000848401525b50505050565b6001600160a01b038116811461094657600080fd5b801515811461094657600080fdfea26469706673582212202797f380f95f7d6c1930f14f37b038e1d1f1f4e6a32e0c8d98e99fd9a648ef2864736f6c63430007060033

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

000000000000000000000000560fb65513a3e9f22df97501393360bf0db448ad000000000000000000000000e6a7338cba0a1070adfb22c07115299605454713000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

-----Decoded View---------------
Arg [0] : admin (address): 0x560FB65513a3E9F22dF97501393360Bf0db448Ad
Arg [1] : daoOperator (address): 0xE6A7338cba0A1070AdfB22c07115299605454713
Arg [2] : executors (address[]):
Arg [3] : votingPowerStrategies (address[]):

-----Encoded View---------------
6 Constructor Arguments found :
Arg [0] : 000000000000000000000000560fb65513a3e9f22df97501393360bf0db448ad
Arg [1] : 000000000000000000000000e6a7338cba0a1070adfb22c07115299605454713
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000080
Arg [3] : 00000000000000000000000000000000000000000000000000000000000000a0
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000000


Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]

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