ETH Price: $2,524.36 (-5.28%)
 

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
Bond57893262018-06-14 20:25:192535 days ago1529007919IN
0x5A951282...5A515fE24
0 ETH0.0020508410
Bond57893132018-06-14 20:22:032535 days ago1529007723IN
0x5A951282...5A515fE24
0 ETH0.0002319210

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
BondingManager

Compiler Version
v0.4.18+commit.9cf6e910

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion
/**
 *Submitted for verification at Etherscan.io on 2018-05-27
*/

pragma solidity 0.4.18;

/**
 * @title ERC20Basic
 * @dev Simpler version of ERC20 interface
 * @dev see https://github.com/ethereum/EIPs/issues/179
 */
contract ERC20Basic {
  uint256 public totalSupply;
  function balanceOf(address who) public view returns (uint256);
  function transfer(address to, uint256 value) public returns (bool);
  event Transfer(address indexed from, address indexed to, uint256 value);
}

/**
 * @title ERC20 interface
 * @dev see https://github.com/ethereum/EIPs/issues/20
 */
contract ERC20 is ERC20Basic {
  function allowance(address owner, address spender) public view returns (uint256);
  function transferFrom(address from, address to, uint256 value) public returns (bool);
  function approve(address spender, uint256 value) public returns (bool);
  event Approval(address indexed owner, address indexed spender, uint256 value);
}

/**
 * @title Ownable
 * @dev The Ownable contract has an owner address, and provides basic authorization control
 * functions, this simplifies the implementation of "user permissions".
 */
contract Ownable {
  address public owner;


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


  /**
   * @dev The Ownable constructor sets the original `owner` of the contract to the sender
   * account.
   */
  function Ownable() public {
    owner = msg.sender;
  }


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


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

}

/**
 * @title Pausable
 * @dev Base contract which allows children to implement an emergency stop mechanism.
 */
contract Pausable is Ownable {
    event Pause();
    event Unpause();

    bool public paused = false;


    /**
     * @dev Modifier to make a function callable only when the contract is not paused.
     */
    modifier whenNotPaused() {
        require(!paused);
        _;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is paused.
     */
    modifier whenPaused() {
        require(paused);
        _;
    }

    /**
     * @dev called by the owner to pause, triggers stopped state
     */
    function pause() onlyOwner whenNotPaused public {
        paused = true;
        Pause();
    }

    /**
     * @dev called by the owner to unpause, returns to normal state
     */
    function unpause() onlyOwner whenPaused public {
        paused = false;
        Unpause();
    }
}

/**
 * @title Math
 * @dev Assorted math operations
 */
library Math {
    function max64(uint64 a, uint64 b) internal pure returns (uint64) {
        return a >= b ? a : b;
    }

    function min64(uint64 a, uint64 b) internal pure returns (uint64) {
        return a < b ? a : b;
    }

    function max256(uint256 a, uint256 b) internal pure returns (uint256) {
        return a >= b ? a : b;
    }

    function min256(uint256 a, uint256 b) internal pure returns (uint256) {
        return a < b ? a : b;
    }
}

/**
 * @title SafeMath
 * @dev Math operations with safety checks that throw on error
 */
library SafeMath {
  function mul(uint256 a, uint256 b) internal pure returns (uint256) {
    if (a == 0) {
      return 0;
    }
    uint256 c = a * b;
    assert(c / a == b);
    return c;
  }

  function div(uint256 a, uint256 b) internal pure returns (uint256) {
    // assert(b > 0); // Solidity automatically throws when dividing by 0
    uint256 c = a / b;
    // assert(a == b * c + a % b); // There is no case in which this doesn't hold
    return c;
  }

  function sub(uint256 a, uint256 b) internal pure returns (uint256) {
    assert(b <= a);
    return a - b;
  }

  function add(uint256 a, uint256 b) internal pure returns (uint256) {
    uint256 c = a + b;
    assert(c >= a);
    return c;
  }
}

library MathUtils {
    using SafeMath for uint256;

    // Divisor used for representing percentages
    uint256 public constant PERC_DIVISOR = 1000000;

    /*
     * @dev Returns whether an amount is a valid percentage out of PERC_DIVISOR
     * @param _amount Amount that is supposed to be a percentage
     */
    function validPerc(uint256 _amount) internal pure returns (bool) {
        return _amount <= PERC_DIVISOR;
    }

    /*
     * @dev Compute percentage of a value with the percentage represented by a fraction
     * @param _amount Amount to take the percentage of
     * @param _fracNum Numerator of fraction representing the percentage
     * @param _fracDenom Denominator of fraction representing the percentage
     */
    function percOf(uint256 _amount, uint256 _fracNum, uint256 _fracDenom) internal pure returns (uint256) {
        return _amount.mul(percPoints(_fracNum, _fracDenom)).div(PERC_DIVISOR);
    }

    /*
     * @dev Compute percentage of a value with the percentage represented by a fraction over PERC_DIVISOR
     * @param _amount Amount to take the percentage of
     * @param _fracNum Numerator of fraction representing the percentage with PERC_DIVISOR as the denominator
     */
    function percOf(uint256 _amount, uint256 _fracNum) internal pure returns (uint256) {
        return _amount.mul(_fracNum).div(PERC_DIVISOR);
    }

    /*
     * @dev Compute percentage representation of a fraction
     * @param _fracNum Numerator of fraction represeting the percentage
     * @param _fracDenom Denominator of fraction represeting the percentage
     */
    function percPoints(uint256 _fracNum, uint256 _fracDenom) internal pure returns (uint256) {
        return _fracNum.mul(PERC_DIVISOR).div(_fracDenom);
    }
}

contract IController is Pausable {
    event SetContractInfo(bytes32 id, address contractAddress, bytes20 gitCommitHash);

    function setContractInfo(bytes32 _id, address _contractAddress, bytes20 _gitCommitHash) external;
    function updateController(bytes32 _id, address _controller) external;
    function getContract(bytes32 _id) public view returns (address);
}

contract IManager {
    event SetController(address controller);
    event ParameterUpdate(string param);

    function setController(address _controller) external;
}

contract Manager is IManager {
    // Controller that contract is registered with
    IController public controller;

    // Check if sender is controller
    modifier onlyController() {
        require(msg.sender == address(controller));
        _;
    }

    // Check if sender is controller owner
    modifier onlyControllerOwner() {
        require(msg.sender == controller.owner());
        _;
    }

    // Check if controller is not paused
    modifier whenSystemNotPaused() {
        require(!controller.paused());
        _;
    }

    // Check if controller is paused
    modifier whenSystemPaused() {
        require(controller.paused());
        _;
    }

    function Manager(address _controller) public {
        controller = IController(_controller);
    }

    /*
     * @dev Set controller. Only callable by current controller
     * @param _controller Controller contract address
     */
    function setController(address _controller) external onlyController {
        controller = IController(_controller);

        SetController(_controller);
    }
}

/**
 * @title ManagerProxyTarget
 * @dev The base contract that target contracts used by a proxy contract should inherit from
 * Note: Both the target contract and the proxy contract (implemented as ManagerProxy) MUST inherit from ManagerProxyTarget in order to guarantee
 * that both contracts have the same storage layout. Differing storage layouts in a proxy contract and target contract can
 * potentially break the delegate proxy upgradeability mechanism
 */
contract ManagerProxyTarget is Manager {
    // Used to look up target contract address in controller's registry
    bytes32 public targetContractId;
}

/*
 * @title A sorted doubly linked list with nodes sorted in descending order. Optionally accepts insert position hints
 *
 * Given a new node with a `key`, a hint is of the form `(prevId, nextId)` s.t. `prevId` and `nextId` are adjacent in the list.
 * `prevId` is a node with a key >= `key` and `nextId` is a node with a key <= `key`. If the sender provides a hint that is a valid insert position
 * the insert operation is a constant time storage write. However, the provided hint in a given transaction might be a valid insert position, but if other transactions are included first, when
 * the given transaction is executed the provided hint may no longer be a valid insert position. For example, one of the nodes referenced might be removed or their keys may
 * be updated such that the the pair of nodes in the hint no longer represent a valid insert position. If one of the nodes in the hint becomes invalid, we still try to use the other
 * valid node as a starting point for finding the appropriate insert position. If both nodes in the hint become invalid, we use the head of the list as a starting point
 * to find the appropriate insert position.
 */
library SortedDoublyLL {
    using SafeMath for uint256;

    // Information for a node in the list
    struct Node {
        uint256 key;                     // Node's key used for sorting
        address nextId;                  // Id of next node (smaller key) in the list
        address prevId;                  // Id of previous node (larger key) in the list
    }

    // Information for the list
    struct Data {
        address head;                        // Head of the list. Also the node in the list with the largest key
        address tail;                        // Tail of the list. Also the node in the list with the smallest key
        uint256 maxSize;                     // Maximum size of the list
        uint256 size;                        // Current size of the list
        mapping (address => Node) nodes;     // Track the corresponding ids for each node in the list
    }

    /*
     * @dev Set the maximum size of the list
     * @param _size Maximum size
     */
    function setMaxSize(Data storage self, uint256 _size) public {
        // New max size must be greater than old max size
        require(_size > self.maxSize);

        self.maxSize = _size;
    }

    /*
     * @dev Add a node to the list
     * @param _id Node's id
     * @param _key Node's key
     * @param _prevId Id of previous node for the insert position
     * @param _nextId Id of next node for the insert position
     */
    function insert(Data storage self, address _id, uint256 _key, address _prevId, address _nextId) public {
        // List must not be full
        require(!isFull(self));
        // List must not already contain node
        require(!contains(self, _id));
        // Node id must not be null
        require(_id != address(0));
        // Key must be non-zero
        require(_key > 0);

        address prevId = _prevId;
        address nextId = _nextId;

        if (!validInsertPosition(self, _key, prevId, nextId)) {
            // Sender's hint was not a valid insert position
            // Use sender's hint to find a valid insert position
            (prevId, nextId) = findInsertPosition(self, _key, prevId, nextId);
        }

        self.nodes[_id].key = _key;

        if (prevId == address(0) && nextId == address(0)) {
            // Insert as head and tail
            self.head = _id;
            self.tail = _id;
        } else if (prevId == address(0)) {
            // Insert before `prevId` as the head
            self.nodes[_id].nextId = self.head;
            self.nodes[self.head].prevId = _id;
            self.head = _id;
        } else if (nextId == address(0)) {
            // Insert after `nextId` as the tail
            self.nodes[_id].prevId = self.tail;
            self.nodes[self.tail].nextId = _id;
            self.tail = _id;
        } else {
            // Insert at insert position between `prevId` and `nextId`
            self.nodes[_id].nextId = nextId;
            self.nodes[_id].prevId = prevId;
            self.nodes[prevId].nextId = _id;
            self.nodes[nextId].prevId = _id;
        }

        self.size = self.size.add(1);
    }

    /*
     * @dev Remove a node from the list
     * @param _id Node's id
     */
    function remove(Data storage self, address _id) public {
        // List must contain the node
        require(contains(self, _id));

        if (self.size > 1) {
            // List contains more than a single node
            if (_id == self.head) {
                // The removed node is the head
                // Set head to next node
                self.head = self.nodes[_id].nextId;
                // Set prev pointer of new head to null
                self.nodes[self.head].prevId = address(0);
            } else if (_id == self.tail) {
                // The removed node is the tail
                // Set tail to previous node
                self.tail = self.nodes[_id].prevId;
                // Set next pointer of new tail to null
                self.nodes[self.tail].nextId = address(0);
            } else {
                // The removed node is neither the head nor the tail
                // Set next pointer of previous node to the next node
                self.nodes[self.nodes[_id].prevId].nextId = self.nodes[_id].nextId;
                // Set prev pointer of next node to the previous node
                self.nodes[self.nodes[_id].nextId].prevId = self.nodes[_id].prevId;
            }
        } else {
            // List contains a single node
            // Set the head and tail to null
            self.head = address(0);
            self.tail = address(0);
        }

        delete self.nodes[_id];
        self.size = self.size.sub(1);
    }

    /*
     * @dev Update the key of a node in the list
     * @param _id Node's id
     * @param _newKey Node's new key
     * @param _prevId Id of previous node for the new insert position
     * @param _nextId Id of next node for the new insert position
     */
    function updateKey(Data storage self, address _id, uint256 _newKey, address _prevId, address _nextId) public {
        // List must contain the node
        require(contains(self, _id));

        // Remove node from the list
        remove(self, _id);

        if (_newKey > 0) {
            // Insert node if it has a non-zero key
            insert(self, _id, _newKey, _prevId, _nextId);
        }
    }

    /*
     * @dev Checks if the list contains a node
     * @param _transcoder Address of transcoder
     */
    function contains(Data storage self, address _id) public view returns (bool) {
        // List only contains non-zero keys, so if key is non-zero the node exists
        return self.nodes[_id].key > 0;
    }

    /*
     * @dev Checks if the list is full
     */
    function isFull(Data storage self) public view returns (bool) {
        return self.size == self.maxSize;
    }

    /*
     * @dev Checks if the list is empty
     */
    function isEmpty(Data storage self) public view returns (bool) {
        return self.size == 0;
    }

    /*
     * @dev Returns the current size of the list
     */
    function getSize(Data storage self) public view returns (uint256) {
        return self.size;
    }

    /*
     * @dev Returns the maximum size of the list
     */
    function getMaxSize(Data storage self) public view returns (uint256) {
        return self.maxSize;
    }

    /*
     * @dev Returns the key of a node in the list
     * @param _id Node's id
     */
    function getKey(Data storage self, address _id) public view returns (uint256) {
        return self.nodes[_id].key;
    }

    /*
     * @dev Returns the first node in the list (node with the largest key)
     */
    function getFirst(Data storage self) public view returns (address) {
        return self.head;
    }

    /*
     * @dev Returns the last node in the list (node with the smallest key)
     */
    function getLast(Data storage self) public view returns (address) {
        return self.tail;
    }

    /*
     * @dev Returns the next node (with a smaller key) in the list for a given node
     * @param _id Node's id
     */
    function getNext(Data storage self, address _id) public view returns (address) {
        return self.nodes[_id].nextId;
    }

    /*
     * @dev Returns the previous node (with a larger key) in the list for a given node
     * @param _id Node's id
     */
    function getPrev(Data storage self, address _id) public view returns (address) {
        return self.nodes[_id].prevId;
    }

    /*
     * @dev Check if a pair of nodes is a valid insertion point for a new node with the given key
     * @param _key Node's key
     * @param _prevId Id of previous node for the insert position
     * @param _nextId Id of next node for the insert position
     */
    function validInsertPosition(Data storage self, uint256 _key, address _prevId, address _nextId) public view returns (bool) {
        if (_prevId == address(0) && _nextId == address(0)) {
            // `(null, null)` is a valid insert position if the list is empty
            return isEmpty(self);
        } else if (_prevId == address(0)) {
            // `(null, _nextId)` is a valid insert position if `_nextId` is the head of the list
            return self.head == _nextId && _key >= self.nodes[_nextId].key;
        } else if (_nextId == address(0)) {
            // `(_prevId, null)` is a valid insert position if `_prevId` is the tail of the list
            return self.tail == _prevId && _key <= self.nodes[_prevId].key;
        } else {
            // `(_prevId, _nextId)` is a valid insert position if they are adjacent nodes and `_key` falls between the two nodes' keys
            return self.nodes[_prevId].nextId == _nextId && self.nodes[_prevId].key >= _key && _key >= self.nodes[_nextId].key;
        }
    }

    /*
     * @dev Descend the list (larger keys to smaller keys) to find a valid insert position
     * @param _key Node's key
     * @param _startId Id of node to start ascending the list from
     */
    function descendList(Data storage self, uint256 _key, address _startId) private view returns (address, address) {
        // If `_startId` is the head, check if the insert position is before the head
        if (self.head == _startId && _key >= self.nodes[_startId].key) {
            return (address(0), _startId);
        }

        address prevId = _startId;
        address nextId = self.nodes[prevId].nextId;

        // Descend the list until we reach the end or until we find a valid insert position
        while (prevId != address(0) && !validInsertPosition(self, _key, prevId, nextId)) {
            prevId = self.nodes[prevId].nextId;
            nextId = self.nodes[prevId].nextId;
        }

        return (prevId, nextId);
    }

    /*
     * @dev Ascend the list (smaller keys to larger keys) to find a valid insert position
     * @param _key Node's key
     * @param _startId Id of node to start descending the list from
     */
    function ascendList(Data storage self, uint256 _key, address _startId) private view returns (address, address) {
        // If `_startId` is the tail, check if the insert position is after the tail
        if (self.tail == _startId && _key <= self.nodes[_startId].key) {
            return (_startId, address(0));
        }

        address nextId = _startId;
        address prevId = self.nodes[nextId].prevId;

        // Ascend the list until we reach the end or until we find a valid insertion point
        while (nextId != address(0) && !validInsertPosition(self, _key, prevId, nextId)) {
            nextId = self.nodes[nextId].prevId;
            prevId = self.nodes[nextId].prevId;
        }

        return (prevId, nextId);
    }

    /*
     * @dev Find the insert position for a new node with the given key
     * @param _key Node's key
     * @param _prevId Id of previous node for the insert position
     * @param _nextId Id of next node for the insert position
     */
    function findInsertPosition(Data storage self, uint256 _key, address _prevId, address _nextId) private view returns (address, address) {
        address prevId = _prevId;
        address nextId = _nextId;

        if (prevId != address(0)) {
            if (!contains(self, prevId) || _key > self.nodes[prevId].key) {
                // `prevId` does not exist anymore or now has a smaller key than the given key
                prevId = address(0);
            }
        }

        if (nextId != address(0)) {
            if (!contains(self, nextId) || _key < self.nodes[nextId].key) {
                // `nextId` does not exist anymore or now has a larger key than the given key
                nextId = address(0);
            }
        }

        if (prevId == address(0) && nextId == address(0)) {
            // No hint - descend list starting from head
            return descendList(self, _key, self.head);
        } else if (prevId == address(0)) {
            // No `prevId` for hint - ascend list starting from `nextId`
            return ascendList(self, _key, nextId);
        } else if (nextId == address(0)) {
            // No `nextId` for hint - descend list starting from `prevId`
            return descendList(self, _key, prevId);
        } else {
            // Descend list starting from `prevId`
            return descendList(self, _key, prevId);
        }
    }
}

library EarningsPool {
    using SafeMath for uint256;

    // Represents rewards and fees to be distributed to delegators
    struct Data {
        uint256 rewardPool;                // Rewards in the pool
        uint256 feePool;                   // Fees in the pool
        uint256 totalStake;                // Transcoder's total stake during the pool's round
        uint256 claimableStake;            // Stake that can be used to claim portions of the fee and reward pool
        uint256 transcoderRewardCut;       // Reward cut for the reward pool
        uint256 transcoderFeeShare;        // Fee share for the fee pool
    }

    function init(EarningsPool.Data storage earningsPool, uint256 _stake, uint256 _rewardCut, uint256 _feeShare) internal {
        earningsPool.totalStake = _stake;
        earningsPool.claimableStake = _stake;
        earningsPool.transcoderRewardCut = _rewardCut;
        earningsPool.transcoderFeeShare = _feeShare;
    }

    function hasClaimableShares(EarningsPool.Data storage earningsPool) internal view returns (bool) {
        return earningsPool.claimableStake > 0;
    }

    function claimShare(EarningsPool.Data storage earningsPool, uint256 _stake, bool _isTranscoder) internal returns (uint256, uint256) {
        uint256 fees = 0;
        uint256 rewards = 0;

        if (earningsPool.feePool > 0) {
            // Compute fee share
            fees = feePoolShare(earningsPool, _stake, _isTranscoder);
            earningsPool.feePool = earningsPool.feePool.sub(fees);
        }

        if (earningsPool.rewardPool > 0) {
            // Compute reward share
            rewards = rewardPoolShare(earningsPool, _stake, _isTranscoder);
            earningsPool.rewardPool = earningsPool.rewardPool.sub(rewards);
        }

        // Update remaning claimable stake for token pools
        earningsPool.claimableStake = earningsPool.claimableStake.sub(_stake);

        return (fees, rewards);
    }

    function feePoolShare(EarningsPool.Data storage earningsPool, uint256 _stake, bool _isTranscoder) internal view returns (uint256) {
        uint256 transcoderFees = 0;
        uint256 delegatorFees = 0;

        if (earningsPool.claimableStake > 0) {
            uint256 delegatorsFees = MathUtils.percOf(earningsPool.feePool, earningsPool.transcoderFeeShare);
            transcoderFees = earningsPool.feePool.sub(delegatorsFees);
            delegatorFees = MathUtils.percOf(delegatorsFees, _stake, earningsPool.claimableStake);
        }

        if (_isTranscoder) {
            return delegatorFees.add(transcoderFees);
        } else {
            return delegatorFees;
        }
    }

    function rewardPoolShare(EarningsPool.Data storage earningsPool, uint256 _stake, bool _isTranscoder) internal view returns (uint256) {
        uint256 transcoderRewards = 0;
        uint256 delegatorRewards = 0;

        if (earningsPool.claimableStake > 0) {
            transcoderRewards = MathUtils.percOf(earningsPool.rewardPool, earningsPool.transcoderRewardCut);
            delegatorRewards = MathUtils.percOf(earningsPool.rewardPool.sub(transcoderRewards), _stake, earningsPool.claimableStake);
        }

        if (_isTranscoder) {
            return delegatorRewards.add(transcoderRewards);
        } else {
            return delegatorRewards;
        }
    }
}

contract ILivepeerToken is ERC20, Ownable {
    function mint(address _to, uint256 _amount) public returns (bool);
    function burn(uint256 _amount) public;
}

/**
 * @title Minter interface
 */
contract IMinter {
    // Events
    event SetCurrentRewardTokens(uint256 currentMintableTokens, uint256 currentInflation);

    // External functions
    function createReward(uint256 _fracNum, uint256 _fracDenom) external returns (uint256);
    function trustedTransferTokens(address _to, uint256 _amount) external;
    function trustedBurnTokens(uint256 _amount) external;
    function trustedWithdrawETH(address _to, uint256 _amount) external;
    function depositETH() external payable returns (bool);
    function setCurrentRewardTokens() external;

    // Public functions
    function getController() public view returns (IController);
}

/**
 * @title RoundsManager interface
 */
contract IRoundsManager {
    // Events
    event NewRound(uint256 round);

    // External functions
    function initializeRound() external;

    // Public functions
    function blockNum() public view returns (uint256);
    function blockHash(uint256 _block) public view returns (bytes32);
    function currentRound() public view returns (uint256);
    function currentRoundStartBlock() public view returns (uint256);
    function currentRoundInitialized() public view returns (bool);
    function currentRoundLocked() public view returns (bool);
}

/*
 * @title Interface for BondingManager
 */
contract IBondingManager {
    event TranscoderUpdate(address indexed transcoder, uint256 pendingRewardCut, uint256 pendingFeeShare, uint256 pendingPricePerSegment, bool registered);
    event TranscoderEvicted(address indexed transcoder);
    event TranscoderResigned(address indexed transcoder);
    event TranscoderSlashed(address indexed transcoder, address finder, uint256 penalty, uint256 finderReward);
    event Reward(address indexed transcoder, uint256 amount);
    event Bond(address indexed delegate, address indexed delegator);
    event Unbond(address indexed delegate, address indexed delegator);
    event WithdrawStake(address indexed delegator);
    event WithdrawFees(address indexed delegator);

    // External functions
    function setActiveTranscoders() external;
    function updateTranscoderWithFees(address _transcoder, uint256 _fees, uint256 _round) external;
    function slashTranscoder(address _transcoder, address _finder, uint256 _slashAmount, uint256 _finderFee) external;
    function electActiveTranscoder(uint256 _maxPricePerSegment, bytes32 _blockHash, uint256 _round) external view returns (address);

    // Public functions
    function transcoderTotalStake(address _transcoder) public view returns (uint256);
    function activeTranscoderTotalStake(address _transcoder, uint256 _round) public view returns (uint256);
    function isRegisteredTranscoder(address _transcoder) public view returns (bool);
    function getTotalBonded() public view returns (uint256);
}

/**
 * @title BondingManager
 * @dev Manages bonding, transcoder and rewards/fee accounting related operations of the Livepeer protocol
 */
contract BondingManager is ManagerProxyTarget, IBondingManager {
    using SafeMath for uint256;
    using SortedDoublyLL for SortedDoublyLL.Data;
    using EarningsPool for EarningsPool.Data;

    // Time between unbonding and possible withdrawl in rounds
    uint64 public unbondingPeriod;
    // Number of active transcoders
    uint256 public numActiveTranscoders;
    // Max number of rounds that a caller can claim earnings for at once
    uint256 public maxEarningsClaimsRounds;

    // Represents a transcoder's current state
    struct Transcoder {
        uint256 lastRewardRound;                             // Last round that the transcoder called reward
        uint256 rewardCut;                                   // % of reward paid to transcoder by a delegator
        uint256 feeShare;                                    // % of fees paid to delegators by transcoder
        uint256 pricePerSegment;                             // Price per segment (denominated in LPT units) for a stream
        uint256 pendingRewardCut;                            // Pending reward cut for next round if the transcoder is active
        uint256 pendingFeeShare;                             // Pending fee share for next round if the transcoder is active
        uint256 pendingPricePerSegment;                      // Pending price per segment for next round if the transcoder is active
        mapping (uint256 => EarningsPool.Data) earningsPoolPerRound;  // Mapping of round => earnings pool for the round
    }

    // The various states a transcoder can be in
    enum TranscoderStatus { NotRegistered, Registered }

    // Represents a delegator's current state
    struct Delegator {
        uint256 bondedAmount;                    // The amount of bonded tokens
        uint256 fees;                            // The amount of fees collected
        address delegateAddress;                 // The address delegated to
        uint256 delegatedAmount;                 // The amount of tokens delegated to the delegator
        uint256 startRound;                      // The round the delegator transitions to bonded phase and is delegated to someone
        uint256 withdrawRound;                   // The round at which a delegator can withdraw
        uint256 lastClaimRound;                  // The last round during which the delegator claimed its earnings
    }

    // The various states a delegator can be in
    enum DelegatorStatus { Pending, Bonded, Unbonding, Unbonded }

    // Keep track of the known transcoders and delegators
    mapping (address => Delegator) private delegators;
    mapping (address => Transcoder) private transcoders;

    // Keep track of total bonded tokens
    uint256 private totalBonded;

    // Candidate and reserve transcoders
    SortedDoublyLL.Data private transcoderPool;

    // Represents the active transcoder set
    struct ActiveTranscoderSet {
        address[] transcoders;
        mapping (address => bool) isActive;
        uint256 totalStake;
    }

    // Keep track of active transcoder set for each round
    mapping (uint256 => ActiveTranscoderSet) public activeTranscoderSet;

    // Check if sender is JobsManager
    modifier onlyJobsManager() {
        require(msg.sender == controller.getContract(keccak256("JobsManager")));
        _;
    }

    // Check if sender is RoundsManager
    modifier onlyRoundsManager() {
        require(msg.sender == controller.getContract(keccak256("RoundsManager")));
        _;
    }

    // Check if current round is initialized
    modifier currentRoundInitialized() {
        require(roundsManager().currentRoundInitialized());
        _;
    }

    // Automatically claim earnings from lastClaimRound through the current round
    modifier autoClaimEarnings() {
        updateDelegatorWithEarnings(msg.sender, roundsManager().currentRound());
        _;
    }

    /**
     * @dev BondingManager constructor. Only invokes constructor of base Manager contract with provided Controller address
     * @param _controller Address of Controller that this contract will be registered with
     */
    function BondingManager(address _controller) public Manager(_controller) {}

    /**
     * @dev Set unbonding period. Only callable by Controller owner
     * @param _unbondingPeriod Rounds between unbonding and possible withdrawal
     */
    function setUnbondingPeriod(uint64 _unbondingPeriod) external onlyControllerOwner {
        unbondingPeriod = _unbondingPeriod;

        ParameterUpdate("unbondingPeriod");
    }

    /**
     * @dev Set max number of registered transcoders. Only callable by Controller owner
     * @param _numTranscoders Max number of registered transcoders
     */
    function setNumTranscoders(uint256 _numTranscoders) external onlyControllerOwner {
        // Max number of transcoders must be greater than or equal to number of active transcoders
        require(_numTranscoders >= numActiveTranscoders);

        transcoderPool.setMaxSize(_numTranscoders);

        ParameterUpdate("numTranscoders");
    }

    /**
     * @dev Set number of active transcoders. Only callable by Controller owner
     * @param _numActiveTranscoders Number of active transcoders
     */
    function setNumActiveTranscoders(uint256 _numActiveTranscoders) external onlyControllerOwner {
        // Number of active transcoders cannot exceed max number of transcoders
        require(_numActiveTranscoders <= transcoderPool.getMaxSize());

        numActiveTranscoders = _numActiveTranscoders;

        ParameterUpdate("numActiveTranscoders");
    }

    /**
     * @dev Set max number of rounds a caller can claim earnings for at once. Only callable by Controller owner
     * @param _maxEarningsClaimsRounds Max number of rounds a caller can claim earnings for at once
     */
    function setMaxEarningsClaimsRounds(uint256 _maxEarningsClaimsRounds) external onlyControllerOwner {
        maxEarningsClaimsRounds = _maxEarningsClaimsRounds;

        ParameterUpdate("maxEarningsClaimsRounds");
    }

    /**
     * @dev The sender is declaring themselves as a candidate for active transcoding.
     * @param _rewardCut % of reward paid to transcoder by a delegator
     * @param _feeShare % of fees paid to delegators by a transcoder
     * @param _pricePerSegment Price per segment (denominated in Wei) for a stream
     */
    function transcoder(uint256 _rewardCut, uint256 _feeShare, uint256 _pricePerSegment)
        external
        whenSystemNotPaused
        currentRoundInitialized
    {
        Transcoder storage t = transcoders[msg.sender];
        Delegator storage del = delegators[msg.sender];

        if (roundsManager().currentRoundLocked()) {
            // If it is the lock period of the current round
            // the lowest price previously set by any transcoder
            // becomes the price floor and the caller can lower its
            // own price to a point greater than or equal to the price floor

            // Caller must already be a registered transcoder
            require(transcoderStatus(msg.sender) == TranscoderStatus.Registered);
            // Provided rewardCut value must equal the current pendingRewardCut value
            // This value cannot change during the lock period
            require(_rewardCut == t.pendingRewardCut);
            // Provided feeShare value must equal the current pendingFeeShare value
            // This value cannot change during the lock period
            require(_feeShare == t.pendingFeeShare);

            // Iterate through the transcoder pool to find the price floor
            // Since the caller must be a registered transcoder, the transcoder pool size will always at least be 1
            // Thus, we can safely set the initial price floor to be the pendingPricePerSegment of the first
            // transcoder in the pool
            address currentTranscoder = transcoderPool.getFirst();
            uint256 priceFloor = transcoders[currentTranscoder].pendingPricePerSegment;
            for (uint256 i = 0; i < transcoderPool.getSize(); i++) {
                if (transcoders[currentTranscoder].pendingPricePerSegment < priceFloor) {
                    priceFloor = transcoders[currentTranscoder].pendingPricePerSegment;
                }

                currentTranscoder = transcoderPool.getNext(currentTranscoder);
            }

            // Provided pricePerSegment must be greater than or equal to the price floor and
            // less than or equal to the previously set pricePerSegment by the caller
            require(_pricePerSegment >= priceFloor && _pricePerSegment <= t.pendingPricePerSegment);

            t.pendingPricePerSegment = _pricePerSegment;

            TranscoderUpdate(msg.sender, t.pendingRewardCut, t.pendingFeeShare, _pricePerSegment, true);
        } else {
            // It is not the lock period of the current round
            // Caller is free to change rewardCut, feeShare, pricePerSegment as it pleases
            // If caller is not a registered transcoder, it can also register and join the transcoder pool
            // if it has sufficient delegated stake
            // If caller is not a registered transcoder and does not have sufficient delegated stake
            // to join the transcoder pool, it can change rewardCut, feeShare, pricePerSegment
            // as information signals to delegators in an effort to camapaign and accumulate
            // more delegated stake

            // Reward cut must be a valid percentage
            require(MathUtils.validPerc(_rewardCut));
            // Fee share must be a valid percentage
            require(MathUtils.validPerc(_feeShare));

            // Must have a non-zero amount bonded to self
            require(del.delegateAddress == msg.sender && del.bondedAmount > 0);

            t.pendingRewardCut = _rewardCut;
            t.pendingFeeShare = _feeShare;
            t.pendingPricePerSegment = _pricePerSegment;

            uint256 delegatedAmount = del.delegatedAmount;

            // Check if transcoder is not already registered
            if (transcoderStatus(msg.sender) == TranscoderStatus.NotRegistered) {
                if (!transcoderPool.isFull()) {
                    // If pool is not full add new transcoder
                    transcoderPool.insert(msg.sender, delegatedAmount, address(0), address(0));
                } else {
                    address lastTranscoder = transcoderPool.getLast();

                    if (delegatedAmount > transcoderPool.getKey(lastTranscoder)) {
                        // If pool is full and caller has more delegated stake than the transcoder in the pool with the least delegated stake:
                        // - Evict transcoder in pool with least delegated stake
                        // - Add caller to pool
                        transcoderPool.remove(lastTranscoder);
                        transcoderPool.insert(msg.sender, delegatedAmount, address(0), address(0));

                        TranscoderEvicted(lastTranscoder);
                    }
                }
            }

            TranscoderUpdate(msg.sender, _rewardCut, _feeShare, _pricePerSegment, transcoderPool.contains(msg.sender));
        }
    }

    /**
     * @dev Delegate stake towards a specific address.
     * @param _amount The amount of LPT to stake.
     * @param _to The address of the transcoder to stake towards.
     */
    function bond(
        uint256 _amount,
        address _to
    )
        external
        whenSystemNotPaused
        currentRoundInitialized
        autoClaimEarnings
    {
        Delegator storage del = delegators[msg.sender];

        uint256 currentRound = roundsManager().currentRound();
        // Amount to delegate
        uint256 delegationAmount = _amount;

        if (delegatorStatus(msg.sender) == DelegatorStatus.Unbonded || delegatorStatus(msg.sender) == DelegatorStatus.Unbonding) {
            // New delegate
            // Set start round
            // Don't set start round if delegator is in pending state because the start round would not change
            del.startRound = currentRound.add(1);
            // If transitioning from unbonding or unbonded state
            // make sure to zero out withdraw round
            del.withdrawRound = 0;
            // Unbonded or unbonding state = no existing delegate
            // Thus, delegation amount = bonded stake + provided amount
            // If caller is bonding for the first time or withdrew previously bonded stake, delegation amount = provided amount
            delegationAmount = delegationAmount.add(del.bondedAmount);
        } else if (del.delegateAddress != address(0) && _to != del.delegateAddress) {
            // A registered transcoder cannot delegate its bonded stake toward another address
            // because it can only be delegated toward itself
            // In the future, if delegation towards another registered transcoder as an already
            // registered transcoder becomes useful (i.e. for transitive delegation), this restriction
            // could be removed
            require(transcoderStatus(msg.sender) == TranscoderStatus.NotRegistered);
            // Changing delegate
            // Set start round
            del.startRound = currentRound.add(1);
            // Update amount to delegate with previous delegation amount
            delegationAmount = delegationAmount.add(del.bondedAmount);
            // Decrease old delegate's delegated amount
            delegators[del.delegateAddress].delegatedAmount = delegators[del.delegateAddress].delegatedAmount.sub(del.bondedAmount);

            if (transcoderStatus(del.delegateAddress) == TranscoderStatus.Registered) {
                // Previously delegated to a transcoder
                // Decrease old transcoder's total stake
                transcoderPool.updateKey(del.delegateAddress, transcoderPool.getKey(del.delegateAddress).sub(del.bondedAmount), address(0), address(0));
            }
        }

        // Delegation amount must be > 0 - cannot delegate to someone without having bonded stake
        require(delegationAmount > 0);
        // Update delegate
        del.delegateAddress = _to;
        // Update current delegate's delegated amount with delegation amount
        delegators[_to].delegatedAmount = delegators[_to].delegatedAmount.add(delegationAmount);

        if (transcoderStatus(_to) == TranscoderStatus.Registered) {
            // Delegated to a transcoder
            // Increase transcoder's total stake
            transcoderPool.updateKey(_to, transcoderPool.getKey(del.delegateAddress).add(delegationAmount), address(0), address(0));
        }

        if (_amount > 0) {
            // Update bonded amount
            del.bondedAmount = del.bondedAmount.add(_amount);
            // Update total bonded tokens
            totalBonded = totalBonded.add(_amount);
            // Transfer the LPT to the Minter
            livepeerToken().transferFrom(msg.sender, minter(), _amount);
        }

        Bond(_to, msg.sender);
    }

    /**
     * @dev Unbond delegator's current stake. Delegator enters unbonding state
     */
    function unbond()
        external
        whenSystemNotPaused
        currentRoundInitialized
        autoClaimEarnings
    {
        // Sender must be in bonded state
        require(delegatorStatus(msg.sender) == DelegatorStatus.Bonded);

        Delegator storage del = delegators[msg.sender];

        uint256 currentRound = roundsManager().currentRound();

        // Transition to unbonding phase
        del.withdrawRound = currentRound.add(unbondingPeriod);
        // Decrease delegate's delegated amount
        delegators[del.delegateAddress].delegatedAmount = delegators[del.delegateAddress].delegatedAmount.sub(del.bondedAmount);
        // Update total bonded tokens
        totalBonded = totalBonded.sub(del.bondedAmount);

        if (transcoderStatus(msg.sender) == TranscoderStatus.Registered) {
            // If caller is a registered transcoder, resign
            // In the future, with partial unbonding there would be a check for 0 bonded stake as well
            resignTranscoder(msg.sender);
        }

        if (del.delegateAddress != msg.sender && transcoderStatus(del.delegateAddress) == TranscoderStatus.Registered) {
            // If delegate is not self and is a registered transcoder, decrease its delegated stake
            // We do not need to decrease delegated stake if delegate is self because we would have already removed self
            // from the transcoder pool
            transcoderPool.updateKey(del.delegateAddress, transcoderPool.getKey(del.delegateAddress).sub(del.bondedAmount), address(0), address(0));
        }

        // Delegator no longer bonded to anyone
        del.delegateAddress = address(0);
        // Unbonding delegator does not have a start round
        del.startRound = 0;

        Unbond(del.delegateAddress, msg.sender);
    }

    /**
     * @dev Withdraws bonded stake to the caller after unbonding period.
     */
    function withdrawStake()
        external
        whenSystemNotPaused
        currentRoundInitialized
    {
        // Delegator must be in the unbonded state
        require(delegatorStatus(msg.sender) == DelegatorStatus.Unbonded);

        uint256 amount = delegators[msg.sender].bondedAmount;
        delegators[msg.sender].bondedAmount = 0;
        delegators[msg.sender].withdrawRound = 0;

        // Tell Minter to transfer stake (LPT) to the delegator
        minter().trustedTransferTokens(msg.sender, amount);

        WithdrawStake(msg.sender);
    }

    /**
     * @dev Withdraws fees to the caller
     */
    function withdrawFees()
        external
        whenSystemNotPaused
        currentRoundInitialized
        autoClaimEarnings
    {
        // Delegator must have fees
        require(delegators[msg.sender].fees > 0);

        uint256 amount = delegators[msg.sender].fees;
        delegators[msg.sender].fees = 0;

        // Tell Minter to transfer fees (ETH) to the delegator
        minter().trustedWithdrawETH(msg.sender, amount);

        WithdrawFees(msg.sender);
    }

    /**
     * @dev Set active transcoder set for the current round
     */
    function setActiveTranscoders() external whenSystemNotPaused onlyRoundsManager {
        uint256 currentRound = roundsManager().currentRound();
        uint256 activeSetSize = Math.min256(numActiveTranscoders, transcoderPool.getSize());

        uint256 totalStake = 0;
        address currentTranscoder = transcoderPool.getFirst();

        for (uint256 i = 0; i < activeSetSize; i++) {
            activeTranscoderSet[currentRound].transcoders.push(currentTranscoder);
            activeTranscoderSet[currentRound].isActive[currentTranscoder] = true;

            uint256 stake = transcoderPool.getKey(currentTranscoder);
            uint256 rewardCut = transcoders[currentTranscoder].pendingRewardCut;
            uint256 feeShare = transcoders[currentTranscoder].pendingFeeShare;
            uint256 pricePerSegment = transcoders[currentTranscoder].pendingPricePerSegment;

            Transcoder storage t = transcoders[currentTranscoder];
            // Set pending rates as current rates
            t.rewardCut = rewardCut;
            t.feeShare = feeShare;
            t.pricePerSegment = pricePerSegment;
            // Initialize token pool
            t.earningsPoolPerRound[currentRound].init(stake, rewardCut, feeShare);

            totalStake = totalStake.add(stake);

            // Get next transcoder in the pool
            currentTranscoder = transcoderPool.getNext(currentTranscoder);
        }

        // Update total stake of all active transcoders
        activeTranscoderSet[currentRound].totalStake = totalStake;
    }

    /**
     * @dev Distribute the token rewards to transcoder and delegates.
     * Active transcoders call this once per cycle when it is their turn.
     */
    function reward() external whenSystemNotPaused currentRoundInitialized {
        uint256 currentRound = roundsManager().currentRound();

        // Sender must be an active transcoder
        require(activeTranscoderSet[currentRound].isActive[msg.sender]);

        // Transcoder must not have called reward for this round already
        require(transcoders[msg.sender].lastRewardRound != currentRound);
        // Set last round that transcoder called reward
        transcoders[msg.sender].lastRewardRound = currentRound;

        // Create reward based on active transcoder's stake relative to the total active stake
        // rewardTokens = (current mintable tokens for the round * active transcoder stake) / total active stake
        uint256 rewardTokens = minter().createReward(activeTranscoderTotalStake(msg.sender, currentRound), activeTranscoderSet[currentRound].totalStake);

        updateTranscoderWithRewards(msg.sender, rewardTokens, currentRound);

        Reward(msg.sender, rewardTokens);
    }

    /**
     * @dev Update transcoder's fee pool
     * @param _transcoder Transcoder address
     * @param _fees Fees from verified job claims
     */
    function updateTranscoderWithFees(
        address _transcoder,
        uint256 _fees,
        uint256 _round
    )
        external
        whenSystemNotPaused
        onlyJobsManager
    {
        // Transcoder must be registered
        require(transcoderStatus(_transcoder) == TranscoderStatus.Registered);

        Transcoder storage t = transcoders[_transcoder];

        EarningsPool.Data storage earningsPool = t.earningsPoolPerRound[_round];
        // Add fees to fee pool
        earningsPool.feePool = earningsPool.feePool.add(_fees);
    }

    /**
     * @dev Slash a transcoder. Slashing can be invoked by the protocol or a finder.
     * @param _transcoder Transcoder address
     * @param _finder Finder that proved a transcoder violated a slashing condition. Null address if there is no finder
     * @param _slashAmount Percentage of transcoder bond to be slashed
     * @param _finderFee Percentage of penalty awarded to finder. Zero if there is no finder
     */
    function slashTranscoder(
        address _transcoder,
        address _finder,
        uint256 _slashAmount,
        uint256 _finderFee
    )
        external
        whenSystemNotPaused
        onlyJobsManager
    {
        Delegator storage del = delegators[_transcoder];

        if (del.bondedAmount > 0) {
            uint256 penalty = MathUtils.percOf(delegators[_transcoder].bondedAmount, _slashAmount);

            // Decrease bonded stake
            del.bondedAmount = del.bondedAmount.sub(penalty);

            // If still bonded
            // - Decrease delegate's delegated amount
            // - Decrease total bonded tokens
            if (delegatorStatus(_transcoder) == DelegatorStatus.Bonded) {
                delegators[del.delegateAddress].delegatedAmount = delegators[del.delegateAddress].delegatedAmount.sub(penalty);
                totalBonded = totalBonded.sub(penalty);
            }

            // If registered transcoder, resign it
            if (transcoderStatus(_transcoder) == TranscoderStatus.Registered) {
                resignTranscoder(_transcoder);
            }

            // Account for penalty
            uint256 burnAmount = penalty;

            // Award finder fee if there is a finder address
            if (_finder != address(0)) {
                uint256 finderAmount = MathUtils.percOf(penalty, _finderFee);
                minter().trustedTransferTokens(_finder, finderAmount);

                // Minter burns the slashed funds - finder reward
                minter().trustedBurnTokens(burnAmount.sub(finderAmount));

                TranscoderSlashed(_transcoder, _finder, penalty, finderAmount);
            } else {
                // Minter burns the slashed funds
                minter().trustedBurnTokens(burnAmount);

                TranscoderSlashed(_transcoder, address(0), penalty, 0);
            }
        } else {
            TranscoderSlashed(_transcoder, _finder, 0, 0);
        }
    }

    /**
     * @dev Pseudorandomly elect a currently active transcoder that charges a price per segment less than or equal to the max price per segment for a job
     * Returns address of elected active transcoder and its price per segment
     * @param _maxPricePerSegment Max price (in LPT base units) per segment of a stream
     * @param _blockHash Job creation block hash used as a pseudorandom seed for assigning an active transcoder
     * @param _round Job creation round
     */
    function electActiveTranscoder(uint256 _maxPricePerSegment, bytes32 _blockHash, uint256 _round) external view returns (address) {
        uint256 activeSetSize = activeTranscoderSet[_round].transcoders.length;
        // Create array to store available transcoders charging an acceptable price per segment
        address[] memory availableTranscoders = new address[](activeSetSize);
        // Keep track of the actual number of available transcoders
        uint256 numAvailableTranscoders = 0;
        // Keep track of total stake of available transcoders
        uint256 totalAvailableTranscoderStake = 0;

        for (uint256 i = 0; i < activeSetSize; i++) {
            address activeTranscoder = activeTranscoderSet[_round].transcoders[i];
            // If a transcoder is active and charges an acceptable price per segment add it to the array of available transcoders
            if (activeTranscoderSet[_round].isActive[activeTranscoder] && transcoders[activeTranscoder].pricePerSegment <= _maxPricePerSegment) {
                availableTranscoders[numAvailableTranscoders] = activeTranscoder;
                numAvailableTranscoders++;
                totalAvailableTranscoderStake = totalAvailableTranscoderStake.add(activeTranscoderTotalStake(activeTranscoder, _round));
            }
        }

        if (numAvailableTranscoders == 0) {
            // There is no currently available transcoder that charges a price per segment less than or equal to the max price per segment for a job
            return address(0);
        } else {
            // Pseudorandomly pick an available transcoder weighted by its stake relative to the total stake of all available transcoders
            uint256 r = uint256(_blockHash) % totalAvailableTranscoderStake;
            uint256 s = 0;
            uint256 j = 0;

            while (s <= r && j < numAvailableTranscoders) {
                s = s.add(activeTranscoderTotalStake(availableTranscoders[j], _round));
                j++;
            }

            return availableTranscoders[j - 1];
        }
    }

    /**
     * @dev Claim token pools shares for a delegator from its lastClaimRound through the end round
     * @param _endRound The last round for which to claim token pools shares for a delegator
     */
    function claimEarnings(uint256 _endRound) external whenSystemNotPaused currentRoundInitialized {
        // End round must be after the last claim round
        require(delegators[msg.sender].lastClaimRound < _endRound);
        // End round must not be after the current round
        require(_endRound <= roundsManager().currentRound());

        updateDelegatorWithEarnings(msg.sender, _endRound);
    }

    /**
     * @dev Returns pending bonded stake for a delegator from its lastClaimRound through an end round
     * @param _delegator Address of delegator
     * @param _endRound The last round to compute pending stake from
     */
    function pendingStake(address _delegator, uint256 _endRound) public view returns (uint256) {
        uint256 currentRound = roundsManager().currentRound();
        Delegator storage del = delegators[_delegator];
        // End round must be before or equal to current round and after lastClaimRound
        require(_endRound <= currentRound && _endRound > del.lastClaimRound);

        uint256 currentBondedAmount = del.bondedAmount;

        for (uint256 i = del.lastClaimRound + 1; i <= _endRound; i++) {
            EarningsPool.Data storage earningsPool = transcoders[del.delegateAddress].earningsPoolPerRound[i];

            bool isTranscoder = _delegator == del.delegateAddress;
            if (earningsPool.hasClaimableShares()) {
                // Calculate and add reward pool share from this round
                currentBondedAmount = currentBondedAmount.add(earningsPool.rewardPoolShare(currentBondedAmount, isTranscoder));
            }
        }

        return currentBondedAmount;
    }

    /**
     * @dev Returns pending fees for a delegator from its lastClaimRound through an end round
     * @param _delegator Address of delegator
     * @param _endRound The last round to compute pending fees from
     */
    function pendingFees(address _delegator, uint256 _endRound) public view returns (uint256) {
        uint256 currentRound = roundsManager().currentRound();
        Delegator storage del = delegators[_delegator];
        // End round must be before or equal to current round and after lastClaimRound
        require(_endRound <= currentRound && _endRound > del.lastClaimRound);

        uint256 currentFees = del.fees;
        uint256 currentBondedAmount = del.bondedAmount;

        for (uint256 i = del.lastClaimRound + 1; i <= _endRound; i++) {
            EarningsPool.Data storage earningsPool = transcoders[del.delegateAddress].earningsPoolPerRound[i];

            if (earningsPool.hasClaimableShares()) {
                bool isTranscoder = _delegator == del.delegateAddress;
                // Calculate and add fee pool share from this round
                currentFees = currentFees.add(earningsPool.feePoolShare(currentBondedAmount, isTranscoder));
                // Calculate new bonded amount with rewards from this round. Updated bonded amount used
                // to calculate fee pool share in next round
                currentBondedAmount = currentBondedAmount.add(earningsPool.rewardPoolShare(currentBondedAmount, isTranscoder));
            }
        }

        return currentFees;
    }

    /**
     * @dev Returns total bonded stake for an active transcoder
     * @param _transcoder Address of a transcoder
     */
    function activeTranscoderTotalStake(address _transcoder, uint256 _round) public view returns (uint256) {
        // Must be active transcoder
        require(activeTranscoderSet[_round].isActive[_transcoder]);

        return transcoders[_transcoder].earningsPoolPerRound[_round].totalStake;
    }

    /**
     * @dev Returns total bonded stake for a transcoder
     * @param _transcoder Address of transcoder
     */
    function transcoderTotalStake(address _transcoder) public view returns (uint256) {
        return transcoderPool.getKey(_transcoder);
    }

    /*
     * @dev Computes transcoder status
     * @param _transcoder Address of transcoder
     */
    function transcoderStatus(address _transcoder) public view returns (TranscoderStatus) {
        if (transcoderPool.contains(_transcoder)) {
            return TranscoderStatus.Registered;
        } else {
            return TranscoderStatus.NotRegistered;
        }
    }

    /**
     * @dev Computes delegator status
     * @param _delegator Address of delegator
     */
    function delegatorStatus(address _delegator) public view returns (DelegatorStatus) {
        Delegator storage del = delegators[_delegator];

        if (del.withdrawRound > 0) {
            // Delegator called unbond
            if (roundsManager().currentRound() >= del.withdrawRound) {
                return DelegatorStatus.Unbonded;
            } else {
                return DelegatorStatus.Unbonding;
            }
        } else if (del.startRound > roundsManager().currentRound()) {
            // Delegator round start is in the future
            return DelegatorStatus.Pending;
        } else if (del.startRound > 0 && del.startRound <= roundsManager().currentRound()) {
            // Delegator round start is now or in the past
            return DelegatorStatus.Bonded;
        } else {
            // Default to unbonded
            return DelegatorStatus.Unbonded;
        }
    }

    /**
     * @dev Return transcoder information
     * @param _transcoder Address of transcoder
     */
    function getTranscoder(
        address _transcoder
    )
        public
        view
        returns (uint256 lastRewardRound, uint256 rewardCut, uint256 feeShare, uint256 pricePerSegment, uint256 pendingRewardCut, uint256 pendingFeeShare, uint256 pendingPricePerSegment)
    {
        Transcoder storage t = transcoders[_transcoder];

        lastRewardRound = t.lastRewardRound;
        rewardCut = t.rewardCut;
        feeShare = t.feeShare;
        pricePerSegment = t.pricePerSegment;
        pendingRewardCut = t.pendingRewardCut;
        pendingFeeShare = t.pendingFeeShare;
        pendingPricePerSegment = t.pendingPricePerSegment;
    }

    /**
     * @dev Return transcoder's token pools for a given round
     * @param _transcoder Address of transcoder
     * @param _round Round number
     */
    function getTranscoderEarningsPoolForRound(
        address _transcoder,
        uint256 _round
    )
        public
        view
        returns (uint256 rewardPool, uint256 feePool, uint256 totalStake, uint256 claimableStake)
    {
        EarningsPool.Data storage earningsPool = transcoders[_transcoder].earningsPoolPerRound[_round];

        rewardPool = earningsPool.rewardPool;
        feePool = earningsPool.feePool;
        totalStake = earningsPool.totalStake;
        claimableStake = earningsPool.claimableStake;
    }

    /**
     * @dev Return delegator info
     * @param _delegator Address of delegator
     */
    function getDelegator(
        address _delegator
    )
        public
        view
        returns (uint256 bondedAmount, uint256 fees, address delegateAddress, uint256 delegatedAmount, uint256 startRound, uint256 withdrawRound, uint256 lastClaimRound)
    {
        Delegator storage del = delegators[_delegator];

        bondedAmount = del.bondedAmount;
        fees = del.fees;
        delegateAddress = del.delegateAddress;
        delegatedAmount = del.delegatedAmount;
        startRound = del.startRound;
        withdrawRound = del.withdrawRound;
        lastClaimRound = del.lastClaimRound;
    }

    /**
     * @dev Returns max size of transcoder pool
     */
    function getTranscoderPoolMaxSize() public view returns (uint256) {
        return transcoderPool.getMaxSize();
    }

    /**
     * @dev Returns size of transcoder pool
     */
    function getTranscoderPoolSize() public view returns (uint256) {
        return transcoderPool.getSize();
    }

    /**
     * @dev Returns transcoder with most stake in pool
     */
    function getFirstTranscoderInPool() public view returns (address) {
        return transcoderPool.getFirst();
    }

    /**
     * @dev Returns next transcoder in pool for a given transcoder
     * @param _transcoder Address of a transcoder in the pool
     */
    function getNextTranscoderInPool(address _transcoder) public view returns (address) {
        return transcoderPool.getNext(_transcoder);
    }

    /**
     * @dev Return total bonded tokens
     */
    function getTotalBonded() public view returns (uint256) {
        return totalBonded;
    }

    /**
     * @dev Return total active stake for a round
     * @param _round Round number
     */
    function getTotalActiveStake(uint256 _round) public view returns (uint256) {
        return activeTranscoderSet[_round].totalStake;
    }

    /**
     * @dev Return whether a transcoder was active during a round
     * @param _transcoder Transcoder address
     * @param _round Round number
     */
    function isActiveTranscoder(address _transcoder, uint256 _round) public view returns (bool) {
        return activeTranscoderSet[_round].isActive[_transcoder];
    }

    /**
     * @dev Return whether a transcoder is registered
     * @param _transcoder Transcoder address
     */
    function isRegisteredTranscoder(address _transcoder) public view returns (bool) {
        return transcoderStatus(_transcoder) == TranscoderStatus.Registered;
    }

    /**
     * @dev Remove transcoder
     */
    function resignTranscoder(address _transcoder) internal {
        uint256 currentRound = roundsManager().currentRound();
        if (activeTranscoderSet[currentRound].isActive[_transcoder]) {
            // Decrease total active stake for the round
            activeTranscoderSet[currentRound].totalStake = activeTranscoderSet[currentRound].totalStake.sub(activeTranscoderTotalStake(_transcoder, currentRound));
            // Set transcoder as inactive
            activeTranscoderSet[currentRound].isActive[_transcoder] = false;
        }

        // Remove transcoder from pools
        transcoderPool.remove(_transcoder);

        TranscoderResigned(_transcoder);
    }

    /**
     * @dev Update a transcoder with rewards
     * @param _transcoder Address of transcoder
     * @param _rewards Amount of rewards
     * @param _round Round that transcoder is updated
     */
    function updateTranscoderWithRewards(address _transcoder, uint256 _rewards, uint256 _round) internal {
        Transcoder storage t = transcoders[_transcoder];
        Delegator storage del = delegators[_transcoder];

        EarningsPool.Data storage earningsPool = t.earningsPoolPerRound[_round];
        // Add rewards to reward pool
        earningsPool.rewardPool = earningsPool.rewardPool.add(_rewards);
        // Update transcoder's delegated amount with rewards
        del.delegatedAmount = del.delegatedAmount.add(_rewards);
        // Update transcoder's total stake with rewards
        uint256 newStake = transcoderPool.getKey(_transcoder).add(_rewards);
        transcoderPool.updateKey(_transcoder, newStake, address(0), address(0));
        // Update total bonded tokens with claimable rewards
        totalBonded = totalBonded.add(_rewards);
    }

    /**
     * @dev Update a delegator with token pools shares from its lastClaimRound through a given round
     * @param _delegator Delegator address
     * @param _endRound The last round for which to update a delegator's stake with token pools shares
     */
    function updateDelegatorWithEarnings(address _delegator, uint256 _endRound) internal {
        Delegator storage del = delegators[_delegator];

        // Only will have earnings to claim if you have a delegate
        // If not delegated, skip the earnings claim process
        if (del.delegateAddress != address(0)) {
            // Cannot claim earnings for more than maxEarningsClaimsRounds
            // This is a number to cause transactions to fail early if
            // we know they will require too much gas to loop through all the necessary rounds to claim earnings
            // The user should instead manually invoke `claimEarnings` to split up the claiming process
            // across multiple transactions
            require(_endRound.sub(del.lastClaimRound) <= maxEarningsClaimsRounds);

            uint256 currentBondedAmount = del.bondedAmount;
            uint256 currentFees = del.fees;

            for (uint256 i = del.lastClaimRound + 1; i <= _endRound; i++) {
                EarningsPool.Data storage earningsPool = transcoders[del.delegateAddress].earningsPoolPerRound[i];

                if (earningsPool.hasClaimableShares()) {
                    bool isTranscoder = _delegator == del.delegateAddress;

                    var (fees, rewards) = earningsPool.claimShare(currentBondedAmount, isTranscoder);

                    currentFees = currentFees.add(fees);
                    currentBondedAmount = currentBondedAmount.add(rewards);
                }
            }

            // Rewards are bonded by default
            del.bondedAmount = currentBondedAmount;
            del.fees = currentFees;
        }

        del.lastClaimRound = _endRound;
    }

    /**
     * @dev Return LivepeerToken interface
     */
    function livepeerToken() internal view returns (ILivepeerToken) {
        return ILivepeerToken(controller.getContract(keccak256("LivepeerToken")));
    }

    /**
     * @dev Return Minter interface
     */
    function minter() internal view returns (IMinter) {
        return IMinter(controller.getContract(keccak256("Minter")));
    }

    /**
     * @dev Return RoundsManager interface
     */
    function roundsManager() internal view returns (IRoundsManager) {
        return IRoundsManager(controller.getContract(keccak256("RoundsManager")));
    }
}

Contract Security Audit

Contract ABI

API
[{"constant":true,"inputs":[],"name":"maxEarningsClaimsRounds","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_delegator","type":"address"}],"name":"delegatorStatus","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"reward","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_transcoder","type":"address"},{"name":"_finder","type":"address"},{"name":"_slashAmount","type":"uint256"},{"name":"_finderFee","type":"uint256"}],"name":"slashTranscoder","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_transcoder","type":"address"}],"name":"getNextTranscoderInPool","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"setActiveTranscoders","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_transcoder","type":"address"},{"name":"_round","type":"uint256"}],"name":"getTranscoderEarningsPoolForRound","outputs":[{"name":"rewardPool","type":"uint256"},{"name":"feePool","type":"uint256"},{"name":"totalStake","type":"uint256"},{"name":"claimableStake","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_endRound","type":"uint256"}],"name":"claimEarnings","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getTranscoderPoolSize","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_transcoder","type":"address"},{"name":"_fees","type":"uint256"},{"name":"_round","type":"uint256"}],"name":"updateTranscoderWithFees","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"activeTranscoderSet","outputs":[{"name":"totalStake","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"withdrawFees","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"targetContractId","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getTranscoderPoolMaxSize","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getTotalBonded","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_transcoder","type":"address"}],"name":"getTranscoder","outputs":[{"name":"lastRewardRound","type":"uint256"},{"name":"rewardCut","type":"uint256"},{"name":"feeShare","type":"uint256"},{"name":"pricePerSegment","type":"uint256"},{"name":"pendingRewardCut","type":"uint256"},{"name":"pendingFeeShare","type":"uint256"},{"name":"pendingPricePerSegment","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"unbond","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_numTranscoders","type":"uint256"}],"name":"setNumTranscoders","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"numActiveTranscoders","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_numActiveTranscoders","type":"uint256"}],"name":"setNumActiveTranscoders","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_transcoder","type":"address"}],"name":"isRegisteredTranscoder","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"unbondingPeriod","outputs":[{"name":"","type":"uint64"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_maxEarningsClaimsRounds","type":"uint256"}],"name":"setMaxEarningsClaimsRounds","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_round","type":"uint256"}],"name":"getTotalActiveStake","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_transcoder","type":"address"},{"name":"_round","type":"uint256"}],"name":"isActiveTranscoder","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_rewardCut","type":"uint256"},{"name":"_feeShare","type":"uint256"},{"name":"_pricePerSegment","type":"uint256"}],"name":"transcoder","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getFirstTranscoderInPool","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_transcoder","type":"address"}],"name":"transcoderStatus","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_maxPricePerSegment","type":"uint256"},{"name":"_blockHash","type":"bytes32"},{"name":"_round","type":"uint256"}],"name":"electActiveTranscoder","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_controller","type":"address"}],"name":"setController","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_delegator","type":"address"},{"name":"_endRound","type":"uint256"}],"name":"pendingStake","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_transcoder","type":"address"}],"name":"transcoderTotalStake","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_delegator","type":"address"}],"name":"getDelegator","outputs":[{"name":"bondedAmount","type":"uint256"},{"name":"fees","type":"uint256"},{"name":"delegateAddress","type":"address"},{"name":"delegatedAmount","type":"uint256"},{"name":"startRound","type":"uint256"},{"name":"withdrawRound","type":"uint256"},{"name":"lastClaimRound","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_amount","type":"uint256"},{"name":"_to","type":"address"}],"name":"bond","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"withdrawStake","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_unbondingPeriod","type":"uint64"}],"name":"setUnbondingPeriod","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_transcoder","type":"address"},{"name":"_round","type":"uint256"}],"name":"activeTranscoderTotalStake","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_delegator","type":"address"},{"name":"_endRound","type":"uint256"}],"name":"pendingFees","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"controller","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"_controller","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"transcoder","type":"address"},{"indexed":false,"name":"pendingRewardCut","type":"uint256"},{"indexed":false,"name":"pendingFeeShare","type":"uint256"},{"indexed":false,"name":"pendingPricePerSegment","type":"uint256"},{"indexed":false,"name":"registered","type":"bool"}],"name":"TranscoderUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"transcoder","type":"address"}],"name":"TranscoderEvicted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"transcoder","type":"address"}],"name":"TranscoderResigned","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"transcoder","type":"address"},{"indexed":false,"name":"finder","type":"address"},{"indexed":false,"name":"penalty","type":"uint256"},{"indexed":false,"name":"finderReward","type":"uint256"}],"name":"TranscoderSlashed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"transcoder","type":"address"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"Reward","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"delegate","type":"address"},{"indexed":true,"name":"delegator","type":"address"}],"name":"Bond","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"delegate","type":"address"},{"indexed":true,"name":"delegator","type":"address"}],"name":"Unbond","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"delegator","type":"address"}],"name":"WithdrawStake","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"delegator","type":"address"}],"name":"WithdrawFees","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"controller","type":"address"}],"name":"SetController","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"param","type":"string"}],"name":"ParameterUpdate","type":"event"}]

6060604052341561000f57600080fd5b6040516020806148308339810160405280805160008054600160a060020a03909216600160a060020a031990921691909117905550506147dc806100546000396000f3006060604052600436106101c95763ffffffff60e060020a600035041663038424c381146101ce5780631544fc67146101f3578063228cb7331461023657806322bf9d7c1461024b578063235c960314610276578063242ed69f146102b157806324454fc4146102c457806324b1babf146103115780632a4e0d55146103275780633aeb512c1461033a5780633da1c2f51461035f578063476343ee1461037557806351720b41146103885780635a2a75a91461039b5780635c50c356146103ae5780635dce9948146103c15780635df6a6bc1461041e57806360c79d001461043157806361e25d2314610447578063673a456b1461045a57806368ba170c146104705780636cf6d675146104a357806372d9f13d146104d357806377517765146104e95780637c0207cb146104ff57806385aaff621461052157806388a6c7491461053d5780638b2f16521461055057806391fdf6b11461057f57806392eefe9b1461059b5780639d0b2c7a146105ba5780639ef9df94146105dc578063a64ad595146105fb578063b78d27dc1461066c578063bed9d8611461068e578063f10d1de1146106a1578063f2083220146106c1578063f595f1cc146106e3578063f77c479114610705575b600080fd5b34156101d957600080fd5b6101e1610718565b60405190815260200160405180910390f35b34156101fe57600080fd5b610212600160a060020a036004351661071e565b6040518082600381111561022257fe5b60ff16815260200191505060405180910390f35b341561024157600080fd5b6102496108de565b005b341561025657600080fd5b610249600160a060020a0360043581169060243516604435606435610b7d565b341561028157600080fd5b610295600160a060020a0360043516611050565b604051600160a060020a03909116815260200160405180910390f35b34156102bc57600080fd5b6102496110db565b34156102cf57600080fd5b6102e6600160a060020a0360043516602435611644565b6040518085815260200184815260200183815260200182815260200194505050505060405180910390f35b341561031c57600080fd5b610249600435611685565b341561033257600080fd5b6101e161180f565b341561034557600080fd5b610249600160a060020a0360043516602435604435611889565b341561036a57600080fd5b6101e1600435611a1e565b341561038057600080fd5b610249611a33565b341561039357600080fd5b6101e1611c73565b34156103a657600080fd5b6101e1611c79565b34156103b957600080fd5b6101e1611cd3565b34156103cc57600080fd5b6103e0600160a060020a0360043516611cd9565b60405196875260208701959095526040808701949094526060860192909252608085015260a084015260c083019190915260e0909101905180910390f35b341561042957600080fd5b610249611d22565b341561043c57600080fd5b610249600435612133565b341561045257600080fd5b6101e1612285565b341561046557600080fd5b61024960043561228b565b341561047b57600080fd5b61048f600160a060020a03600435166123e9565b604051901515815260200160405180910390f35b34156104ae57600080fd5b6104b6612408565b60405167ffffffffffffffff909116815260200160405180910390f35b34156104de57600080fd5b610249600435612418565b34156104f457600080fd5b6101e16004356124f6565b341561050a57600080fd5b61048f600160a060020a036004351660243561250b565b341561052c57600080fd5b610249600435602435604435612539565b341561054857600080fd5b610295612e2f565b341561055b57600080fd5b61056f600160a060020a0360043516612e89565b6040518082600181111561022257fe5b341561058a57600080fd5b610295600435602435604435612f22565b34156105a657600080fd5b610249600160a060020a03600435166130f3565b34156105c557600080fd5b6101e1600160a060020a0360043516602435613176565b34156105e757600080fd5b6101e1600160a060020a03600435166132b6565b341561060657600080fd5b61061a600160a060020a036004351661331f565b6040518088815260200187815260200186600160a060020a0316600160a060020a0316815260200185815260200184815260200183815260200182815260200197505050505050505060405180910390f35b341561067757600080fd5b610249600435600160a060020a036024351661336c565b341561069957600080fd5b610249613a03565b34156106ac57600080fd5b61024967ffffffffffffffff60043516613bd1565b34156106cc57600080fd5b6101e1600160a060020a0360043516602435613cc7565b34156106ee57600080fd5b6101e1600160a060020a0360043516602435613d2b565b341561071057600080fd5b610295613e97565b60045481565b600160a060020a0381166000908152600560208190526040822090810154829011156107ca578060050154610751613ea6565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561079657600080fd5b6102c65a03f115156107a757600080fd5b505050604051805190501015156107c157600391506108d8565b600291506108d8565b6107d2613ea6565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561081757600080fd5b6102c65a03f1151561082857600080fd5b505050604051805190508160040154111561084657600091506108d8565b600081600401541180156108c5575061085d613ea6565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156108a257600080fd5b6102c65a03f115156108b357600080fd5b50505060405180519050816004015411155b156108d357600191506108d8565b600391505b50919050565b600080548190600160a060020a0316635c975abb82604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561092857600080fd5b6102c65a03f1151561093957600080fd5b505050604051805115905061094d57600080fd5b610955613ea6565b600160a060020a031663219bc76c6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561099a57600080fd5b6102c65a03f115156109ab57600080fd5b5050506040518051905015156109c057600080fd5b6109c8613ea6565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515610a0d57600080fd5b6102c65a03f11515610a1e57600080fd5b50505060405180516000818152600d60209081526040808320600160a060020a033316845260010190915290205490935060ff1615159050610a5f57600080fd5b600160a060020a033316600090815260066020526040902054821415610a8457600080fd5b600160a060020a0333166000908152600660205260409020829055610aa7613f39565b600160a060020a0316637dbedad5610abf3385613cc7565b6000858152600d6020526040808220600201549190516020015260405160e060020a63ffffffff851602815260048101929092526024820152604401602060405180830381600087803b1515610b1457600080fd5b6102c65a03f11515610b2557600080fd5b505050604051805190509050610b3c338284613fbb565b33600160a060020a03167f619caafabdd75649b302ba8419e48cccf64f37f1983ac4727cfb38b57703ffc98260405190815260200160405180910390a25050565b60008054819081908190600160a060020a0316635c975abb82604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515610bcb57600080fd5b6102c65a03f11515610bdc57600080fd5b5050506040518051159050610bf057600080fd5b600054600160a060020a031663e16c7d986040517f4a6f62734d616e616765720000000000000000000000000000000000000000008152600b01604051809103902060006040516020015260405160e060020a63ffffffff84160281526004810191909152602401602060405180830381600087803b1515610c7157600080fd5b6102c65a03f11515610c8257600080fd5b50505060405180519050600160a060020a031633600160a060020a0316141515610cab57600080fd5b600160a060020a038816600090815260056020526040812080549095501115610fe157600160a060020a038816600090815260056020526040902054610cf19087614137565b8454909350610d06908463ffffffff61416316565b84556001610d138961071e565b6003811115610d1e57fe5b1415610d8b576002840154600160a060020a0316600090815260056020526040902060030154610d54908463ffffffff61416316565b6002850154600160a060020a0316600090815260056020526040902060030155600754610d87908463ffffffff61416316565b6007555b6001610d9689612e89565b6001811115610da157fe5b1415610db057610db088614175565b829150600160a060020a03871615610f1557610dcc8386614137565b9050610dd6613f39565b600160a060020a031663e7a49c2b888360405160e060020a63ffffffff8516028152600160a060020a0390921660048301526024820152604401600060405180830381600087803b1515610e2957600080fd5b6102c65a03f11515610e3a57600080fd5b505050610e45613f39565b600160a060020a031663c7ee98c2610e63848463ffffffff61416316565b60405160e060020a63ffffffff84160281526004810191909152602401600060405180830381600087803b1515610e9957600080fd5b6102c65a03f11515610eaa57600080fd5b50505087600160a060020a03167ff4b71fed8e2c9a8c67c388bc6d35ad20b9368a24eed6d565459f2b277b6c0c228885846040518084600160a060020a0316600160a060020a03168152602001838152602001828152602001935050505060405180910390a2610fdc565b610f1d613f39565b600160a060020a031663c7ee98c28360405160e060020a63ffffffff84160281526004810191909152602401600060405180830381600087803b1515610f6257600080fd5b6102c65a03f11515610f7357600080fd5b50505087600160a060020a03167ff4b71fed8e2c9a8c67c388bc6d35ad20b9368a24eed6d565459f2b277b6c0c2260008560006040518084600160a060020a0316600160a060020a03168152602001838152602001828152602001935050505060405180910390a25b611046565b87600160a060020a03167ff4b71fed8e2c9a8c67c388bc6d35ad20b9368a24eed6d565459f2b277b6c0c22886000806040518084600160a060020a0316600160a060020a03168152602001838152602001828152602001935050505060405180910390a25b5050505050505050565b6000731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63e189dedb600884846040516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b15156110b957600080fd5b6102c65a03f415156110ca57600080fd5b50505060405180519150505b919050565b6000806000806000806000806000806000809054906101000a9004600160a060020a0316600160a060020a0316635c975abb6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561114457600080fd5b6102c65a03f1151561115557600080fd5b505050604051805115905061116957600080fd5b600054600160a060020a031663e16c7d986040517f526f756e64734d616e61676572000000000000000000000000000000000000008152600d01604051809103902060006040516020015260405160e060020a63ffffffff84160281526004810191909152602401602060405180830381600087803b15156111ea57600080fd5b6102c65a03f115156111fb57600080fd5b50505060405180519050600160a060020a031633600160a060020a031614151561122457600080fd5b61122c613ea6565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561127157600080fd5b6102c65a03f1151561128257600080fd5b5050506040518051600354909b5061130e9150731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63b32ece58600860006040516020015260405160e060020a63ffffffff8416028152600481019190915260240160206040518083038186803b15156112ee57600080fd5b6102c65a03f415156112ff57600080fd5b5050506040518051905061431e565b985060009750731a0b2ca69ca2c7f96e2529faa6d63f881655d81a632ebb2fed60088a6040516020015260405160e060020a63ffffffff8416028152600481019190915260240160206040518083038186803b151561136c57600080fd5b6102c65a03f4151561137d57600080fd5b5050506040518051975060009650505b888610156116245760008a8152600d602052604090208054600181016113b38382614737565b506000918252602080832091909101805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a038b169081179091558c8352600d825260408084209184526001918201909252818320805460ff19169091179055731a0b2ca69ca2c7f96e2529faa6d63f881655d81a9163d8681128916008918b91516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b151561147857600080fd5b6102c65a03f4151561148957600080fd5b5050506040518051905094506006600088600160a060020a0316600160a060020a031681526020019081526020016000206004015493506006600088600160a060020a0316600160a060020a031681526020019081526020016000206005015492506006600088600160a060020a0316600160a060020a031681526020019081526020016000206006015491506006600088600160a060020a0316600160a060020a0316815260200190815260200160002090508381600101819055508281600201819055508181600301819055506115838585858460070160008f8152602001908152602001600020614334909392919063ffffffff16565b611593888663ffffffff61435016565b9750731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63e189dedb60088960006040516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b15156115fd57600080fd5b6102c65a03f4151561160e57600080fd5b505050604051805197505060019095019461138d565b50505060009687525050600d602052505060409092206002019190915550565b600160a060020a0390911660009081526006602090815260408083209383526007909301905220805460018201546002830154600390930154919390929190565b60008054600160a060020a031690635c975abb90604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156116ce57600080fd5b6102c65a03f115156116df57600080fd5b50505060405180511590506116f357600080fd5b6116fb613ea6565b600160a060020a031663219bc76c6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561174057600080fd5b6102c65a03f1151561175157600080fd5b50505060405180519050151561176657600080fd5b600160a060020a03331660009081526005602052604090206006015481901061178e57600080fd5b611796613ea6565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156117db57600080fd5b6102c65a03f115156117ec57600080fd5b5050506040518051821115905061180257600080fd5b61180c338261436a565b50565b6000731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63b32ece586008836040516020015260405160e060020a63ffffffff8416028152600481019190915260240160206040518083038186803b151561186957600080fd5b6102c65a03f4151561187a57600080fd5b50505060405180519150505b90565b600080548190600160a060020a0316635c975abb82604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156118d357600080fd5b6102c65a03f115156118e457600080fd5b50505060405180511590506118f857600080fd5b600054600160a060020a031663e16c7d986040517f4a6f62734d616e616765720000000000000000000000000000000000000000008152600b01604051809103902060006040516020015260405160e060020a63ffffffff84160281526004810191909152602401602060405180830381600087803b151561197957600080fd5b6102c65a03f1151561198a57600080fd5b50505060405180519050600160a060020a031633600160a060020a03161415156119b357600080fd5b60016119be86612e89565b60018111156119c957fe5b146119d357600080fd5b5050600160a060020a0383166000908152600660209081526040808320848452600781019092529091206001810154611a12908563ffffffff61435016565b60019091015550505050565b600d6020526000908152604090206002015481565b60008054600160a060020a0316635c975abb82604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515611a7b57600080fd5b6102c65a03f11515611a8c57600080fd5b5050506040518051159050611aa057600080fd5b611aa8613ea6565b600160a060020a031663219bc76c6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515611aed57600080fd5b6102c65a03f11515611afe57600080fd5b505050604051805190501515611b1357600080fd5b611b8433611b1f613ea6565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515611b6457600080fd5b6102c65a03f11515611b7557600080fd5b5050506040518051905061436a565b600160a060020a03331660009081526005602052604081206001015411611baa57600080fd5b50600160a060020a03331660009081526005602052604081206001018054919055611bd3613f39565b600160a060020a03166320283da9338360405160e060020a63ffffffff8516028152600160a060020a0390921660048301526024820152604401600060405180830381600087803b1515611c2657600080fd5b6102c65a03f11515611c3757600080fd5b50505033600160a060020a03167fd3719f04262b628e1d01a6ed24707f542cda51f144b5271149c7d0419436d00c60405160405180910390a250565b60015481565b6000731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63735bc2ca6008836040516020015260405160e060020a63ffffffff8416028152600481019190915260240160206040518083038186803b151561186957600080fd5b60075490565b600160a060020a03166000908152600660208190526040909120805460018201546002830154600384015460048501546005860154959096015493969295919490939192909190565b600080548190600160a060020a0316635c975abb82604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515611d6c57600080fd5b6102c65a03f11515611d7d57600080fd5b5050506040518051159050611d9157600080fd5b611d99613ea6565b600160a060020a031663219bc76c6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515611dde57600080fd5b6102c65a03f11515611def57600080fd5b505050604051805190501515611e0457600080fd5b611e1033611b1f613ea6565b6001611e1b3361071e565b6003811115611e2657fe5b14611e3057600080fd5b600160a060020a03331660009081526005602052604090209150611e52613ea6565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515611e9757600080fd5b6102c65a03f11515611ea857600080fd5b5050506040518051600254909250611ed29150829067ffffffffffffffff1663ffffffff61435016565b60058084019190915582546002840154600160a060020a03166000908152602092909252604090912060030154611f0e9163ffffffff61416316565b6002830154600160a060020a03166000908152600560205260409020600301558154600754611f429163ffffffff61416316565b6007556001611f5033612e89565b6001811115611f5b57fe5b1415611f6a57611f6a33614175565b600282015433600160a060020a03908116911614801590611fac575060016002830154611f9f90600160a060020a0316612e89565b6001811115611faa57fe5b145b156120d05760028201548254731a0b2ca69ca2c7f96e2529faa6d63f881655d81a916338237efe91600891600160a060020a03169061205f908563d8681128858560006040516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b151561203857600080fd5b6102c65a03f4151561204957600080fd5b505050604051805191905063ffffffff61416316565b60008060405160e060020a63ffffffff88160281526004810195909552600160a060020a03938416602486015260448501929092528216606484015216608482015260a40160006040518083038186803b15156120bb57600080fd5b6102c65a03f415156120cc57600080fd5b5050505b60028201805473ffffffffffffffffffffffffffffffffffffffff1916905560006004830181905533600160a060020a0316907f4907de7e87b3873cb501376a57df5a00ff20db617b18f56eb5768717564a00e460405160405180910390a35050565b60008054600160a060020a031690638da5cb5b90604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561217c57600080fd5b6102c65a03f1151561218d57600080fd5b50505060405180519050600160a060020a031633600160a060020a03161415156121b657600080fd5b6003548110156121c557600080fd5b731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63a176adaf60088360405160e060020a63ffffffff85160281526004810192909252602482015260440160006040518083038186803b151561221b57600080fd5b6102c65a03f4151561222c57600080fd5b5050506000805160206147918339815191526040516020808252600e908201527f6e756d5472616e73636f646572730000000000000000000000000000000000006040808301919091526060909101905180910390a150565b60035481565b60008054600160a060020a031690638da5cb5b90604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156122d457600080fd5b6102c65a03f115156122e557600080fd5b50505060405180519050600160a060020a031633600160a060020a031614151561230e57600080fd5b731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63735bc2ca600860006040516020015260405160e060020a63ffffffff8416028152600481019190915260240160206040518083038186803b151561236757600080fd5b6102c65a03f4151561237857600080fd5b5050506040518051821115905061238e57600080fd5b600381905560008051602061479183398151915260405160208082526014908201527f6e756d4163746976655472616e73636f646572730000000000000000000000006040808301919091526060909101905180910390a150565b600060016123f683612e89565b600181111561240157fe5b1492915050565b60025467ffffffffffffffff1681565b60008054600160a060020a031690638da5cb5b90604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561246157600080fd5b6102c65a03f1151561247257600080fd5b50505060405180519050600160a060020a031633600160a060020a031614151561249b57600080fd5b600481905560008051602061479183398151915260405160208082526017908201527f6d61784561726e696e6773436c61696d73526f756e64730000000000000000006040808301919091526060909101905180910390a150565b6000908152600d602052604090206002015490565b6000908152600d60209081526040808320600160a060020a0394909416835260019093019052205460ff1690565b60008054819081908190819081908190600160a060020a0316635c975abb82604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561258d57600080fd5b6102c65a03f1151561259e57600080fd5b50505060405180511590506125b257600080fd5b6125ba613ea6565b600160a060020a031663219bc76c6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156125ff57600080fd5b6102c65a03f1151561261057600080fd5b50505060405180519050151561262557600080fd5b600160a060020a033316600090815260066020908152604080832060059092529091209097509550612655613ea6565b600160a060020a0316636841f2536000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561269a57600080fd5b6102c65a03f115156126ab57600080fd5b50505060405180519050156129715760016126c533612e89565b60018111156126d057fe5b146126da57600080fd5b60048701548a146126ea57600080fd5b600587015489146126fa57600080fd5b731a0b2ca69ca2c7f96e2529faa6d63f881655d81a632ebb2fed600860006040516020015260405160e060020a63ffffffff8416028152600481019190915260240160206040518083038186803b151561275357600080fd5b6102c65a03f4151561276457600080fd5b5050506040518051600160a060020a0381166000908152600660208190526040822001549197509095509350505b731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63b32ece58600860006040516020015260405160e060020a63ffffffff8416028152600481019190915260240160206040518083038186803b15156127eb57600080fd5b6102c65a03f415156127fc57600080fd5b505050604051805190508310156128e157600160a060020a038516600090815260066020819052604090912001548490101561285257600160a060020a0385166000908152600660208190526040909120015493505b731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63e189dedb60088760006040516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b15156128ba57600080fd5b6102c65a03f415156128cb57600080fd5b5050506040518051955050600190920191612792565b8388101580156128f5575086600601548811155b151561290057600080fd5b87876006018190555033600160a060020a03167fe01026d5db477d9ceaec44dc8efd731e76bcbc51256aecba7d28dd1cb4968be7886004015489600501548b6001604051938452602084019290925260408084019190915290151560608301526080909101905180910390a2612e23565b61297a8a614490565b151561298557600080fd5b61298e89614490565b151561299957600080fd5b600286015433600160a060020a0390811691161480156129bb57508554600090115b15156129c657600080fd5b600487018a905560058701899055600687018890556003860154915060006129ed33612e89565b60018111156129f857fe5b1415612d4457731a0b2ca69ca2c7f96e2529faa6d63f881655d81a634aa12990600860006040516020015260405160e060020a63ffffffff8416028152600481019190915260240160206040518083038186803b1515612a5757600080fd5b6102c65a03f41515612a6857600080fd5b505050604051805190501515612b0b57731a0b2ca69ca2c7f96e2529faa6d63f881655d81a634fbaa9a66008338560008060405160e060020a63ffffffff88160281526004810195909552600160a060020a03938416602486015260448501929092528216606484015216608482015260a40160006040518083038186803b1515612af257600080fd5b6102c65a03f41515612b0357600080fd5b505050612d44565b731a0b2ca69ca2c7f96e2529faa6d63f881655d81a6372e40b26600860006040516020015260405160e060020a63ffffffff8416028152600481019190915260240160206040518083038186803b1515612b6457600080fd5b6102c65a03f41515612b7557600080fd5b50505060405180519150731a0b2ca69ca2c7f96e2529faa6d63f881655d81a905063d868112860088360006040516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b1515612be957600080fd5b6102c65a03f41515612bfa57600080fd5b50505060405180519050821115612d4457731a0b2ca69ca2c7f96e2529faa6d63f881655d81a635d35e00760088360405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160006040518083038186803b1515612c6a57600080fd5b6102c65a03f41515612c7b57600080fd5b5050506008731a0b2ca69ca2c7f96e2529faa6d63f881655d81a634fbaa9a69091338560008060405160e060020a63ffffffff88160281526004810195909552600160a060020a03938416602486015260448501929092528216606484015216608482015260a40160006040518083038186803b1515612cfa57600080fd5b6102c65a03f41515612d0b57600080fd5b50505080600160a060020a03167e05588101bf85a737dacb8be2233b33113aaa5c5743525cfbfe2f6a77c2f6ff60405160405180910390a25b33600160a060020a03167fe01026d5db477d9ceaec44dc8efd731e76bcbc51256aecba7d28dd1cb4968be78b8b8b6008731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63b0138c4790913360006040516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b1515612ddc57600080fd5b6102c65a03f41515612ded57600080fd5b50505060405180519050604051938452602084019290925260408084019190915290151560608301526080909101905180910390a25b50505050505050505050565b6000731a0b2ca69ca2c7f96e2529faa6d63f881655d81a632ebb2fed6008836040516020015260405160e060020a63ffffffff8416028152600481019190915260240160206040518083038186803b151561186957600080fd5b6000731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63b0138c47600884846040516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b1515612ef257600080fd5b6102c65a03f41515612f0357600080fd5b5050506040518051905015612f1a575060016110d6565b5060006110d6565b600080612f2d614760565b6000848152600d6020526040808220549350819081908190819081908190899051805910612f585750595b908082528060200260200182016040525097506000965060009550600094505b888510156130535760008b8152600d60205260409020805486908110612f9a57fe5b60009182526020808320909101548d8352600d82526040808420600160a060020a0390921680855260019290920190925291205490945060ff168015612ffc5750600160a060020a0384166000908152600660205260409020600301548d9011155b15613048578388888151811061300e57fe5b600160a060020a03909216602092830290910190910152600190960195613045613038858d613cc7565b879063ffffffff61435016565b95505b600190940193612f78565b86151561306357600099506130e3565b858c81151561306e57fe5b06925060009150600090505b82821115801561308957508681105b156130c7576130bd6130b08983815181106130a057fe5b906020019060200201518d613cc7565b839063ffffffff61435016565b915060010161307a565b8760018203815181106130d657fe5b9060200190602002015199505b5050505050505050509392505050565b60005433600160a060020a0390811691161461310e57600080fd5b6000805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0383161790557f4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f7081604051600160a060020a03909116815260200160405180910390a150565b6000806000806000806000613189613ea6565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156131ce57600080fd5b6102c65a03f115156131df57600080fd5b5050506040518051600160a060020a038b1660009081526005602052604090209097509550508588118015906132185750846006015488115b151561322357600080fd5b8454600686015490945060010192505b8783116132a95750506002830154600160a060020a0390811660008181526006602090815260408083208684526007019091529020918916146132758261449a565b1561329e5761329b61328e83868463ffffffff6144a516565b859063ffffffff61435016565b93505b600190920191613233565b5091979650505050505050565b6000731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63d8681128600884846040516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b15156110b957600080fd5b600160a060020a0390811660009081526005602081905260409091208054600182015460028301546003840154600485015495850154600690950154939792969190911694909390929091565b6000805481908190600160a060020a0316635c975abb82604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156133b857600080fd5b6102c65a03f115156133c957600080fd5b50505060405180511590506133dd57600080fd5b6133e5613ea6565b600160a060020a031663219bc76c6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561342a57600080fd5b6102c65a03f1151561343b57600080fd5b50505060405180519050151561345057600080fd5b61345c33611b1f613ea6565b600160a060020a0333166000908152600560205260409020925061347e613ea6565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156134c357600080fd5b6102c65a03f115156134d457600080fd5b50505060405180519250859150600390506134ee3361071e565b60038111156134f957fe5b14806135185750600261350b3361071e565b600381111561351657fe5b145b156135545761352e82600163ffffffff61435016565b600484015560006005840155825461354d90829063ffffffff61435016565b9050613745565b6002830154600160a060020a03161580159061358057506002830154600160a060020a03858116911614155b1561374557600061359033612e89565b600181111561359b57fe5b146135a557600080fd5b6135b682600163ffffffff61435016565b600484015582546135ce90829063ffffffff61435016565b83546002850154600160a060020a0316600090815260056020526040902060030154919250613603919063ffffffff61416316565b6002840154600160a060020a03166000908152600560205260409020600301556001600284015461363c90600160a060020a0316612e89565b600181111561364757fe5b14156137455760028301548354731a0b2ca69ca2c7f96e2529faa6d63f881655d81a916338237efe91600891600160a060020a0316906136d4908563d8681128858560006040516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b151561203857600080fd5b60008060405160e060020a63ffffffff88160281526004810195909552600160a060020a03938416602486015260448501929092528216606484015216608482015260a40160006040518083038186803b151561373057600080fd5b6102c65a03f4151561374157600080fd5b5050505b6000811161375257600080fd5b60028301805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a03861690811790915560009081526005602052604090206003015461379b9082614350565b600160a060020a03851660009081526005602052604090206003015560016137c285612e89565b60018111156137cd57fe5b14156138f5576002830154731a0b2ca69ca2c7f96e2529faa6d63f881655d81a906338237efe906008908790613884908690869063d8681128908690600160a060020a031660006040516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b151561385d57600080fd5b6102c65a03f4151561386e57600080fd5b505050604051805191905063ffffffff61435016565b60008060405160e060020a63ffffffff88160281526004810195909552600160a060020a03938416602486015260448501929092528216606484015216608482015260a40160006040518083038186803b15156138e057600080fd5b6102c65a03f415156138f157600080fd5b5050505b60008511156139bc578254613910908663ffffffff61435016565b8355600754613925908663ffffffff61435016565b60075561393061451c565b600160a060020a03166323b872dd33613947613f39565b8860006040516020015260405160e060020a63ffffffff8616028152600160a060020a0393841660048201529190921660248201526044810191909152606401602060405180830381600087803b15156139a057600080fd5b6102c65a03f115156139b157600080fd5b505050604051805150505b33600160a060020a031684600160a060020a03167f926f98e4b543897a75b3e34b7494ba68a47829d3aa39ffd9c478ccc51bfbfb4460405160405180910390a35050505050565b60008054600160a060020a0316635c975abb82604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515613a4b57600080fd5b6102c65a03f11515613a5c57600080fd5b5050506040518051159050613a7057600080fd5b613a78613ea6565b600160a060020a031663219bc76c6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515613abd57600080fd5b6102c65a03f11515613ace57600080fd5b505050604051805190501515613ae357600080fd5b6003613aee3361071e565b6003811115613af957fe5b14613b0357600080fd5b50600160a060020a033316600090815260056020819052604082208054838255910191909155613b31613f39565b600160a060020a031663e7a49c2b338360405160e060020a63ffffffff8516028152600160a060020a0390921660048301526024820152604401600060405180830381600087803b1515613b8457600080fd5b6102c65a03f11515613b9557600080fd5b50505033600160a060020a03167f32b4834046d70a9d8d9c79995359892376424492753f04a190f871bbbc8d26ce60405160405180910390a250565b60008054600160a060020a031690638da5cb5b90604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515613c1a57600080fd5b6102c65a03f11515613c2b57600080fd5b50505060405180519050600160a060020a031633600160a060020a0316141515613c5457600080fd5b6002805467ffffffffffffffff191667ffffffffffffffff83161790556000805160206147918339815191526040516020808252600f908201527f756e626f6e64696e67506572696f6400000000000000000000000000000000006040808301919091526060909101905180910390a150565b6000818152600d60209081526040808320600160a060020a038616845260010190915281205460ff161515613cfb57600080fd5b50600160a060020a0391909116600090815260066020908152604080832093835260079093019052206002015490565b600080600080600080600080613d3f613ea6565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515613d8457600080fd5b6102c65a03f11515613d9557600080fd5b5050506040518051600160a060020a038c166000908152600560205260409020909850965050868911801590613dce5750856006015489115b1515613dd957600080fd5b6001808701548754600689015491975095500192505b888311613e89576002860154600160a060020a0316600090815260066020908152604080832086845260070190915290209150613e2b8261449a565b15613e7e57506002850154600160a060020a038a8116911614613e65613e5883868463ffffffff61459e16565b869063ffffffff61435016565b9450613e7b61328e83868463ffffffff6144a516565b93505b600190920191613def565b509298975050505050505050565b600054600160a060020a031681565b60008054600160a060020a031663e16c7d986040517f526f756e64734d616e61676572000000000000000000000000000000000000008152600d01604051809103902060006040516020015260405160e060020a63ffffffff84160281526004810191909152602401602060405180830381600087803b1515613f2857600080fd5b6102c65a03f1151561187a57600080fd5b60008054600160a060020a031663e16c7d986040517f4d696e74657200000000000000000000000000000000000000000000000000008152600601604051809103902060006040516020015260405160e060020a63ffffffff84160281526004810191909152602401602060405180830381600087803b1515613f2857600080fd5b600160a060020a03831660009081526006602090815260408083206005835281842085855260078201909352908320805491939091614000908763ffffffff61435016565b82556003830154614017908763ffffffff61435016565b600384015561408886731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63d868112860088b60006040516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b151561385d57600080fd5b9050731a0b2ca69ca2c7f96e2529faa6d63f881655d81a6338237efe6008898460008060405160e060020a63ffffffff88160281526004810195909552600160a060020a03938416602486015260448501929092528216606484015216608482015260a40160006040518083038186803b151561410457600080fd5b6102c65a03f4151561411557600080fd5b505060075461412b91508763ffffffff61435016565b60075550505050505050565b600061415c620f4240614150858563ffffffff61461d16565b9063ffffffff61464816565b9392505050565b60008282111561416f57fe5b50900390565b600061417f613ea6565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156141c457600080fd5b6102c65a03f115156141d557600080fd5b50505060405180516000818152600d60209081526040808320600160a060020a038816845260010190915290205490925060ff161590506142715761423b61421d8383613cc7565b6000838152600d60205260409020600201549063ffffffff61416316565b6000828152600d602090815260408083206002810194909455600160a060020a03861683526001909301905220805460ff191690555b731a0b2ca69ca2c7f96e2529faa6d63f881655d81a635d35e00760088460405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160006040518083038186803b15156142d057600080fd5b6102c65a03f415156142e157600080fd5b50505081600160a060020a03167fc6be59bdc33151833b6dbb6823a9bddecde3c685a1bf4d253d20b4a93fbae56c60405160405180910390a25050565b600081831061432d578161415c565b5090919050565b6002840183905560038401929092556004830155600590910155565b60008282018381101561435f57fe5b8091505b5092915050565b600160a060020a03808316600090815260056020526040812060028101549092829182918291829182918291161561447d5760045460068901546143b5908b9063ffffffff61416316565b11156143c057600080fd5b87546001808a015460068b015492995097500194505b888511614472576002880154600160a060020a03166000908152600660209081526040808320888452600701909152902093506144128461449a565b15614467576002880154600160a060020a038b8116911614925061443d84888563ffffffff61465f16565b9092509050614452868363ffffffff61435016565b9550614464878263ffffffff61435016565b96505b6001909401936143d6565b868855600188018690555b5050505060069093019390935550505050565b620f424090111590565b600301546000901190565b600383015460009081908190819011156144f2576144cb86600001548760040154614137565b86549092506144ef906144e4908463ffffffff61416316565b8688600301546146f3565b90505b831561450f57614508818363ffffffff61435016565b9250614513565b8092505b50509392505050565b60008054600160a060020a031663e16c7d986040517f4c69766570656572546f6b656e000000000000000000000000000000000000008152600d01604051809103902060006040516020015260405160e060020a63ffffffff84160281526004810191909152602401602060405180830381600087803b1515613f2857600080fd5b6003830154600090819081908190819011156145f2576145c687600101548860050154614137565b60018801549091506145de908263ffffffff61416316565b92506145ef818789600301546146f3565b91505b841561460f57614608828463ffffffff61435016565b9350614613565b8193505b5050509392505050565b6000808315156146305760009150614363565b5082820282848281151561464057fe5b041461435f57fe5b600080828481151561465657fe5b04949350505050565b60018301546000908190819081908190111561469e5761468087878761459e565b6001880154909250614698908363ffffffff61416316565b60018801555b865460009011156146cc576146b48787876144a5565b87549091506146c9908263ffffffff61416316565b87555b60038701546146e1908763ffffffff61416316565b60038801559092509050935093915050565b6000614716620f4240614150614709868661471e565b879063ffffffff61461d16565b949350505050565b600061415c8261415085620f424063ffffffff61461d16565b81548183558181151161475b5760008381526020902061475b918101908301614772565b505050565b60206040519081016040526000815290565b61188691905b8082111561478c5760008155600101614778565b509056009f5033568d78ae30f29f01e944f97b2216493bd19d1b46d429673acff3dcd674a165627a7a72305820dd0ce954ef7b6a6647e6719eeb9e945b0a8825cdeba54568e24951f4879770280029000000000000000000000000f96d54e490317c557a967abfa5d6e33006be69b3

Deployed Bytecode

0x6060604052600436106101c95763ffffffff60e060020a600035041663038424c381146101ce5780631544fc67146101f3578063228cb7331461023657806322bf9d7c1461024b578063235c960314610276578063242ed69f146102b157806324454fc4146102c457806324b1babf146103115780632a4e0d55146103275780633aeb512c1461033a5780633da1c2f51461035f578063476343ee1461037557806351720b41146103885780635a2a75a91461039b5780635c50c356146103ae5780635dce9948146103c15780635df6a6bc1461041e57806360c79d001461043157806361e25d2314610447578063673a456b1461045a57806368ba170c146104705780636cf6d675146104a357806372d9f13d146104d357806377517765146104e95780637c0207cb146104ff57806385aaff621461052157806388a6c7491461053d5780638b2f16521461055057806391fdf6b11461057f57806392eefe9b1461059b5780639d0b2c7a146105ba5780639ef9df94146105dc578063a64ad595146105fb578063b78d27dc1461066c578063bed9d8611461068e578063f10d1de1146106a1578063f2083220146106c1578063f595f1cc146106e3578063f77c479114610705575b600080fd5b34156101d957600080fd5b6101e1610718565b60405190815260200160405180910390f35b34156101fe57600080fd5b610212600160a060020a036004351661071e565b6040518082600381111561022257fe5b60ff16815260200191505060405180910390f35b341561024157600080fd5b6102496108de565b005b341561025657600080fd5b610249600160a060020a0360043581169060243516604435606435610b7d565b341561028157600080fd5b610295600160a060020a0360043516611050565b604051600160a060020a03909116815260200160405180910390f35b34156102bc57600080fd5b6102496110db565b34156102cf57600080fd5b6102e6600160a060020a0360043516602435611644565b6040518085815260200184815260200183815260200182815260200194505050505060405180910390f35b341561031c57600080fd5b610249600435611685565b341561033257600080fd5b6101e161180f565b341561034557600080fd5b610249600160a060020a0360043516602435604435611889565b341561036a57600080fd5b6101e1600435611a1e565b341561038057600080fd5b610249611a33565b341561039357600080fd5b6101e1611c73565b34156103a657600080fd5b6101e1611c79565b34156103b957600080fd5b6101e1611cd3565b34156103cc57600080fd5b6103e0600160a060020a0360043516611cd9565b60405196875260208701959095526040808701949094526060860192909252608085015260a084015260c083019190915260e0909101905180910390f35b341561042957600080fd5b610249611d22565b341561043c57600080fd5b610249600435612133565b341561045257600080fd5b6101e1612285565b341561046557600080fd5b61024960043561228b565b341561047b57600080fd5b61048f600160a060020a03600435166123e9565b604051901515815260200160405180910390f35b34156104ae57600080fd5b6104b6612408565b60405167ffffffffffffffff909116815260200160405180910390f35b34156104de57600080fd5b610249600435612418565b34156104f457600080fd5b6101e16004356124f6565b341561050a57600080fd5b61048f600160a060020a036004351660243561250b565b341561052c57600080fd5b610249600435602435604435612539565b341561054857600080fd5b610295612e2f565b341561055b57600080fd5b61056f600160a060020a0360043516612e89565b6040518082600181111561022257fe5b341561058a57600080fd5b610295600435602435604435612f22565b34156105a657600080fd5b610249600160a060020a03600435166130f3565b34156105c557600080fd5b6101e1600160a060020a0360043516602435613176565b34156105e757600080fd5b6101e1600160a060020a03600435166132b6565b341561060657600080fd5b61061a600160a060020a036004351661331f565b6040518088815260200187815260200186600160a060020a0316600160a060020a0316815260200185815260200184815260200183815260200182815260200197505050505050505060405180910390f35b341561067757600080fd5b610249600435600160a060020a036024351661336c565b341561069957600080fd5b610249613a03565b34156106ac57600080fd5b61024967ffffffffffffffff60043516613bd1565b34156106cc57600080fd5b6101e1600160a060020a0360043516602435613cc7565b34156106ee57600080fd5b6101e1600160a060020a0360043516602435613d2b565b341561071057600080fd5b610295613e97565b60045481565b600160a060020a0381166000908152600560208190526040822090810154829011156107ca578060050154610751613ea6565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561079657600080fd5b6102c65a03f115156107a757600080fd5b505050604051805190501015156107c157600391506108d8565b600291506108d8565b6107d2613ea6565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561081757600080fd5b6102c65a03f1151561082857600080fd5b505050604051805190508160040154111561084657600091506108d8565b600081600401541180156108c5575061085d613ea6565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156108a257600080fd5b6102c65a03f115156108b357600080fd5b50505060405180519050816004015411155b156108d357600191506108d8565b600391505b50919050565b600080548190600160a060020a0316635c975abb82604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561092857600080fd5b6102c65a03f1151561093957600080fd5b505050604051805115905061094d57600080fd5b610955613ea6565b600160a060020a031663219bc76c6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561099a57600080fd5b6102c65a03f115156109ab57600080fd5b5050506040518051905015156109c057600080fd5b6109c8613ea6565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515610a0d57600080fd5b6102c65a03f11515610a1e57600080fd5b50505060405180516000818152600d60209081526040808320600160a060020a033316845260010190915290205490935060ff1615159050610a5f57600080fd5b600160a060020a033316600090815260066020526040902054821415610a8457600080fd5b600160a060020a0333166000908152600660205260409020829055610aa7613f39565b600160a060020a0316637dbedad5610abf3385613cc7565b6000858152600d6020526040808220600201549190516020015260405160e060020a63ffffffff851602815260048101929092526024820152604401602060405180830381600087803b1515610b1457600080fd5b6102c65a03f11515610b2557600080fd5b505050604051805190509050610b3c338284613fbb565b33600160a060020a03167f619caafabdd75649b302ba8419e48cccf64f37f1983ac4727cfb38b57703ffc98260405190815260200160405180910390a25050565b60008054819081908190600160a060020a0316635c975abb82604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515610bcb57600080fd5b6102c65a03f11515610bdc57600080fd5b5050506040518051159050610bf057600080fd5b600054600160a060020a031663e16c7d986040517f4a6f62734d616e616765720000000000000000000000000000000000000000008152600b01604051809103902060006040516020015260405160e060020a63ffffffff84160281526004810191909152602401602060405180830381600087803b1515610c7157600080fd5b6102c65a03f11515610c8257600080fd5b50505060405180519050600160a060020a031633600160a060020a0316141515610cab57600080fd5b600160a060020a038816600090815260056020526040812080549095501115610fe157600160a060020a038816600090815260056020526040902054610cf19087614137565b8454909350610d06908463ffffffff61416316565b84556001610d138961071e565b6003811115610d1e57fe5b1415610d8b576002840154600160a060020a0316600090815260056020526040902060030154610d54908463ffffffff61416316565b6002850154600160a060020a0316600090815260056020526040902060030155600754610d87908463ffffffff61416316565b6007555b6001610d9689612e89565b6001811115610da157fe5b1415610db057610db088614175565b829150600160a060020a03871615610f1557610dcc8386614137565b9050610dd6613f39565b600160a060020a031663e7a49c2b888360405160e060020a63ffffffff8516028152600160a060020a0390921660048301526024820152604401600060405180830381600087803b1515610e2957600080fd5b6102c65a03f11515610e3a57600080fd5b505050610e45613f39565b600160a060020a031663c7ee98c2610e63848463ffffffff61416316565b60405160e060020a63ffffffff84160281526004810191909152602401600060405180830381600087803b1515610e9957600080fd5b6102c65a03f11515610eaa57600080fd5b50505087600160a060020a03167ff4b71fed8e2c9a8c67c388bc6d35ad20b9368a24eed6d565459f2b277b6c0c228885846040518084600160a060020a0316600160a060020a03168152602001838152602001828152602001935050505060405180910390a2610fdc565b610f1d613f39565b600160a060020a031663c7ee98c28360405160e060020a63ffffffff84160281526004810191909152602401600060405180830381600087803b1515610f6257600080fd5b6102c65a03f11515610f7357600080fd5b50505087600160a060020a03167ff4b71fed8e2c9a8c67c388bc6d35ad20b9368a24eed6d565459f2b277b6c0c2260008560006040518084600160a060020a0316600160a060020a03168152602001838152602001828152602001935050505060405180910390a25b611046565b87600160a060020a03167ff4b71fed8e2c9a8c67c388bc6d35ad20b9368a24eed6d565459f2b277b6c0c22886000806040518084600160a060020a0316600160a060020a03168152602001838152602001828152602001935050505060405180910390a25b5050505050505050565b6000731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63e189dedb600884846040516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b15156110b957600080fd5b6102c65a03f415156110ca57600080fd5b50505060405180519150505b919050565b6000806000806000806000806000806000809054906101000a9004600160a060020a0316600160a060020a0316635c975abb6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561114457600080fd5b6102c65a03f1151561115557600080fd5b505050604051805115905061116957600080fd5b600054600160a060020a031663e16c7d986040517f526f756e64734d616e61676572000000000000000000000000000000000000008152600d01604051809103902060006040516020015260405160e060020a63ffffffff84160281526004810191909152602401602060405180830381600087803b15156111ea57600080fd5b6102c65a03f115156111fb57600080fd5b50505060405180519050600160a060020a031633600160a060020a031614151561122457600080fd5b61122c613ea6565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561127157600080fd5b6102c65a03f1151561128257600080fd5b5050506040518051600354909b5061130e9150731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63b32ece58600860006040516020015260405160e060020a63ffffffff8416028152600481019190915260240160206040518083038186803b15156112ee57600080fd5b6102c65a03f415156112ff57600080fd5b5050506040518051905061431e565b985060009750731a0b2ca69ca2c7f96e2529faa6d63f881655d81a632ebb2fed60088a6040516020015260405160e060020a63ffffffff8416028152600481019190915260240160206040518083038186803b151561136c57600080fd5b6102c65a03f4151561137d57600080fd5b5050506040518051975060009650505b888610156116245760008a8152600d602052604090208054600181016113b38382614737565b506000918252602080832091909101805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a038b169081179091558c8352600d825260408084209184526001918201909252818320805460ff19169091179055731a0b2ca69ca2c7f96e2529faa6d63f881655d81a9163d8681128916008918b91516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b151561147857600080fd5b6102c65a03f4151561148957600080fd5b5050506040518051905094506006600088600160a060020a0316600160a060020a031681526020019081526020016000206004015493506006600088600160a060020a0316600160a060020a031681526020019081526020016000206005015492506006600088600160a060020a0316600160a060020a031681526020019081526020016000206006015491506006600088600160a060020a0316600160a060020a0316815260200190815260200160002090508381600101819055508281600201819055508181600301819055506115838585858460070160008f8152602001908152602001600020614334909392919063ffffffff16565b611593888663ffffffff61435016565b9750731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63e189dedb60088960006040516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b15156115fd57600080fd5b6102c65a03f4151561160e57600080fd5b505050604051805197505060019095019461138d565b50505060009687525050600d602052505060409092206002019190915550565b600160a060020a0390911660009081526006602090815260408083209383526007909301905220805460018201546002830154600390930154919390929190565b60008054600160a060020a031690635c975abb90604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156116ce57600080fd5b6102c65a03f115156116df57600080fd5b50505060405180511590506116f357600080fd5b6116fb613ea6565b600160a060020a031663219bc76c6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561174057600080fd5b6102c65a03f1151561175157600080fd5b50505060405180519050151561176657600080fd5b600160a060020a03331660009081526005602052604090206006015481901061178e57600080fd5b611796613ea6565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156117db57600080fd5b6102c65a03f115156117ec57600080fd5b5050506040518051821115905061180257600080fd5b61180c338261436a565b50565b6000731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63b32ece586008836040516020015260405160e060020a63ffffffff8416028152600481019190915260240160206040518083038186803b151561186957600080fd5b6102c65a03f4151561187a57600080fd5b50505060405180519150505b90565b600080548190600160a060020a0316635c975abb82604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156118d357600080fd5b6102c65a03f115156118e457600080fd5b50505060405180511590506118f857600080fd5b600054600160a060020a031663e16c7d986040517f4a6f62734d616e616765720000000000000000000000000000000000000000008152600b01604051809103902060006040516020015260405160e060020a63ffffffff84160281526004810191909152602401602060405180830381600087803b151561197957600080fd5b6102c65a03f1151561198a57600080fd5b50505060405180519050600160a060020a031633600160a060020a03161415156119b357600080fd5b60016119be86612e89565b60018111156119c957fe5b146119d357600080fd5b5050600160a060020a0383166000908152600660209081526040808320848452600781019092529091206001810154611a12908563ffffffff61435016565b60019091015550505050565b600d6020526000908152604090206002015481565b60008054600160a060020a0316635c975abb82604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515611a7b57600080fd5b6102c65a03f11515611a8c57600080fd5b5050506040518051159050611aa057600080fd5b611aa8613ea6565b600160a060020a031663219bc76c6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515611aed57600080fd5b6102c65a03f11515611afe57600080fd5b505050604051805190501515611b1357600080fd5b611b8433611b1f613ea6565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515611b6457600080fd5b6102c65a03f11515611b7557600080fd5b5050506040518051905061436a565b600160a060020a03331660009081526005602052604081206001015411611baa57600080fd5b50600160a060020a03331660009081526005602052604081206001018054919055611bd3613f39565b600160a060020a03166320283da9338360405160e060020a63ffffffff8516028152600160a060020a0390921660048301526024820152604401600060405180830381600087803b1515611c2657600080fd5b6102c65a03f11515611c3757600080fd5b50505033600160a060020a03167fd3719f04262b628e1d01a6ed24707f542cda51f144b5271149c7d0419436d00c60405160405180910390a250565b60015481565b6000731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63735bc2ca6008836040516020015260405160e060020a63ffffffff8416028152600481019190915260240160206040518083038186803b151561186957600080fd5b60075490565b600160a060020a03166000908152600660208190526040909120805460018201546002830154600384015460048501546005860154959096015493969295919490939192909190565b600080548190600160a060020a0316635c975abb82604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515611d6c57600080fd5b6102c65a03f11515611d7d57600080fd5b5050506040518051159050611d9157600080fd5b611d99613ea6565b600160a060020a031663219bc76c6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515611dde57600080fd5b6102c65a03f11515611def57600080fd5b505050604051805190501515611e0457600080fd5b611e1033611b1f613ea6565b6001611e1b3361071e565b6003811115611e2657fe5b14611e3057600080fd5b600160a060020a03331660009081526005602052604090209150611e52613ea6565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515611e9757600080fd5b6102c65a03f11515611ea857600080fd5b5050506040518051600254909250611ed29150829067ffffffffffffffff1663ffffffff61435016565b60058084019190915582546002840154600160a060020a03166000908152602092909252604090912060030154611f0e9163ffffffff61416316565b6002830154600160a060020a03166000908152600560205260409020600301558154600754611f429163ffffffff61416316565b6007556001611f5033612e89565b6001811115611f5b57fe5b1415611f6a57611f6a33614175565b600282015433600160a060020a03908116911614801590611fac575060016002830154611f9f90600160a060020a0316612e89565b6001811115611faa57fe5b145b156120d05760028201548254731a0b2ca69ca2c7f96e2529faa6d63f881655d81a916338237efe91600891600160a060020a03169061205f908563d8681128858560006040516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b151561203857600080fd5b6102c65a03f4151561204957600080fd5b505050604051805191905063ffffffff61416316565b60008060405160e060020a63ffffffff88160281526004810195909552600160a060020a03938416602486015260448501929092528216606484015216608482015260a40160006040518083038186803b15156120bb57600080fd5b6102c65a03f415156120cc57600080fd5b5050505b60028201805473ffffffffffffffffffffffffffffffffffffffff1916905560006004830181905533600160a060020a0316907f4907de7e87b3873cb501376a57df5a00ff20db617b18f56eb5768717564a00e460405160405180910390a35050565b60008054600160a060020a031690638da5cb5b90604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561217c57600080fd5b6102c65a03f1151561218d57600080fd5b50505060405180519050600160a060020a031633600160a060020a03161415156121b657600080fd5b6003548110156121c557600080fd5b731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63a176adaf60088360405160e060020a63ffffffff85160281526004810192909252602482015260440160006040518083038186803b151561221b57600080fd5b6102c65a03f4151561222c57600080fd5b5050506000805160206147918339815191526040516020808252600e908201527f6e756d5472616e73636f646572730000000000000000000000000000000000006040808301919091526060909101905180910390a150565b60035481565b60008054600160a060020a031690638da5cb5b90604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156122d457600080fd5b6102c65a03f115156122e557600080fd5b50505060405180519050600160a060020a031633600160a060020a031614151561230e57600080fd5b731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63735bc2ca600860006040516020015260405160e060020a63ffffffff8416028152600481019190915260240160206040518083038186803b151561236757600080fd5b6102c65a03f4151561237857600080fd5b5050506040518051821115905061238e57600080fd5b600381905560008051602061479183398151915260405160208082526014908201527f6e756d4163746976655472616e73636f646572730000000000000000000000006040808301919091526060909101905180910390a150565b600060016123f683612e89565b600181111561240157fe5b1492915050565b60025467ffffffffffffffff1681565b60008054600160a060020a031690638da5cb5b90604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561246157600080fd5b6102c65a03f1151561247257600080fd5b50505060405180519050600160a060020a031633600160a060020a031614151561249b57600080fd5b600481905560008051602061479183398151915260405160208082526017908201527f6d61784561726e696e6773436c61696d73526f756e64730000000000000000006040808301919091526060909101905180910390a150565b6000908152600d602052604090206002015490565b6000908152600d60209081526040808320600160a060020a0394909416835260019093019052205460ff1690565b60008054819081908190819081908190600160a060020a0316635c975abb82604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561258d57600080fd5b6102c65a03f1151561259e57600080fd5b50505060405180511590506125b257600080fd5b6125ba613ea6565b600160a060020a031663219bc76c6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156125ff57600080fd5b6102c65a03f1151561261057600080fd5b50505060405180519050151561262557600080fd5b600160a060020a033316600090815260066020908152604080832060059092529091209097509550612655613ea6565b600160a060020a0316636841f2536000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561269a57600080fd5b6102c65a03f115156126ab57600080fd5b50505060405180519050156129715760016126c533612e89565b60018111156126d057fe5b146126da57600080fd5b60048701548a146126ea57600080fd5b600587015489146126fa57600080fd5b731a0b2ca69ca2c7f96e2529faa6d63f881655d81a632ebb2fed600860006040516020015260405160e060020a63ffffffff8416028152600481019190915260240160206040518083038186803b151561275357600080fd5b6102c65a03f4151561276457600080fd5b5050506040518051600160a060020a0381166000908152600660208190526040822001549197509095509350505b731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63b32ece58600860006040516020015260405160e060020a63ffffffff8416028152600481019190915260240160206040518083038186803b15156127eb57600080fd5b6102c65a03f415156127fc57600080fd5b505050604051805190508310156128e157600160a060020a038516600090815260066020819052604090912001548490101561285257600160a060020a0385166000908152600660208190526040909120015493505b731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63e189dedb60088760006040516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b15156128ba57600080fd5b6102c65a03f415156128cb57600080fd5b5050506040518051955050600190920191612792565b8388101580156128f5575086600601548811155b151561290057600080fd5b87876006018190555033600160a060020a03167fe01026d5db477d9ceaec44dc8efd731e76bcbc51256aecba7d28dd1cb4968be7886004015489600501548b6001604051938452602084019290925260408084019190915290151560608301526080909101905180910390a2612e23565b61297a8a614490565b151561298557600080fd5b61298e89614490565b151561299957600080fd5b600286015433600160a060020a0390811691161480156129bb57508554600090115b15156129c657600080fd5b600487018a905560058701899055600687018890556003860154915060006129ed33612e89565b60018111156129f857fe5b1415612d4457731a0b2ca69ca2c7f96e2529faa6d63f881655d81a634aa12990600860006040516020015260405160e060020a63ffffffff8416028152600481019190915260240160206040518083038186803b1515612a5757600080fd5b6102c65a03f41515612a6857600080fd5b505050604051805190501515612b0b57731a0b2ca69ca2c7f96e2529faa6d63f881655d81a634fbaa9a66008338560008060405160e060020a63ffffffff88160281526004810195909552600160a060020a03938416602486015260448501929092528216606484015216608482015260a40160006040518083038186803b1515612af257600080fd5b6102c65a03f41515612b0357600080fd5b505050612d44565b731a0b2ca69ca2c7f96e2529faa6d63f881655d81a6372e40b26600860006040516020015260405160e060020a63ffffffff8416028152600481019190915260240160206040518083038186803b1515612b6457600080fd5b6102c65a03f41515612b7557600080fd5b50505060405180519150731a0b2ca69ca2c7f96e2529faa6d63f881655d81a905063d868112860088360006040516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b1515612be957600080fd5b6102c65a03f41515612bfa57600080fd5b50505060405180519050821115612d4457731a0b2ca69ca2c7f96e2529faa6d63f881655d81a635d35e00760088360405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160006040518083038186803b1515612c6a57600080fd5b6102c65a03f41515612c7b57600080fd5b5050506008731a0b2ca69ca2c7f96e2529faa6d63f881655d81a634fbaa9a69091338560008060405160e060020a63ffffffff88160281526004810195909552600160a060020a03938416602486015260448501929092528216606484015216608482015260a40160006040518083038186803b1515612cfa57600080fd5b6102c65a03f41515612d0b57600080fd5b50505080600160a060020a03167e05588101bf85a737dacb8be2233b33113aaa5c5743525cfbfe2f6a77c2f6ff60405160405180910390a25b33600160a060020a03167fe01026d5db477d9ceaec44dc8efd731e76bcbc51256aecba7d28dd1cb4968be78b8b8b6008731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63b0138c4790913360006040516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b1515612ddc57600080fd5b6102c65a03f41515612ded57600080fd5b50505060405180519050604051938452602084019290925260408084019190915290151560608301526080909101905180910390a25b50505050505050505050565b6000731a0b2ca69ca2c7f96e2529faa6d63f881655d81a632ebb2fed6008836040516020015260405160e060020a63ffffffff8416028152600481019190915260240160206040518083038186803b151561186957600080fd5b6000731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63b0138c47600884846040516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b1515612ef257600080fd5b6102c65a03f41515612f0357600080fd5b5050506040518051905015612f1a575060016110d6565b5060006110d6565b600080612f2d614760565b6000848152600d6020526040808220549350819081908190819081908190899051805910612f585750595b908082528060200260200182016040525097506000965060009550600094505b888510156130535760008b8152600d60205260409020805486908110612f9a57fe5b60009182526020808320909101548d8352600d82526040808420600160a060020a0390921680855260019290920190925291205490945060ff168015612ffc5750600160a060020a0384166000908152600660205260409020600301548d9011155b15613048578388888151811061300e57fe5b600160a060020a03909216602092830290910190910152600190960195613045613038858d613cc7565b879063ffffffff61435016565b95505b600190940193612f78565b86151561306357600099506130e3565b858c81151561306e57fe5b06925060009150600090505b82821115801561308957508681105b156130c7576130bd6130b08983815181106130a057fe5b906020019060200201518d613cc7565b839063ffffffff61435016565b915060010161307a565b8760018203815181106130d657fe5b9060200190602002015199505b5050505050505050509392505050565b60005433600160a060020a0390811691161461310e57600080fd5b6000805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0383161790557f4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f7081604051600160a060020a03909116815260200160405180910390a150565b6000806000806000806000613189613ea6565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156131ce57600080fd5b6102c65a03f115156131df57600080fd5b5050506040518051600160a060020a038b1660009081526005602052604090209097509550508588118015906132185750846006015488115b151561322357600080fd5b8454600686015490945060010192505b8783116132a95750506002830154600160a060020a0390811660008181526006602090815260408083208684526007019091529020918916146132758261449a565b1561329e5761329b61328e83868463ffffffff6144a516565b859063ffffffff61435016565b93505b600190920191613233565b5091979650505050505050565b6000731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63d8681128600884846040516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b15156110b957600080fd5b600160a060020a0390811660009081526005602081905260409091208054600182015460028301546003840154600485015495850154600690950154939792969190911694909390929091565b6000805481908190600160a060020a0316635c975abb82604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156133b857600080fd5b6102c65a03f115156133c957600080fd5b50505060405180511590506133dd57600080fd5b6133e5613ea6565b600160a060020a031663219bc76c6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561342a57600080fd5b6102c65a03f1151561343b57600080fd5b50505060405180519050151561345057600080fd5b61345c33611b1f613ea6565b600160a060020a0333166000908152600560205260409020925061347e613ea6565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156134c357600080fd5b6102c65a03f115156134d457600080fd5b50505060405180519250859150600390506134ee3361071e565b60038111156134f957fe5b14806135185750600261350b3361071e565b600381111561351657fe5b145b156135545761352e82600163ffffffff61435016565b600484015560006005840155825461354d90829063ffffffff61435016565b9050613745565b6002830154600160a060020a03161580159061358057506002830154600160a060020a03858116911614155b1561374557600061359033612e89565b600181111561359b57fe5b146135a557600080fd5b6135b682600163ffffffff61435016565b600484015582546135ce90829063ffffffff61435016565b83546002850154600160a060020a0316600090815260056020526040902060030154919250613603919063ffffffff61416316565b6002840154600160a060020a03166000908152600560205260409020600301556001600284015461363c90600160a060020a0316612e89565b600181111561364757fe5b14156137455760028301548354731a0b2ca69ca2c7f96e2529faa6d63f881655d81a916338237efe91600891600160a060020a0316906136d4908563d8681128858560006040516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b151561203857600080fd5b60008060405160e060020a63ffffffff88160281526004810195909552600160a060020a03938416602486015260448501929092528216606484015216608482015260a40160006040518083038186803b151561373057600080fd5b6102c65a03f4151561374157600080fd5b5050505b6000811161375257600080fd5b60028301805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a03861690811790915560009081526005602052604090206003015461379b9082614350565b600160a060020a03851660009081526005602052604090206003015560016137c285612e89565b60018111156137cd57fe5b14156138f5576002830154731a0b2ca69ca2c7f96e2529faa6d63f881655d81a906338237efe906008908790613884908690869063d8681128908690600160a060020a031660006040516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b151561385d57600080fd5b6102c65a03f4151561386e57600080fd5b505050604051805191905063ffffffff61435016565b60008060405160e060020a63ffffffff88160281526004810195909552600160a060020a03938416602486015260448501929092528216606484015216608482015260a40160006040518083038186803b15156138e057600080fd5b6102c65a03f415156138f157600080fd5b5050505b60008511156139bc578254613910908663ffffffff61435016565b8355600754613925908663ffffffff61435016565b60075561393061451c565b600160a060020a03166323b872dd33613947613f39565b8860006040516020015260405160e060020a63ffffffff8616028152600160a060020a0393841660048201529190921660248201526044810191909152606401602060405180830381600087803b15156139a057600080fd5b6102c65a03f115156139b157600080fd5b505050604051805150505b33600160a060020a031684600160a060020a03167f926f98e4b543897a75b3e34b7494ba68a47829d3aa39ffd9c478ccc51bfbfb4460405160405180910390a35050505050565b60008054600160a060020a0316635c975abb82604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515613a4b57600080fd5b6102c65a03f11515613a5c57600080fd5b5050506040518051159050613a7057600080fd5b613a78613ea6565b600160a060020a031663219bc76c6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515613abd57600080fd5b6102c65a03f11515613ace57600080fd5b505050604051805190501515613ae357600080fd5b6003613aee3361071e565b6003811115613af957fe5b14613b0357600080fd5b50600160a060020a033316600090815260056020819052604082208054838255910191909155613b31613f39565b600160a060020a031663e7a49c2b338360405160e060020a63ffffffff8516028152600160a060020a0390921660048301526024820152604401600060405180830381600087803b1515613b8457600080fd5b6102c65a03f11515613b9557600080fd5b50505033600160a060020a03167f32b4834046d70a9d8d9c79995359892376424492753f04a190f871bbbc8d26ce60405160405180910390a250565b60008054600160a060020a031690638da5cb5b90604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515613c1a57600080fd5b6102c65a03f11515613c2b57600080fd5b50505060405180519050600160a060020a031633600160a060020a0316141515613c5457600080fd5b6002805467ffffffffffffffff191667ffffffffffffffff83161790556000805160206147918339815191526040516020808252600f908201527f756e626f6e64696e67506572696f6400000000000000000000000000000000006040808301919091526060909101905180910390a150565b6000818152600d60209081526040808320600160a060020a038616845260010190915281205460ff161515613cfb57600080fd5b50600160a060020a0391909116600090815260066020908152604080832093835260079093019052206002015490565b600080600080600080600080613d3f613ea6565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515613d8457600080fd5b6102c65a03f11515613d9557600080fd5b5050506040518051600160a060020a038c166000908152600560205260409020909850965050868911801590613dce5750856006015489115b1515613dd957600080fd5b6001808701548754600689015491975095500192505b888311613e89576002860154600160a060020a0316600090815260066020908152604080832086845260070190915290209150613e2b8261449a565b15613e7e57506002850154600160a060020a038a8116911614613e65613e5883868463ffffffff61459e16565b869063ffffffff61435016565b9450613e7b61328e83868463ffffffff6144a516565b93505b600190920191613def565b509298975050505050505050565b600054600160a060020a031681565b60008054600160a060020a031663e16c7d986040517f526f756e64734d616e61676572000000000000000000000000000000000000008152600d01604051809103902060006040516020015260405160e060020a63ffffffff84160281526004810191909152602401602060405180830381600087803b1515613f2857600080fd5b6102c65a03f1151561187a57600080fd5b60008054600160a060020a031663e16c7d986040517f4d696e74657200000000000000000000000000000000000000000000000000008152600601604051809103902060006040516020015260405160e060020a63ffffffff84160281526004810191909152602401602060405180830381600087803b1515613f2857600080fd5b600160a060020a03831660009081526006602090815260408083206005835281842085855260078201909352908320805491939091614000908763ffffffff61435016565b82556003830154614017908763ffffffff61435016565b600384015561408886731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63d868112860088b60006040516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b151561385d57600080fd5b9050731a0b2ca69ca2c7f96e2529faa6d63f881655d81a6338237efe6008898460008060405160e060020a63ffffffff88160281526004810195909552600160a060020a03938416602486015260448501929092528216606484015216608482015260a40160006040518083038186803b151561410457600080fd5b6102c65a03f4151561411557600080fd5b505060075461412b91508763ffffffff61435016565b60075550505050505050565b600061415c620f4240614150858563ffffffff61461d16565b9063ffffffff61464816565b9392505050565b60008282111561416f57fe5b50900390565b600061417f613ea6565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156141c457600080fd5b6102c65a03f115156141d557600080fd5b50505060405180516000818152600d60209081526040808320600160a060020a038816845260010190915290205490925060ff161590506142715761423b61421d8383613cc7565b6000838152600d60205260409020600201549063ffffffff61416316565b6000828152600d602090815260408083206002810194909455600160a060020a03861683526001909301905220805460ff191690555b731a0b2ca69ca2c7f96e2529faa6d63f881655d81a635d35e00760088460405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160006040518083038186803b15156142d057600080fd5b6102c65a03f415156142e157600080fd5b50505081600160a060020a03167fc6be59bdc33151833b6dbb6823a9bddecde3c685a1bf4d253d20b4a93fbae56c60405160405180910390a25050565b600081831061432d578161415c565b5090919050565b6002840183905560038401929092556004830155600590910155565b60008282018381101561435f57fe5b8091505b5092915050565b600160a060020a03808316600090815260056020526040812060028101549092829182918291829182918291161561447d5760045460068901546143b5908b9063ffffffff61416316565b11156143c057600080fd5b87546001808a015460068b015492995097500194505b888511614472576002880154600160a060020a03166000908152600660209081526040808320888452600701909152902093506144128461449a565b15614467576002880154600160a060020a038b8116911614925061443d84888563ffffffff61465f16565b9092509050614452868363ffffffff61435016565b9550614464878263ffffffff61435016565b96505b6001909401936143d6565b868855600188018690555b5050505060069093019390935550505050565b620f424090111590565b600301546000901190565b600383015460009081908190819011156144f2576144cb86600001548760040154614137565b86549092506144ef906144e4908463ffffffff61416316565b8688600301546146f3565b90505b831561450f57614508818363ffffffff61435016565b9250614513565b8092505b50509392505050565b60008054600160a060020a031663e16c7d986040517f4c69766570656572546f6b656e000000000000000000000000000000000000008152600d01604051809103902060006040516020015260405160e060020a63ffffffff84160281526004810191909152602401602060405180830381600087803b1515613f2857600080fd5b6003830154600090819081908190819011156145f2576145c687600101548860050154614137565b60018801549091506145de908263ffffffff61416316565b92506145ef818789600301546146f3565b91505b841561460f57614608828463ffffffff61435016565b9350614613565b8193505b5050509392505050565b6000808315156146305760009150614363565b5082820282848281151561464057fe5b041461435f57fe5b600080828481151561465657fe5b04949350505050565b60018301546000908190819081908190111561469e5761468087878761459e565b6001880154909250614698908363ffffffff61416316565b60018801555b865460009011156146cc576146b48787876144a5565b87549091506146c9908263ffffffff61416316565b87555b60038701546146e1908763ffffffff61416316565b60038801559092509050935093915050565b6000614716620f4240614150614709868661471e565b879063ffffffff61461d16565b949350505050565b600061415c8261415085620f424063ffffffff61461d16565b81548183558181151161475b5760008381526020902061475b918101908301614772565b505050565b60206040519081016040526000815290565b61188691905b8082111561478c5760008155600101614778565b509056009f5033568d78ae30f29f01e944f97b2216493bd19d1b46d429673acff3dcd674a165627a7a72305820dd0ce954ef7b6a6647e6719eeb9e945b0a8825cdeba54568e24951f4879770280029

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

000000000000000000000000f96d54e490317c557a967abfa5d6e33006be69b3

-----Decoded View---------------
Arg [0] : _controller (address): 0xF96D54E490317c557A967ABfA5d6e33006BE69b3

-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000f96d54e490317c557a967abfa5d6e33006be69b3


Libraries Used


Swarm Source

bzzr://dd0ce954ef7b6a6647e6719eeb9e945b0a8825cdeba54568e24951f487977028

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

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

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